1 import * as validator from 'validator'
2 import { ACTIVITY_PUB, CONSTRAINTS_FIELDS } from '../../../initializers'
3 import { peertubeTruncate } from '../../core-utils'
4 import { exists, isBooleanValid, isDateValid, isUUIDValid } from '../misc'
10 isVideoTruncatedDescriptionValid,
13 import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'
14 import { VideoState } from '../../../../shared/models/videos'
15 import { isVideoAbuseReasonValid } from '../video-abuses'
17 function sanitizeAndCheckVideoTorrentUpdateActivity (activity: any) {
18 return isBaseActivityValid(activity, 'Update') &&
19 sanitizeAndCheckVideoTorrentObject(activity.object)
22 function isActivityPubVideoDurationValid (value: string) {
23 // https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration
24 return exists(value) &&
25 typeof value === 'string' &&
26 value.startsWith('PT') &&
27 value.endsWith('S') &&
28 isVideoDurationValid(value.replace(/[^0-9]+/g, ''))
31 function sanitizeAndCheckVideoTorrentObject (video: any) {
32 if (!video || video.type !== 'Video') return false
34 if (!setValidRemoteTags(video)) return false
35 if (!setValidRemoteVideoUrls(video)) return false
36 if (!setRemoteVideoTruncatedContent(video)) return false
37 if (!setValidAttributedTo(video)) return false
38 if (!setValidRemoteCaptions(video)) return false
41 if (!isVideoStateValid(video.state)) video.state = VideoState.PUBLISHED
42 if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false
44 return isActivityPubUrlValid(video.id) &&
45 isVideoNameValid(video.name) &&
46 isActivityPubVideoDurationValid(video.duration) &&
47 isUUIDValid(video.uuid) &&
48 (!video.category || isRemoteNumberIdentifierValid(video.category)) &&
49 (!video.licence || isRemoteNumberIdentifierValid(video.licence)) &&
50 (!video.language || isRemoteStringIdentifierValid(video.language)) &&
51 isVideoViewsValid(video.views) &&
52 isBooleanValid(video.sensitive) &&
53 isBooleanValid(video.commentsEnabled) &&
54 isDateValid(video.published) &&
55 isDateValid(video.updated) &&
56 (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) &&
57 isRemoteVideoIconValid(video.icon) &&
58 video.url.length !== 0 &&
59 video.attributedTo.length !== 0
62 function isRemoteVideoUrlValid (url: any) {
63 // FIXME: Old bug, we used the width to represent the resolution. Remove it in a few release (currently beta.11)
64 if (url.width && !url.height) url.height = url.width
66 return url.type === 'Link' &&
68 // TODO: remove mimeType (backward compatibility, introduced in v1.1.0)
69 ACTIVITY_PUB.URL_MIME_TYPES.VIDEO.indexOf(url.mediaType || url.mimeType) !== -1 &&
70 isActivityPubUrlValid(url.href) &&
71 validator.isInt(url.height + '', { min: 0 }) &&
72 validator.isInt(url.size + '', { min: 0 }) &&
73 (!url.fps || validator.isInt(url.fps + '', { min: -1 }))
76 ACTIVITY_PUB.URL_MIME_TYPES.TORRENT.indexOf(url.mediaType || url.mimeType) !== -1 &&
77 isActivityPubUrlValid(url.href) &&
78 validator.isInt(url.height + '', { min: 0 })
81 ACTIVITY_PUB.URL_MIME_TYPES.MAGNET.indexOf(url.mediaType || url.mimeType) !== -1 &&
82 validator.isLength(url.href, { min: 5 }) &&
83 validator.isInt(url.height + '', { min: 0 })
87 // ---------------------------------------------------------------------------
90 sanitizeAndCheckVideoTorrentUpdateActivity,
91 isRemoteStringIdentifierValid,
92 sanitizeAndCheckVideoTorrentObject,
96 // ---------------------------------------------------------------------------
98 function setValidRemoteTags (video: any) {
99 if (Array.isArray(video.tag) === false) return false
101 video.tag = video.tag.filter(t => {
102 return t.type === 'Hashtag' &&
103 isVideoTagValid(t.name)
109 function setValidRemoteCaptions (video: any) {
110 if (!video.subtitleLanguage) video.subtitleLanguage = []
112 if (Array.isArray(video.subtitleLanguage) === false) return false
114 video.subtitleLanguage = video.subtitleLanguage.filter(caption => {
115 return isRemoteStringIdentifierValid(caption)
121 function isRemoteNumberIdentifierValid (data: any) {
122 return validator.isInt(data.identifier, { min: 0 })
125 function isRemoteStringIdentifierValid (data: any) {
126 return typeof data.identifier === 'string'
129 function isRemoteVideoContentValid (mediaType: string, content: string) {
130 return mediaType === 'text/markdown' && isVideoTruncatedDescriptionValid(content)
133 function isRemoteVideoIconValid (icon: any) {
134 return icon.type === 'Image' &&
135 isActivityPubUrlValid(icon.url) &&
136 icon.mediaType === 'image/jpeg' &&
137 validator.isInt(icon.width + '', { min: 0 }) &&
138 validator.isInt(icon.height + '', { min: 0 })
141 function setValidRemoteVideoUrls (video: any) {
142 if (Array.isArray(video.url) === false) return false
144 video.url = video.url.filter(u => isRemoteVideoUrlValid(u))
149 function setRemoteVideoTruncatedContent (video: any) {
151 video.content = peertubeTruncate(video.content, CONSTRAINTS_FIELDS.VIDEOS.TRUNCATED_DESCRIPTION.max)