]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - shared/extra-utils/videos/videos.ts
Translated using Weblate (Kabyle)
[github/Chocobozzz/PeerTube.git] / shared / extra-utils / videos / videos.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
a20399c9
C
2
3import { expect } from 'chai'
df0b219d 4import { pathExists, readdir, readFile } from 'fs-extra'
fdbda9e3 5import * as parseTorrent from 'parse-torrent'
1d791a26 6import { extname, join } from 'path'
c5d31dba 7import * as request from 'supertest'
8eb07b01
C
8import { v4 as uuidv4 } from 'uuid'
9import validator from 'validator'
d61893f7 10import { HttpStatusCode } from '@shared/core-utils'
8eb07b01
C
11import { loadLanguages, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants'
12import { VideoDetails, VideoPrivacy } from '../../models/videos'
d61893f7
C
13import {
14 buildAbsoluteFixturePath,
15 buildServerDirectory,
16 dateIsValid,
17 immutableAssign,
18 testImage,
19 wait,
20 webtorrentAdd
21} from '../miscs/miscs'
90a8bd30 22import { makeGetRequest, makePutBodyRequest, makeRawRequest, makeUploadRequest } from '../requests/requests'
8eb07b01
C
23import { waitJobs } from '../server/jobs'
24import { ServerInfo } from '../server/servers'
25import { getMyUserInformation } from '../users/users'
0e1dc3e7 26
8f0bc73d
C
27loadLanguages()
28
0e1dc3e7
C
29type VideoAttributes = {
30 name?: string
31 category?: number
32 licence?: number
9d3ef9fe 33 language?: string
0e1dc3e7 34 nsfw?: boolean
47564bbe 35 commentsEnabled?: boolean
7f2cfe3a 36 downloadEnabled?: boolean
2186386c 37 waitTranscoding?: boolean
0e1dc3e7 38 description?: string
7519127b 39 originallyPublishedAt?: string
0e1dc3e7 40 tags?: string[]
5f04dd2f 41 channelId?: number
11474c3c 42 privacy?: VideoPrivacy
0e1dc3e7 43 fixture?: string
ac81d1a0
C
44 thumbnailfile?: string
45 previewfile?: string
2baea0c7
C
46 scheduleUpdate?: {
47 updateAt: string
48 privacy?: VideoPrivacy
49 }
0e1dc3e7
C
50}
51
52function getVideoCategories (url: string) {
53 const path = '/api/v1/videos/categories'
54
eec63bbc
C
55 return makeGetRequest({
56 url,
59651eee 57 path,
2d53be02 58 statusCodeExpected: HttpStatusCode.OK_200
eec63bbc 59 })
0e1dc3e7
C
60}
61
62function getVideoLicences (url: string) {
63 const path = '/api/v1/videos/licences'
64
eec63bbc
C
65 return makeGetRequest({
66 url,
59651eee 67 path,
2d53be02 68 statusCodeExpected: HttpStatusCode.OK_200
eec63bbc 69 })
0e1dc3e7
C
70}
71
72function getVideoLanguages (url: string) {
73 const path = '/api/v1/videos/languages'
74
eec63bbc
C
75 return makeGetRequest({
76 url,
59651eee 77 path,
2d53be02 78 statusCodeExpected: HttpStatusCode.OK_200
eec63bbc 79 })
0e1dc3e7
C
80}
81
11474c3c
C
82function getVideoPrivacies (url: string) {
83 const path = '/api/v1/videos/privacies'
84
eec63bbc
C
85 return makeGetRequest({
86 url,
59651eee 87 path,
2d53be02 88 statusCodeExpected: HttpStatusCode.OK_200
eec63bbc 89 })
11474c3c
C
90}
91
2d53be02 92function getVideo (url: string, id: number | string, expectedStatus = HttpStatusCode.OK_200) {
0e1dc3e7
C
93 const path = '/api/v1/videos/' + id
94
95 return request(url)
96 .get(path)
97 .set('Accept', 'application/json')
11474c3c
C
98 .expect(expectedStatus)
99}
100
696d83fd
C
101async function getVideoIdFromUUID (url: string, uuid: string) {
102 const res = await getVideo(url, uuid)
103
104 return res.body.id
105}
106
8319d6ae
RK
107function getVideoFileMetadataUrl (url: string) {
108 return request(url)
109 .get('/')
110 .set('Accept', 'application/json')
2d53be02 111 .expect(HttpStatusCode.OK_200)
8319d6ae
RK
112 .expect('Content-Type', /json/)
113}
114
2d53be02 115function viewVideo (url: string, id: number | string, expectedStatus = HttpStatusCode.NO_CONTENT_204, xForwardedFor?: string) {
1f3e9fec
C
116 const path = '/api/v1/videos/' + id + '/views'
117
490b595a 118 const req = request(url)
1f3e9fec
C
119 .post(path)
120 .set('Accept', 'application/json')
490b595a
C
121
122 if (xForwardedFor) {
123 req.set('X-Forwarded-For', xForwardedFor)
124 }
125
126 return req.expect(expectedStatus)
1f3e9fec
C
127}
128
2d53be02 129function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = HttpStatusCode.OK_200) {
11474c3c
C
130 const path = '/api/v1/videos/' + id
131
132 return request(url)
133 .get(path)
134 .set('Authorization', 'Bearer ' + token)
135 .set('Accept', 'application/json')
136 .expect(expectedStatus)
0e1dc3e7
C
137}
138
9567011b
C
139function getVideoDescription (url: string, descriptionPath: string) {
140 return request(url)
141 .get(descriptionPath)
142 .set('Accept', 'application/json')
2d53be02 143 .expect(HttpStatusCode.OK_200)
9567011b
C
144 .expect('Content-Type', /json/)
145}
146
0e1dc3e7
C
147function getVideosList (url: string) {
148 const path = '/api/v1/videos'
149
150 return request(url)
151 .get(path)
152 .query({ sort: 'name' })
153 .set('Accept', 'application/json')
2d53be02 154 .expect(HttpStatusCode.OK_200)
0e1dc3e7
C
155 .expect('Content-Type', /json/)
156}
157
d525fc39 158function getVideosListWithToken (url: string, token: string, query: { nsfw?: boolean } = {}) {
0883b324
C
159 const path = '/api/v1/videos'
160
161 return request(url)
162 .get(path)
163 .set('Authorization', 'Bearer ' + token)
d525fc39 164 .query(immutableAssign(query, { sort: 'name' }))
0883b324 165 .set('Accept', 'application/json')
f2eb23cd 166 .expect(HttpStatusCode.OK_200)
0883b324
C
167 .expect('Content-Type', /json/)
168}
169
066e94c5
C
170function getLocalVideos (url: string) {
171 const path = '/api/v1/videos'
172
173 return request(url)
174 .get(path)
175 .query({ sort: 'name', filter: 'local' })
176 .set('Accept', 'application/json')
f2eb23cd 177 .expect(HttpStatusCode.OK_200)
066e94c5
C
178 .expect('Content-Type', /json/)
179}
180
cca1e13b 181function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string, search?: string) {
11474c3c
C
182 const path = '/api/v1/users/me/videos'
183
184 const req = request(url)
185 .get(path)
186 .query({ start: start })
187 .query({ count: count })
cca1e13b 188 .query({ search: search })
11474c3c
C
189
190 if (sort) req.query({ sort })
191
192 return req.set('Accept', 'application/json')
193 .set('Authorization', 'Bearer ' + accessToken)
2d53be02 194 .expect(HttpStatusCode.OK_200)
11474c3c
C
195 .expect('Content-Type', /json/)
196}
197
d525fc39
C
198function getAccountVideos (
199 url: string,
200 accessToken: string,
201 accountName: string,
202 start: number,
203 count: number,
204 sort?: string,
37024082
RK
205 query: {
206 nsfw?: boolean
207 search?: string
208 } = {}
d525fc39 209) {
ad9e39fb 210 const path = '/api/v1/accounts/' + accountName + '/videos'
6b738c7a
C
211
212 return makeGetRequest({
213 url,
214 path,
d525fc39 215 query: immutableAssign(query, {
6b738c7a
C
216 start,
217 count,
218 sort
d525fc39 219 }),
6b738c7a 220 token: accessToken,
2d53be02 221 statusCodeExpected: HttpStatusCode.OK_200
6b738c7a
C
222 })
223}
224
225function getVideoChannelVideos (
226 url: string,
227 accessToken: string,
8a19bee1 228 videoChannelName: string,
6b738c7a
C
229 start: number,
230 count: number,
d525fc39
C
231 sort?: string,
232 query: { nsfw?: boolean } = {}
6b738c7a 233) {
8a19bee1 234 const path = '/api/v1/video-channels/' + videoChannelName + '/videos'
6b738c7a
C
235
236 return makeGetRequest({
237 url,
238 path,
d525fc39 239 query: immutableAssign(query, {
6b738c7a
C
240 start,
241 count,
242 sort
d525fc39 243 }),
6b738c7a 244 token: accessToken,
2d53be02 245 statusCodeExpected: HttpStatusCode.OK_200
6b738c7a
C
246 })
247}
248
418d092a
C
249function getPlaylistVideos (
250 url: string,
251 accessToken: string,
252 playlistId: number | string,
253 start: number,
254 count: number,
255 query: { nsfw?: boolean } = {}
256) {
257 const path = '/api/v1/video-playlists/' + playlistId + '/videos'
258
259 return makeGetRequest({
260 url,
261 path,
262 query: immutableAssign(query, {
263 start,
264 count
265 }),
266 token: accessToken,
2d53be02 267 statusCodeExpected: HttpStatusCode.OK_200
418d092a
C
268 })
269}
270
fe987656 271function getVideosListPagination (url: string, start: number, count: number, sort?: string, skipCount?: boolean) {
0e1dc3e7
C
272 const path = '/api/v1/videos'
273
274 const req = request(url)
275 .get(path)
276 .query({ start: start })
277 .query({ count: count })
278
279 if (sort) req.query({ sort })
fe987656 280 if (skipCount) req.query({ skipCount })
0e1dc3e7
C
281
282 return req.set('Accept', 'application/json')
2d53be02 283 .expect(HttpStatusCode.OK_200)
0e1dc3e7
C
284 .expect('Content-Type', /json/)
285}
286
287function getVideosListSort (url: string, sort: string) {
288 const path = '/api/v1/videos'
289
290 return request(url)
291 .get(path)
292 .query({ sort: sort })
293 .set('Accept', 'application/json')
2d53be02 294 .expect(HttpStatusCode.OK_200)
0e1dc3e7
C
295 .expect('Content-Type', /json/)
296}
297
d525fc39 298function getVideosWithFilters (url: string, query: { tagsAllOf: string[], categoryOneOf: number[] | number }) {
0e1dc3e7
C
299 const path = '/api/v1/videos'
300
301 return request(url)
57c36b27 302 .get(path)
d525fc39 303 .query(query)
f3aaa9a9 304 .set('Accept', 'application/json')
2d53be02 305 .expect(HttpStatusCode.OK_200)
f3aaa9a9 306 .expect('Content-Type', /json/)
0e1dc3e7
C
307}
308
2d53be02 309function removeVideo (url: string, token: string, id: number | string, expectedStatus = HttpStatusCode.NO_CONTENT_204) {
0883b324 310 const path = '/api/v1/videos'
0e1dc3e7
C
311
312 return request(url)
d525fc39 313 .delete(path + '/' + id)
0e1dc3e7 314 .set('Accept', 'application/json')
d525fc39
C
315 .set('Authorization', 'Bearer ' + token)
316 .expect(expectedStatus)
0e1dc3e7
C
317}
318
68e70a74
C
319async function removeAllVideos (server: ServerInfo) {
320 const resVideos = await getVideosList(server.url)
321
322 for (const v of resVideos.body.data) {
323 await removeVideo(server.url, server.accessToken, v.id)
324 }
325}
326
25378bc8
C
327async function checkVideoFilesWereRemoved (
328 videoUUID: string,
329 serverNumber: number,
09209296
C
330 directories = [
331 'redundancy',
332 'videos',
333 'thumbnails',
334 'torrents',
335 'previews',
336 'captions',
337 join('playlists', 'hls'),
338 join('redundancy', 'hls')
339 ]
25378bc8 340) {
25378bc8 341 for (const directory of directories) {
ca5c612b 342 const directoryPath = buildServerDirectory({ internalServerNumber: serverNumber }, directory)
f05a1c30 343
df0b219d
C
344 const directoryExists = await pathExists(directoryPath)
345 if (directoryExists === false) continue
f05a1c30 346
62689b94 347 const files = await readdir(directoryPath)
f05a1c30 348 for (const file of files) {
7448551f 349 expect(file, `File ${file} should not exist in ${directoryPath}`).to.not.contain(videoUUID)
f05a1c30
C
350 }
351 }
352}
353
2d53be02 354async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = HttpStatusCode.OK_200) {
e95561cd 355 const path = '/api/v1/videos/upload'
5f04dd2f
C
356 let defaultChannelId = '1'
357
358 try {
359 const res = await getMyUserInformation(url, accessToken)
360 defaultChannelId = res.body.videoChannels[0].id
361 } catch (e) { /* empty */ }
0e1dc3e7 362
ac81d1a0
C
363 // Override default attributes
364 const attributes = Object.assign({
0e1dc3e7
C
365 name: 'my super video',
366 category: 5,
367 licence: 4,
9d3ef9fe 368 language: 'zh',
5f04dd2f 369 channelId: defaultChannelId,
0e1dc3e7 370 nsfw: true,
2186386c 371 waitTranscoding: false,
0e1dc3e7 372 description: 'my super description',
2422c46b 373 support: 'my super support text',
0e1dc3e7 374 tags: [ 'tag' ],
11474c3c 375 privacy: VideoPrivacy.PUBLIC,
47564bbe 376 commentsEnabled: true,
7f2cfe3a 377 downloadEnabled: true,
0e1dc3e7 378 fixture: 'video_short.webm'
ac81d1a0 379 }, videoAttributesArg)
0e1dc3e7
C
380
381 const req = request(url)
382 .post(path)
383 .set('Accept', 'application/json')
384 .set('Authorization', 'Bearer ' + accessToken)
385 .field('name', attributes.name)
0e1dc3e7 386 .field('nsfw', JSON.stringify(attributes.nsfw))
47564bbe 387 .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled))
7f2cfe3a 388 .field('downloadEnabled', JSON.stringify(attributes.downloadEnabled))
2186386c 389 .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding))
11474c3c 390 .field('privacy', attributes.privacy.toString())
5f04dd2f 391 .field('channelId', attributes.channelId)
0e1dc3e7 392
fc8c024a
C
393 if (attributes.support !== undefined) {
394 req.field('support', attributes.support)
395 }
396
a87d467a
C
397 if (attributes.description !== undefined) {
398 req.field('description', attributes.description)
399 }
8df87ce7
C
400 if (attributes.language !== undefined) {
401 req.field('language', attributes.language.toString())
402 }
a7fea183
C
403 if (attributes.category !== undefined) {
404 req.field('category', attributes.category.toString())
405 }
406 if (attributes.licence !== undefined) {
407 req.field('licence', attributes.licence.toString())
408 }
8df87ce7 409
970ceac0
C
410 const tags = attributes.tags || []
411 for (let i = 0; i < tags.length; i++) {
2422c46b
C
412 req.field('tags[' + i + ']', attributes.tags[i])
413 }
414
ac81d1a0
C
415 if (attributes.thumbnailfile !== undefined) {
416 req.attach('thumbnailfile', buildAbsoluteFixturePath(attributes.thumbnailfile))
417 }
418 if (attributes.previewfile !== undefined) {
419 req.attach('previewfile', buildAbsoluteFixturePath(attributes.previewfile))
0e1dc3e7
C
420 }
421
2baea0c7
C
422 if (attributes.scheduleUpdate) {
423 req.field('scheduleUpdate[updateAt]', attributes.scheduleUpdate.updateAt)
424
425 if (attributes.scheduleUpdate.privacy) {
426 req.field('scheduleUpdate[privacy]', attributes.scheduleUpdate.privacy)
427 }
428 }
429
84929846
AM
430 if (attributes.originallyPublishedAt !== undefined) {
431 req.field('originallyPublishedAt', attributes.originallyPublishedAt)
432 }
433
d61893f7 434 const res = await req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture))
0e1dc3e7 435 .expect(specialStatus)
d61893f7
C
436
437 // Wait torrent generation
438 if (specialStatus === HttpStatusCode.OK_200) {
439 let video: VideoDetails
440 do {
441 const resVideo = await getVideoWithToken(url, accessToken, res.body.video.uuid)
442 video = resVideo.body
443
444 await wait(50)
445 } while (!video.files[0].torrentUrl)
446 }
447
448 return res
0e1dc3e7
C
449}
450
2d53be02
RK
451function updateVideo (
452 url: string,
453 accessToken: string,
454 id: number | string,
455 attributes: VideoAttributes,
456 statusCodeExpected = HttpStatusCode.NO_CONTENT_204
457) {
0e1dc3e7
C
458 const path = '/api/v1/videos/' + id
459 const body = {}
460
461 if (attributes.name) body['name'] = attributes.name
462 if (attributes.category) body['category'] = attributes.category
463 if (attributes.licence) body['licence'] = attributes.licence
464 if (attributes.language) body['language'] = attributes.language
47564bbe
C
465 if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw)
466 if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled)
7f2cfe3a 467 if (attributes.downloadEnabled !== undefined) body['downloadEnabled'] = JSON.stringify(attributes.downloadEnabled)
7519127b 468 if (attributes.originallyPublishedAt !== undefined) body['originallyPublishedAt'] = attributes.originallyPublishedAt
0e1dc3e7
C
469 if (attributes.description) body['description'] = attributes.description
470 if (attributes.tags) body['tags'] = attributes.tags
11474c3c 471 if (attributes.privacy) body['privacy'] = attributes.privacy
0f320037 472 if (attributes.channelId) body['channelId'] = attributes.channelId
2baea0c7 473 if (attributes.scheduleUpdate) body['scheduleUpdate'] = attributes.scheduleUpdate
0e1dc3e7 474
ac81d1a0
C
475 // Upload request
476 if (attributes.thumbnailfile || attributes.previewfile) {
477 const attaches: any = {}
478 if (attributes.thumbnailfile) attaches.thumbnailfile = attributes.thumbnailfile
479 if (attributes.previewfile) attaches.previewfile = attributes.previewfile
480
481 return makeUploadRequest({
482 url,
483 method: 'PUT',
484 path,
485 token: accessToken,
486 fields: body,
487 attaches,
488 statusCodeExpected
489 })
490 }
491
492 return makePutBodyRequest({
493 url,
494 path,
495 fields: body,
496 token: accessToken,
497 statusCodeExpected
498 })
0e1dc3e7
C
499}
500
74d249bc 501function rateVideo (url: string, accessToken: string, id: number | string, rating: string, specialStatus = HttpStatusCode.NO_CONTENT_204) {
0e1dc3e7
C
502 const path = '/api/v1/videos/' + id + '/rate'
503
504 return request(url)
505 .put(path)
506 .set('Accept', 'application/json')
507 .set('Authorization', 'Bearer ' + accessToken)
508 .send({ rating })
509 .expect(specialStatus)
510}
511
14d3270f 512function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
fdbda9e3 513 return new Promise<any>((res, rej) => {
14d3270f 514 const torrentName = videoUUID + '-' + resolution + '.torrent'
ca5c612b
C
515 const torrentPath = buildServerDirectory(server, join('torrents', torrentName))
516
fdbda9e3
C
517 readFile(torrentPath, (err, data) => {
518 if (err) return rej(err)
519
520 return res(parseTorrent(data))
521 })
522 })
523}
524
a20399c9
C
525async function completeVideoCheck (
526 url: string,
527 video: any,
528 attributes: {
529 name: string
530 category: number
531 licence: number
9d3ef9fe 532 language: string
a20399c9 533 nsfw: boolean
47564bbe 534 commentsEnabled: boolean
7f2cfe3a 535 downloadEnabled: boolean
a20399c9 536 description: string
53a61317 537 publishedAt?: string
2422c46b 538 support: string
a1587156 539 originallyPublishedAt?: string
b64c950a
C
540 account: {
541 name: string
542 host: string
543 }
f6eebcb3
C
544 isLocal: boolean
545 tags: string[]
546 privacy: number
547 likes?: number
548 dislikes?: number
549 duration: number
a20399c9 550 channel: {
f6eebcb3
C
551 displayName: string
552 name: string
b1f5b93e 553 description
a20399c9
C
554 isLocal: boolean
555 }
f6eebcb3 556 fixture: string
a20399c9
C
557 files: {
558 resolution: number
559 size: number
a1587156 560 }[]
ac81d1a0
C
561 thumbnailfile?: string
562 previewfile?: string
a20399c9
C
563 }
564) {
b1f5b93e
C
565 if (!attributes.likes) attributes.likes = 0
566 if (!attributes.dislikes) attributes.dislikes = 0
567
90a8bd30
C
568 const host = new URL(url).host
569 const originHost = attributes.account.host
570
a20399c9 571 expect(video.name).to.equal(attributes.name)
09700934 572 expect(video.category.id).to.equal(attributes.category)
9d3ef9fe 573 expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Misc')
09700934 574 expect(video.licence.id).to.equal(attributes.licence)
9d3ef9fe 575 expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown')
09700934 576 expect(video.language.id).to.equal(attributes.language)
9d3ef9fe 577 expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown')
2243730c
C
578 expect(video.privacy.id).to.deep.equal(attributes.privacy)
579 expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy])
a20399c9
C
580 expect(video.nsfw).to.equal(attributes.nsfw)
581 expect(video.description).to.equal(attributes.description)
03e12d7c 582 expect(video.account.id).to.be.a('number')
b64c950a
C
583 expect(video.account.host).to.equal(attributes.account.host)
584 expect(video.account.name).to.equal(attributes.account.name)
f6eebcb3
C
585 expect(video.channel.displayName).to.equal(attributes.channel.displayName)
586 expect(video.channel.name).to.equal(attributes.channel.name)
b1f5b93e
C
587 expect(video.likes).to.equal(attributes.likes)
588 expect(video.dislikes).to.equal(attributes.dislikes)
a20399c9 589 expect(video.isLocal).to.equal(attributes.isLocal)
b1f5b93e 590 expect(video.duration).to.equal(attributes.duration)
a20399c9 591 expect(dateIsValid(video.createdAt)).to.be.true
c49db162 592 expect(dateIsValid(video.publishedAt)).to.be.true
a20399c9
C
593 expect(dateIsValid(video.updatedAt)).to.be.true
594
53a61317 595 if (attributes.publishedAt) {
53a61317
C
596 expect(video.publishedAt).to.equal(attributes.publishedAt)
597 }
598
7519127b
C
599 if (attributes.originallyPublishedAt) {
600 expect(video.originallyPublishedAt).to.equal(attributes.originallyPublishedAt)
601 } else {
602 expect(video.originallyPublishedAt).to.be.null
603 }
604
66b16caf 605 const res = await getVideo(url, video.uuid)
0f320037 606 const videoDetails: VideoDetails = res.body
a20399c9
C
607
608 expect(videoDetails.files).to.have.lengthOf(attributes.files.length)
609 expect(videoDetails.tags).to.deep.equal(attributes.tags)
19a3b914
C
610 expect(videoDetails.account.name).to.equal(attributes.account.name)
611 expect(videoDetails.account.host).to.equal(attributes.account.host)
f6eebcb3
C
612 expect(video.channel.displayName).to.equal(attributes.channel.displayName)
613 expect(video.channel.name).to.equal(attributes.channel.name)
0f320037 614 expect(videoDetails.channel.host).to.equal(attributes.account.host)
a20399c9 615 expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal)
0f320037
C
616 expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true
617 expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true
618 expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled)
7f2cfe3a 619 expect(videoDetails.downloadEnabled).to.equal(attributes.downloadEnabled)
a20399c9
C
620
621 for (const attributeFile of attributes.files) {
5d00a3d7 622 const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution)
a20399c9
C
623 expect(file).not.to.be.undefined
624
b1f5b93e 625 let extension = extname(attributes.fixture)
48f07b4a
C
626 // Transcoding enabled: extension will always be .mp4
627 if (attributes.files.length > 1) extension = '.mp4'
b1f5b93e 628
a20399c9 629 expect(file.magnetUri).to.have.lengthOf.above(2)
90a8bd30
C
630
631 expect(file.torrentDownloadUrl).to.equal(`http://${host}/download/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`)
632 expect(file.torrentUrl).to.equal(`http://${host}/lazy-static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`)
633
634 expect(file.fileUrl).to.equal(`http://${originHost}/static/webseed/${videoDetails.uuid}-${file.resolution.id}${extension}`)
635 expect(file.fileDownloadUrl).to.equal(`http://${originHost}/download/videos/${videoDetails.uuid}-${file.resolution.id}${extension}`)
636
637 await Promise.all([
638 makeRawRequest(file.torrentUrl, 200),
639 makeRawRequest(file.torrentDownloadUrl, 200),
640 makeRawRequest(file.metadataUrl, 200),
641 // Backward compatibility
642 makeRawRequest(`http://${originHost}/static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`, 200)
643 ])
644
09700934
C
645 expect(file.resolution.id).to.equal(attributeFile.resolution)
646 expect(file.resolution.label).to.equal(attributeFile.resolution + 'p')
b1f5b93e
C
647
648 const minSize = attributeFile.size - ((10 * attributeFile.size) / 100)
649 const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100)
a1587156
C
650 expect(
651 file.size,
652 'File size for resolution ' + file.resolution.label + ' outside confidence interval (' + minSize + '> size <' + maxSize + ')'
653 ).to.be.above(minSize).and.below(maxSize)
a20399c9 654
d7a25329 655 const torrent = await webtorrentAdd(file.magnetUri, true)
a20399c9
C
656 expect(torrent.files).to.be.an('array')
657 expect(torrent.files.length).to.equal(1)
658 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
659 }
44d4ee4f
C
660
661 await testImage(url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath)
662
663 if (attributes.previewfile) {
664 await testImage(url, attributes.previewfile, videoDetails.previewPath)
665 }
a20399c9
C
666}
667
df0b219d
C
668async function videoUUIDToId (url: string, id: number | string) {
669 if (validator.isUUID('' + id) === false) return id
670
671 const res = await getVideo(url, id)
672 return res.body.id
673}
674
b764380a 675async function uploadVideoAndGetId (options: {
a1587156
C
676 server: ServerInfo
677 videoName: string
678 nsfw?: boolean
679 privacy?: VideoPrivacy
b764380a 680 token?: string
a8537c62 681 fixture?: string
b764380a 682}) {
df0b219d
C
683 const videoAttrs: any = { name: options.videoName }
684 if (options.nsfw) videoAttrs.nsfw = options.nsfw
b764380a 685 if (options.privacy) videoAttrs.privacy = options.privacy
a8537c62 686 if (options.fixture) videoAttrs.fixture = options.fixture
df0b219d 687
df0b219d
C
688 const res = await uploadVideo(options.server.url, options.token || options.server.accessToken, videoAttrs)
689
690 return { id: res.body.video.id, uuid: res.body.video.uuid }
691}
692
b764380a
C
693async function getLocalIdByUUID (url: string, uuid: string) {
694 const res = await getVideo(url, uuid)
695
696 return res.body.id
697}
698
8eb07b01
C
699// serverNumber starts from 1
700async function uploadRandomVideoOnServers (servers: ServerInfo[], serverNumber: number, additionalParams: any = {}) {
701 const server = servers.find(s => s.serverNumber === serverNumber)
702 const res = await uploadRandomVideo(server, false, additionalParams)
703
704 await waitJobs(servers)
705
706 return res
707}
708
709async function uploadRandomVideo (server: ServerInfo, wait = true, additionalParams: any = {}) {
710 const prefixName = additionalParams.prefixName || ''
711 const name = prefixName + uuidv4()
712
713 const data = Object.assign({ name }, additionalParams)
714 const res = await uploadVideo(server.url, server.accessToken, data)
715
716 if (wait) await waitJobs([ server ])
717
718 return { uuid: res.body.video.uuid, name }
719}
720
0e1dc3e7
C
721// ---------------------------------------------------------------------------
722
723export {
9567011b 724 getVideoDescription,
0e1dc3e7 725 getVideoCategories,
8eb07b01 726 uploadRandomVideo,
0e1dc3e7 727 getVideoLicences,
df0b219d 728 videoUUIDToId,
11474c3c 729 getVideoPrivacies,
0e1dc3e7 730 getVideoLanguages,
11474c3c 731 getMyVideos,
6b738c7a
C
732 getAccountVideos,
733 getVideoChannelVideos,
0e1dc3e7 734 getVideo,
8319d6ae 735 getVideoFileMetadataUrl,
11474c3c 736 getVideoWithToken,
0e1dc3e7 737 getVideosList,
68e70a74 738 removeAllVideos,
0e1dc3e7
C
739 getVideosListPagination,
740 getVideosListSort,
741 removeVideo,
0883b324 742 getVideosListWithToken,
0e1dc3e7 743 uploadVideo,
d525fc39 744 getVideosWithFilters,
8eb07b01 745 uploadRandomVideoOnServers,
0e1dc3e7 746 updateVideo,
fdbda9e3 747 rateVideo,
1f3e9fec 748 viewVideo,
a20399c9 749 parseTorrentVideo,
066e94c5 750 getLocalVideos,
f05a1c30 751 completeVideoCheck,
418d092a 752 checkVideoFilesWereRemoved,
df0b219d 753 getPlaylistVideos,
b764380a 754 uploadVideoAndGetId,
696d83fd
C
755 getLocalIdByUUID,
756 getVideoIdFromUUID
0e1dc3e7 757}