1 import { readFile } from 'fs'
2 import * as request from 'supertest'
3 import { join, isAbsolute } from 'path'
4 import * as parseTorrent from 'parse-torrent'
6 import { makeGetRequest } from './requests'
7 import { readFilePromise } from './miscs'
8 import { ServerInfo } from './servers'
9 import { getMyUserInformation } from './users'
10 import { VideoPrivacy } from '../../../shared'
12 type VideoAttributes = {
21 privacy?: VideoPrivacy
25 function getVideoCategories (url: string) {
26 const path = '/api/v1/videos/categories'
28 return makeGetRequest(url, path)
31 function getVideoLicences (url: string) {
32 const path = '/api/v1/videos/licences'
34 return makeGetRequest(url, path)
37 function getVideoLanguages (url: string) {
38 const path = '/api/v1/videos/languages'
40 return makeGetRequest(url, path)
43 function getVideoPrivacies (url: string) {
44 const path = '/api/v1/videos/privacies'
46 return makeGetRequest(url, path)
49 function getVideo (url: string, id: number | string, expectedStatus = 200) {
50 const path = '/api/v1/videos/' + id
54 .set('Accept', 'application/json')
55 .expect(expectedStatus)
58 function viewVideo (url: string, id: number | string, expectedStatus = 204) {
59 const path = '/api/v1/videos/' + id + '/views'
63 .set('Accept', 'application/json')
64 .expect(expectedStatus)
67 function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
68 const path = '/api/v1/videos/' + id
72 .set('Authorization', 'Bearer ' + token)
73 .set('Accept', 'application/json')
74 .expect(expectedStatus)
77 function getVideoDescription (url: string, descriptionPath: string) {
80 .set('Accept', 'application/json')
82 .expect('Content-Type', /json/)
85 function getVideosList (url: string) {
86 const path = '/api/v1/videos'
90 .query({ sort: 'name' })
91 .set('Accept', 'application/json')
93 .expect('Content-Type', /json/)
96 function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
97 const path = '/api/v1/users/me/videos'
99 const req = request(url)
101 .query({ start: start })
102 .query({ count: count })
104 if (sort) req.query({ sort })
106 return req.set('Accept', 'application/json')
107 .set('Authorization', 'Bearer ' + accessToken)
109 .expect('Content-Type', /json/)
112 function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
113 const path = '/api/v1/videos'
115 const req = request(url)
117 .query({ start: start })
118 .query({ count: count })
120 if (sort) req.query({ sort })
122 return req.set('Accept', 'application/json')
124 .expect('Content-Type', /json/)
127 function getVideosListSort (url: string, sort: string) {
128 const path = '/api/v1/videos'
132 .query({ sort: sort })
133 .set('Accept', 'application/json')
135 .expect('Content-Type', /json/)
138 function removeVideo (url: string, token: string, id: number, expectedStatus = 204) {
139 const path = '/api/v1/videos'
142 .delete(path + '/' + id)
143 .set('Accept', 'application/json')
144 .set('Authorization', 'Bearer ' + token)
145 .expect(expectedStatus)
148 function searchVideo (url: string, search: string, field?: string) {
149 const path = '/api/v1/videos'
150 const req = request(url)
151 .get(path + '/search/' + search)
152 .set('Accept', 'application/json')
154 if (field) req.query({ field })
156 return req.expect(200)
157 .expect('Content-Type', /json/)
160 function searchVideoWithPagination (url: string, search: string, field: string, start: number, count: number, sort?: string) {
161 const path = '/api/v1/videos'
163 const req = request(url)
164 .get(path + '/search/' + search)
169 if (sort) req.query({ sort })
171 return req.set('Accept', 'application/json')
173 .expect('Content-Type', /json/)
176 function searchVideoWithSort (url: string, search: string, sort: string) {
177 const path = '/api/v1/videos'
180 .get(path + '/search/' + search)
182 .set('Accept', 'application/json')
184 .expect('Content-Type', /json/)
187 async function testVideoImage (url: string, imageName: string, imagePath: string) {
188 // Don't test images if the node env is not set
189 // Because we need a special ffmpeg version for this test
190 if (process.env['NODE_TEST_IMAGE']) {
191 const res = await request(url)
195 const data = await readFilePromise(join(__dirname, '..', 'api', 'fixtures', imageName + '.jpg'))
197 return data.equals(res.body)
199 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
204 async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 204) {
205 const path = '/api/v1/videos/upload'
206 let defaultChannelId = '1'
209 const res = await getMyUserInformation(url, accessToken)
210 defaultChannelId = res.body.videoChannels[0].id
211 } catch (e) { /* empty */ }
213 // Default attributes
215 name: 'my super video',
219 channelId: defaultChannelId,
221 description: 'my super description',
223 privacy: VideoPrivacy.PUBLIC,
224 fixture: 'video_short.webm'
226 attributes = Object.assign(attributes, videoAttributesArg)
228 const req = request(url)
230 .set('Accept', 'application/json')
231 .set('Authorization', 'Bearer ' + accessToken)
232 .field('name', attributes.name)
233 .field('category', attributes.category.toString())
234 .field('licence', attributes.licence.toString())
235 .field('nsfw', JSON.stringify(attributes.nsfw))
236 .field('description', attributes.description)
237 .field('privacy', attributes.privacy.toString())
238 .field('channelId', attributes.channelId)
240 if (attributes.language !== undefined) {
241 req.field('language', attributes.language.toString())
244 for (let i = 0; i < attributes.tags.length; i++) {
245 req.field('tags[' + i + ']', attributes.tags[i])
249 if (isAbsolute(attributes.fixture)) {
250 filePath = attributes.fixture
252 filePath = join(__dirname, '..', 'api', 'fixtures', attributes.fixture)
255 return req.attach('videofile', filePath)
256 .expect(specialStatus)
259 function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) {
260 const path = '/api/v1/videos/' + id
263 if (attributes.name) body['name'] = attributes.name
264 if (attributes.category) body['category'] = attributes.category
265 if (attributes.licence) body['licence'] = attributes.licence
266 if (attributes.language) body['language'] = attributes.language
267 if (attributes.nsfw) body['nsfw'] = attributes.nsfw
268 if (attributes.description) body['description'] = attributes.description
269 if (attributes.tags) body['tags'] = attributes.tags
270 if (attributes.privacy) body['privacy'] = attributes.privacy
275 .set('Accept', 'application/json')
276 .set('Authorization', 'Bearer ' + accessToken)
277 .expect(specialStatus)
280 function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
281 const path = '/api/v1/videos/' + id + '/rate'
285 .set('Accept', 'application/json')
286 .set('Authorization', 'Bearer ' + accessToken)
288 .expect(specialStatus)
291 function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
292 return new Promise<any>((res, rej) => {
293 const torrentName = videoUUID + '-' + resolution + '.torrent'
294 const torrentPath = join(__dirname, '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
295 readFile(torrentPath, (err, data) => {
296 if (err) return rej(err)
298 return res(parseTorrent(data))
303 // ---------------------------------------------------------------------------
315 getVideosListPagination,
319 searchVideoWithPagination,