aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/shared/video-import/video-import.service.ts1
-rw-r--r--client/src/app/shared/video/video-details.model.ts2
-rw-r--r--client/src/app/shared/video/video-edit.model.ts13
-rw-r--r--client/src/app/shared/video/video.service.ts1
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.component.html5
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.component.ts2
-rw-r--r--client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts2
-rw-r--r--client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts2
-rw-r--r--client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts2
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html2
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.ts4
-rw-r--r--server/controllers/api/videos/import.ts1
-rw-r--r--server/controllers/api/videos/index.ts2
-rw-r--r--server/helpers/activitypub.ts1
-rw-r--r--server/helpers/audit-logger.ts3
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts2
-rw-r--r--server/initializers/migrations/0280-video-downloading-enabled.ts27
-rw-r--r--server/lib/activitypub/videos.ts2
-rw-r--r--server/middlewares/validators/videos/videos.ts4
-rw-r--r--server/models/video/video-format-utils.ts2
-rw-r--r--server/models/video/video.ts4
-rw-r--r--server/tests/api/check-params/video-imports.ts1
-rw-r--r--server/tests/api/check-params/videos.ts2
-rw-r--r--server/tests/api/server/follows.ts1
-rw-r--r--server/tests/api/server/handle-down.ts1
-rw-r--r--server/tests/api/videos/multiple-servers.ts12
-rw-r--r--server/tests/api/videos/single-server.ts3
-rw-r--r--server/tools/peertube-import-videos.ts1
-rw-r--r--server/tools/peertube-upload.ts2
-rw-r--r--shared/models/activitypub/objects/video-torrent-object.ts3
-rw-r--r--shared/models/videos/video-create.model.ts1
-rw-r--r--shared/models/videos/video-update.model.ts1
-rw-r--r--shared/models/videos/video.model.ts1
-rw-r--r--shared/utils/videos/videos.ts6
34 files changed, 113 insertions, 6 deletions
diff --git a/client/src/app/shared/video-import/video-import.service.ts b/client/src/app/shared/video-import/video-import.service.ts
index 7ae66ddfc..2163eb905 100644
--- a/client/src/app/shared/video-import/video-import.service.ts
+++ b/client/src/app/shared/video-import/video-import.service.ts
@@ -81,6 +81,7 @@ export class VideoImportService {
81 nsfw: video.nsfw, 81 nsfw: video.nsfw,
82 waitTranscoding: video.waitTranscoding, 82 waitTranscoding: video.waitTranscoding,
83 commentsEnabled: video.commentsEnabled, 83 commentsEnabled: video.commentsEnabled,
84 downloadEnabled: video.downloadEnabled,
84 thumbnailfile: video.thumbnailfile, 85 thumbnailfile: video.thumbnailfile,
85 previewfile: video.previewfile, 86 previewfile: video.previewfile,
86 scheduleUpdate 87 scheduleUpdate
diff --git a/client/src/app/shared/video/video-details.model.ts b/client/src/app/shared/video/video-details.model.ts
index f44b4138b..388357343 100644
--- a/client/src/app/shared/video/video-details.model.ts
+++ b/client/src/app/shared/video/video-details.model.ts
@@ -14,6 +14,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
14 files: VideoFile[] 14 files: VideoFile[]
15 account: Account 15 account: Account
16 commentsEnabled: boolean 16 commentsEnabled: boolean
17 downloadEnabled: boolean
17 18
18 waitTranscoding: boolean 19 waitTranscoding: boolean
19 state: VideoConstant<VideoState> 20 state: VideoConstant<VideoState>
@@ -35,6 +36,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
35 this.tags = hash.tags 36 this.tags = hash.tags
36 this.support = hash.support 37 this.support = hash.support
37 this.commentsEnabled = hash.commentsEnabled 38 this.commentsEnabled = hash.commentsEnabled
39 this.downloadEnabled = hash.downloadEnabled
38 40
39 this.trackerUrls = hash.trackerUrls 41 this.trackerUrls = hash.trackerUrls
40 this.streamingPlaylists = hash.streamingPlaylists 42 this.streamingPlaylists = hash.streamingPlaylists
diff --git a/client/src/app/shared/video/video-edit.model.ts b/client/src/app/shared/video/video-edit.model.ts
index fc772a3cf..18c62a1f9 100644
--- a/client/src/app/shared/video/video-edit.model.ts
+++ b/client/src/app/shared/video/video-edit.model.ts
@@ -14,6 +14,7 @@ export class VideoEdit implements VideoUpdate {
14 tags: string[] 14 tags: string[]
15 nsfw: boolean 15 nsfw: boolean
16 commentsEnabled: boolean 16 commentsEnabled: boolean
17 downloadEnabled: boolean
17 waitTranscoding: boolean 18 waitTranscoding: boolean
18 channelId: number 19 channelId: number
19 privacy: VideoPrivacy 20 privacy: VideoPrivacy
@@ -26,7 +27,15 @@ export class VideoEdit implements VideoUpdate {
26 id?: number 27 id?: number
27 scheduleUpdate?: VideoScheduleUpdate 28 scheduleUpdate?: VideoScheduleUpdate
28 29
29 constructor (video?: Video & { tags: string[], commentsEnabled: boolean, support: string, thumbnailUrl: string, previewUrl: string }) { 30 constructor (
31 video?: Video & {
32 tags: string[],
33 commentsEnabled: boolean,
34 downloadEnabled: boolean,
35 support: string,
36 thumbnailUrl: string,
37 previewUrl: string
38 }) {
30 if (video) { 39 if (video) {
31 this.id = video.id 40 this.id = video.id
32 this.uuid = video.uuid 41 this.uuid = video.uuid
@@ -38,6 +47,7 @@ export class VideoEdit implements VideoUpdate {
38 this.tags = video.tags 47 this.tags = video.tags
39 this.nsfw = video.nsfw 48 this.nsfw = video.nsfw
40 this.commentsEnabled = video.commentsEnabled 49 this.commentsEnabled = video.commentsEnabled
50 this.downloadEnabled = video.downloadEnabled
41 this.waitTranscoding = video.waitTranscoding 51 this.waitTranscoding = video.waitTranscoding
42 this.channelId = video.channel.id 52 this.channelId = video.channel.id
43 this.privacy = video.privacy.id 53 this.privacy = video.privacy.id
@@ -80,6 +90,7 @@ export class VideoEdit implements VideoUpdate {
80 tags: this.tags, 90 tags: this.tags,
81 nsfw: this.nsfw, 91 nsfw: this.nsfw,
82 commentsEnabled: this.commentsEnabled, 92 commentsEnabled: this.commentsEnabled,
93 downloadEnabled: this.downloadEnabled,
83 waitTranscoding: this.waitTranscoding, 94 waitTranscoding: this.waitTranscoding,
84 channelId: this.channelId, 95 channelId: this.channelId,
85 privacy: this.privacy 96 privacy: this.privacy
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index 55844f988..565aad93b 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -95,6 +95,7 @@ export class VideoService implements VideosProvider {
95 nsfw: video.nsfw, 95 nsfw: video.nsfw,
96 waitTranscoding: video.waitTranscoding, 96 waitTranscoding: video.waitTranscoding,
97 commentsEnabled: video.commentsEnabled, 97 commentsEnabled: video.commentsEnabled,
98 downloadEnabled: video.downloadEnabled,
98 thumbnailfile: video.thumbnailfile, 99 thumbnailfile: video.thumbnailfile,
99 previewfile: video.previewfile, 100 previewfile: video.previewfile,
100 scheduleUpdate 101 scheduleUpdate
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html
index 092c0e862..7fd9af208 100644
--- a/client/src/app/videos/+video-edit/shared/video-edit.component.html
+++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html
@@ -126,6 +126,11 @@
126 ></my-peertube-checkbox> 126 ></my-peertube-checkbox>
127 127
128 <my-peertube-checkbox 128 <my-peertube-checkbox
129 inputName="downloadEnabled" formControlName="downloadEnabled"
130 i18n-labelText labelText="Download enabled"
131 ></my-peertube-checkbox>
132
133 <my-peertube-checkbox
129 *ngIf="waitTranscodingEnabled" 134 *ngIf="waitTranscodingEnabled"
130 inputName="waitTranscoding" formControlName="waitTranscoding" 135 inputName="waitTranscoding" formControlName="waitTranscoding"
131 i18n-labelText labelText="Wait transcoding before publishing the video" 136 i18n-labelText labelText="Wait transcoding before publishing the video"
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.ts b/client/src/app/videos/+video-edit/shared/video-edit.component.ts
index 85e015901..3ed7a4a10 100644
--- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts
+++ b/client/src/app/videos/+video-edit/shared/video-edit.component.ts
@@ -81,6 +81,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
81 const defaultValues: any = { 81 const defaultValues: any = {
82 nsfw: 'false', 82 nsfw: 'false',
83 commentsEnabled: 'true', 83 commentsEnabled: 'true',
84 downloadEnabled: 'true',
84 waitTranscoding: 'true', 85 waitTranscoding: 'true',
85 tags: [] 86 tags: []
86 } 87 }
@@ -90,6 +91,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
90 channelId: this.videoValidatorsService.VIDEO_CHANNEL, 91 channelId: this.videoValidatorsService.VIDEO_CHANNEL,
91 nsfw: null, 92 nsfw: null,
92 commentsEnabled: null, 93 commentsEnabled: null,
94 downloadEnabled: null,
93 waitTranscoding: null, 95 waitTranscoding: null,
94 category: this.videoValidatorsService.VIDEO_CATEGORY, 96 category: this.videoValidatorsService.VIDEO_CATEGORY,
95 licence: this.videoValidatorsService.VIDEO_LICENCE, 97 licence: this.videoValidatorsService.VIDEO_LICENCE,
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts
index 307806bb9..c12a1d653 100644
--- a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts
+++ b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts
@@ -79,6 +79,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca
79 privacy: this.firstStepPrivacyId, 79 privacy: this.firstStepPrivacyId,
80 waitTranscoding: false, 80 waitTranscoding: false,
81 commentsEnabled: true, 81 commentsEnabled: true,
82 downloadEnabled: true,
82 channelId: this.firstStepChannelId 83 channelId: this.firstStepChannelId
83 } 84 }
84 85
@@ -93,6 +94,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca
93 94
94 this.video = new VideoEdit(Object.assign(res.video, { 95 this.video = new VideoEdit(Object.assign(res.video, {
95 commentsEnabled: videoUpdate.commentsEnabled, 96 commentsEnabled: videoUpdate.commentsEnabled,
97 downloadEnabled: videoUpdate.downloadEnabled,
96 support: null, 98 support: null,
97 thumbnailUrl: null, 99 thumbnailUrl: null,
98 previewUrl: null 100 previewUrl: null
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts
index 257c6e5db..d11685916 100644
--- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts
+++ b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.ts
@@ -70,6 +70,7 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, CanCom
70 privacy: this.firstStepPrivacyId, 70 privacy: this.firstStepPrivacyId,
71 waitTranscoding: false, 71 waitTranscoding: false,
72 commentsEnabled: true, 72 commentsEnabled: true,
73 downloadEnabled: true,
73 channelId: this.firstStepChannelId 74 channelId: this.firstStepChannelId
74 } 75 }
75 76
@@ -84,6 +85,7 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, CanCom
84 85
85 this.video = new VideoEdit(Object.assign(res.video, { 86 this.video = new VideoEdit(Object.assign(res.video, {
86 commentsEnabled: videoUpdate.commentsEnabled, 87 commentsEnabled: videoUpdate.commentsEnabled,
88 downloadEnabled: videoUpdate.downloadEnabled,
87 support: null, 89 support: null,
88 thumbnailUrl: null, 90 thumbnailUrl: null,
89 previewUrl: null 91 previewUrl: null
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts
index e4d54b654..9cadf52cb 100644
--- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts
+++ b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts
@@ -166,6 +166,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
166 const nsfw = false 166 const nsfw = false
167 const waitTranscoding = true 167 const waitTranscoding = true
168 const commentsEnabled = true 168 const commentsEnabled = true
169 const downloadEnabled = true
169 const channelId = this.firstStepChannelId.toString() 170 const channelId = this.firstStepChannelId.toString()
170 171
171 const formData = new FormData() 172 const formData = new FormData()
@@ -174,6 +175,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
174 formData.append('privacy', VideoPrivacy.PRIVATE.toString()) 175 formData.append('privacy', VideoPrivacy.PRIVATE.toString())
175 formData.append('nsfw', '' + nsfw) 176 formData.append('nsfw', '' + nsfw)
176 formData.append('commentsEnabled', '' + commentsEnabled) 177 formData.append('commentsEnabled', '' + commentsEnabled)
178 formData.append('downloadEnabled', '' + downloadEnabled)
177 formData.append('waitTranscoding', '' + waitTranscoding) 179 formData.append('waitTranscoding', '' + waitTranscoding)
178 formData.append('channelId', '' + channelId) 180 formData.append('channelId', '' + channelId)
179 formData.append('videofile', videofile) 181 formData.append('videofile', videofile)
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html
index 709eb91a8..1875230d8 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -82,7 +82,7 @@
82 </div> 82 </div>
83 83
84 <div ngbDropdownMenu> 84 <div ngbDropdownMenu>
85 <a class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)"> 85 <a *ngIf="isVideoDownloadable()" class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
86 <my-global-icon iconName="download"></my-global-icon> <ng-container i18n>Download</ng-container> 86 <my-global-icon iconName="download"></my-global-icon> <ng-container i18n>Download</ng-container>
87 </a> 87 </a>
88 88
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts
index e801f03ad..4dbfa41e5 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/videos/+video-watch/video-watch.component.ts
@@ -308,6 +308,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
308 return this.video && this.video.state.id === VideoState.TO_TRANSCODE 308 return this.video && this.video.state.id === VideoState.TO_TRANSCODE
309 } 309 }
310 310
311 isVideoDownloadable () {
312 return this.video && this.video.downloadEnabled
313 }
314
311 isVideoToImport () { 315 isVideoToImport () {
312 return this.video && this.video.state.id === VideoState.TO_IMPORT 316 return this.video && this.video.state.id === VideoState.TO_IMPORT
313 } 317 }
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts
index 98366cd82..7053d5253 100644
--- a/server/controllers/api/videos/import.ts
+++ b/server/controllers/api/videos/import.ts
@@ -164,6 +164,7 @@ function buildVideo (channelId: number, body: VideoImportCreate, importData: You
164 licence: body.licence || importData.licence, 164 licence: body.licence || importData.licence,
165 language: body.language || undefined, 165 language: body.language || undefined,
166 commentsEnabled: body.commentsEnabled || true, 166 commentsEnabled: body.commentsEnabled || true,
167 downloadEnabled: body.downloadEnabled || true,
167 waitTranscoding: body.waitTranscoding || false, 168 waitTranscoding: body.waitTranscoding || false,
168 state: VideoState.TO_IMPORT, 169 state: VideoState.TO_IMPORT,
169 nsfw: body.nsfw || importData.nsfw || false, 170 nsfw: body.nsfw || importData.nsfw || false,
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 3b1c2d255..76a318d13 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -182,6 +182,7 @@ async function addVideo (req: express.Request, res: express.Response) {
182 licence: videoInfo.licence, 182 licence: videoInfo.licence,
183 language: videoInfo.language, 183 language: videoInfo.language,
184 commentsEnabled: videoInfo.commentsEnabled || false, 184 commentsEnabled: videoInfo.commentsEnabled || false,
185 downloadEnabled: videoInfo.downloadEnabled || true,
185 waitTranscoding: videoInfo.waitTranscoding || false, 186 waitTranscoding: videoInfo.waitTranscoding || false,
186 state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED, 187 state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED,
187 nsfw: videoInfo.nsfw || false, 188 nsfw: videoInfo.nsfw || false,
@@ -326,6 +327,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
326 if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support) 327 if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support)
327 if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) 328 if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description)
328 if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) 329 if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled)
330 if (videoInfoToUpdate.downloadEnabled !== undefined) videoInstance.set('downloadEnabled', videoInfoToUpdate.downloadEnabled)
329 if (videoInfoToUpdate.privacy !== undefined) { 331 if (videoInfoToUpdate.privacy !== undefined) {
330 const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10) 332 const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10)
331 videoInstance.set('privacy', newPrivacy) 333 videoInstance.set('privacy', newPrivacy)
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index eba552524..62d78373e 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -29,6 +29,7 @@ function activityPubContextify <T> (data: T) {
29 size: 'sc:Number', 29 size: 'sc:Number',
30 fps: 'sc:Number', 30 fps: 'sc:Number',
31 commentsEnabled: 'sc:Boolean', 31 commentsEnabled: 'sc:Boolean',
32 downloadEnabled: 'sc:Boolean',
32 waitTranscoding: 'sc:Boolean', 33 waitTranscoding: 'sc:Boolean',
33 expires: 'sc:expires', 34 expires: 'sc:expires',
34 support: 'sc:Text', 35 support: 'sc:Text',
diff --git a/server/helpers/audit-logger.ts b/server/helpers/audit-logger.ts
index 00311fce1..a121f0b8a 100644
--- a/server/helpers/audit-logger.ts
+++ b/server/helpers/audit-logger.ts
@@ -117,7 +117,8 @@ const videoKeysToKeep = [
117 'channel-uuid', 117 'channel-uuid',
118 'channel-name', 118 'channel-name',
119 'support', 119 'support',
120 'commentsEnabled' 120 'commentsEnabled',
121 'downloadEnabled'
121] 122]
122class VideoAuditView extends EntityAuditView { 123class VideoAuditView extends EntityAuditView {
123 constructor (private video: VideoDetails) { 124 constructor (private video: VideoDetails) {
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
index ad99c2724..53ad0588d 100644
--- a/server/helpers/custom-validators/activitypub/videos.ts
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -39,6 +39,7 @@ function sanitizeAndCheckVideoTorrentObject (video: any) {
39 // Default attributes 39 // Default attributes
40 if (!isVideoStateValid(video.state)) video.state = VideoState.PUBLISHED 40 if (!isVideoStateValid(video.state)) video.state = VideoState.PUBLISHED
41 if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false 41 if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false
42 if (!isBooleanValid(video.downloadEnabled)) video.downloadEnabled = true
42 43
43 return isActivityPubUrlValid(video.id) && 44 return isActivityPubUrlValid(video.id) &&
44 isVideoNameValid(video.name) && 45 isVideoNameValid(video.name) &&
@@ -50,6 +51,7 @@ function sanitizeAndCheckVideoTorrentObject (video: any) {
50 isVideoViewsValid(video.views) && 51 isVideoViewsValid(video.views) &&
51 isBooleanValid(video.sensitive) && 52 isBooleanValid(video.sensitive) &&
52 isBooleanValid(video.commentsEnabled) && 53 isBooleanValid(video.commentsEnabled) &&
54 isBooleanValid(video.downloadEnabled) &&
53 isDateValid(video.published) && 55 isDateValid(video.published) &&
54 isDateValid(video.updated) && 56 isDateValid(video.updated) &&
55 (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && 57 (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) &&
diff --git a/server/initializers/migrations/0280-video-downloading-enabled.ts b/server/initializers/migrations/0280-video-downloading-enabled.ts
new file mode 100644
index 000000000..e79466447
--- /dev/null
+++ b/server/initializers/migrations/0280-video-downloading-enabled.ts
@@ -0,0 +1,27 @@
1import * as Sequelize from 'sequelize'
2import { Migration } from '../../models/migrations'
3
4async function up (utils: {
5 transaction: Sequelize.Transaction,
6 queryInterface: Sequelize.QueryInterface,
7 sequelize: Sequelize.Sequelize
8}): Promise<void> {
9 const data = {
10 type: Sequelize.BOOLEAN,
11 allowNull: false,
12 defaultValue: true
13 } as Migration.Boolean
14 await utils.queryInterface.addColumn('video', 'downloadEnabled', data)
15
16 data.defaultValue = null
17 return utils.queryInterface.changeColumn('video', 'downloadEnabled', data)
18}
19
20function down (options) {
21 throw new Error('Not implemented.')
22}
23
24export {
25 up,
26 down
27}
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index edd01234f..710929aac 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -243,6 +243,7 @@ async function updateVideoFromAP (options: {
243 options.video.set('support', videoData.support) 243 options.video.set('support', videoData.support)
244 options.video.set('nsfw', videoData.nsfw) 244 options.video.set('nsfw', videoData.nsfw)
245 options.video.set('commentsEnabled', videoData.commentsEnabled) 245 options.video.set('commentsEnabled', videoData.commentsEnabled)
246 options.video.set('downloadEnabled', videoData.downloadEnabled)
246 options.video.set('waitTranscoding', videoData.waitTranscoding) 247 options.video.set('waitTranscoding', videoData.waitTranscoding)
247 options.video.set('state', videoData.state) 248 options.video.set('state', videoData.state)
248 options.video.set('duration', videoData.duration) 249 options.video.set('duration', videoData.duration)
@@ -503,6 +504,7 @@ async function videoActivityObjectToDBAttributes (
503 support, 504 support,
504 nsfw: videoObject.sensitive, 505 nsfw: videoObject.sensitive,
505 commentsEnabled: videoObject.commentsEnabled, 506 commentsEnabled: videoObject.commentsEnabled,
507 downloadEnabled: videoObject.downloadEnabled,
506 waitTranscoding: videoObject.waitTranscoding, 508 waitTranscoding: videoObject.waitTranscoding,
507 state: videoObject.state, 509 state: videoObject.state,
508 channelId: videoChannel.id, 510 channelId: videoChannel.id,
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts
index 051a19e16..d9626929c 100644
--- a/server/middlewares/validators/videos/videos.ts
+++ b/server/middlewares/validators/videos/videos.ts
@@ -340,6 +340,10 @@ function getCommonVideoAttributes () {
340 .optional() 340 .optional()
341 .toBoolean() 341 .toBoolean()
342 .custom(isBooleanValid).withMessage('Should have comments enabled boolean'), 342 .custom(isBooleanValid).withMessage('Should have comments enabled boolean'),
343 body('downloadEnabled')
344 .optional()
345 .toBoolean()
346 .custom(isBooleanValid).withMessage('Should have downloading enabled boolean'),
343 347
344 body('scheduleUpdate') 348 body('scheduleUpdate')
345 .optional() 349 .optional()
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts
index e49dbee30..76d0445d4 100644
--- a/server/models/video/video-format-utils.ts
+++ b/server/models/video/video-format-utils.ts
@@ -140,6 +140,7 @@ function videoModelToFormattedDetailsJSON (video: VideoModel): VideoDetails {
140 account: video.VideoChannel.Account.toFormattedJSON(), 140 account: video.VideoChannel.Account.toFormattedJSON(),
141 tags, 141 tags,
142 commentsEnabled: video.commentsEnabled, 142 commentsEnabled: video.commentsEnabled,
143 downloadEnabled: video.downloadEnabled,
143 waitTranscoding: video.waitTranscoding, 144 waitTranscoding: video.waitTranscoding,
144 state: { 145 state: {
145 id: video.state, 146 id: video.state,
@@ -320,6 +321,7 @@ function videoModelToActivityPubObject (video: VideoModel): VideoTorrentObject {
320 waitTranscoding: video.waitTranscoding, 321 waitTranscoding: video.waitTranscoding,
321 state: video.state, 322 state: video.state,
322 commentsEnabled: video.commentsEnabled, 323 commentsEnabled: video.commentsEnabled,
324 downloadEnabled: video.downloadEnabled,
323 published: video.publishedAt.toISOString(), 325 published: video.publishedAt.toISOString(),
324 updated: video.updatedAt.toISOString(), 326 updated: video.updatedAt.toISOString(),
325 mediaType: 'text/markdown', 327 mediaType: 'text/markdown',
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 702260772..0feeed4f8 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -717,6 +717,10 @@ export class VideoModel extends Model<VideoModel> {
717 717
718 @AllowNull(false) 718 @AllowNull(false)
719 @Column 719 @Column
720 downloadEnabled: boolean
721
722 @AllowNull(false)
723 @Column
720 waitTranscoding: boolean 724 waitTranscoding: boolean
721 725
722 @AllowNull(false) 726 @AllowNull(false)
diff --git a/server/tests/api/check-params/video-imports.ts b/server/tests/api/check-params/video-imports.ts
index 7bf187007..6dd9f15f7 100644
--- a/server/tests/api/check-params/video-imports.ts
+++ b/server/tests/api/check-params/video-imports.ts
@@ -88,6 +88,7 @@ describe('Test video imports API validator', function () {
88 language: 'pt', 88 language: 'pt',
89 nsfw: false, 89 nsfw: false,
90 commentsEnabled: true, 90 commentsEnabled: true,
91 downloadEnabled: true,
91 waitTranscoding: true, 92 waitTranscoding: true,
92 description: 'my super description', 93 description: 'my super description',
93 support: 'my super support text', 94 support: 'my super support text',
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index f26b91435..878ffe025 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -179,6 +179,7 @@ describe('Test videos API validator', function () {
179 language: 'pt', 179 language: 'pt',
180 nsfw: false, 180 nsfw: false,
181 commentsEnabled: true, 181 commentsEnabled: true,
182 downloadEnabled: true,
182 waitTranscoding: true, 183 waitTranscoding: true,
183 description: 'my super description', 184 description: 'my super description',
184 support: 'my super support text', 185 support: 'my super support text',
@@ -428,6 +429,7 @@ describe('Test videos API validator', function () {
428 language: 'pt', 429 language: 'pt',
429 nsfw: false, 430 nsfw: false,
430 commentsEnabled: false, 431 commentsEnabled: false,
432 downloadEnabled: false,
431 description: 'my super description', 433 description: 'my super description',
432 privacy: VideoPrivacy.PUBLIC, 434 privacy: VideoPrivacy.PUBLIC,
433 tags: [ 'tag1', 'tag2' ] 435 tags: [ 'tag1', 'tag2' ]
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts
index b0fc5d293..ad4c87c73 100644
--- a/server/tests/api/server/follows.ts
+++ b/server/tests/api/server/follows.ts
@@ -348,6 +348,7 @@ describe('Test follows', function () {
348 }, 348 },
349 isLocal, 349 isLocal,
350 commentsEnabled: true, 350 commentsEnabled: true,
351 downloadEnabled: true,
351 duration: 5, 352 duration: 5,
352 tags: [ 'tag1', 'tag2', 'tag3' ], 353 tags: [ 'tag1', 'tag2', 'tag3' ],
353 privacy: VideoPrivacy.PUBLIC, 354 privacy: VideoPrivacy.PUBLIC,
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts
index cd7baadad..cd5acbe16 100644
--- a/server/tests/api/server/handle-down.ts
+++ b/server/tests/api/server/handle-down.ts
@@ -76,6 +76,7 @@ describe('Test handle downs', function () {
76 tags: [ 'tag1p1', 'tag2p1' ], 76 tags: [ 'tag1p1', 'tag2p1' ],
77 privacy: VideoPrivacy.PUBLIC, 77 privacy: VideoPrivacy.PUBLIC,
78 commentsEnabled: true, 78 commentsEnabled: true,
79 downloadEnabled: true,
79 channel: { 80 channel: {
80 name: 'root_channel', 81 name: 'root_channel',
81 displayName: 'Main root channel', 82 displayName: 'Main root channel',
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index 6c281e49e..1b471ba79 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -128,6 +128,7 @@ describe('Test multiple servers', function () {
128 tags: [ 'tag1p1', 'tag2p1' ], 128 tags: [ 'tag1p1', 'tag2p1' ],
129 privacy: VideoPrivacy.PUBLIC, 129 privacy: VideoPrivacy.PUBLIC,
130 commentsEnabled: true, 130 commentsEnabled: true,
131 downloadEnabled: true,
131 channel: { 132 channel: {
132 displayName: 'my channel', 133 displayName: 'my channel',
133 name: 'super_channel_name', 134 name: 'super_channel_name',
@@ -199,6 +200,7 @@ describe('Test multiple servers', function () {
199 }, 200 },
200 isLocal, 201 isLocal,
201 commentsEnabled: true, 202 commentsEnabled: true,
203 downloadEnabled: true,
202 duration: 5, 204 duration: 5,
203 tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], 205 tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ],
204 privacy: VideoPrivacy.PUBLIC, 206 privacy: VideoPrivacy.PUBLIC,
@@ -307,6 +309,7 @@ describe('Test multiple servers', function () {
307 isLocal, 309 isLocal,
308 duration: 5, 310 duration: 5,
309 commentsEnabled: true, 311 commentsEnabled: true,
312 downloadEnabled: true,
310 tags: [ 'tag1p3' ], 313 tags: [ 'tag1p3' ],
311 privacy: VideoPrivacy.PUBLIC, 314 privacy: VideoPrivacy.PUBLIC,
312 channel: { 315 channel: {
@@ -338,6 +341,7 @@ describe('Test multiple servers', function () {
338 host: 'localhost:9003' 341 host: 'localhost:9003'
339 }, 342 },
340 commentsEnabled: true, 343 commentsEnabled: true,
344 downloadEnabled: true,
341 isLocal, 345 isLocal,
342 duration: 5, 346 duration: 5,
343 tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], 347 tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
@@ -655,6 +659,7 @@ describe('Test multiple servers', function () {
655 isLocal, 659 isLocal,
656 duration: 5, 660 duration: 5,
657 commentsEnabled: true, 661 commentsEnabled: true,
662 downloadEnabled: true,
658 tags: [ 'tag_up_1', 'tag_up_2' ], 663 tags: [ 'tag_up_1', 'tag_up_2' ],
659 privacy: VideoPrivacy.PUBLIC, 664 privacy: VideoPrivacy.PUBLIC,
660 channel: { 665 channel: {
@@ -914,11 +919,12 @@ describe('Test multiple servers', function () {
914 } 919 }
915 }) 920 })
916 921
917 it('Should disable comments', async function () { 922 it('Should disable comments and download', async function () {
918 this.timeout(20000) 923 this.timeout(20000)
919 924
920 const attributes = { 925 const attributes = {
921 commentsEnabled: false 926 commentsEnabled: false,
927 downloadEnabled: false
922 } 928 }
923 929
924 await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, attributes) 930 await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, attributes)
@@ -928,6 +934,7 @@ describe('Test multiple servers', function () {
928 for (const server of servers) { 934 for (const server of servers) {
929 const res = await getVideo(server.url, videoUUID) 935 const res = await getVideo(server.url, videoUUID)
930 expect(res.body.commentsEnabled).to.be.false 936 expect(res.body.commentsEnabled).to.be.false
937 expect(res.body.downloadEnabled).to.be.false
931 938
932 const text = 'my super forbidden comment' 939 const text = 'my super forbidden comment'
933 await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, 409) 940 await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, 409)
@@ -976,6 +983,7 @@ describe('Test multiple servers', function () {
976 isLocal, 983 isLocal,
977 duration: 5, 984 duration: 5,
978 commentsEnabled: false, 985 commentsEnabled: false,
986 downloadEnabled: false,
979 tags: [ ], 987 tags: [ ],
980 privacy: VideoPrivacy.PUBLIC, 988 privacy: VideoPrivacy.PUBLIC,
981 channel: { 989 channel: {
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts
index 069dec67c..cfdcbaf3f 100644
--- a/server/tests/api/videos/single-server.ts
+++ b/server/tests/api/videos/single-server.ts
@@ -55,6 +55,7 @@ describe('Test a single server', function () {
55 tags: [ 'tag1', 'tag2', 'tag3' ], 55 tags: [ 'tag1', 'tag2', 'tag3' ],
56 privacy: VideoPrivacy.PUBLIC, 56 privacy: VideoPrivacy.PUBLIC,
57 commentsEnabled: true, 57 commentsEnabled: true,
58 downloadEnabled: true,
58 channel: { 59 channel: {
59 displayName: 'Main root channel', 60 displayName: 'Main root channel',
60 name: 'root_channel', 61 name: 'root_channel',
@@ -87,6 +88,7 @@ describe('Test a single server', function () {
87 privacy: VideoPrivacy.PUBLIC, 88 privacy: VideoPrivacy.PUBLIC,
88 duration: 5, 89 duration: 5,
89 commentsEnabled: false, 90 commentsEnabled: false,
91 downloadEnabled: false,
90 channel: { 92 channel: {
91 name: 'root_channel', 93 name: 'root_channel',
92 displayName: 'Main root channel', 94 displayName: 'Main root channel',
@@ -356,6 +358,7 @@ describe('Test a single server', function () {
356 nsfw: false, 358 nsfw: false,
357 description: 'my super description updated', 359 description: 'my super description updated',
358 commentsEnabled: false, 360 commentsEnabled: false,
361 downloadEnabled: false,
359 tags: [ 'tagup1', 'tagup2' ] 362 tags: [ 'tagup1', 'tagup2' ]
360 } 363 }
361 await updateVideo(server.url, server.accessToken, videoId, attributes) 364 await updateVideo(server.url, server.accessToken, videoId, attributes)
diff --git a/server/tools/peertube-import-videos.ts b/server/tools/peertube-import-videos.ts
index f50aafc35..151c5a989 100644
--- a/server/tools/peertube-import-videos.ts
+++ b/server/tools/peertube-import-videos.ts
@@ -224,6 +224,7 @@ async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string, cwd: st
224 nsfw: isNSFW(videoInfo), 224 nsfw: isNSFW(videoInfo),
225 waitTranscoding: true, 225 waitTranscoding: true,
226 commentsEnabled: true, 226 commentsEnabled: true,
227 downloadEnabled: true,
227 description: videoInfo.description || undefined, 228 description: videoInfo.description || undefined,
228 support: undefined, 229 support: undefined,
229 tags, 230 tags,
diff --git a/server/tools/peertube-upload.ts b/server/tools/peertube-upload.ts
index cc7bd9b4c..ebc62c965 100644
--- a/server/tools/peertube-upload.ts
+++ b/server/tools/peertube-upload.ts
@@ -30,6 +30,7 @@ if (!program['tags']) program['tags'] = []
30if (!program['nsfw']) program['nsfw'] = false 30if (!program['nsfw']) program['nsfw'] = false
31if (!program['privacy']) program['privacy'] = VideoPrivacy.PUBLIC 31if (!program['privacy']) program['privacy'] = VideoPrivacy.PUBLIC
32if (!program['commentsEnabled']) program['commentsEnabled'] = false 32if (!program['commentsEnabled']) program['commentsEnabled'] = false
33if (!program['downloadEnabled']) program['downloadEnabled'] = true
33 34
34getSettings() 35getSettings()
35 .then(settings => { 36 .then(settings => {
@@ -116,6 +117,7 @@ async function run () {
116 description: program['videoDescription'], 117 description: program['videoDescription'],
117 tags: program['tags'], 118 tags: program['tags'],
118 commentsEnabled: program['commentsEnabled'], 119 commentsEnabled: program['commentsEnabled'],
120 downloadEnabled: program['downloadEnabled'],
119 fixture: program['file'], 121 fixture: program['file'],
120 thumbnailfile: program['thumbnail'], 122 thumbnailfile: program['thumbnail'],
121 previewfile: program['preview'], 123 previewfile: program['preview'],
diff --git a/shared/models/activitypub/objects/video-torrent-object.ts b/shared/models/activitypub/objects/video-torrent-object.ts
index 8504c178f..4231fbb68 100644
--- a/shared/models/activitypub/objects/video-torrent-object.ts
+++ b/shared/models/activitypub/objects/video-torrent-object.ts
@@ -20,7 +20,8 @@ export interface VideoTorrentObject {
20 subtitleLanguage: ActivityIdentifierObject[] 20 subtitleLanguage: ActivityIdentifierObject[]
21 views: number 21 views: number
22 sensitive: boolean 22 sensitive: boolean
23 commentsEnabled: boolean 23 commentsEnabled: boolean,
24 downloadEnabled: boolean,
24 waitTranscoding: boolean 25 waitTranscoding: boolean
25 state: VideoState 26 state: VideoState
26 published: string 27 published: string
diff --git a/shared/models/videos/video-create.model.ts b/shared/models/videos/video-create.model.ts
index 190d63783..f153a1d00 100644
--- a/shared/models/videos/video-create.model.ts
+++ b/shared/models/videos/video-create.model.ts
@@ -13,6 +13,7 @@ export interface VideoCreate {
13 name: string 13 name: string
14 tags?: string[] 14 tags?: string[]
15 commentsEnabled?: boolean 15 commentsEnabled?: boolean
16 downloadEnabled?: boolean
16 privacy: VideoPrivacy 17 privacy: VideoPrivacy
17 scheduleUpdate?: VideoScheduleUpdate 18 scheduleUpdate?: VideoScheduleUpdate
18} 19}
diff --git a/shared/models/videos/video-update.model.ts b/shared/models/videos/video-update.model.ts
index ed141a824..6f96633ae 100644
--- a/shared/models/videos/video-update.model.ts
+++ b/shared/models/videos/video-update.model.ts
@@ -11,6 +11,7 @@ export interface VideoUpdate {
11 privacy?: VideoPrivacy 11 privacy?: VideoPrivacy
12 tags?: string[] 12 tags?: string[]
13 commentsEnabled?: boolean 13 commentsEnabled?: boolean
14 downloadEnabled?: boolean
14 nsfw?: boolean 15 nsfw?: boolean
15 waitTranscoding?: boolean 16 waitTranscoding?: boolean
16 channelId?: number 17 channelId?: number
diff --git a/shared/models/videos/video.model.ts b/shared/models/videos/video.model.ts
index 803db8255..891831a9e 100644
--- a/shared/models/videos/video.model.ts
+++ b/shared/models/videos/video.model.ts
@@ -83,6 +83,7 @@ export interface VideoDetails extends Video {
83 files: VideoFile[] 83 files: VideoFile[]
84 account: Account 84 account: Account
85 commentsEnabled: boolean 85 commentsEnabled: boolean
86 downloadEnabled: boolean
86 87
87 // Not optional in details (unlike in Video) 88 // Not optional in details (unlike in Video)
88 waitTranscoding: boolean 89 waitTranscoding: boolean
diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts
index b5b33e038..39c808d1f 100644
--- a/shared/utils/videos/videos.ts
+++ b/shared/utils/videos/videos.ts
@@ -28,6 +28,7 @@ type VideoAttributes = {
28 language?: string 28 language?: string
29 nsfw?: boolean 29 nsfw?: boolean
30 commentsEnabled?: boolean 30 commentsEnabled?: boolean
31 downloadEnabled?: boolean
31 waitTranscoding?: boolean 32 waitTranscoding?: boolean
32 description?: string 33 description?: string
33 tags?: string[] 34 tags?: string[]
@@ -320,6 +321,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg
320 tags: [ 'tag' ], 321 tags: [ 'tag' ],
321 privacy: VideoPrivacy.PUBLIC, 322 privacy: VideoPrivacy.PUBLIC,
322 commentsEnabled: true, 323 commentsEnabled: true,
324 downloadEnabled: true,
323 fixture: 'video_short.webm' 325 fixture: 'video_short.webm'
324 }, videoAttributesArg) 326 }, videoAttributesArg)
325 327
@@ -330,6 +332,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg
330 .field('name', attributes.name) 332 .field('name', attributes.name)
331 .field('nsfw', JSON.stringify(attributes.nsfw)) 333 .field('nsfw', JSON.stringify(attributes.nsfw))
332 .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled)) 334 .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled))
335 .field('downloadEnabled', JSON.stringify(attributes.downloadEnabled))
333 .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding)) 336 .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding))
334 .field('privacy', attributes.privacy.toString()) 337 .field('privacy', attributes.privacy.toString())
335 .field('channelId', attributes.channelId) 338 .field('channelId', attributes.channelId)
@@ -380,6 +383,7 @@ function updateVideo (url: string, accessToken: string, id: number | string, att
380 if (attributes.language) body['language'] = attributes.language 383 if (attributes.language) body['language'] = attributes.language
381 if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) 384 if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw)
382 if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled) 385 if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled)
386 if (attributes.downloadEnabled !== undefined) body['downloadEnabled'] = JSON.stringify(attributes.downloadEnabled)
383 if (attributes.description) body['description'] = attributes.description 387 if (attributes.description) body['description'] = attributes.description
384 if (attributes.tags) body['tags'] = attributes.tags 388 if (attributes.tags) body['tags'] = attributes.tags
385 if (attributes.privacy) body['privacy'] = attributes.privacy 389 if (attributes.privacy) body['privacy'] = attributes.privacy
@@ -445,6 +449,7 @@ async function completeVideoCheck (
445 language: string 449 language: string
446 nsfw: boolean 450 nsfw: boolean
447 commentsEnabled: boolean 451 commentsEnabled: boolean
452 downloadEnabled: boolean
448 description: string 453 description: string
449 publishedAt?: string 454 publishedAt?: string
450 support: string 455 support: string
@@ -519,6 +524,7 @@ async function completeVideoCheck (
519 expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true 524 expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true
520 expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true 525 expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true
521 expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) 526 expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled)
527 expect(videoDetails.downloadEnabled).to.equal(attributes.downloadEnabled)
522 528
523 for (const attributeFile of attributes.files) { 529 for (const attributeFile of attributes.files) {
524 const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution) 530 const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution)