diff options
Diffstat (limited to 'shared/utils')
-rw-r--r-- | shared/utils/index.ts | 2 | ||||
-rw-r--r-- | shared/utils/requests/requests.ts | 17 | ||||
-rw-r--r-- | shared/utils/server/config.ts | 3 | ||||
-rw-r--r-- | shared/utils/server/servers.ts | 15 | ||||
-rw-r--r-- | shared/utils/users/user-notifications.ts | 3 | ||||
-rw-r--r-- | shared/utils/users/users.ts | 2 | ||||
-rw-r--r-- | shared/utils/videos/video-blacklist.ts | 11 | ||||
-rw-r--r-- | shared/utils/videos/video-playlists.ts | 51 | ||||
-rw-r--r-- | shared/utils/videos/videos.ts | 19 |
9 files changed, 113 insertions, 10 deletions
diff --git a/shared/utils/index.ts b/shared/utils/index.ts index e08bbfd2a..156901372 100644 --- a/shared/utils/index.ts +++ b/shared/utils/index.ts | |||
@@ -17,6 +17,8 @@ export * from './users/users' | |||
17 | export * from './videos/video-abuses' | 17 | export * from './videos/video-abuses' |
18 | export * from './videos/video-blacklist' | 18 | export * from './videos/video-blacklist' |
19 | export * from './videos/video-channels' | 19 | export * from './videos/video-channels' |
20 | export * from './videos/video-comments' | ||
21 | export * from './videos/video-playlists' | ||
20 | export * from './videos/videos' | 22 | export * from './videos/videos' |
21 | export * from './videos/video-change-ownership' | 23 | export * from './videos/video-change-ownership' |
22 | export * from './feeds/feeds' | 24 | export * from './feeds/feeds' |
diff --git a/shared/utils/requests/requests.ts b/shared/utils/requests/requests.ts index 77e9f6164..6b59e24fc 100644 --- a/shared/utils/requests/requests.ts +++ b/shared/utils/requests/requests.ts | |||
@@ -1,24 +1,32 @@ | |||
1 | import * as request from 'supertest' | 1 | import * as request from 'supertest' |
2 | import { buildAbsoluteFixturePath, root } from '../miscs/miscs' | 2 | import { buildAbsoluteFixturePath, root } from '../miscs/miscs' |
3 | import { isAbsolute, join } from 'path' | 3 | import { isAbsolute, join } from 'path' |
4 | import { parse } from 'url' | ||
5 | |||
6 | function makeRawRequest (url: string, statusCodeExpected?: number, range?: string) { | ||
7 | const { host, protocol, pathname } = parse(url) | ||
8 | |||
9 | return makeGetRequest({ url: `${protocol}//${host}`, path: pathname, statusCodeExpected, range }) | ||
10 | } | ||
4 | 11 | ||
5 | function makeGetRequest (options: { | 12 | function makeGetRequest (options: { |
6 | url: string, | 13 | url: string, |
7 | path: string, | 14 | path?: string, |
8 | query?: any, | 15 | query?: any, |
9 | token?: string, | 16 | token?: string, |
10 | statusCodeExpected?: number, | 17 | statusCodeExpected?: number, |
11 | contentType?: string | 18 | contentType?: string, |
19 | range?: string | ||
12 | }) { | 20 | }) { |
13 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | 21 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 |
14 | if (options.contentType === undefined) options.contentType = 'application/json' | 22 | if (options.contentType === undefined) options.contentType = 'application/json' |
15 | 23 | ||
16 | const req = request(options.url) | 24 | const req = request(options.url).get(options.path) |
17 | .get(options.path) | ||
18 | 25 | ||
19 | if (options.contentType) req.set('Accept', options.contentType) | 26 | if (options.contentType) req.set('Accept', options.contentType) |
20 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | 27 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) |
21 | if (options.query) req.query(options.query) | 28 | if (options.query) req.query(options.query) |
29 | if (options.range) req.set('Range', options.range) | ||
22 | 30 | ||
23 | return req.expect(options.statusCodeExpected) | 31 | return req.expect(options.statusCodeExpected) |
24 | } | 32 | } |
@@ -164,5 +172,6 @@ export { | |||
164 | makePostBodyRequest, | 172 | makePostBodyRequest, |
165 | makePutBodyRequest, | 173 | makePutBodyRequest, |
166 | makeDeleteRequest, | 174 | makeDeleteRequest, |
175 | makeRawRequest, | ||
167 | updateAvatarRequest | 176 | updateAvatarRequest |
168 | } | 177 | } |
diff --git a/shared/utils/server/config.ts b/shared/utils/server/config.ts index 0c5512bab..29c24cff9 100644 --- a/shared/utils/server/config.ts +++ b/shared/utils/server/config.ts | |||
@@ -97,6 +97,9 @@ function updateCustomSubConfig (url: string, token: string, newConfig: any) { | |||
97 | '480p': true, | 97 | '480p': true, |
98 | '720p': false, | 98 | '720p': false, |
99 | '1080p': false | 99 | '1080p': false |
100 | }, | ||
101 | hls: { | ||
102 | enabled: false | ||
100 | } | 103 | } |
101 | }, | 104 | }, |
102 | import: { | 105 | import: { |
diff --git a/shared/utils/server/servers.ts b/shared/utils/server/servers.ts index 568385a41..bde7dd5c2 100644 --- a/shared/utils/server/servers.ts +++ b/shared/utils/server/servers.ts | |||
@@ -145,8 +145,16 @@ function runServer (serverNumber: number, configOverride?: Object, args = []) { | |||
145 | if (dontContinue === true) return | 145 | if (dontContinue === true) return |
146 | 146 | ||
147 | server.app.stdout.removeListener('data', onStdout) | 147 | server.app.stdout.removeListener('data', onStdout) |
148 | |||
149 | process.on('exit', () => { | ||
150 | try { | ||
151 | process.kill(server.app.pid) | ||
152 | } catch { /* empty */ } | ||
153 | }) | ||
154 | |||
148 | res(server) | 155 | res(server) |
149 | }) | 156 | }) |
157 | |||
150 | }) | 158 | }) |
151 | } | 159 | } |
152 | 160 | ||
@@ -158,9 +166,13 @@ async function reRunServer (server: ServerInfo, configOverride?: any) { | |||
158 | } | 166 | } |
159 | 167 | ||
160 | async function checkTmpIsEmpty (server: ServerInfo) { | 168 | async function checkTmpIsEmpty (server: ServerInfo) { |
169 | return checkDirectoryIsEmpty(server, 'tmp') | ||
170 | } | ||
171 | |||
172 | async function checkDirectoryIsEmpty (server: ServerInfo, directory: string) { | ||
161 | const testDirectory = 'test' + server.serverNumber | 173 | const testDirectory = 'test' + server.serverNumber |
162 | 174 | ||
163 | const directoryPath = join(root(), testDirectory, 'tmp') | 175 | const directoryPath = join(root(), testDirectory, directory) |
164 | 176 | ||
165 | const directoryExists = existsSync(directoryPath) | 177 | const directoryExists = existsSync(directoryPath) |
166 | expect(directoryExists).to.be.true | 178 | expect(directoryExists).to.be.true |
@@ -191,6 +203,7 @@ async function waitUntilLog (server: ServerInfo, str: string, count = 1) { | |||
191 | // --------------------------------------------------------------------------- | 203 | // --------------------------------------------------------------------------- |
192 | 204 | ||
193 | export { | 205 | export { |
206 | checkDirectoryIsEmpty, | ||
194 | checkTmpIsEmpty, | 207 | checkTmpIsEmpty, |
195 | ServerInfo, | 208 | ServerInfo, |
196 | flushAndRunMultipleServers, | 209 | flushAndRunMultipleServers, |
diff --git a/shared/utils/users/user-notifications.ts b/shared/utils/users/user-notifications.ts index bcbe29fc7..c8ed7df30 100644 --- a/shared/utils/users/user-notifications.ts +++ b/shared/utils/users/user-notifications.ts | |||
@@ -146,6 +146,7 @@ function checkVideo (video: any, videoName?: string, videoUUID?: string) { | |||
146 | function checkActor (actor: any) { | 146 | function checkActor (actor: any) { |
147 | expect(actor.displayName).to.be.a('string') | 147 | expect(actor.displayName).to.be.a('string') |
148 | expect(actor.displayName).to.not.be.empty | 148 | expect(actor.displayName).to.not.be.empty |
149 | expect(actor.host).to.not.be.undefined | ||
149 | } | 150 | } |
150 | 151 | ||
151 | function checkComment (comment: any, commentId: number, threadId: number) { | 152 | function checkComment (comment: any, commentId: number, threadId: number) { |
@@ -273,8 +274,8 @@ async function checkNewActorFollow ( | |||
273 | checkActor(notification.actorFollow.follower) | 274 | checkActor(notification.actorFollow.follower) |
274 | expect(notification.actorFollow.follower.displayName).to.equal(followerDisplayName) | 275 | expect(notification.actorFollow.follower.displayName).to.equal(followerDisplayName) |
275 | expect(notification.actorFollow.follower.name).to.equal(followerName) | 276 | expect(notification.actorFollow.follower.name).to.equal(followerName) |
277 | expect(notification.actorFollow.follower.host).to.not.be.undefined | ||
276 | 278 | ||
277 | checkActor(notification.actorFollow.following) | ||
278 | expect(notification.actorFollow.following.displayName).to.equal(followingDisplayName) | 279 | expect(notification.actorFollow.following.displayName).to.equal(followingDisplayName) |
279 | expect(notification.actorFollow.following.type).to.equal(followType) | 280 | expect(notification.actorFollow.following.type).to.equal(followType) |
280 | } else { | 281 | } else { |
diff --git a/shared/utils/users/users.ts b/shared/utils/users/users.ts index 61a7e3757..7191b263e 100644 --- a/shared/utils/users/users.ts +++ b/shared/utils/users/users.ts | |||
@@ -213,11 +213,13 @@ function updateUser (options: { | |||
213 | emailVerified?: boolean, | 213 | emailVerified?: boolean, |
214 | videoQuota?: number, | 214 | videoQuota?: number, |
215 | videoQuotaDaily?: number, | 215 | videoQuotaDaily?: number, |
216 | password?: string, | ||
216 | role?: UserRole | 217 | role?: UserRole |
217 | }) { | 218 | }) { |
218 | const path = '/api/v1/users/' + options.userId | 219 | const path = '/api/v1/users/' + options.userId |
219 | 220 | ||
220 | const toSend = {} | 221 | const toSend = {} |
222 | if (options.password !== undefined && options.password !== null) toSend['password'] = options.password | ||
221 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email | 223 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email |
222 | if (options.emailVerified !== undefined && options.emailVerified !== null) toSend['emailVerified'] = options.emailVerified | 224 | if (options.emailVerified !== undefined && options.emailVerified !== null) toSend['emailVerified'] = options.emailVerified |
223 | if (options.videoQuota !== undefined && options.videoQuota !== null) toSend['videoQuota'] = options.videoQuota | 225 | if (options.videoQuota !== undefined && options.videoQuota !== null) toSend['videoQuota'] = options.videoQuota |
diff --git a/shared/utils/videos/video-blacklist.ts b/shared/utils/videos/video-blacklist.ts index 2c176fde0..f2ae0ed26 100644 --- a/shared/utils/videos/video-blacklist.ts +++ b/shared/utils/videos/video-blacklist.ts | |||
@@ -1,11 +1,18 @@ | |||
1 | import * as request from 'supertest' | 1 | import * as request from 'supertest' |
2 | 2 | ||
3 | function addVideoToBlacklist (url: string, token: string, videoId: number | string, reason?: string, specialStatus = 204) { | 3 | function addVideoToBlacklist ( |
4 | url: string, | ||
5 | token: string, | ||
6 | videoId: number | string, | ||
7 | reason?: string, | ||
8 | unfederate?: boolean, | ||
9 | specialStatus = 204 | ||
10 | ) { | ||
4 | const path = '/api/v1/videos/' + videoId + '/blacklist' | 11 | const path = '/api/v1/videos/' + videoId + '/blacklist' |
5 | 12 | ||
6 | return request(url) | 13 | return request(url) |
7 | .post(path) | 14 | .post(path) |
8 | .send({ reason }) | 15 | .send({ reason, unfederate }) |
9 | .set('Accept', 'application/json') | 16 | .set('Accept', 'application/json') |
10 | .set('Authorization', 'Bearer ' + token) | 17 | .set('Authorization', 'Bearer ' + token) |
11 | .expect(specialStatus) | 18 | .expect(specialStatus) |
diff --git a/shared/utils/videos/video-playlists.ts b/shared/utils/videos/video-playlists.ts new file mode 100644 index 000000000..eb25011cb --- /dev/null +++ b/shared/utils/videos/video-playlists.ts | |||
@@ -0,0 +1,51 @@ | |||
1 | import { makeRawRequest } from '../requests/requests' | ||
2 | import { sha256 } from '../../../server/helpers/core-utils' | ||
3 | import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model' | ||
4 | import { expect } from 'chai' | ||
5 | |||
6 | function getPlaylist (url: string, statusCodeExpected = 200) { | ||
7 | return makeRawRequest(url, statusCodeExpected) | ||
8 | } | ||
9 | |||
10 | function getSegment (url: string, statusCodeExpected = 200, range?: string) { | ||
11 | return makeRawRequest(url, statusCodeExpected, range) | ||
12 | } | ||
13 | |||
14 | function getSegmentSha256 (url: string, statusCodeExpected = 200) { | ||
15 | return makeRawRequest(url, statusCodeExpected) | ||
16 | } | ||
17 | |||
18 | async function checkSegmentHash ( | ||
19 | baseUrlPlaylist: string, | ||
20 | baseUrlSegment: string, | ||
21 | videoUUID: string, | ||
22 | resolution: number, | ||
23 | hlsPlaylist: VideoStreamingPlaylist | ||
24 | ) { | ||
25 | const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`) | ||
26 | const playlist = res.text | ||
27 | |||
28 | const videoName = `${videoUUID}-${resolution}-fragmented.mp4` | ||
29 | |||
30 | const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) | ||
31 | |||
32 | const length = parseInt(matches[1], 10) | ||
33 | const offset = parseInt(matches[2], 10) | ||
34 | const range = `${offset}-${offset + length - 1}` | ||
35 | |||
36 | const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, 206, `bytes=${range}`) | ||
37 | |||
38 | const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url) | ||
39 | |||
40 | const sha256Server = resSha.body[ videoName ][range] | ||
41 | expect(sha256(res2.body)).to.equal(sha256Server) | ||
42 | } | ||
43 | |||
44 | // --------------------------------------------------------------------------- | ||
45 | |||
46 | export { | ||
47 | getPlaylist, | ||
48 | getSegment, | ||
49 | getSegmentSha256, | ||
50 | checkSegmentHash | ||
51 | } | ||
diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts index 0cf6e7c4f..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[] |
@@ -271,7 +272,16 @@ function removeVideo (url: string, token: string, id: number | string, expectedS | |||
271 | async function checkVideoFilesWereRemoved ( | 272 | async function checkVideoFilesWereRemoved ( |
272 | videoUUID: string, | 273 | videoUUID: string, |
273 | serverNumber: number, | 274 | serverNumber: number, |
274 | directories = [ 'redundancy', 'videos', 'thumbnails', 'torrents', 'previews', 'captions' ] | 275 | directories = [ |
276 | 'redundancy', | ||
277 | 'videos', | ||
278 | 'thumbnails', | ||
279 | 'torrents', | ||
280 | 'previews', | ||
281 | 'captions', | ||
282 | join('playlists', 'hls'), | ||
283 | join('redundancy', 'hls') | ||
284 | ] | ||
275 | ) { | 285 | ) { |
276 | const testDirectory = 'test' + serverNumber | 286 | const testDirectory = 'test' + serverNumber |
277 | 287 | ||
@@ -279,7 +289,7 @@ async function checkVideoFilesWereRemoved ( | |||
279 | const directoryPath = join(root(), testDirectory, directory) | 289 | const directoryPath = join(root(), testDirectory, directory) |
280 | 290 | ||
281 | const directoryExists = existsSync(directoryPath) | 291 | const directoryExists = existsSync(directoryPath) |
282 | expect(directoryExists).to.be.true | 292 | if (!directoryExists) continue |
283 | 293 | ||
284 | const files = await readdir(directoryPath) | 294 | const files = await readdir(directoryPath) |
285 | for (const file of files) { | 295 | for (const file of files) { |
@@ -311,6 +321,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
311 | tags: [ 'tag' ], | 321 | tags: [ 'tag' ], |
312 | privacy: VideoPrivacy.PUBLIC, | 322 | privacy: VideoPrivacy.PUBLIC, |
313 | commentsEnabled: true, | 323 | commentsEnabled: true, |
324 | downloadEnabled: true, | ||
314 | fixture: 'video_short.webm' | 325 | fixture: 'video_short.webm' |
315 | }, videoAttributesArg) | 326 | }, videoAttributesArg) |
316 | 327 | ||
@@ -321,6 +332,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg | |||
321 | .field('name', attributes.name) | 332 | .field('name', attributes.name) |
322 | .field('nsfw', JSON.stringify(attributes.nsfw)) | 333 | .field('nsfw', JSON.stringify(attributes.nsfw)) |
323 | .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled)) | 334 | .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled)) |
335 | .field('downloadEnabled', JSON.stringify(attributes.downloadEnabled)) | ||
324 | .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding)) | 336 | .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding)) |
325 | .field('privacy', attributes.privacy.toString()) | 337 | .field('privacy', attributes.privacy.toString()) |
326 | .field('channelId', attributes.channelId) | 338 | .field('channelId', attributes.channelId) |
@@ -371,6 +383,7 @@ function updateVideo (url: string, accessToken: string, id: number | string, att | |||
371 | if (attributes.language) body['language'] = attributes.language | 383 | if (attributes.language) body['language'] = attributes.language |
372 | if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) | 384 | if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) |
373 | 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) | ||
374 | if (attributes.description) body['description'] = attributes.description | 387 | if (attributes.description) body['description'] = attributes.description |
375 | if (attributes.tags) body['tags'] = attributes.tags | 388 | if (attributes.tags) body['tags'] = attributes.tags |
376 | if (attributes.privacy) body['privacy'] = attributes.privacy | 389 | if (attributes.privacy) body['privacy'] = attributes.privacy |
@@ -436,6 +449,7 @@ async function completeVideoCheck ( | |||
436 | language: string | 449 | language: string |
437 | nsfw: boolean | 450 | nsfw: boolean |
438 | commentsEnabled: boolean | 451 | commentsEnabled: boolean |
452 | downloadEnabled: boolean | ||
439 | description: string | 453 | description: string |
440 | publishedAt?: string | 454 | publishedAt?: string |
441 | support: string | 455 | support: string |
@@ -510,6 +524,7 @@ async function completeVideoCheck ( | |||
510 | expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true | 524 | expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true |
511 | expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true | 525 | expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true |
512 | expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) | 526 | expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) |
527 | expect(videoDetails.downloadEnabled).to.equal(attributes.downloadEnabled) | ||
513 | 528 | ||
514 | for (const attributeFile of attributes.files) { | 529 | for (const attributeFile of attributes.files) { |
515 | const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution) | 530 | const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution) |