]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/custom-validators/videos.ts
emit more specific status codes on video upload (#3423)
[github/Chocobozzz/PeerTube.git] / server / helpers / custom-validators / videos.ts
1 import { values } from 'lodash'
2 import validator from 'validator'
3 import { VideoFilter, VideoPrivacy, VideoRateType } from '../../../shared'
4 import {
5 CONSTRAINTS_FIELDS,
6 MIMETYPES,
7 VIDEO_CATEGORIES,
8 VIDEO_LICENCES,
9 VIDEO_PRIVACIES,
10 VIDEO_RATE_TYPES,
11 VIDEO_STATES,
12 VIDEO_LIVE
13 } from '../../initializers/constants'
14 import { exists, isArray, isDateValid, isFileMimeTypeValid, isFileValid } from './misc'
15 import * as magnetUtil from 'magnet-uri'
16
17 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
18
19 function isVideoFilterValid (filter: VideoFilter) {
20 return filter === 'local' || filter === 'all-local' || filter === 'all'
21 }
22
23 function isVideoCategoryValid (value: any) {
24 return value === null || VIDEO_CATEGORIES[value] !== undefined
25 }
26
27 function isVideoStateValid (value: any) {
28 return exists(value) && VIDEO_STATES[value] !== undefined
29 }
30
31 function isVideoLicenceValid (value: any) {
32 return value === null || VIDEO_LICENCES[value] !== undefined
33 }
34
35 function isVideoLanguageValid (value: any) {
36 return value === null ||
37 (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
38 }
39
40 function isVideoDurationValid (value: string) {
41 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
42 }
43
44 function isVideoTruncatedDescriptionValid (value: string) {
45 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
46 }
47
48 function isVideoDescriptionValid (value: string) {
49 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
50 }
51
52 function isVideoSupportValid (value: string) {
53 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
54 }
55
56 function isVideoNameValid (value: string) {
57 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
58 }
59
60 function isVideoTagValid (tag: string) {
61 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
62 }
63
64 function isVideoTagsValid (tags: string[]) {
65 return tags === null || (
66 isArray(tags) &&
67 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
68 tags.every(tag => isVideoTagValid(tag))
69 )
70 }
71
72 function isVideoViewsValid (value: string) {
73 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
74 }
75
76 function isVideoRatingTypeValid (value: string) {
77 return value === 'none' || values(VIDEO_RATE_TYPES).includes(value as VideoRateType)
78 }
79
80 function isVideoFileExtnameValid (value: string) {
81 return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
82 }
83
84 function isVideoFileMimeTypeValid (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
85 return isFileMimeTypeValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile')
86 }
87
88 const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
89 .map(v => v.replace('.', ''))
90 .join('|')
91 const videoImageTypesRegex = `image/(${videoImageTypes})`
92
93 function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
94 return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
95 }
96
97 function isVideoPrivacyValid (value: number) {
98 return VIDEO_PRIVACIES[value] !== undefined
99 }
100
101 function isScheduleVideoUpdatePrivacyValid (value: number) {
102 return value === VideoPrivacy.UNLISTED || value === VideoPrivacy.PUBLIC || value === VideoPrivacy.INTERNAL
103 }
104
105 function isVideoOriginallyPublishedAtValid (value: string | null) {
106 return value === null || isDateValid(value)
107 }
108
109 function isVideoFileInfoHashValid (value: string | null | undefined) {
110 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
111 }
112
113 function isVideoFileResolutionValid (value: string) {
114 return exists(value) && validator.isInt(value + '')
115 }
116
117 function isVideoFPSResolutionValid (value: string) {
118 return value === null || validator.isInt(value + '')
119 }
120
121 function isVideoFileSizeValid (value: string) {
122 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
123 }
124
125 function isVideoMagnetUriValid (value: string) {
126 if (!exists(value)) return false
127
128 const parsed = magnetUtil.decode(value)
129 return parsed && isVideoFileInfoHashValid(parsed.infoHash)
130 }
131
132 // ---------------------------------------------------------------------------
133
134 export {
135 isVideoCategoryValid,
136 isVideoLicenceValid,
137 isVideoLanguageValid,
138 isVideoTruncatedDescriptionValid,
139 isVideoDescriptionValid,
140 isVideoFileInfoHashValid,
141 isVideoNameValid,
142 isVideoTagsValid,
143 isVideoFPSResolutionValid,
144 isScheduleVideoUpdatePrivacyValid,
145 isVideoOriginallyPublishedAtValid,
146 isVideoMagnetUriValid,
147 isVideoStateValid,
148 isVideoViewsValid,
149 isVideoRatingTypeValid,
150 isVideoFileExtnameValid,
151 isVideoFileMimeTypeValid,
152 isVideoDurationValid,
153 isVideoTagValid,
154 isVideoPrivacyValid,
155 isVideoFileResolutionValid,
156 isVideoFileSizeValid,
157 isVideoImage,
158 isVideoSupportValid,
159 isVideoFilterValid
160 }