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