diff options
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/custom-validators/video-captions.ts | 13 | ||||
-rw-r--r-- | server/helpers/youtube-dl/youtube-dl-info-builder.ts | 49 |
2 files changed, 62 insertions, 0 deletions
diff --git a/server/helpers/custom-validators/video-captions.ts b/server/helpers/custom-validators/video-captions.ts index 528edf60c..4cc7dcaf4 100644 --- a/server/helpers/custom-validators/video-captions.ts +++ b/server/helpers/custom-validators/video-captions.ts | |||
@@ -1,3 +1,5 @@ | |||
1 | import { getFileSize } from '@shared/extra-utils' | ||
2 | import { readFile } from 'fs-extra' | ||
1 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_LANGUAGES } from '../../initializers/constants' | 3 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_LANGUAGES } from '../../initializers/constants' |
2 | import { exists, isFileValid } from './misc' | 4 | import { exists, isFileValid } from './misc' |
3 | 5 | ||
@@ -13,9 +15,20 @@ function isVideoCaptionFile (files: { [ fieldname: string ]: Express.Multer.File | |||
13 | return isFileValid(files, videoCaptionTypesRegex, field, CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max) | 15 | return isFileValid(files, videoCaptionTypesRegex, field, CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max) |
14 | } | 16 | } |
15 | 17 | ||
18 | async function isVTTFileValid (filePath: string) { | ||
19 | const size = await getFileSize(filePath) | ||
20 | |||
21 | if (size > CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max) return false | ||
22 | |||
23 | const content = await readFile(filePath, 'utf8') | ||
24 | |||
25 | return content?.startsWith('WEBVTT\n') | ||
26 | } | ||
27 | |||
16 | // --------------------------------------------------------------------------- | 28 | // --------------------------------------------------------------------------- |
17 | 29 | ||
18 | export { | 30 | export { |
19 | isVideoCaptionFile, | 31 | isVideoCaptionFile, |
32 | isVTTFileValid, | ||
20 | isVideoCaptionLanguageValid | 33 | isVideoCaptionLanguageValid |
21 | } | 34 | } |
diff --git a/server/helpers/youtube-dl/youtube-dl-info-builder.ts b/server/helpers/youtube-dl/youtube-dl-info-builder.ts index 9746a7067..71572f292 100644 --- a/server/helpers/youtube-dl/youtube-dl-info-builder.ts +++ b/server/helpers/youtube-dl/youtube-dl-info-builder.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../../initializers/constants' | 1 | import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../../initializers/constants' |
2 | import { peertubeTruncate } from '../core-utils' | 2 | import { peertubeTruncate } from '../core-utils' |
3 | import { isUrlValid } from '../custom-validators/activitypub/misc' | ||
3 | 4 | ||
4 | type YoutubeDLInfo = { | 5 | type YoutubeDLInfo = { |
5 | name?: string | 6 | name?: string |
@@ -12,6 +13,8 @@ type YoutubeDLInfo = { | |||
12 | thumbnailUrl?: string | 13 | thumbnailUrl?: string |
13 | ext?: string | 14 | ext?: string |
14 | originallyPublishedAt?: Date | 15 | originallyPublishedAt?: Date |
16 | |||
17 | urls?: string[] | ||
15 | } | 18 | } |
16 | 19 | ||
17 | class YoutubeDLInfoBuilder { | 20 | class YoutubeDLInfoBuilder { |
@@ -76,11 +79,57 @@ class YoutubeDLInfoBuilder { | |||
76 | nsfw: this.isNSFW(obj), | 79 | nsfw: this.isNSFW(obj), |
77 | tags: this.getTags(obj.tags), | 80 | tags: this.getTags(obj.tags), |
78 | thumbnailUrl: obj.thumbnail || undefined, | 81 | thumbnailUrl: obj.thumbnail || undefined, |
82 | urls: this.buildAvailableUrl(obj), | ||
79 | originallyPublishedAt: this.buildOriginallyPublishedAt(obj), | 83 | originallyPublishedAt: this.buildOriginallyPublishedAt(obj), |
80 | ext: obj.ext | 84 | ext: obj.ext |
81 | } | 85 | } |
82 | } | 86 | } |
83 | 87 | ||
88 | private buildAvailableUrl (obj: any) { | ||
89 | const urls: string[] = [] | ||
90 | |||
91 | if (obj.url) urls.push(obj.url) | ||
92 | if (obj.urls) { | ||
93 | if (Array.isArray(obj.urls)) urls.push(...obj.urls) | ||
94 | else urls.push(obj.urls) | ||
95 | } | ||
96 | |||
97 | const formats = Array.isArray(obj.formats) | ||
98 | ? obj.formats | ||
99 | : [] | ||
100 | |||
101 | for (const format of formats) { | ||
102 | if (!format.url) continue | ||
103 | |||
104 | urls.push(format.url) | ||
105 | } | ||
106 | |||
107 | const thumbnails = Array.isArray(obj.thumbnails) | ||
108 | ? obj.thumbnails | ||
109 | : [] | ||
110 | |||
111 | for (const thumbnail of thumbnails) { | ||
112 | if (!thumbnail.url) continue | ||
113 | |||
114 | urls.push(thumbnail.url) | ||
115 | } | ||
116 | |||
117 | if (obj.thumbnail) urls.push(obj.thumbnail) | ||
118 | |||
119 | for (const subtitleKey of Object.keys(obj.subtitles || {})) { | ||
120 | const subtitles = obj.subtitles[subtitleKey] | ||
121 | if (!Array.isArray(subtitles)) continue | ||
122 | |||
123 | for (const subtitle of subtitles) { | ||
124 | if (!subtitle.url) continue | ||
125 | |||
126 | urls.push(subtitle.url) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return urls.filter(u => u && isUrlValid(u)) | ||
131 | } | ||
132 | |||
84 | private titleTruncation (title: string) { | 133 | private titleTruncation (title: string) { |
85 | return peertubeTruncate(title, { | 134 | return peertubeTruncate(title, { |
86 | length: CONSTRAINTS_FIELDS.VIDEOS.NAME.max, | 135 | length: CONSTRAINTS_FIELDS.VIDEOS.NAME.max, |