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 sanitizeAndCheckVideoTorrentCreateActivity (activity: any) {
18 return isBaseActivityValid(activity, 'Create') &&
19 sanitizeAndCheckVideoTorrentObject(activity.object)
22 function sanitizeAndCheckVideoTorrentUpdateActivity (activity: any) {
23 return isBaseActivityValid(activity, 'Update') &&
24 sanitizeAndCheckVideoTorrentObject(activity.object)
27 function isVideoTorrentDeleteActivityValid (activity: any) {
28 return isBaseActivityValid(activity, 'Delete')
31 function isVideoFlagValid (activity: any) {
32 return isBaseActivityValid(activity, 'Create') &&
33 activity.object.type === 'Flag' &&
34 isVideoAbuseReasonValid(activity.object.content) &&
35 isActivityPubUrlValid(activity.object.object)
38 function isActivityPubVideoDurationValid (value: string) {
39 // https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration
40 return exists(value) &&
41 typeof value === 'string' &&
42 value.startsWith('PT') &&
43 value.endsWith('S') &&
44 isVideoDurationValid(value.replace(/[^0-9]+/g, ''))
47 function sanitizeAndCheckVideoTorrentObject (video: any) {
48 if (!video || video.type !== 'Video') return false
50 if (!setValidRemoteTags(video)) return false
51 if (!setValidRemoteVideoUrls(video)) return false
52 if (!setRemoteVideoTruncatedContent(video)) return false
53 if (!setValidAttributedTo(video)) return false
54 if (!setValidRemoteCaptions(video)) return false
57 if (!isVideoStateValid(video.state)) video.state = VideoState.PUBLISHED
58 if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false
60 return isActivityPubUrlValid(video.id) &&
61 isVideoNameValid(video.name) &&
62 isActivityPubVideoDurationValid(video.duration) &&
63 isUUIDValid(video.uuid) &&
64 (!video.category || isRemoteNumberIdentifierValid(video.category)) &&
65 (!video.licence || isRemoteNumberIdentifierValid(video.licence)) &&
66 (!video.language || isRemoteStringIdentifierValid(video.language)) &&
67 isVideoViewsValid(video.views) &&
68 isBooleanValid(video.sensitive) &&
69 isBooleanValid(video.commentsEnabled) &&
70 isDateValid(video.published) &&
71 isDateValid(video.updated) &&
72 (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) &&
73 isRemoteVideoIconValid(video.icon) &&
74 video.url.length !== 0 &&
75 video.attributedTo.length !== 0
78 function isRemoteVideoUrlValid (url: any) {
79 // FIXME: Old bug, we used the width to represent the resolution. Remove it in a few release (currently beta.11)
80 if (url.width && !url.height) url.height = url.width
82 return url.type === 'Link' &&
84 ACTIVITY_PUB.URL_MIME_TYPES.VIDEO.indexOf(url.mimeType) !== -1 &&
85 isActivityPubUrlValid(url.href) &&
86 validator.isInt(url.height + '', { min: 0 }) &&
87 validator.isInt(url.size + '', { min: 0 }) &&
88 (!url.fps || validator.isInt(url.fps + '', { min: 0 }))
91 ACTIVITY_PUB.URL_MIME_TYPES.TORRENT.indexOf(url.mimeType) !== -1 &&
92 isActivityPubUrlValid(url.href) &&
93 validator.isInt(url.height + '', { min: 0 })
96 ACTIVITY_PUB.URL_MIME_TYPES.MAGNET.indexOf(url.mimeType) !== -1 &&
97 validator.isLength(url.href, { min: 5 }) &&
98 validator.isInt(url.height + '', { min: 0 })
102 // ---------------------------------------------------------------------------
105 sanitizeAndCheckVideoTorrentCreateActivity,
106 sanitizeAndCheckVideoTorrentUpdateActivity,
107 isVideoTorrentDeleteActivityValid,
108 isRemoteStringIdentifierValid,
110 sanitizeAndCheckVideoTorrentObject,
111 isRemoteVideoUrlValid
114 // ---------------------------------------------------------------------------
116 function setValidRemoteTags (video: any) {
117 if (Array.isArray(video.tag) === false) return false
119 video.tag = video.tag.filter(t => {
120 return t.type === 'Hashtag' &&
121 isVideoTagValid(t.name)
127 function setValidRemoteCaptions (video: any) {
128 if (!video.subtitleLanguage) video.subtitleLanguage = []
130 if (Array.isArray(video.subtitleLanguage) === false) return false
132 video.subtitleLanguage = video.subtitleLanguage.filter(caption => {
133 return isRemoteStringIdentifierValid(caption)
139 function isRemoteNumberIdentifierValid (data: any) {
140 return validator.isInt(data.identifier, { min: 0 })
143 function isRemoteStringIdentifierValid (data: any) {
144 return typeof data.identifier === 'string'
147 function isRemoteVideoContentValid (mediaType: string, content: string) {
148 return mediaType === 'text/markdown' && isVideoTruncatedDescriptionValid(content)
151 function isRemoteVideoIconValid (icon: any) {
152 return icon.type === 'Image' &&
153 isActivityPubUrlValid(icon.url) &&
154 icon.mediaType === 'image/jpeg' &&
155 validator.isInt(icon.width + '', { min: 0 }) &&
156 validator.isInt(icon.height + '', { min: 0 })
159 function setValidRemoteVideoUrls (video: any) {
160 if (Array.isArray(video.url) === false) return false
162 video.url = video.url.filter(u => isRemoteVideoUrlValid(u))
167 function setRemoteVideoTruncatedContent (video: any) {
169 video.content = peertubeTruncate(video.content, CONSTRAINTS_FIELDS.VIDEOS.TRUNCATED_DESCRIPTION.max)