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