aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-07-08 15:54:39 +0200
committerChocobozzz <me@florianbigard.com>2021-07-20 15:27:18 +0200
commite6346d59e63135cf012ed18c102d3b0179ef565f (patch)
treee65259adb50daa6376c9878abeef051d99191328
parent72cbfc5695ec5ebdb9721d3648218f63feeaeac5 (diff)
downloadPeerTube-e6346d59e63135cf012ed18c102d3b0179ef565f.tar.gz
PeerTube-e6346d59e63135cf012ed18c102d3b0179ef565f.tar.zst
PeerTube-e6346d59e63135cf012ed18c102d3b0179ef565f.zip
Introduce playlist command
-rw-r--r--server/controllers/api/video-playlist.ts7
-rw-r--r--server/tests/api/activitypub/client.ts6
-rw-r--r--server/tests/api/activitypub/refresher.ts22
-rw-r--r--server/tests/api/check-params/services.ts18
-rw-r--r--server/tests/api/check-params/video-playlists.ts347
-rw-r--r--server/tests/api/search/search-activitypub-video-playlists.ts45
-rw-r--r--server/tests/api/search/search-playlists.ts26
-rw-r--r--server/tests/api/server/services.ts18
-rw-r--r--server/tests/api/server/stats.ts7
-rw-r--r--server/tests/api/videos/video-playlist-thumbnails.ts123
-rw-r--r--server/tests/api/videos/video-playlists.ts564
-rw-r--r--server/tests/cli/prune-storage.ts7
-rw-r--r--server/tests/client.ts14
-rw-r--r--server/tests/plugins/action-hooks.ts17
-rw-r--r--server/tests/plugins/filter-hooks.ts10
-rw-r--r--server/tests/plugins/video-constants.ts17
-rw-r--r--shared/extra-utils/server/servers.ts4
-rw-r--r--shared/extra-utils/videos/index.ts3
-rw-r--r--shared/extra-utils/videos/playlists-command.ts280
-rw-r--r--shared/extra-utils/videos/playlists.ts25
-rw-r--r--shared/extra-utils/videos/video-playlists.ts320
-rw-r--r--shared/extra-utils/videos/videos.ts23
-rw-r--r--shared/models/videos/playlist/index.ts1
-rw-r--r--shared/models/videos/playlist/video-playlist-element-create-result.model.ts3
24 files changed, 853 insertions, 1054 deletions
diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts
index 87a6f6bbe..78cbd9cff 100644
--- a/server/controllers/api/video-playlist.ts
+++ b/server/controllers/api/video-playlist.ts
@@ -5,6 +5,7 @@ import { scheduleRefreshIfNeeded } from '@server/lib/activitypub/playlists'
5import { Hooks } from '@server/lib/plugins/hooks' 5import { Hooks } from '@server/lib/plugins/hooks'
6import { getServerActor } from '@server/models/application/application' 6import { getServerActor } from '@server/models/application/application'
7import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/types/models' 7import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/types/models'
8import { VideoPlaylistCreateResult, VideoPlaylistElementCreateResult } from '@shared/models'
8import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' 9import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
9import { VideoPlaylistCreate } from '../../../shared/models/videos/playlist/video-playlist-create.model' 10import { VideoPlaylistCreate } from '../../../shared/models/videos/playlist/video-playlist-create.model'
10import { VideoPlaylistElementCreate } from '../../../shared/models/videos/playlist/video-playlist-element-create.model' 11import { VideoPlaylistElementCreate } from '../../../shared/models/videos/playlist/video-playlist-element-create.model'
@@ -202,7 +203,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
202 id: videoPlaylistCreated.id, 203 id: videoPlaylistCreated.id,
203 shortUUID: uuidToShort(videoPlaylistCreated.uuid), 204 shortUUID: uuidToShort(videoPlaylistCreated.uuid),
204 uuid: videoPlaylistCreated.uuid 205 uuid: videoPlaylistCreated.uuid
205 } 206 } as VideoPlaylistCreateResult
206 }) 207 })
207} 208}
208 209
@@ -338,8 +339,8 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response)
338 return res.json({ 339 return res.json({
339 videoPlaylistElement: { 340 videoPlaylistElement: {
340 id: playlistElement.id 341 id: playlistElement.id
341 } 342 } as VideoPlaylistElementCreateResult
342 }).end() 343 })
343} 344}
344 345
345async function updateVideoPlaylistElement (req: express.Request, res: express.Response) { 346async function updateVideoPlaylistElement (req: express.Request, res: express.Response) {
diff --git a/server/tests/api/activitypub/client.ts b/server/tests/api/activitypub/client.ts
index be94e219c..e8536a214 100644
--- a/server/tests/api/activitypub/client.ts
+++ b/server/tests/api/activitypub/client.ts
@@ -6,7 +6,6 @@ import { VideoPlaylistPrivacy } from '@shared/models'
6import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' 6import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
7import { 7import {
8 cleanupTests, 8 cleanupTests,
9 createVideoPlaylist,
10 doubleFollow, 9 doubleFollow,
11 flushAndRunMultipleServers, 10 flushAndRunMultipleServers,
12 makeActivityPubGetRequest, 11 makeActivityPubGetRequest,
@@ -74,9 +73,8 @@ describe('Test activitypub', function () {
74 } 73 }
75 74
76 { 75 {
77 const playlistAttrs = { displayName: 'playlist', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[0].videoChannel.id } 76 const attributes = { displayName: 'playlist', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[0].videoChannel.id }
78 const resCreate = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs }) 77 playlist = await servers[0].playlistsCommand.create({ attributes })
79 playlist = resCreate.body.videoPlaylist
80 } 78 }
81 79
82 await doubleFollow(servers[0], servers[1]) 80 await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts
index 0d5452ea4..f295dfab7 100644
--- a/server/tests/api/activitypub/refresher.ts
+++ b/server/tests/api/activitypub/refresher.ts
@@ -5,12 +5,10 @@ import { HttpStatusCode } from '@shared/core-utils'
5import { 5import {
6 cleanupTests, 6 cleanupTests,
7 closeAllSequelize, 7 closeAllSequelize,
8 createVideoPlaylist,
9 doubleFollow, 8 doubleFollow,
10 flushAndRunMultipleServers, 9 flushAndRunMultipleServers,
11 generateUserAccessToken, 10 generateUserAccessToken,
12 getVideo, 11 getVideo,
13 getVideoPlaylist,
14 killallServers, 12 killallServers,
15 reRunServer, 13 reRunServer,
16 ServerInfo, 14 ServerInfo,
@@ -58,15 +56,15 @@ describe('Test AP refresher', function () {
58 } 56 }
59 57
60 { 58 {
61 const playlistAttrs = { displayName: 'playlist1', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].videoChannel.id } 59 const attributes = { displayName: 'playlist1', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].videoChannel.id }
62 const res = await createVideoPlaylist({ url: servers[1].url, token: servers[1].accessToken, playlistAttrs }) 60 const created = await servers[1].playlistsCommand.create({ attributes })
63 playlistUUID1 = res.body.videoPlaylist.uuid 61 playlistUUID1 = created.uuid
64 } 62 }
65 63
66 { 64 {
67 const playlistAttrs = { displayName: 'playlist2', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].videoChannel.id } 65 const attributes = { displayName: 'playlist2', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].videoChannel.id }
68 const res = await createVideoPlaylist({ url: servers[1].url, token: servers[1].accessToken, playlistAttrs }) 66 const created = await servers[1].playlistsCommand.create({ attributes })
69 playlistUUID2 = res.body.videoPlaylist.uuid 67 playlistUUID2 = created.uuid
70 } 68 }
71 69
72 await doubleFollow(servers[0], servers[1]) 70 await doubleFollow(servers[0], servers[1])
@@ -144,13 +142,13 @@ describe('Test AP refresher', function () {
144 // Change UUID so the remote server returns a 404 142 // Change UUID so the remote server returns a 404
145 await setPlaylistField(servers[1].internalServerNumber, playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e') 143 await setPlaylistField(servers[1].internalServerNumber, playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e')
146 144
147 await getVideoPlaylist(servers[0].url, playlistUUID1) 145 await servers[0].playlistsCommand.get({ playlistId: playlistUUID1 })
148 await getVideoPlaylist(servers[0].url, playlistUUID2) 146 await servers[0].playlistsCommand.get({ playlistId: playlistUUID2 })
149 147
150 await waitJobs(servers) 148 await waitJobs(servers)
151 149
152 await getVideoPlaylist(servers[0].url, playlistUUID1, HttpStatusCode.OK_200) 150 await servers[0].playlistsCommand.get({ playlistId: playlistUUID1, expectedStatus: HttpStatusCode.OK_200 })
153 await getVideoPlaylist(servers[0].url, playlistUUID2, HttpStatusCode.NOT_FOUND_404) 151 await servers[0].playlistsCommand.get({ playlistId: playlistUUID2, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
154 }) 152 })
155 }) 153 })
156 154
diff --git a/server/tests/api/check-params/services.ts b/server/tests/api/check-params/services.ts
index 514e3da70..595fab70d 100644
--- a/server/tests/api/check-params/services.ts
+++ b/server/tests/api/check-params/services.ts
@@ -1,19 +1,17 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import 'mocha' 3import 'mocha'
4 4import { VideoPlaylistPrivacy } from '@shared/models'
5import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
5import { 6import {
6 cleanupTests, 7 cleanupTests,
7 flushAndRunServer, 8 flushAndRunServer,
8 makeGetRequest, 9 makeGetRequest,
9 ServerInfo, 10 ServerInfo,
10 setAccessTokensToServers, 11 setAccessTokensToServers,
11 uploadVideo, 12 setDefaultVideoChannel,
12 createVideoPlaylist, 13 uploadVideo
13 setDefaultVideoChannel
14} from '../../../../shared/extra-utils' 14} from '../../../../shared/extra-utils'
15import { VideoPlaylistPrivacy } from '@shared/models'
16import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
17 15
18describe('Test services API validators', function () { 16describe('Test services API validators', function () {
19 let server: ServerInfo 17 let server: ServerInfo
@@ -34,17 +32,15 @@ describe('Test services API validators', function () {
34 } 32 }
35 33
36 { 34 {
37 const res = await createVideoPlaylist({ 35 const created = await server.playlistsCommand.create({
38 url: server.url, 36 attributes: {
39 token: server.accessToken,
40 playlistAttrs: {
41 displayName: 'super playlist', 37 displayName: 'super playlist',
42 privacy: VideoPlaylistPrivacy.PUBLIC, 38 privacy: VideoPlaylistPrivacy.PUBLIC,
43 videoChannelId: server.videoChannel.id 39 videoChannelId: server.videoChannel.id
44 } 40 }
45 }) 41 })
46 42
47 playlistUUID = res.body.videoPlaylist.uuid 43 playlistUUID = created.uuid
48 } 44 }
49 }) 45 })
50 46
diff --git a/server/tests/api/check-params/video-playlists.ts b/server/tests/api/check-params/video-playlists.ts
index 18253d11a..1c507a047 100644
--- a/server/tests/api/check-params/video-playlists.ts
+++ b/server/tests/api/check-params/video-playlists.ts
@@ -1,29 +1,29 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import 'mocha' 3import 'mocha'
4import { VideoPlaylistCreateResult, VideoPlaylistPrivacy, VideoPlaylistType } from '@shared/models' 4import {
5 VideoPlaylistCreate,
6 VideoPlaylistCreateResult,
7 VideoPlaylistElementCreate,
8 VideoPlaylistElementUpdate,
9 VideoPlaylistPrivacy,
10 VideoPlaylistReorder,
11 VideoPlaylistType
12} from '@shared/models'
5import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' 13import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
6import { 14import {
7 addVideoInPlaylist,
8 checkBadCountPagination, 15 checkBadCountPagination,
9 checkBadSortPagination, 16 checkBadSortPagination,
10 checkBadStartPagination, 17 checkBadStartPagination,
11 cleanupTests, 18 cleanupTests,
12 createVideoPlaylist,
13 deleteVideoPlaylist,
14 flushAndRunServer, 19 flushAndRunServer,
15 generateUserAccessToken, 20 generateUserAccessToken,
16 getAccountPlaylistsListWithToken,
17 getVideoPlaylist,
18 immutableAssign, 21 immutableAssign,
19 makeGetRequest, 22 makeGetRequest,
20 removeVideoFromPlaylist, 23 PlaylistsCommand,
21 reorderVideosPlaylist,
22 ServerInfo, 24 ServerInfo,
23 setAccessTokensToServers, 25 setAccessTokensToServers,
24 setDefaultVideoChannel, 26 setDefaultVideoChannel,
25 updateVideoPlaylist,
26 updateVideoPlaylistElement,
27 uploadVideoAndGetId 27 uploadVideoAndGetId
28} from '../../../../shared/extra-utils' 28} from '../../../../shared/extra-utils'
29 29
@@ -36,7 +36,9 @@ describe('Test video playlists API validator', function () {
36 36
37 let watchLaterPlaylistId: number 37 let watchLaterPlaylistId: number
38 let videoId: number 38 let videoId: number
39 let playlistElementId: number 39 let elementId: number
40
41 let command: PlaylistsCommand
40 42
41 // --------------------------------------------------------------- 43 // ---------------------------------------------------------------
42 44
@@ -51,34 +53,37 @@ describe('Test video playlists API validator', function () {
51 userAccessToken = await generateUserAccessToken(server, 'user1') 53 userAccessToken = await generateUserAccessToken(server, 'user1')
52 videoId = (await uploadVideoAndGetId({ server, videoName: 'video 1' })).id 54 videoId = (await uploadVideoAndGetId({ server, videoName: 'video 1' })).id
53 55
56 command = server.playlistsCommand
57
54 { 58 {
55 const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER) 59 const { data } = await command.listByAccount({
56 watchLaterPlaylistId = res.body.data[0].id 60 token: server.accessToken,
61 handle: 'root',
62 start: 0,
63 count: 5,
64 playlistType: VideoPlaylistType.WATCH_LATER
65 })
66 watchLaterPlaylistId = data[0].id
57 } 67 }
58 68
59 { 69 {
60 const res = await createVideoPlaylist({ 70 playlist = await command.create({
61 url: server.url, 71 attributes: {
62 token: server.accessToken,
63 playlistAttrs: {
64 displayName: 'super playlist', 72 displayName: 'super playlist',
65 privacy: VideoPlaylistPrivacy.PUBLIC, 73 privacy: VideoPlaylistPrivacy.PUBLIC,
66 videoChannelId: server.videoChannel.id 74 videoChannelId: server.videoChannel.id
67 } 75 }
68 }) 76 })
69 playlist = res.body.videoPlaylist
70 } 77 }
71 78
72 { 79 {
73 const res = await createVideoPlaylist({ 80 const created = await command.create({
74 url: server.url, 81 attributes: {
75 token: server.accessToken,
76 playlistAttrs: {
77 displayName: 'private', 82 displayName: 'private',
78 privacy: VideoPlaylistPrivacy.PRIVATE 83 privacy: VideoPlaylistPrivacy.PRIVATE
79 } 84 }
80 }) 85 })
81 privatePlaylistUUID = res.body.videoPlaylist.uuid 86 privatePlaylistUUID = created.uuid
82 } 87 }
83 }) 88 })
84 89
@@ -163,47 +168,50 @@ describe('Test video playlists API validator', function () {
163 168
164 describe('When getting a video playlist', function () { 169 describe('When getting a video playlist', function () {
165 it('Should fail with a bad id or uuid', async function () { 170 it('Should fail with a bad id or uuid', async function () {
166 await getVideoPlaylist(server.url, 'toto', HttpStatusCode.BAD_REQUEST_400) 171 await command.get({ playlistId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
167 }) 172 })
168 173
169 it('Should fail with an unknown playlist', async function () { 174 it('Should fail with an unknown playlist', async function () {
170 await getVideoPlaylist(server.url, 42, HttpStatusCode.NOT_FOUND_404) 175 await command.get({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
171 }) 176 })
172 177
173 it('Should fail to get an unlisted playlist with the number id', async function () { 178 it('Should fail to get an unlisted playlist with the number id', async function () {
174 const res = await createVideoPlaylist({ 179 const playlist = await command.create({
175 url: server.url, 180 attributes: {
176 token: server.accessToken,
177 playlistAttrs: {
178 displayName: 'super playlist', 181 displayName: 'super playlist',
179 videoChannelId: server.videoChannel.id, 182 videoChannelId: server.videoChannel.id,
180 privacy: VideoPlaylistPrivacy.UNLISTED 183 privacy: VideoPlaylistPrivacy.UNLISTED
181 } 184 }
182 }) 185 })
183 const playlist = res.body.videoPlaylist
184 186
185 await getVideoPlaylist(server.url, playlist.id, HttpStatusCode.NOT_FOUND_404) 187 await command.get({ playlistId: playlist.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
186 await getVideoPlaylist(server.url, playlist.uuid, HttpStatusCode.OK_200) 188 await command.get({ playlistId: playlist.uuid, expectedStatus: HttpStatusCode.OK_200 })
187 }) 189 })
188 190
189 it('Should succeed with the correct params', async function () { 191 it('Should succeed with the correct params', async function () {
190 await getVideoPlaylist(server.url, playlist.uuid, HttpStatusCode.OK_200) 192 await command.get({ playlistId: playlist.uuid, expectedStatus: HttpStatusCode.OK_200 })
191 }) 193 })
192 }) 194 })
193 195
194 describe('When creating/updating a video playlist', function () { 196 describe('When creating/updating a video playlist', function () {
195 const getBase = (playlistAttrs: any = {}, wrapper: any = {}) => { 197 const getBase = (
196 return Object.assign({ 198 attributes?: Partial<VideoPlaylistCreate>,
197 expectedStatus: HttpStatusCode.BAD_REQUEST_400, 199 wrapper?: Partial<Parameters<PlaylistsCommand['create']>[0]>
198 url: server.url, 200 ) => {
199 token: server.accessToken, 201 return {
200 playlistAttrs: Object.assign({ 202 attributes: {
201 displayName: 'display name', 203 displayName: 'display name',
202 privacy: VideoPlaylistPrivacy.UNLISTED, 204 privacy: VideoPlaylistPrivacy.UNLISTED,
203 thumbnailfile: 'thumbnail.jpg', 205 thumbnailfile: 'thumbnail.jpg',
204 videoChannelId: server.videoChannel.id 206 videoChannelId: server.videoChannel.id,
205 }, playlistAttrs) 207
206 }, wrapper) 208 ...attributes
209 },
210
211 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
212
213 ...wrapper
214 }
207 } 215 }
208 const getUpdate = (params: any, playlistId: number | string) => { 216 const getUpdate = (params: any, playlistId: number | string) => {
209 return immutableAssign(params, { playlistId: playlistId }) 217 return immutableAssign(params, { playlistId: playlistId })
@@ -212,86 +220,86 @@ describe('Test video playlists API validator', function () {
212 it('Should fail with an unauthenticated user', async function () { 220 it('Should fail with an unauthenticated user', async function () {
213 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 221 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
214 222
215 await createVideoPlaylist(params) 223 await command.create(params)
216 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 224 await command.update(getUpdate(params, playlist.shortUUID))
217 }) 225 })
218 226
219 it('Should fail without displayName', async function () { 227 it('Should fail without displayName', async function () {
220 const params = getBase({ displayName: undefined }) 228 const params = getBase({ displayName: undefined })
221 229
222 await createVideoPlaylist(params) 230 await command.create(params)
223 }) 231 })
224 232
225 it('Should fail with an incorrect display name', async function () { 233 it('Should fail with an incorrect display name', async function () {
226 const params = getBase({ displayName: 's'.repeat(300) }) 234 const params = getBase({ displayName: 's'.repeat(300) })
227 235
228 await createVideoPlaylist(params) 236 await command.create(params)
229 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 237 await command.update(getUpdate(params, playlist.shortUUID))
230 }) 238 })
231 239
232 it('Should fail with an incorrect description', async function () { 240 it('Should fail with an incorrect description', async function () {
233 const params = getBase({ description: 't' }) 241 const params = getBase({ description: 't' })
234 242
235 await createVideoPlaylist(params) 243 await command.create(params)
236 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 244 await command.update(getUpdate(params, playlist.shortUUID))
237 }) 245 })
238 246
239 it('Should fail with an incorrect privacy', async function () { 247 it('Should fail with an incorrect privacy', async function () {
240 const params = getBase({ privacy: 45 }) 248 const params = getBase({ privacy: 45 })
241 249
242 await createVideoPlaylist(params) 250 await command.create(params)
243 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 251 await command.update(getUpdate(params, playlist.shortUUID))
244 }) 252 })
245 253
246 it('Should fail with an unknown video channel id', async function () { 254 it('Should fail with an unknown video channel id', async function () {
247 const params = getBase({ videoChannelId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 255 const params = getBase({ videoChannelId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 })
248 256
249 await createVideoPlaylist(params) 257 await command.create(params)
250 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 258 await command.update(getUpdate(params, playlist.shortUUID))
251 }) 259 })
252 260
253 it('Should fail with an incorrect thumbnail file', async function () { 261 it('Should fail with an incorrect thumbnail file', async function () {
254 const params = getBase({ thumbnailfile: 'video_short.mp4' }) 262 const params = getBase({ thumbnailfile: 'video_short.mp4' })
255 263
256 await createVideoPlaylist(params) 264 await command.create(params)
257 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 265 await command.update(getUpdate(params, playlist.shortUUID))
258 }) 266 })
259 267
260 it('Should fail with a thumbnail file too big', async function () { 268 it('Should fail with a thumbnail file too big', async function () {
261 const params = getBase({ thumbnailfile: 'preview-big.png' }) 269 const params = getBase({ thumbnailfile: 'preview-big.png' })
262 270
263 await createVideoPlaylist(params) 271 await command.create(params)
264 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 272 await command.update(getUpdate(params, playlist.shortUUID))
265 }) 273 })
266 274
267 it('Should fail to set "public" a playlist not assigned to a channel', async function () { 275 it('Should fail to set "public" a playlist not assigned to a channel', async function () {
268 const params = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: undefined }) 276 const params = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: undefined })
269 const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' }) 277 const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' as any })
270 const params3 = getBase({ privacy: undefined, videoChannelId: 'null' }) 278 const params3 = getBase({ privacy: undefined, videoChannelId: 'null' as any })
271 279
272 await createVideoPlaylist(params) 280 await command.create(params)
273 await createVideoPlaylist(params2) 281 await command.create(params2)
274 await updateVideoPlaylist(getUpdate(params, privatePlaylistUUID)) 282 await command.update(getUpdate(params, privatePlaylistUUID))
275 await updateVideoPlaylist(getUpdate(params2, playlist.shortUUID)) 283 await command.update(getUpdate(params2, playlist.shortUUID))
276 await updateVideoPlaylist(getUpdate(params3, playlist.shortUUID)) 284 await command.update(getUpdate(params3, playlist.shortUUID))
277 }) 285 })
278 286
279 it('Should fail with an unknown playlist to update', async function () { 287 it('Should fail with an unknown playlist to update', async function () {
280 await updateVideoPlaylist(getUpdate( 288 await command.update(getUpdate(
281 getBase({}, { expectedStatus: HttpStatusCode.NOT_FOUND_404 }), 289 getBase({}, { expectedStatus: HttpStatusCode.NOT_FOUND_404 }),
282 42 290 42
283 )) 291 ))
284 }) 292 })
285 293
286 it('Should fail to update a playlist of another user', async function () { 294 it('Should fail to update a playlist of another user', async function () {
287 await updateVideoPlaylist(getUpdate( 295 await command.update(getUpdate(
288 getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }), 296 getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }),
289 playlist.shortUUID 297 playlist.shortUUID
290 )) 298 ))
291 }) 299 })
292 300
293 it('Should fail to update the watch later playlist', async function () { 301 it('Should fail to update the watch later playlist', async function () {
294 await updateVideoPlaylist(getUpdate( 302 await command.update(getUpdate(
295 getBase({}, { expectedStatus: HttpStatusCode.BAD_REQUEST_400 }), 303 getBase({}, { expectedStatus: HttpStatusCode.BAD_REQUEST_400 }),
296 watchLaterPlaylistId 304 watchLaterPlaylistId
297 )) 305 ))
@@ -300,146 +308,158 @@ describe('Test video playlists API validator', function () {
300 it('Should succeed with the correct params', async function () { 308 it('Should succeed with the correct params', async function () {
301 { 309 {
302 const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 }) 310 const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 })
303 await createVideoPlaylist(params) 311 await command.create(params)
304 } 312 }
305 313
306 { 314 {
307 const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 }) 315 const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
308 await updateVideoPlaylist(getUpdate(params, playlist.shortUUID)) 316 await command.update(getUpdate(params, playlist.shortUUID))
309 } 317 }
310 }) 318 })
311 }) 319 })
312 320
313 describe('When adding an element in a playlist', function () { 321 describe('When adding an element in a playlist', function () {
314 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => { 322 const getBase = (
315 return Object.assign({ 323 attributes?: Partial<VideoPlaylistElementCreate>,
316 expectedStatus: HttpStatusCode.BAD_REQUEST_400, 324 wrapper?: Partial<Parameters<PlaylistsCommand['addElement']>[0]>
317 url: server.url, 325 ) => {
318 token: server.accessToken, 326 return {
319 playlistId: playlist.id, 327 attributes: {
320 elementAttrs: Object.assign({
321 videoId, 328 videoId,
322 startTimestamp: 2, 329 startTimestamp: 2,
323 stopTimestamp: 3 330 stopTimestamp: 3,
324 }, elementAttrs) 331
325 }, wrapper) 332 ...attributes
333 },
334
335 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
336 playlistId: playlist.id,
337
338 ...wrapper
339 }
326 } 340 }
327 341
328 it('Should fail with an unauthenticated user', async function () { 342 it('Should fail with an unauthenticated user', async function () {
329 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 343 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
330 await addVideoInPlaylist(params) 344 await command.addElement(params)
331 }) 345 })
332 346
333 it('Should fail with the playlist of another user', async function () { 347 it('Should fail with the playlist of another user', async function () {
334 const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 348 const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
335 await addVideoInPlaylist(params) 349 await command.addElement(params)
336 }) 350 })
337 351
338 it('Should fail with an unknown or incorrect playlist id', async function () { 352 it('Should fail with an unknown or incorrect playlist id', async function () {
339 { 353 {
340 const params = getBase({}, { playlistId: 'toto' }) 354 const params = getBase({}, { playlistId: 'toto' })
341 await addVideoInPlaylist(params) 355 await command.addElement(params)
342 } 356 }
343 357
344 { 358 {
345 const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 359 const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
346 await addVideoInPlaylist(params) 360 await command.addElement(params)
347 } 361 }
348 }) 362 })
349 363
350 it('Should fail with an unknown or incorrect video id', async function () { 364 it('Should fail with an unknown or incorrect video id', async function () {
351 const params = getBase({ videoId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 365 const params = getBase({ videoId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 })
352 await addVideoInPlaylist(params) 366 await command.addElement(params)
353 }) 367 })
354 368
355 it('Should fail with a bad start/stop timestamp', async function () { 369 it('Should fail with a bad start/stop timestamp', async function () {
356 { 370 {
357 const params = getBase({ startTimestamp: -42 }) 371 const params = getBase({ startTimestamp: -42 })
358 await addVideoInPlaylist(params) 372 await command.addElement(params)
359 } 373 }
360 374
361 { 375 {
362 const params = getBase({ stopTimestamp: 'toto' as any }) 376 const params = getBase({ stopTimestamp: 'toto' as any })
363 await addVideoInPlaylist(params) 377 await command.addElement(params)
364 } 378 }
365 }) 379 })
366 380
367 it('Succeed with the correct params', async function () { 381 it('Succeed with the correct params', async function () {
368 const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 }) 382 const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 })
369 const res = await addVideoInPlaylist(params) 383 const created = await command.addElement(params)
370 playlistElementId = res.body.videoPlaylistElement.id 384 elementId = created.id
371 }) 385 })
372 }) 386 })
373 387
374 describe('When updating an element in a playlist', function () { 388 describe('When updating an element in a playlist', function () {
375 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => { 389 const getBase = (
376 return Object.assign({ 390 attributes?: Partial<VideoPlaylistElementUpdate>,
377 url: server.url, 391 wrapper?: Partial<Parameters<PlaylistsCommand['updateElement']>[0]>
378 token: server.accessToken, 392 ) => {
379 elementAttrs: Object.assign({ 393 return {
394 attributes: {
380 startTimestamp: 1, 395 startTimestamp: 1,
381 stopTimestamp: 2 396 stopTimestamp: 2,
382 }, elementAttrs), 397
383 playlistElementId, 398 ...attributes
399 },
400
401 elementId,
384 playlistId: playlist.id, 402 playlistId: playlist.id,
385 expectedStatus: HttpStatusCode.BAD_REQUEST_400 403 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
386 }, wrapper) 404
405 ...wrapper
406 }
387 } 407 }
388 408
389 it('Should fail with an unauthenticated user', async function () { 409 it('Should fail with an unauthenticated user', async function () {
390 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 410 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
391 await updateVideoPlaylistElement(params) 411 await command.updateElement(params)
392 }) 412 })
393 413
394 it('Should fail with the playlist of another user', async function () { 414 it('Should fail with the playlist of another user', async function () {
395 const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 415 const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
396 await updateVideoPlaylistElement(params) 416 await command.updateElement(params)
397 }) 417 })
398 418
399 it('Should fail with an unknown or incorrect playlist id', async function () { 419 it('Should fail with an unknown or incorrect playlist id', async function () {
400 { 420 {
401 const params = getBase({}, { playlistId: 'toto' }) 421 const params = getBase({}, { playlistId: 'toto' })
402 await updateVideoPlaylistElement(params) 422 await command.updateElement(params)
403 } 423 }
404 424
405 { 425 {
406 const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 426 const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
407 await updateVideoPlaylistElement(params) 427 await command.updateElement(params)
408 } 428 }
409 }) 429 })
410 430
411 it('Should fail with an unknown or incorrect playlistElement id', async function () { 431 it('Should fail with an unknown or incorrect playlistElement id', async function () {
412 { 432 {
413 const params = getBase({}, { playlistElementId: 'toto' }) 433 const params = getBase({}, { elementId: 'toto' })
414 await updateVideoPlaylistElement(params) 434 await command.updateElement(params)
415 } 435 }
416 436
417 { 437 {
418 const params = getBase({}, { playlistElementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 438 const params = getBase({}, { elementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
419 await updateVideoPlaylistElement(params) 439 await command.updateElement(params)
420 } 440 }
421 }) 441 })
422 442
423 it('Should fail with a bad start/stop timestamp', async function () { 443 it('Should fail with a bad start/stop timestamp', async function () {
424 { 444 {
425 const params = getBase({ startTimestamp: 'toto' as any }) 445 const params = getBase({ startTimestamp: 'toto' as any })
426 await updateVideoPlaylistElement(params) 446 await command.updateElement(params)
427 } 447 }
428 448
429 { 449 {
430 const params = getBase({ stopTimestamp: -42 }) 450 const params = getBase({ stopTimestamp: -42 })
431 await updateVideoPlaylistElement(params) 451 await command.updateElement(params)
432 } 452 }
433 }) 453 })
434 454
435 it('Should fail with an unknown element', async function () { 455 it('Should fail with an unknown element', async function () {
436 const params = getBase({}, { playlistElementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 456 const params = getBase({}, { elementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
437 await updateVideoPlaylistElement(params) 457 await command.updateElement(params)
438 }) 458 })
439 459
440 it('Succeed with the correct params', async function () { 460 it('Succeed with the correct params', async function () {
441 const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 }) 461 const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
442 await updateVideoPlaylistElement(params) 462 await command.updateElement(params)
443 }) 463 })
444 }) 464 })
445 465
@@ -447,18 +467,24 @@ describe('Test video playlists API validator', function () {
447 let videoId3: number 467 let videoId3: number
448 let videoId4: number 468 let videoId4: number
449 469
450 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => { 470 const getBase = (
451 return Object.assign({ 471 attributes?: Partial<VideoPlaylistReorder>,
452 url: server.url, 472 wrapper?: Partial<Parameters<PlaylistsCommand['reorderElements']>[0]>
453 token: server.accessToken, 473 ) => {
454 playlistId: playlist.shortUUID, 474 return {
455 elementAttrs: Object.assign({ 475 attributes: {
456 startPosition: 1, 476 startPosition: 1,
457 insertAfterPosition: 2, 477 insertAfterPosition: 2,
458 reorderLength: 3 478 reorderLength: 3,
459 }, elementAttrs), 479
460 expectedStatus: HttpStatusCode.BAD_REQUEST_400 480 ...attributes
461 }, wrapper) 481 },
482
483 playlistId: playlist.shortUUID,
484 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
485
486 ...wrapper
487 }
462 } 488 }
463 489
464 before(async function () { 490 before(async function () {
@@ -466,91 +492,86 @@ describe('Test video playlists API validator', function () {
466 videoId4 = (await uploadVideoAndGetId({ server, videoName: 'video 4' })).id 492 videoId4 = (await uploadVideoAndGetId({ server, videoName: 'video 4' })).id
467 493
468 for (const id of [ videoId3, videoId4 ]) { 494 for (const id of [ videoId3, videoId4 ]) {
469 await addVideoInPlaylist({ 495 await command.addElement({ playlistId: playlist.shortUUID, attributes: { videoId: id } })
470 url: server.url,
471 token: server.accessToken,
472 playlistId: playlist.shortUUID,
473 elementAttrs: { videoId: id }
474 })
475 } 496 }
476 }) 497 })
477 498
478 it('Should fail with an unauthenticated user', async function () { 499 it('Should fail with an unauthenticated user', async function () {
479 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 500 const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
480 await reorderVideosPlaylist(params) 501 await command.reorderElements(params)
481 }) 502 })
482 503
483 it('Should fail with the playlist of another user', async function () { 504 it('Should fail with the playlist of another user', async function () {
484 const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 505 const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
485 await reorderVideosPlaylist(params) 506 await command.reorderElements(params)
486 }) 507 })
487 508
488 it('Should fail with an invalid playlist', async function () { 509 it('Should fail with an invalid playlist', async function () {
489 { 510 {
490 const params = getBase({}, { playlistId: 'toto' }) 511 const params = getBase({}, { playlistId: 'toto' })
491 await reorderVideosPlaylist(params) 512 await command.reorderElements(params)
492 } 513 }
493 514
494 { 515 {
495 const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 516 const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
496 await reorderVideosPlaylist(params) 517 await command.reorderElements(params)
497 } 518 }
498 }) 519 })
499 520
500 it('Should fail with an invalid start position', async function () { 521 it('Should fail with an invalid start position', async function () {
501 { 522 {
502 const params = getBase({ startPosition: -1 }) 523 const params = getBase({ startPosition: -1 })
503 await reorderVideosPlaylist(params) 524 await command.reorderElements(params)
504 } 525 }
505 526
506 { 527 {
507 const params = getBase({ startPosition: 'toto' as any }) 528 const params = getBase({ startPosition: 'toto' as any })
508 await reorderVideosPlaylist(params) 529 await command.reorderElements(params)
509 } 530 }
510 531
511 { 532 {
512 const params = getBase({ startPosition: 42 }) 533 const params = getBase({ startPosition: 42 })
513 await reorderVideosPlaylist(params) 534 await command.reorderElements(params)
514 } 535 }
515 }) 536 })
516 537
517 it('Should fail with an invalid insert after position', async function () { 538 it('Should fail with an invalid insert after position', async function () {
518 { 539 {
519 const params = getBase({ insertAfterPosition: 'toto' as any }) 540 const params = getBase({ insertAfterPosition: 'toto' as any })
520 await reorderVideosPlaylist(params) 541 await command.reorderElements(params)
521 } 542 }
522 543
523 { 544 {
524 const params = getBase({ insertAfterPosition: -2 }) 545 const params = getBase({ insertAfterPosition: -2 })
525 await reorderVideosPlaylist(params) 546 await command.reorderElements(params)
526 } 547 }
527 548
528 { 549 {
529 const params = getBase({ insertAfterPosition: 42 }) 550 const params = getBase({ insertAfterPosition: 42 })
530 await reorderVideosPlaylist(params) 551 await command.reorderElements(params)
531 } 552 }
532 }) 553 })
533 554
534 it('Should fail with an invalid reorder length', async function () { 555 it('Should fail with an invalid reorder length', async function () {
535 { 556 {
536 const params = getBase({ reorderLength: 'toto' as any }) 557 const params = getBase({ reorderLength: 'toto' as any })
537 await reorderVideosPlaylist(params) 558 await command.reorderElements(params)
538 } 559 }
539 560
540 { 561 {
541 const params = getBase({ reorderLength: -2 }) 562 const params = getBase({ reorderLength: -2 })
542 await reorderVideosPlaylist(params) 563 await command.reorderElements(params)
543 } 564 }
544 565
545 { 566 {
546 const params = getBase({ reorderLength: 42 }) 567 const params = getBase({ reorderLength: 42 })
547 await reorderVideosPlaylist(params) 568 await command.reorderElements(params)
548 } 569 }
549 }) 570 })
550 571
551 it('Succeed with the correct params', async function () { 572 it('Succeed with the correct params', async function () {
552 const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 }) 573 const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
553 await reorderVideosPlaylist(params) 574 await command.reorderElements(params)
554 }) 575 })
555 }) 576 })
556 577
@@ -601,76 +622,76 @@ describe('Test video playlists API validator', function () {
601 }) 622 })
602 623
603 describe('When deleting an element in a playlist', function () { 624 describe('When deleting an element in a playlist', function () {
604 const getBase = (wrapper: any = {}) => { 625 const getBase = (wrapper: Partial<Parameters<PlaylistsCommand['removeElement']>[0]>) => {
605 return Object.assign({ 626 return {
606 url: server.url, 627 elementId,
607 token: server.accessToken,
608 playlistElementId,
609 playlistId: playlist.uuid, 628 playlistId: playlist.uuid,
610 expectedStatus: HttpStatusCode.BAD_REQUEST_400 629 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
611 }, wrapper) 630
631 ...wrapper
632 }
612 } 633 }
613 634
614 it('Should fail with an unauthenticated user', async function () { 635 it('Should fail with an unauthenticated user', async function () {
615 const params = getBase({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 636 const params = getBase({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
616 await removeVideoFromPlaylist(params) 637 await command.removeElement(params)
617 }) 638 })
618 639
619 it('Should fail with the playlist of another user', async function () { 640 it('Should fail with the playlist of another user', async function () {
620 const params = getBase({ token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 641 const params = getBase({ token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
621 await removeVideoFromPlaylist(params) 642 await command.removeElement(params)
622 }) 643 })
623 644
624 it('Should fail with an unknown or incorrect playlist id', async function () { 645 it('Should fail with an unknown or incorrect playlist id', async function () {
625 { 646 {
626 const params = getBase({ playlistId: 'toto' }) 647 const params = getBase({ playlistId: 'toto' })
627 await removeVideoFromPlaylist(params) 648 await command.removeElement(params)
628 } 649 }
629 650
630 { 651 {
631 const params = getBase({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 652 const params = getBase({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
632 await removeVideoFromPlaylist(params) 653 await command.removeElement(params)
633 } 654 }
634 }) 655 })
635 656
636 it('Should fail with an unknown or incorrect video id', async function () { 657 it('Should fail with an unknown or incorrect video id', async function () {
637 { 658 {
638 const params = getBase({ playlistElementId: 'toto' }) 659 const params = getBase({ elementId: 'toto' as any })
639 await removeVideoFromPlaylist(params) 660 await command.removeElement(params)
640 } 661 }
641 662
642 { 663 {
643 const params = getBase({ playlistElementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 664 const params = getBase({ elementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
644 await removeVideoFromPlaylist(params) 665 await command.removeElement(params)
645 } 666 }
646 }) 667 })
647 668
648 it('Should fail with an unknown element', async function () { 669 it('Should fail with an unknown element', async function () {
649 const params = getBase({ playlistElementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) 670 const params = getBase({ elementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
650 await removeVideoFromPlaylist(params) 671 await command.removeElement(params)
651 }) 672 })
652 673
653 it('Succeed with the correct params', async function () { 674 it('Succeed with the correct params', async function () {
654 const params = getBase({ expectedStatus: HttpStatusCode.NO_CONTENT_204 }) 675 const params = getBase({ expectedStatus: HttpStatusCode.NO_CONTENT_204 })
655 await removeVideoFromPlaylist(params) 676 await command.removeElement(params)
656 }) 677 })
657 }) 678 })
658 679
659 describe('When deleting a playlist', function () { 680 describe('When deleting a playlist', function () {
660 it('Should fail with an unknown playlist', async function () { 681 it('Should fail with an unknown playlist', async function () {
661 await deleteVideoPlaylist(server.url, server.accessToken, 42, HttpStatusCode.NOT_FOUND_404) 682 await command.delete({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
662 }) 683 })
663 684
664 it('Should fail with a playlist of another user', async function () { 685 it('Should fail with a playlist of another user', async function () {
665 await deleteVideoPlaylist(server.url, userAccessToken, playlist.uuid, HttpStatusCode.FORBIDDEN_403) 686 await command.delete({ token: userAccessToken, playlistId: playlist.uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
666 }) 687 })
667 688
668 it('Should fail with the watch later playlist', async function () { 689 it('Should fail with the watch later playlist', async function () {
669 await deleteVideoPlaylist(server.url, server.accessToken, watchLaterPlaylistId, HttpStatusCode.BAD_REQUEST_400) 690 await command.delete({ playlistId: watchLaterPlaylistId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
670 }) 691 })
671 692
672 it('Should succeed with the correct params', async function () { 693 it('Should succeed with the correct params', async function () {
673 await deleteVideoPlaylist(server.url, server.accessToken, playlist.uuid) 694 await command.delete({ playlistId: playlist.uuid })
674 }) 695 })
675 }) 696 })
676 697
diff --git a/server/tests/api/search/search-activitypub-video-playlists.ts b/server/tests/api/search/search-activitypub-video-playlists.ts
index 1df18173a..cb7582d29 100644
--- a/server/tests/api/search/search-activitypub-video-playlists.ts
+++ b/server/tests/api/search/search-activitypub-video-playlists.ts
@@ -3,12 +3,8 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { 5import {
6 addVideoInPlaylist,
7 cleanupTests, 6 cleanupTests,
8 createVideoPlaylist,
9 deleteVideoPlaylist,
10 flushAndRunMultipleServers, 7 flushAndRunMultipleServers,
11 getVideoPlaylistsList,
12 SearchCommand, 8 SearchCommand,
13 ServerInfo, 9 ServerInfo,
14 setAccessTokensToServers, 10 setAccessTokensToServers,
@@ -46,16 +42,11 @@ describe('Test ActivityPub playlists search', function () {
46 privacy: VideoPlaylistPrivacy.PUBLIC, 42 privacy: VideoPlaylistPrivacy.PUBLIC,
47 videoChannelId: servers[0].videoChannel.id 43 videoChannelId: servers[0].videoChannel.id
48 } 44 }
49 const res = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs: attributes }) 45 const created = await servers[0].playlistsCommand.create({ attributes })
50 playlistServer1UUID = res.body.videoPlaylist.uuid 46 playlistServer1UUID = created.uuid
51 47
52 for (const videoId of [ video1, video2 ]) { 48 for (const videoId of [ video1, video2 ]) {
53 await addVideoInPlaylist({ 49 await servers[0].playlistsCommand.addElement({ playlistId: playlistServer1UUID, attributes: { videoId } })
54 url: servers[0].url,
55 token: servers[0].accessToken,
56 playlistId: playlistServer1UUID,
57 elementAttrs: { videoId }
58 })
59 } 50 }
60 } 51 }
61 52
@@ -68,15 +59,10 @@ describe('Test ActivityPub playlists search', function () {
68 privacy: VideoPlaylistPrivacy.PUBLIC, 59 privacy: VideoPlaylistPrivacy.PUBLIC,
69 videoChannelId: servers[1].videoChannel.id 60 videoChannelId: servers[1].videoChannel.id
70 } 61 }
71 const res = await createVideoPlaylist({ url: servers[1].url, token: servers[1].accessToken, playlistAttrs: attributes }) 62 const created = await servers[1].playlistsCommand.create({ attributes })
72 playlistServer2UUID = res.body.videoPlaylist.uuid 63 playlistServer2UUID = created.uuid
73 64
74 await addVideoInPlaylist({ 65 await servers[1].playlistsCommand.addElement({ playlistId: playlistServer2UUID, attributes: { videoId } })
75 url: servers[1].url,
76 token: servers[1].accessToken,
77 playlistId: playlistServer2UUID,
78 elementAttrs: { videoId }
79 })
80 } 66 }
81 67
82 await waitJobs(servers) 68 await waitJobs(servers)
@@ -154,21 +140,16 @@ describe('Test ActivityPub playlists search', function () {
154 }) 140 })
155 141
156 it('Should not list this remote playlist', async function () { 142 it('Should not list this remote playlist', async function () {
157 const res = await getVideoPlaylistsList(servers[0].url, 0, 10) 143 const body = await servers[0].playlistsCommand.list({ start: 0, count: 10 })
158 expect(res.body.total).to.equal(1) 144 expect(body.total).to.equal(1)
159 expect(res.body.data).to.have.lengthOf(1) 145 expect(body.data).to.have.lengthOf(1)
160 expect(res.body.data[0].displayName).to.equal('playlist 1 on server 1') 146 expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
161 }) 147 })
162 148
163 it('Should update the playlist of server 2, and refresh it on server 1', async function () { 149 it('Should update the playlist of server 2, and refresh it on server 1', async function () {
164 this.timeout(60000) 150 this.timeout(60000)
165 151
166 await addVideoInPlaylist({ 152 await servers[1].playlistsCommand.addElement({ playlistId: playlistServer2UUID, attributes: { videoId: video2Server2 } })
167 url: servers[1].url,
168 token: servers[1].accessToken,
169 playlistId: playlistServer2UUID,
170 elementAttrs: { videoId: video2Server2 }
171 })
172 153
173 await waitJobs(servers) 154 await waitJobs(servers)
174 // Expire playlist 155 // Expire playlist
@@ -192,7 +173,7 @@ describe('Test ActivityPub playlists search', function () {
192 it('Should delete playlist of server 2, and delete it on server 1', async function () { 173 it('Should delete playlist of server 2, and delete it on server 1', async function () {
193 this.timeout(60000) 174 this.timeout(60000)
194 175
195 await deleteVideoPlaylist(servers[1].url, servers[1].accessToken, playlistServer2UUID) 176 await servers[1].playlistsCommand.delete({ playlistId: playlistServer2UUID })
196 177
197 await waitJobs(servers) 178 await waitJobs(servers)
198 // Expiration 179 // Expiration
diff --git a/server/tests/api/search/search-playlists.ts b/server/tests/api/search/search-playlists.ts
index 1862ecd31..517884503 100644
--- a/server/tests/api/search/search-playlists.ts
+++ b/server/tests/api/search/search-playlists.ts
@@ -4,9 +4,7 @@ import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { VideoPlaylistPrivacy } from '@shared/models' 5import { VideoPlaylistPrivacy } from '@shared/models'
6import { 6import {
7 addVideoInPlaylist,
8 cleanupTests, 7 cleanupTests,
9 createVideoPlaylist,
10 flushAndRunServer, 8 flushAndRunServer,
11 SearchCommand, 9 SearchCommand,
12 ServerInfo, 10 ServerInfo,
@@ -37,14 +35,9 @@ describe('Test playlists search', function () {
37 privacy: VideoPlaylistPrivacy.PUBLIC, 35 privacy: VideoPlaylistPrivacy.PUBLIC,
38 videoChannelId: server.videoChannel.id 36 videoChannelId: server.videoChannel.id
39 } 37 }
40 const res = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attributes }) 38 const created = await server.playlistsCommand.create({ attributes })
41 39
42 await addVideoInPlaylist({ 40 await server.playlistsCommand.addElement({ playlistId: created.id, attributes: { videoId } })
43 url: server.url,
44 token: server.accessToken,
45 playlistId: res.body.videoPlaylist.id,
46 elementAttrs: { videoId }
47 })
48 } 41 }
49 42
50 { 43 {
@@ -53,14 +46,9 @@ describe('Test playlists search', function () {
53 privacy: VideoPlaylistPrivacy.PUBLIC, 46 privacy: VideoPlaylistPrivacy.PUBLIC,
54 videoChannelId: server.videoChannel.id 47 videoChannelId: server.videoChannel.id
55 } 48 }
56 const res = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attributes }) 49 const created = await server.playlistsCommand.create({ attributes })
57 50
58 await addVideoInPlaylist({ 51 await server.playlistsCommand.addElement({ playlistId: created.id, attributes: { videoId } })
59 url: server.url,
60 token: server.accessToken,
61 playlistId: res.body.videoPlaylist.id,
62 elementAttrs: { videoId }
63 })
64 } 52 }
65 53
66 { 54 {
@@ -69,7 +57,7 @@ describe('Test playlists search', function () {
69 privacy: VideoPlaylistPrivacy.PUBLIC, 57 privacy: VideoPlaylistPrivacy.PUBLIC,
70 videoChannelId: server.videoChannel.id 58 videoChannelId: server.videoChannel.id
71 } 59 }
72 await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attributes }) 60 await server.playlistsCommand.create({ attributes })
73 } 61 }
74 62
75 command = server.searchCommand 63 command = server.searchCommand
diff --git a/server/tests/api/server/services.ts b/server/tests/api/server/services.ts
index 0adf6b667..77b95de10 100644
--- a/server/tests/api/server/services.ts
+++ b/server/tests/api/server/services.ts
@@ -4,8 +4,6 @@ import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { Video, VideoPlaylistPrivacy } from '@shared/models' 5import { Video, VideoPlaylistPrivacy } from '@shared/models'
6import { 6import {
7 addVideoInPlaylist,
8 createVideoPlaylist,
9 getVideosList, 7 getVideosList,
10 ServerInfo, 8 ServerInfo,
11 setAccessTokensToServers, 9 setAccessTokensToServers,
@@ -41,24 +39,20 @@ describe('Test services', function () {
41 } 39 }
42 40
43 { 41 {
44 const res = await createVideoPlaylist({ 42 const created = await server.playlistsCommand.create({
45 url: server.url, 43 attributes: {
46 token: server.accessToken,
47 playlistAttrs: {
48 displayName: 'The Life and Times of Scrooge McDuck', 44 displayName: 'The Life and Times of Scrooge McDuck',
49 privacy: VideoPlaylistPrivacy.PUBLIC, 45 privacy: VideoPlaylistPrivacy.PUBLIC,
50 videoChannelId: server.videoChannel.id 46 videoChannelId: server.videoChannel.id
51 } 47 }
52 }) 48 })
53 49
54 playlistUUID = res.body.videoPlaylist.uuid 50 playlistUUID = created.uuid
55 playlistDisplayName = 'The Life and Times of Scrooge McDuck' 51 playlistDisplayName = 'The Life and Times of Scrooge McDuck'
56 52
57 await addVideoInPlaylist({ 53 await server.playlistsCommand.addElement({
58 url: server.url, 54 playlistId: created.id,
59 token: server.accessToken, 55 attributes: {
60 playlistId: res.body.videoPlaylist.id,
61 elementAttrs: {
62 videoId: video.id 56 videoId: video.id
63 } 57 }
64 }) 58 })
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts
index f01188d67..c877a65eb 100644
--- a/server/tests/api/server/stats.ts
+++ b/server/tests/api/server/stats.ts
@@ -7,7 +7,6 @@ import {
7 addVideoCommentThread, 7 addVideoCommentThread,
8 cleanupTests, 8 cleanupTests,
9 createUser, 9 createUser,
10 createVideoPlaylist,
11 doubleFollow, 10 doubleFollow,
12 flushAndRunMultipleServers, 11 flushAndRunMultipleServers,
13 ServerInfo, 12 ServerInfo,
@@ -178,10 +177,8 @@ describe('Test stats (excluding redundancy)', function () {
178 } 177 }
179 178
180 { 179 {
181 await createVideoPlaylist({ 180 await server.playlistsCommand.create({
182 url: server.url, 181 attributes: {
183 token: server.accessToken,
184 playlistAttrs: {
185 displayName: 'playlist for count', 182 displayName: 'playlist for count',
186 privacy: VideoPlaylistPrivacy.PUBLIC, 183 privacy: VideoPlaylistPrivacy.PUBLIC,
187 videoChannelId: channelId 184 videoChannelId: channelId
diff --git a/server/tests/api/videos/video-playlist-thumbnails.ts b/server/tests/api/videos/video-playlist-thumbnails.ts
index a93a0b7de..af5df8d90 100644
--- a/server/tests/api/videos/video-playlist-thumbnails.ts
+++ b/server/tests/api/videos/video-playlist-thumbnails.ts
@@ -1,16 +1,11 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai'
4import 'mocha' 3import 'mocha'
4import * as chai from 'chai'
5import { 5import {
6 addVideoInPlaylist,
7 cleanupTests, 6 cleanupTests,
8 createVideoPlaylist,
9 doubleFollow, 7 doubleFollow,
10 flushAndRunMultipleServers, 8 flushAndRunMultipleServers,
11 getVideoPlaylistsList,
12 removeVideoFromPlaylist,
13 reorderVideosPlaylist,
14 ServerInfo, 9 ServerInfo,
15 setAccessTokensToServers, 10 setAccessTokensToServers,
16 setDefaultVideoChannel, 11 setDefaultVideoChannel,
@@ -25,8 +20,8 @@ const expect = chai.expect
25describe('Playlist thumbnail', function () { 20describe('Playlist thumbnail', function () {
26 let servers: ServerInfo[] = [] 21 let servers: ServerInfo[] = []
27 22
28 let playlistWithoutThumbnail: number 23 let playlistWithoutThumbnailId: number
29 let playlistWithThumbnail: number 24 let playlistWithThumbnailId: number
30 25
31 let withThumbnailE1: number 26 let withThumbnailE1: number
32 let withThumbnailE2: number 27 let withThumbnailE2: number
@@ -37,15 +32,15 @@ describe('Playlist thumbnail', function () {
37 let video2: number 32 let video2: number
38 33
39 async function getPlaylistWithoutThumbnail (server: ServerInfo) { 34 async function getPlaylistWithoutThumbnail (server: ServerInfo) {
40 const res = await getVideoPlaylistsList(server.url, 0, 10) 35 const body = await server.playlistsCommand.list({ start: 0, count: 10 })
41 36
42 return res.body.data.find(p => p.displayName === 'playlist without thumbnail') 37 return body.data.find(p => p.displayName === 'playlist without thumbnail')
43 } 38 }
44 39
45 async function getPlaylistWithThumbnail (server: ServerInfo) { 40 async function getPlaylistWithThumbnail (server: ServerInfo) {
46 const res = await getVideoPlaylistsList(server.url, 0, 10) 41 const body = await server.playlistsCommand.list({ start: 0, count: 10 })
47 42
48 return res.body.data.find(p => p.displayName === 'playlist with thumbnail') 43 return body.data.find(p => p.displayName === 'playlist with thumbnail')
49 } 44 }
50 45
51 before(async function () { 46 before(async function () {
@@ -69,24 +64,20 @@ describe('Playlist thumbnail', function () {
69 it('Should automatically update the thumbnail when adding an element', async function () { 64 it('Should automatically update the thumbnail when adding an element', async function () {
70 this.timeout(30000) 65 this.timeout(30000)
71 66
72 const res = await createVideoPlaylist({ 67 const created = await servers[1].playlistsCommand.create({
73 url: servers[1].url, 68 attributes: {
74 token: servers[1].accessToken,
75 playlistAttrs: {
76 displayName: 'playlist without thumbnail', 69 displayName: 'playlist without thumbnail',
77 privacy: VideoPlaylistPrivacy.PUBLIC, 70 privacy: VideoPlaylistPrivacy.PUBLIC,
78 videoChannelId: servers[1].videoChannel.id 71 videoChannelId: servers[1].videoChannel.id
79 } 72 }
80 }) 73 })
81 playlistWithoutThumbnail = res.body.videoPlaylist.id 74 playlistWithoutThumbnailId = created.id
82 75
83 const res2 = await addVideoInPlaylist({ 76 const added = await servers[1].playlistsCommand.addElement({
84 url: servers[1].url, 77 playlistId: playlistWithoutThumbnailId,
85 token: servers[1].accessToken, 78 attributes: { videoId: video1 }
86 playlistId: playlistWithoutThumbnail,
87 elementAttrs: { videoId: video1 }
88 }) 79 })
89 withoutThumbnailE1 = res2.body.videoPlaylistElement.id 80 withoutThumbnailE1 = added.id
90 81
91 await waitJobs(servers) 82 await waitJobs(servers)
92 83
@@ -99,25 +90,21 @@ describe('Playlist thumbnail', function () {
99 it('Should not update the thumbnail if we explicitly uploaded a thumbnail', async function () { 90 it('Should not update the thumbnail if we explicitly uploaded a thumbnail', async function () {
100 this.timeout(30000) 91 this.timeout(30000)
101 92
102 const res = await createVideoPlaylist({ 93 const created = await servers[1].playlistsCommand.create({
103 url: servers[1].url, 94 attributes: {
104 token: servers[1].accessToken,
105 playlistAttrs: {
106 displayName: 'playlist with thumbnail', 95 displayName: 'playlist with thumbnail',
107 privacy: VideoPlaylistPrivacy.PUBLIC, 96 privacy: VideoPlaylistPrivacy.PUBLIC,
108 videoChannelId: servers[1].videoChannel.id, 97 videoChannelId: servers[1].videoChannel.id,
109 thumbnailfile: 'thumbnail.jpg' 98 thumbnailfile: 'thumbnail.jpg'
110 } 99 }
111 }) 100 })
112 playlistWithThumbnail = res.body.videoPlaylist.id 101 playlistWithThumbnailId = created.id
113 102
114 const res2 = await addVideoInPlaylist({ 103 const added = await servers[1].playlistsCommand.addElement({
115 url: servers[1].url, 104 playlistId: playlistWithThumbnailId,
116 token: servers[1].accessToken, 105 attributes: { videoId: video1 }
117 playlistId: playlistWithThumbnail,
118 elementAttrs: { videoId: video1 }
119 }) 106 })
120 withThumbnailE1 = res2.body.videoPlaylistElement.id 107 withThumbnailE1 = added.id
121 108
122 await waitJobs(servers) 109 await waitJobs(servers)
123 110
@@ -130,19 +117,15 @@ describe('Playlist thumbnail', function () {
130 it('Should automatically update the thumbnail when moving the first element', async function () { 117 it('Should automatically update the thumbnail when moving the first element', async function () {
131 this.timeout(30000) 118 this.timeout(30000)
132 119
133 const res = await addVideoInPlaylist({ 120 const added = await servers[1].playlistsCommand.addElement({
134 url: servers[1].url, 121 playlistId: playlistWithoutThumbnailId,
135 token: servers[1].accessToken, 122 attributes: { videoId: video2 }
136 playlistId: playlistWithoutThumbnail,
137 elementAttrs: { videoId: video2 }
138 }) 123 })
139 withoutThumbnailE2 = res.body.videoPlaylistElement.id 124 withoutThumbnailE2 = added.id
140 125
141 await reorderVideosPlaylist({ 126 await servers[1].playlistsCommand.reorderElements({
142 url: servers[1].url, 127 playlistId: playlistWithoutThumbnailId,
143 token: servers[1].accessToken, 128 attributes: {
144 playlistId: playlistWithoutThumbnail,
145 elementAttrs: {
146 startPosition: 1, 129 startPosition: 1,
147 insertAfterPosition: 2 130 insertAfterPosition: 2
148 } 131 }
@@ -159,19 +142,15 @@ describe('Playlist thumbnail', function () {
159 it('Should not update the thumbnail when moving the first element if we explicitly uploaded a thumbnail', async function () { 142 it('Should not update the thumbnail when moving the first element if we explicitly uploaded a thumbnail', async function () {
160 this.timeout(30000) 143 this.timeout(30000)
161 144
162 const res = await addVideoInPlaylist({ 145 const added = await servers[1].playlistsCommand.addElement({
163 url: servers[1].url, 146 playlistId: playlistWithThumbnailId,
164 token: servers[1].accessToken, 147 attributes: { videoId: video2 }
165 playlistId: playlistWithThumbnail,
166 elementAttrs: { videoId: video2 }
167 }) 148 })
168 withThumbnailE2 = res.body.videoPlaylistElement.id 149 withThumbnailE2 = added.id
169 150
170 await reorderVideosPlaylist({ 151 await servers[1].playlistsCommand.reorderElements({
171 url: servers[1].url, 152 playlistId: playlistWithThumbnailId,
172 token: servers[1].accessToken, 153 attributes: {
173 playlistId: playlistWithThumbnail,
174 elementAttrs: {
175 startPosition: 1, 154 startPosition: 1,
176 insertAfterPosition: 2 155 insertAfterPosition: 2
177 } 156 }
@@ -188,11 +167,9 @@ describe('Playlist thumbnail', function () {
188 it('Should automatically update the thumbnail when deleting the first element', async function () { 167 it('Should automatically update the thumbnail when deleting the first element', async function () {
189 this.timeout(30000) 168 this.timeout(30000)
190 169
191 await removeVideoFromPlaylist({ 170 await servers[1].playlistsCommand.removeElement({
192 url: servers[1].url, 171 playlistId: playlistWithoutThumbnailId,
193 token: servers[1].accessToken, 172 elementId: withoutThumbnailE1
194 playlistId: playlistWithoutThumbnail,
195 playlistElementId: withoutThumbnailE1
196 }) 173 })
197 174
198 await waitJobs(servers) 175 await waitJobs(servers)
@@ -206,11 +183,9 @@ describe('Playlist thumbnail', function () {
206 it('Should not update the thumbnail when deleting the first element if we explicitly uploaded a thumbnail', async function () { 183 it('Should not update the thumbnail when deleting the first element if we explicitly uploaded a thumbnail', async function () {
207 this.timeout(30000) 184 this.timeout(30000)
208 185
209 await removeVideoFromPlaylist({ 186 await servers[1].playlistsCommand.removeElement({
210 url: servers[1].url, 187 playlistId: playlistWithThumbnailId,
211 token: servers[1].accessToken, 188 elementId: withThumbnailE1
212 playlistId: playlistWithThumbnail,
213 playlistElementId: withThumbnailE1
214 }) 189 })
215 190
216 await waitJobs(servers) 191 await waitJobs(servers)
@@ -224,11 +199,9 @@ describe('Playlist thumbnail', function () {
224 it('Should the thumbnail when we delete the last element', async function () { 199 it('Should the thumbnail when we delete the last element', async function () {
225 this.timeout(30000) 200 this.timeout(30000)
226 201
227 await removeVideoFromPlaylist({ 202 await servers[1].playlistsCommand.removeElement({
228 url: servers[1].url, 203 playlistId: playlistWithoutThumbnailId,
229 token: servers[1].accessToken, 204 elementId: withoutThumbnailE2
230 playlistId: playlistWithoutThumbnail,
231 playlistElementId: withoutThumbnailE2
232 }) 205 })
233 206
234 await waitJobs(servers) 207 await waitJobs(servers)
@@ -242,11 +215,9 @@ describe('Playlist thumbnail', function () {
242 it('Should not update the thumbnail when we delete the last element if we explicitly uploaded a thumbnail', async function () { 215 it('Should not update the thumbnail when we delete the last element if we explicitly uploaded a thumbnail', async function () {
243 this.timeout(30000) 216 this.timeout(30000)
244 217
245 await removeVideoFromPlaylist({ 218 await servers[1].playlistsCommand.removeElement({
246 url: servers[1].url, 219 playlistId: playlistWithThumbnailId,
247 token: servers[1].accessToken, 220 elementId: withThumbnailE2
248 playlistId: playlistWithThumbnail,
249 playlistElementId: withThumbnailE2
250 }) 221 })
251 222
252 await waitJobs(servers) 223 await waitJobs(servers)
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index 069450453..4de6b3abf 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -5,37 +5,22 @@ import * as chai from 'chai'
5import { HttpStatusCode } from '@shared/core-utils' 5import { HttpStatusCode } from '@shared/core-utils'
6import { 6import {
7 addVideoChannel, 7 addVideoChannel,
8 addVideoInPlaylist,
9 checkPlaylistFilesWereRemoved, 8 checkPlaylistFilesWereRemoved,
10 cleanupTests, 9 cleanupTests,
11 createUser, 10 createUser,
12 createVideoPlaylist,
13 deleteVideoChannel, 11 deleteVideoChannel,
14 deleteVideoPlaylist,
15 doubleFollow, 12 doubleFollow,
16 doVideosExistInMyPlaylist,
17 flushAndRunMultipleServers, 13 flushAndRunMultipleServers,
18 generateUserAccessToken, 14 generateUserAccessToken,
19 getAccessToken, 15 getAccessToken,
20 getAccountPlaylistsList,
21 getAccountPlaylistsListWithToken,
22 getMyUserInformation, 16 getMyUserInformation,
23 getPlaylistVideos, 17 PlaylistsCommand,
24 getVideoChannelPlaylistsList,
25 getVideoPlaylist,
26 getVideoPlaylistPrivacies,
27 getVideoPlaylistsList,
28 getVideoPlaylistWithToken,
29 removeUser, 18 removeUser,
30 removeVideoFromPlaylist,
31 reorderVideosPlaylist,
32 ServerInfo, 19 ServerInfo,
33 setAccessTokensToServers, 20 setAccessTokensToServers,
34 setDefaultVideoChannel, 21 setDefaultVideoChannel,
35 testImage, 22 testImage,
36 updateVideo, 23 updateVideo,
37 updateVideoPlaylist,
38 updateVideoPlaylistElement,
39 uploadVideo, 24 uploadVideo,
40 uploadVideoAndGetId, 25 uploadVideoAndGetId,
41 userLogin, 26 userLogin,
@@ -44,10 +29,8 @@ import {
44} from '@shared/extra-utils' 29} from '@shared/extra-utils'
45import { 30import {
46 User, 31 User,
47 VideoExistInPlaylist,
48 VideoPlaylist, 32 VideoPlaylist,
49 VideoPlaylistCreateResult, 33 VideoPlaylistCreateResult,
50 VideoPlaylistElement,
51 VideoPlaylistElementType, 34 VideoPlaylistElementType,
52 VideoPlaylistPrivacy, 35 VideoPlaylistPrivacy,
53 VideoPlaylistType, 36 VideoPlaylistType,
@@ -65,10 +48,10 @@ async function checkPlaylistElementType (
65 total: number 48 total: number
66) { 49) {
67 for (const server of servers) { 50 for (const server of servers) {
68 const res = await getPlaylistVideos(server.url, server.accessToken, playlistId, 0, 10) 51 const body = await server.playlistsCommand.listVideos({ token: server.accessToken, playlistId, start: 0, count: 10 })
69 expect(res.body.total).to.equal(total) 52 expect(body.total).to.equal(total)
70 53
71 const videoElement: VideoPlaylistElement = res.body.data.find((e: VideoPlaylistElement) => e.position === position) 54 const videoElement = body.data.find(e => e.position === position)
72 expect(videoElement.type).to.equal(type, 'On server ' + server.url) 55 expect(videoElement.type).to.equal(type, 'On server ' + server.url)
73 56
74 if (type === VideoPlaylistElementType.REGULAR) { 57 if (type === VideoPlaylistElementType.REGULAR) {
@@ -85,7 +68,7 @@ describe('Test video playlists', function () {
85 68
86 let playlistServer2Id1: number 69 let playlistServer2Id1: number
87 let playlistServer2Id2: number 70 let playlistServer2Id2: number
88 let playlistServer2UUID2: number 71 let playlistServer2UUID2: string
89 72
90 let playlistServer1Id: number 73 let playlistServer1Id: number
91 let playlistServer1UUID: string 74 let playlistServer1UUID: string
@@ -97,7 +80,9 @@ describe('Test video playlists', function () {
97 80
98 let nsfwVideoServer1: number 81 let nsfwVideoServer1: number
99 82
100 let userAccessTokenServer1: string 83 let userTokenServer1: string
84
85 let commands: PlaylistsCommand[]
101 86
102 before(async function () { 87 before(async function () {
103 this.timeout(120000) 88 this.timeout(120000)
@@ -113,6 +98,8 @@ describe('Test video playlists', function () {
113 // Server 1 and server 3 follow each other 98 // Server 1 and server 3 follow each other
114 await doubleFollow(servers[0], servers[2]) 99 await doubleFollow(servers[0], servers[2])
115 100
101 commands = servers.map(s => s.playlistsCommand)
102
116 { 103 {
117 servers[0].videos = [] 104 servers[0].videos = []
118 servers[1].videos = [] 105 servers[1].videos = []
@@ -137,62 +124,60 @@ describe('Test video playlists', function () {
137 username: 'user1', 124 username: 'user1',
138 password: 'password' 125 password: 'password'
139 }) 126 })
140 userAccessTokenServer1 = await getAccessToken(servers[0].url, 'user1', 'password') 127 userTokenServer1 = await getAccessToken(servers[0].url, 'user1', 'password')
141 } 128 }
142 129
143 await waitJobs(servers) 130 await waitJobs(servers)
144 }) 131 })
145 132
146 describe('Get default playlists', function () { 133 describe('Get default playlists', function () {
134
147 it('Should list video playlist privacies', async function () { 135 it('Should list video playlist privacies', async function () {
148 const res = await getVideoPlaylistPrivacies(servers[0].url) 136 const privacies = await commands[0].getPrivacies()
149 137
150 const privacies = res.body
151 expect(Object.keys(privacies)).to.have.length.at.least(3) 138 expect(Object.keys(privacies)).to.have.length.at.least(3)
152
153 expect(privacies[3]).to.equal('Private') 139 expect(privacies[3]).to.equal('Private')
154 }) 140 })
155 141
156 it('Should list watch later playlist', async function () { 142 it('Should list watch later playlist', async function () {
157 const url = servers[0].url 143 const token = servers[0].accessToken
158 const accessToken = servers[0].accessToken
159 144
160 { 145 {
161 const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER) 146 const body = await commands[0].listByAccount({ token, handle: 'root', playlistType: VideoPlaylistType.WATCH_LATER })
162 147
163 expect(res.body.total).to.equal(1) 148 expect(body.total).to.equal(1)
164 expect(res.body.data).to.have.lengthOf(1) 149 expect(body.data).to.have.lengthOf(1)
165 150
166 const playlist: VideoPlaylist = res.body.data[0] 151 const playlist = body.data[0]
167 expect(playlist.displayName).to.equal('Watch later') 152 expect(playlist.displayName).to.equal('Watch later')
168 expect(playlist.type.id).to.equal(VideoPlaylistType.WATCH_LATER) 153 expect(playlist.type.id).to.equal(VideoPlaylistType.WATCH_LATER)
169 expect(playlist.type.label).to.equal('Watch later') 154 expect(playlist.type.label).to.equal('Watch later')
170 } 155 }
171 156
172 { 157 {
173 const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.REGULAR) 158 const body = await commands[0].listByAccount({ token, handle: 'root', playlistType: VideoPlaylistType.REGULAR })
174 159
175 expect(res.body.total).to.equal(0) 160 expect(body.total).to.equal(0)
176 expect(res.body.data).to.have.lengthOf(0) 161 expect(body.data).to.have.lengthOf(0)
177 } 162 }
178 163
179 { 164 {
180 const res = await getAccountPlaylistsList(url, 'root', 0, 5) 165 const body = await commands[0].listByAccount({ handle: 'root' })
181 expect(res.body.total).to.equal(0) 166 expect(body.total).to.equal(0)
182 expect(res.body.data).to.have.lengthOf(0) 167 expect(body.data).to.have.lengthOf(0)
183 } 168 }
184 }) 169 })
185 170
186 it('Should get private playlist for a classic user', async function () { 171 it('Should get private playlist for a classic user', async function () {
187 const token = await generateUserAccessToken(servers[0], 'toto') 172 const token = await generateUserAccessToken(servers[0], 'toto')
188 173
189 const res = await getAccountPlaylistsListWithToken(servers[0].url, token, 'toto', 0, 5) 174 const body = await commands[0].listByAccount({ token, handle: 'toto' })
190 175
191 expect(res.body.total).to.equal(1) 176 expect(body.total).to.equal(1)
192 expect(res.body.data).to.have.lengthOf(1) 177 expect(body.data).to.have.lengthOf(1)
193 178
194 const playlistId = res.body.data[0].id 179 const playlistId = body.data[0].id
195 await getPlaylistVideos(servers[0].url, token, playlistId, 0, 5) 180 await commands[0].listVideos({ token, playlistId })
196 }) 181 })
197 }) 182 })
198 183
@@ -201,10 +186,8 @@ describe('Test video playlists', function () {
201 it('Should create a playlist on server 1 and have the playlist on server 2 and 3', async function () { 186 it('Should create a playlist on server 1 and have the playlist on server 2 and 3', async function () {
202 this.timeout(30000) 187 this.timeout(30000)
203 188
204 await createVideoPlaylist({ 189 await commands[0].create({
205 url: servers[0].url, 190 attributes: {
206 token: servers[0].accessToken,
207 playlistAttrs: {
208 displayName: 'my super playlist', 191 displayName: 'my super playlist',
209 privacy: VideoPlaylistPrivacy.PUBLIC, 192 privacy: VideoPlaylistPrivacy.PUBLIC,
210 description: 'my super description', 193 description: 'my super description',
@@ -218,14 +201,13 @@ describe('Test video playlists', function () {
218 await wait(3000) 201 await wait(3000)
219 202
220 for (const server of servers) { 203 for (const server of servers) {
221 const res = await getVideoPlaylistsList(server.url, 0, 5) 204 const body = await server.playlistsCommand.list({ start: 0, count: 5 })
222 expect(res.body.total).to.equal(1) 205 expect(body.total).to.equal(1)
223 expect(res.body.data).to.have.lengthOf(1) 206 expect(body.data).to.have.lengthOf(1)
224 207
225 const playlistFromList = res.body.data[0] as VideoPlaylist 208 const playlistFromList = body.data[0]
226 209
227 const res2 = await getVideoPlaylist(server.url, playlistFromList.uuid) 210 const playlistFromGet = await server.playlistsCommand.get({ playlistId: playlistFromList.uuid })
228 const playlistFromGet = res2.body as VideoPlaylist
229 211
230 for (const playlist of [ playlistFromGet, playlistFromList ]) { 212 for (const playlist of [ playlistFromGet, playlistFromList ]) {
231 expect(playlist.id).to.be.a('number') 213 expect(playlist.id).to.be.a('number')
@@ -255,23 +237,19 @@ describe('Test video playlists', function () {
255 this.timeout(30000) 237 this.timeout(30000)
256 238
257 { 239 {
258 const res = await createVideoPlaylist({ 240 const playlist = await servers[1].playlistsCommand.create({
259 url: servers[1].url, 241 attributes: {
260 token: servers[1].accessToken,
261 playlistAttrs: {
262 displayName: 'playlist 2', 242 displayName: 'playlist 2',
263 privacy: VideoPlaylistPrivacy.PUBLIC, 243 privacy: VideoPlaylistPrivacy.PUBLIC,
264 videoChannelId: servers[1].videoChannel.id 244 videoChannelId: servers[1].videoChannel.id
265 } 245 }
266 }) 246 })
267 playlistServer2Id1 = res.body.videoPlaylist.id 247 playlistServer2Id1 = playlist.id
268 } 248 }
269 249
270 { 250 {
271 const res = await createVideoPlaylist({ 251 const playlist = await servers[1].playlistsCommand.create({
272 url: servers[1].url, 252 attributes: {
273 token: servers[1].accessToken,
274 playlistAttrs: {
275 displayName: 'playlist 3', 253 displayName: 'playlist 3',
276 privacy: VideoPlaylistPrivacy.PUBLIC, 254 privacy: VideoPlaylistPrivacy.PUBLIC,
277 thumbnailfile: 'thumbnail.jpg', 255 thumbnailfile: 'thumbnail.jpg',
@@ -279,22 +257,18 @@ describe('Test video playlists', function () {
279 } 257 }
280 }) 258 })
281 259
282 playlistServer2Id2 = res.body.videoPlaylist.id 260 playlistServer2Id2 = playlist.id
283 playlistServer2UUID2 = res.body.videoPlaylist.uuid 261 playlistServer2UUID2 = playlist.uuid
284 } 262 }
285 263
286 for (const id of [ playlistServer2Id1, playlistServer2Id2 ]) { 264 for (const id of [ playlistServer2Id1, playlistServer2Id2 ]) {
287 await addVideoInPlaylist({ 265 await servers[1].playlistsCommand.addElement({
288 url: servers[1].url,
289 token: servers[1].accessToken,
290 playlistId: id, 266 playlistId: id,
291 elementAttrs: { videoId: servers[1].videos[0].id, startTimestamp: 1, stopTimestamp: 2 } 267 attributes: { videoId: servers[1].videos[0].id, startTimestamp: 1, stopTimestamp: 2 }
292 }) 268 })
293 await addVideoInPlaylist({ 269 await servers[1].playlistsCommand.addElement({
294 url: servers[1].url,
295 token: servers[1].accessToken,
296 playlistId: id, 270 playlistId: id,
297 elementAttrs: { videoId: servers[1].videos[1].id } 271 attributes: { videoId: servers[1].videos[1].id }
298 }) 272 })
299 } 273 }
300 274
@@ -302,20 +276,20 @@ describe('Test video playlists', function () {
302 await wait(3000) 276 await wait(3000)
303 277
304 for (const server of [ servers[0], servers[1] ]) { 278 for (const server of [ servers[0], servers[1] ]) {
305 const res = await getVideoPlaylistsList(server.url, 0, 5) 279 const body = await server.playlistsCommand.list({ start: 0, count: 5 })
306 280
307 const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2') 281 const playlist2 = body.data.find(p => p.displayName === 'playlist 2')
308 expect(playlist2).to.not.be.undefined 282 expect(playlist2).to.not.be.undefined
309 await testImage(server.url, 'thumbnail-playlist', playlist2.thumbnailPath) 283 await testImage(server.url, 'thumbnail-playlist', playlist2.thumbnailPath)
310 284
311 const playlist3 = res.body.data.find(p => p.displayName === 'playlist 3') 285 const playlist3 = body.data.find(p => p.displayName === 'playlist 3')
312 expect(playlist3).to.not.be.undefined 286 expect(playlist3).to.not.be.undefined
313 await testImage(server.url, 'thumbnail', playlist3.thumbnailPath) 287 await testImage(server.url, 'thumbnail', playlist3.thumbnailPath)
314 } 288 }
315 289
316 const res = await getVideoPlaylistsList(servers[2].url, 0, 5) 290 const body = await servers[2].playlistsCommand.list({ start: 0, count: 5 })
317 expect(res.body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined 291 expect(body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined
318 expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined 292 expect(body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined
319 }) 293 })
320 294
321 it('Should have the playlist on server 3 after a new follow', async function () { 295 it('Should have the playlist on server 3 after a new follow', async function () {
@@ -324,13 +298,13 @@ describe('Test video playlists', function () {
324 // Server 2 and server 3 follow each other 298 // Server 2 and server 3 follow each other
325 await doubleFollow(servers[1], servers[2]) 299 await doubleFollow(servers[1], servers[2])
326 300
327 const res = await getVideoPlaylistsList(servers[2].url, 0, 5) 301 const body = await servers[2].playlistsCommand.list({ start: 0, count: 5 })
328 302
329 const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2') 303 const playlist2 = body.data.find(p => p.displayName === 'playlist 2')
330 expect(playlist2).to.not.be.undefined 304 expect(playlist2).to.not.be.undefined
331 await testImage(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath) 305 await testImage(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath)
332 306
333 expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined 307 expect(body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined
334 }) 308 })
335 }) 309 })
336 310
@@ -340,22 +314,20 @@ describe('Test video playlists', function () {
340 this.timeout(30000) 314 this.timeout(30000)
341 315
342 { 316 {
343 const res = await getVideoPlaylistsList(servers[2].url, 1, 2, 'createdAt') 317 const body = await servers[2].playlistsCommand.list({ start: 1, count: 2, sort: 'createdAt' })
318 expect(body.total).to.equal(3)
344 319
345 expect(res.body.total).to.equal(3) 320 const data = body.data
346
347 const data: VideoPlaylist[] = res.body.data
348 expect(data).to.have.lengthOf(2) 321 expect(data).to.have.lengthOf(2)
349 expect(data[0].displayName).to.equal('playlist 2') 322 expect(data[0].displayName).to.equal('playlist 2')
350 expect(data[1].displayName).to.equal('playlist 3') 323 expect(data[1].displayName).to.equal('playlist 3')
351 } 324 }
352 325
353 { 326 {
354 const res = await getVideoPlaylistsList(servers[2].url, 1, 2, '-createdAt') 327 const body = await servers[2].playlistsCommand.list({ start: 1, count: 2, sort: '-createdAt' })
355 328 expect(body.total).to.equal(3)
356 expect(res.body.total).to.equal(3)
357 329
358 const data: VideoPlaylist[] = res.body.data 330 const data = body.data
359 expect(data).to.have.lengthOf(2) 331 expect(data).to.have.lengthOf(2)
360 expect(data[0].displayName).to.equal('playlist 2') 332 expect(data[0].displayName).to.equal('playlist 2')
361 expect(data[1].displayName).to.equal('my super playlist') 333 expect(data[1].displayName).to.equal('my super playlist')
@@ -366,11 +338,10 @@ describe('Test video playlists', function () {
366 this.timeout(30000) 338 this.timeout(30000)
367 339
368 { 340 {
369 const res = await getVideoChannelPlaylistsList(servers[0].url, 'root_channel', 0, 2, '-createdAt') 341 const body = await commands[0].listByChannel({ handle: 'root_channel', start: 0, count: 2, sort: '-createdAt' })
342 expect(body.total).to.equal(1)
370 343
371 expect(res.body.total).to.equal(1) 344 const data = body.data
372
373 const data: VideoPlaylist[] = res.body.data
374 expect(data).to.have.lengthOf(1) 345 expect(data).to.have.lengthOf(1)
375 expect(data[0].displayName).to.equal('my super playlist') 346 expect(data[0].displayName).to.equal('my super playlist')
376 } 347 }
@@ -380,41 +351,37 @@ describe('Test video playlists', function () {
380 this.timeout(30000) 351 this.timeout(30000)
381 352
382 { 353 {
383 const res = await getAccountPlaylistsList(servers[1].url, 'root', 1, 2, '-createdAt') 354 const body = await servers[1].playlistsCommand.listByAccount({ handle: 'root', start: 1, count: 2, sort: '-createdAt' })
384 355 expect(body.total).to.equal(2)
385 expect(res.body.total).to.equal(2)
386 356
387 const data: VideoPlaylist[] = res.body.data 357 const data = body.data
388 expect(data).to.have.lengthOf(1) 358 expect(data).to.have.lengthOf(1)
389 expect(data[0].displayName).to.equal('playlist 2') 359 expect(data[0].displayName).to.equal('playlist 2')
390 } 360 }
391 361
392 { 362 {
393 const res = await getAccountPlaylistsList(servers[1].url, 'root', 1, 2, 'createdAt') 363 const body = await servers[1].playlistsCommand.listByAccount({ handle: 'root', start: 1, count: 2, sort: 'createdAt' })
364 expect(body.total).to.equal(2)
394 365
395 expect(res.body.total).to.equal(2) 366 const data = body.data
396
397 const data: VideoPlaylist[] = res.body.data
398 expect(data).to.have.lengthOf(1) 367 expect(data).to.have.lengthOf(1)
399 expect(data[0].displayName).to.equal('playlist 3') 368 expect(data[0].displayName).to.equal('playlist 3')
400 } 369 }
401 370
402 { 371 {
403 const res = await getAccountPlaylistsList(servers[1].url, 'root', 0, 10, 'createdAt', '3') 372 const body = await servers[1].playlistsCommand.listByAccount({ handle: 'root', sort: 'createdAt', search: '3' })
404 373 expect(body.total).to.equal(1)
405 expect(res.body.total).to.equal(1)
406 374
407 const data: VideoPlaylist[] = res.body.data 375 const data = body.data
408 expect(data).to.have.lengthOf(1) 376 expect(data).to.have.lengthOf(1)
409 expect(data[0].displayName).to.equal('playlist 3') 377 expect(data[0].displayName).to.equal('playlist 3')
410 } 378 }
411 379
412 { 380 {
413 const res = await getAccountPlaylistsList(servers[1].url, 'root', 0, 10, 'createdAt', '4') 381 const body = await servers[1].playlistsCommand.listByAccount({ handle: 'root', sort: 'createdAt', search: '4' })
414 382 expect(body.total).to.equal(0)
415 expect(res.body.total).to.equal(0)
416 383
417 const data: VideoPlaylist[] = res.body.data 384 const data = body.data
418 expect(data).to.have.lengthOf(0) 385 expect(data).to.have.lengthOf(0)
419 } 386 }
420 }) 387 })
@@ -428,28 +395,22 @@ describe('Test video playlists', function () {
428 this.timeout(30000) 395 this.timeout(30000)
429 396
430 { 397 {
431 const res = await createVideoPlaylist({ 398 unlistedPlaylist = await servers[1].playlistsCommand.create({
432 url: servers[1].url, 399 attributes: {
433 token: servers[1].accessToken,
434 playlistAttrs: {
435 displayName: 'playlist unlisted', 400 displayName: 'playlist unlisted',
436 privacy: VideoPlaylistPrivacy.UNLISTED, 401 privacy: VideoPlaylistPrivacy.UNLISTED,
437 videoChannelId: servers[1].videoChannel.id 402 videoChannelId: servers[1].videoChannel.id
438 } 403 }
439 }) 404 })
440 unlistedPlaylist = res.body.videoPlaylist
441 } 405 }
442 406
443 { 407 {
444 const res = await createVideoPlaylist({ 408 privatePlaylist = await servers[1].playlistsCommand.create({
445 url: servers[1].url, 409 attributes: {
446 token: servers[1].accessToken,
447 playlistAttrs: {
448 displayName: 'playlist private', 410 displayName: 'playlist private',
449 privacy: VideoPlaylistPrivacy.PRIVATE 411 privacy: VideoPlaylistPrivacy.PRIVATE
450 } 412 }
451 }) 413 })
452 privatePlaylist = res.body.videoPlaylist
453 } 414 }
454 415
455 await waitJobs(servers) 416 await waitJobs(servers)
@@ -459,15 +420,15 @@ describe('Test video playlists', function () {
459 it('Should not list unlisted or private playlists', async function () { 420 it('Should not list unlisted or private playlists', async function () {
460 for (const server of servers) { 421 for (const server of servers) {
461 const results = [ 422 const results = [
462 await getAccountPlaylistsList(server.url, 'root@localhost:' + servers[1].port, 0, 5, '-createdAt'), 423 await server.playlistsCommand.listByAccount({ handle: 'root@localhost:' + servers[1].port, sort: '-createdAt' }),
463 await getVideoPlaylistsList(server.url, 0, 2, '-createdAt') 424 await server.playlistsCommand.list({ start: 0, count: 2, sort: '-createdAt' })
464 ] 425 ]
465 426
466 expect(results[0].body.total).to.equal(2) 427 expect(results[0].total).to.equal(2)
467 expect(results[1].body.total).to.equal(3) 428 expect(results[1].total).to.equal(3)
468 429
469 for (const res of results) { 430 for (const body of results) {
470 const data: VideoPlaylist[] = res.body.data 431 const data = body.data
471 expect(data).to.have.lengthOf(2) 432 expect(data).to.have.lengthOf(2)
472 expect(data[0].displayName).to.equal('playlist 3') 433 expect(data[0].displayName).to.equal('playlist 3')
473 expect(data[1].displayName).to.equal('playlist 2') 434 expect(data[1].displayName).to.equal('playlist 2')
@@ -476,23 +437,23 @@ describe('Test video playlists', function () {
476 }) 437 })
477 438
478 it('Should not get unlisted playlist using only the id', async function () { 439 it('Should not get unlisted playlist using only the id', async function () {
479 await getVideoPlaylist(servers[1].url, unlistedPlaylist.id, 404) 440 await servers[1].playlistsCommand.get({ playlistId: unlistedPlaylist.id, expectedStatus: 404 })
480 }) 441 })
481 442
482 it('Should get unlisted plyaylist using uuid or shortUUID', async function () { 443 it('Should get unlisted plyaylist using uuid or shortUUID', async function () {
483 await getVideoPlaylist(servers[1].url, unlistedPlaylist.uuid) 444 await servers[1].playlistsCommand.get({ playlistId: unlistedPlaylist.uuid })
484 await getVideoPlaylist(servers[1].url, unlistedPlaylist.shortUUID) 445 await servers[1].playlistsCommand.get({ playlistId: unlistedPlaylist.shortUUID })
485 }) 446 })
486 447
487 it('Should not get private playlist without token', async function () { 448 it('Should not get private playlist without token', async function () {
488 for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) { 449 for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
489 await getVideoPlaylist(servers[1].url, id, 401) 450 await servers[1].playlistsCommand.get({ playlistId: id, expectedStatus: 401 })
490 } 451 }
491 }) 452 })
492 453
493 it('Should get private playlist with a token', async function () { 454 it('Should get private playlist with a token', async function () {
494 for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) { 455 for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
495 await getVideoPlaylistWithToken(servers[1].url, servers[1].accessToken, id) 456 await servers[1].playlistsCommand.get({ token: servers[1].accessToken, playlistId: id })
496 } 457 }
497 }) 458 })
498 }) 459 })
@@ -502,10 +463,8 @@ describe('Test video playlists', function () {
502 it('Should update a playlist', async function () { 463 it('Should update a playlist', async function () {
503 this.timeout(30000) 464 this.timeout(30000)
504 465
505 await updateVideoPlaylist({ 466 await servers[1].playlistsCommand.update({
506 url: servers[1].url, 467 attributes: {
507 token: servers[1].accessToken,
508 playlistAttrs: {
509 displayName: 'playlist 3 updated', 468 displayName: 'playlist 3 updated',
510 description: 'description updated', 469 description: 'description updated',
511 privacy: VideoPlaylistPrivacy.UNLISTED, 470 privacy: VideoPlaylistPrivacy.UNLISTED,
@@ -518,8 +477,7 @@ describe('Test video playlists', function () {
518 await waitJobs(servers) 477 await waitJobs(servers)
519 478
520 for (const server of servers) { 479 for (const server of servers) {
521 const res = await getVideoPlaylist(server.url, playlistServer2UUID2) 480 const playlist = await server.playlistsCommand.get({ playlistId: playlistServer2UUID2 })
522 const playlist: VideoPlaylist = res.body
523 481
524 expect(playlist.displayName).to.equal('playlist 3 updated') 482 expect(playlist.displayName).to.equal('playlist 3 updated')
525 expect(playlist.description).to.equal('description updated') 483 expect(playlist.description).to.equal('description updated')
@@ -545,39 +503,37 @@ describe('Test video playlists', function () {
545 it('Should create a playlist containing different startTimestamp/endTimestamp videos', async function () { 503 it('Should create a playlist containing different startTimestamp/endTimestamp videos', async function () {
546 this.timeout(30000) 504 this.timeout(30000)
547 505
548 const addVideo = (elementAttrs: any) => { 506 const addVideo = (attributes: any) => {
549 return addVideoInPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: playlistServer1Id, elementAttrs }) 507 return commands[0].addElement({ playlistId: playlistServer1Id, attributes })
550 } 508 }
551 509
552 const res = await createVideoPlaylist({ 510 const playlist = await commands[0].create({
553 url: servers[0].url, 511 attributes: {
554 token: servers[0].accessToken,
555 playlistAttrs: {
556 displayName: 'playlist 4', 512 displayName: 'playlist 4',
557 privacy: VideoPlaylistPrivacy.PUBLIC, 513 privacy: VideoPlaylistPrivacy.PUBLIC,
558 videoChannelId: servers[0].videoChannel.id 514 videoChannelId: servers[0].videoChannel.id
559 } 515 }
560 }) 516 })
561 517
562 playlistServer1Id = res.body.videoPlaylist.id 518 playlistServer1Id = playlist.id
563 playlistServer1UUID = res.body.videoPlaylist.uuid 519 playlistServer1UUID = playlist.uuid
564 520
565 await addVideo({ videoId: servers[0].videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 }) 521 await addVideo({ videoId: servers[0].videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
566 await addVideo({ videoId: servers[2].videos[1].uuid, startTimestamp: 35 }) 522 await addVideo({ videoId: servers[2].videos[1].uuid, startTimestamp: 35 })
567 await addVideo({ videoId: servers[2].videos[2].uuid }) 523 await addVideo({ videoId: servers[2].videos[2].uuid })
568 { 524 {
569 const res = await addVideo({ videoId: servers[0].videos[3].uuid, stopTimestamp: 35 }) 525 const element = await addVideo({ videoId: servers[0].videos[3].uuid, stopTimestamp: 35 })
570 playlistElementServer1Video4 = res.body.videoPlaylistElement.id 526 playlistElementServer1Video4 = element.id
571 } 527 }
572 528
573 { 529 {
574 const res = await addVideo({ videoId: servers[0].videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 }) 530 const element = await addVideo({ videoId: servers[0].videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 })
575 playlistElementServer1Video5 = res.body.videoPlaylistElement.id 531 playlistElementServer1Video5 = element.id
576 } 532 }
577 533
578 { 534 {
579 const res = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 }) 535 const element = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
580 playlistElementNSFW = res.body.videoPlaylistElement.id 536 playlistElementNSFW = element.id
581 537
582 await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 4 }) 538 await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 4 })
583 await addVideo({ videoId: nsfwVideoServer1 }) 539 await addVideo({ videoId: nsfwVideoServer1 })
@@ -590,55 +546,59 @@ describe('Test video playlists', function () {
590 this.timeout(30000) 546 this.timeout(30000)
591 547
592 for (const server of servers) { 548 for (const server of servers) {
593 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) 549 {
594 550 const body = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
595 expect(res.body.total).to.equal(8) 551
596 552 expect(body.total).to.equal(8)
597 const videoElements: VideoPlaylistElement[] = res.body.data 553
598 expect(videoElements).to.have.lengthOf(8) 554 const videoElements = body.data
599 555 expect(videoElements).to.have.lengthOf(8)
600 expect(videoElements[0].video.name).to.equal('video 0 server 1') 556
601 expect(videoElements[0].position).to.equal(1) 557 expect(videoElements[0].video.name).to.equal('video 0 server 1')
602 expect(videoElements[0].startTimestamp).to.equal(15) 558 expect(videoElements[0].position).to.equal(1)
603 expect(videoElements[0].stopTimestamp).to.equal(28) 559 expect(videoElements[0].startTimestamp).to.equal(15)
604 560 expect(videoElements[0].stopTimestamp).to.equal(28)
605 expect(videoElements[1].video.name).to.equal('video 1 server 3') 561
606 expect(videoElements[1].position).to.equal(2) 562 expect(videoElements[1].video.name).to.equal('video 1 server 3')
607 expect(videoElements[1].startTimestamp).to.equal(35) 563 expect(videoElements[1].position).to.equal(2)
608 expect(videoElements[1].stopTimestamp).to.be.null 564 expect(videoElements[1].startTimestamp).to.equal(35)
609 565 expect(videoElements[1].stopTimestamp).to.be.null
610 expect(videoElements[2].video.name).to.equal('video 2 server 3') 566
611 expect(videoElements[2].position).to.equal(3) 567 expect(videoElements[2].video.name).to.equal('video 2 server 3')
612 expect(videoElements[2].startTimestamp).to.be.null 568 expect(videoElements[2].position).to.equal(3)
613 expect(videoElements[2].stopTimestamp).to.be.null 569 expect(videoElements[2].startTimestamp).to.be.null
614 570 expect(videoElements[2].stopTimestamp).to.be.null
615 expect(videoElements[3].video.name).to.equal('video 3 server 1') 571
616 expect(videoElements[3].position).to.equal(4) 572 expect(videoElements[3].video.name).to.equal('video 3 server 1')
617 expect(videoElements[3].startTimestamp).to.be.null 573 expect(videoElements[3].position).to.equal(4)
618 expect(videoElements[3].stopTimestamp).to.equal(35) 574 expect(videoElements[3].startTimestamp).to.be.null
619 575 expect(videoElements[3].stopTimestamp).to.equal(35)
620 expect(videoElements[4].video.name).to.equal('video 4 server 1') 576
621 expect(videoElements[4].position).to.equal(5) 577 expect(videoElements[4].video.name).to.equal('video 4 server 1')
622 expect(videoElements[4].startTimestamp).to.equal(45) 578 expect(videoElements[4].position).to.equal(5)
623 expect(videoElements[4].stopTimestamp).to.equal(60) 579 expect(videoElements[4].startTimestamp).to.equal(45)
624 580 expect(videoElements[4].stopTimestamp).to.equal(60)
625 expect(videoElements[5].video.name).to.equal('NSFW video') 581
626 expect(videoElements[5].position).to.equal(6) 582 expect(videoElements[5].video.name).to.equal('NSFW video')
627 expect(videoElements[5].startTimestamp).to.equal(5) 583 expect(videoElements[5].position).to.equal(6)
628 expect(videoElements[5].stopTimestamp).to.be.null 584 expect(videoElements[5].startTimestamp).to.equal(5)
629 585 expect(videoElements[5].stopTimestamp).to.be.null
630 expect(videoElements[6].video.name).to.equal('NSFW video') 586
631 expect(videoElements[6].position).to.equal(7) 587 expect(videoElements[6].video.name).to.equal('NSFW video')
632 expect(videoElements[6].startTimestamp).to.equal(4) 588 expect(videoElements[6].position).to.equal(7)
633 expect(videoElements[6].stopTimestamp).to.be.null 589 expect(videoElements[6].startTimestamp).to.equal(4)
634 590 expect(videoElements[6].stopTimestamp).to.be.null
635 expect(videoElements[7].video.name).to.equal('NSFW video') 591
636 expect(videoElements[7].position).to.equal(8) 592 expect(videoElements[7].video.name).to.equal('NSFW video')
637 expect(videoElements[7].startTimestamp).to.be.null 593 expect(videoElements[7].position).to.equal(8)
638 expect(videoElements[7].stopTimestamp).to.be.null 594 expect(videoElements[7].startTimestamp).to.be.null
639 595 expect(videoElements[7].stopTimestamp).to.be.null
640 const res3 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 2) 596 }
641 expect(res3.body.data).to.have.lengthOf(2) 597
598 {
599 const body = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 2 })
600 expect(body.data).to.have.lengthOf(2)
601 }
642 } 602 }
643 }) 603 })
644 }) 604 })
@@ -656,29 +616,28 @@ describe('Test video playlists', function () {
656 before(async function () { 616 before(async function () {
657 this.timeout(60000) 617 this.timeout(60000)
658 618
659 groupUser1 = [ Object.assign({}, servers[0], { accessToken: userAccessTokenServer1 }) ] 619 groupUser1 = [ Object.assign({}, servers[0], { accessToken: userTokenServer1 }) ]
660 groupWithoutToken1 = [ Object.assign({}, servers[0], { accessToken: undefined }) ] 620 groupWithoutToken1 = [ Object.assign({}, servers[0], { accessToken: undefined }) ]
661 group1 = [ servers[0] ] 621 group1 = [ servers[0] ]
662 group2 = [ servers[1], servers[2] ] 622 group2 = [ servers[1], servers[2] ]
663 623
664 const res = await createVideoPlaylist({ 624 const playlist = await commands[0].create({
665 url: servers[0].url, 625 token: userTokenServer1,
666 token: userAccessTokenServer1, 626 attributes: {
667 playlistAttrs: {
668 displayName: 'playlist 56', 627 displayName: 'playlist 56',
669 privacy: VideoPlaylistPrivacy.PUBLIC, 628 privacy: VideoPlaylistPrivacy.PUBLIC,
670 videoChannelId: servers[0].videoChannel.id 629 videoChannelId: servers[0].videoChannel.id
671 } 630 }
672 }) 631 })
673 632
674 const playlistServer1Id2 = res.body.videoPlaylist.id 633 const playlistServer1Id2 = playlist.id
675 playlistServer1UUID2 = res.body.videoPlaylist.uuid 634 playlistServer1UUID2 = playlist.uuid
676 635
677 const addVideo = (elementAttrs: any) => { 636 const addVideo = (attributes: any) => {
678 return addVideoInPlaylist({ url: servers[0].url, token: userAccessTokenServer1, playlistId: playlistServer1Id2, elementAttrs }) 637 return commands[0].addElement({ token: userTokenServer1, playlistId: playlistServer1Id2, attributes })
679 } 638 }
680 639
681 video1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 89', token: userAccessTokenServer1 })).uuid 640 video1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 89', token: userTokenServer1 })).uuid
682 video2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 90' })).uuid 641 video2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 90' })).uuid
683 video3 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 91', nsfw: true })).uuid 642 video3 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 91', nsfw: true })).uuid
684 643
@@ -756,26 +715,26 @@ describe('Test video playlists', function () {
756 const position = 2 715 const position = 2
757 716
758 { 717 {
759 await command.addToMyBlocklist({ token: userAccessTokenServer1, account: 'root@localhost:' + servers[1].port }) 718 await command.addToMyBlocklist({ token: userTokenServer1, account: 'root@localhost:' + servers[1].port })
760 await waitJobs(servers) 719 await waitJobs(servers)
761 720
762 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3) 721 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
763 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3) 722 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
764 723
765 await command.removeFromMyBlocklist({ token: userAccessTokenServer1, account: 'root@localhost:' + servers[1].port }) 724 await command.removeFromMyBlocklist({ token: userTokenServer1, account: 'root@localhost:' + servers[1].port })
766 await waitJobs(servers) 725 await waitJobs(servers)
767 726
768 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3) 727 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
769 } 728 }
770 729
771 { 730 {
772 await command.addToMyBlocklist({ token: userAccessTokenServer1, server: 'localhost:' + servers[1].port }) 731 await command.addToMyBlocklist({ token: userTokenServer1, server: 'localhost:' + servers[1].port })
773 await waitJobs(servers) 732 await waitJobs(servers)
774 733
775 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3) 734 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
776 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3) 735 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
777 736
778 await command.removeFromMyBlocklist({ token: userAccessTokenServer1, server: 'localhost:' + servers[1].port }) 737 await command.removeFromMyBlocklist({ token: userTokenServer1, server: 'localhost:' + servers[1].port })
779 await waitJobs(servers) 738 await waitJobs(servers)
780 739
781 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3) 740 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
@@ -809,10 +768,10 @@ describe('Test video playlists', function () {
809 }) 768 })
810 769
811 it('Should hide the video if it is NSFW', async function () { 770 it('Should hide the video if it is NSFW', async function () {
812 const res = await getPlaylistVideos(servers[0].url, userAccessTokenServer1, playlistServer1UUID2, 0, 10, { nsfw: false }) 771 const body = await commands[0].listVideos({ token: userTokenServer1, playlistId: playlistServer1UUID2, query: { nsfw: 'false' } })
813 expect(res.body.total).to.equal(3) 772 expect(body.total).to.equal(3)
814 773
815 const elements: VideoPlaylistElement[] = res.body.data 774 const elements = body.data
816 const element = elements.find(e => e.position === 3) 775 const element = elements.find(e => e.position === 3)
817 776
818 expect(element).to.exist 777 expect(element).to.exist
@@ -828,11 +787,9 @@ describe('Test video playlists', function () {
828 this.timeout(30000) 787 this.timeout(30000)
829 788
830 { 789 {
831 await reorderVideosPlaylist({ 790 await commands[0].reorderElements({
832 url: servers[0].url,
833 token: servers[0].accessToken,
834 playlistId: playlistServer1Id, 791 playlistId: playlistServer1Id,
835 elementAttrs: { 792 attributes: {
836 startPosition: 2, 793 startPosition: 2,
837 insertAfterPosition: 3 794 insertAfterPosition: 3
838 } 795 }
@@ -841,8 +798,8 @@ describe('Test video playlists', function () {
841 await waitJobs(servers) 798 await waitJobs(servers)
842 799
843 for (const server of servers) { 800 for (const server of servers) {
844 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) 801 const body = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
845 const names = (res.body.data as VideoPlaylistElement[]).map(v => v.video.name) 802 const names = body.data.map(v => v.video.name)
846 803
847 expect(names).to.deep.equal([ 804 expect(names).to.deep.equal([
848 'video 0 server 1', 805 'video 0 server 1',
@@ -858,11 +815,9 @@ describe('Test video playlists', function () {
858 } 815 }
859 816
860 { 817 {
861 await reorderVideosPlaylist({ 818 await commands[0].reorderElements({
862 url: servers[0].url,
863 token: servers[0].accessToken,
864 playlistId: playlistServer1Id, 819 playlistId: playlistServer1Id,
865 elementAttrs: { 820 attributes: {
866 startPosition: 1, 821 startPosition: 1,
867 reorderLength: 3, 822 reorderLength: 3,
868 insertAfterPosition: 4 823 insertAfterPosition: 4
@@ -872,8 +827,8 @@ describe('Test video playlists', function () {
872 await waitJobs(servers) 827 await waitJobs(servers)
873 828
874 for (const server of servers) { 829 for (const server of servers) {
875 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) 830 const body = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
876 const names = (res.body.data as VideoPlaylistElement[]).map(v => v.video.name) 831 const names = body.data.map(v => v.video.name)
877 832
878 expect(names).to.deep.equal([ 833 expect(names).to.deep.equal([
879 'video 3 server 1', 834 'video 3 server 1',
@@ -889,11 +844,9 @@ describe('Test video playlists', function () {
889 } 844 }
890 845
891 { 846 {
892 await reorderVideosPlaylist({ 847 await commands[0].reorderElements({
893 url: servers[0].url,
894 token: servers[0].accessToken,
895 playlistId: playlistServer1Id, 848 playlistId: playlistServer1Id,
896 elementAttrs: { 849 attributes: {
897 startPosition: 6, 850 startPosition: 6,
898 insertAfterPosition: 3 851 insertAfterPosition: 3
899 } 852 }
@@ -902,8 +855,7 @@ describe('Test video playlists', function () {
902 await waitJobs(servers) 855 await waitJobs(servers)
903 856
904 for (const server of servers) { 857 for (const server of servers) {
905 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) 858 const { data: elements } = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
906 const elements: VideoPlaylistElement[] = res.body.data
907 const names = elements.map(v => v.video.name) 859 const names = elements.map(v => v.video.name)
908 860
909 expect(names).to.deep.equal([ 861 expect(names).to.deep.equal([
@@ -927,22 +879,18 @@ describe('Test video playlists', function () {
927 it('Should update startTimestamp/endTimestamp of some elements', async function () { 879 it('Should update startTimestamp/endTimestamp of some elements', async function () {
928 this.timeout(30000) 880 this.timeout(30000)
929 881
930 await updateVideoPlaylistElement({ 882 await commands[0].updateElement({
931 url: servers[0].url,
932 token: servers[0].accessToken,
933 playlistId: playlistServer1Id, 883 playlistId: playlistServer1Id,
934 playlistElementId: playlistElementServer1Video4, 884 elementId: playlistElementServer1Video4,
935 elementAttrs: { 885 attributes: {
936 startTimestamp: 1 886 startTimestamp: 1
937 } 887 }
938 }) 888 })
939 889
940 await updateVideoPlaylistElement({ 890 await commands[0].updateElement({
941 url: servers[0].url,
942 token: servers[0].accessToken,
943 playlistId: playlistServer1Id, 891 playlistId: playlistServer1Id,
944 playlistElementId: playlistElementServer1Video5, 892 elementId: playlistElementServer1Video5,
945 elementAttrs: { 893 attributes: {
946 stopTimestamp: null 894 stopTimestamp: null
947 } 895 }
948 }) 896 })
@@ -950,8 +898,7 @@ describe('Test video playlists', function () {
950 await waitJobs(servers) 898 await waitJobs(servers)
951 899
952 for (const server of servers) { 900 for (const server of servers) {
953 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) 901 const { data: elements } = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
954 const elements: VideoPlaylistElement[] = res.body.data
955 902
956 expect(elements[0].video.name).to.equal('video 3 server 1') 903 expect(elements[0].video.name).to.equal('video 3 server 1')
957 expect(elements[0].position).to.equal(1) 904 expect(elements[0].position).to.equal(1)
@@ -973,8 +920,7 @@ describe('Test video playlists', function () {
973 43000, 920 43000,
974 servers[0].videos[4].id 921 servers[0].videos[4].id
975 ] 922 ]
976 const res = await doVideosExistInMyPlaylist(servers[0].url, servers[0].accessToken, videoIds) 923 const obj = await commands[0].videosExist({ videoIds })
977 const obj = res.body as VideoExistInPlaylist
978 924
979 { 925 {
980 const elem = obj[servers[0].videos[0].id] 926 const elem = obj[servers[0].videos[0].id]
@@ -1011,39 +957,26 @@ describe('Test video playlists', function () {
1011 const videoId = servers[1].videos[5].id 957 const videoId = servers[1].videos[5].id
1012 958
1013 async function getPlaylistNames () { 959 async function getPlaylistNames () {
1014 const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, undefined, '-updatedAt') 960 const { data } = await server.playlistsCommand.listByAccount({ token: server.accessToken, handle: 'root', sort: '-updatedAt' })
1015 961
1016 return (res.body.data as VideoPlaylist[]).map(p => p.displayName) 962 return data.map(p => p.displayName)
1017 } 963 }
1018 964
1019 const elementAttrs = { videoId } 965 const attributes = { videoId }
1020 const res1 = await addVideoInPlaylist({ url: server.url, token: server.accessToken, playlistId: playlistServer2Id1, elementAttrs }) 966 const element1 = await server.playlistsCommand.addElement({ playlistId: playlistServer2Id1, attributes })
1021 const res2 = await addVideoInPlaylist({ url: server.url, token: server.accessToken, playlistId: playlistServer2Id2, elementAttrs }) 967 const element2 = await server.playlistsCommand.addElement({ playlistId: playlistServer2Id2, attributes })
1022
1023 const element1 = res1.body.videoPlaylistElement.id
1024 const element2 = res2.body.videoPlaylistElement.id
1025 968
1026 const names1 = await getPlaylistNames() 969 const names1 = await getPlaylistNames()
1027 expect(names1[0]).to.equal('playlist 3 updated') 970 expect(names1[0]).to.equal('playlist 3 updated')
1028 expect(names1[1]).to.equal('playlist 2') 971 expect(names1[1]).to.equal('playlist 2')
1029 972
1030 await removeVideoFromPlaylist({ 973 await server.playlistsCommand.removeElement({ playlistId: playlistServer2Id1, elementId: element1.id })
1031 url: server.url,
1032 token: server.accessToken,
1033 playlistId: playlistServer2Id1,
1034 playlistElementId: element1
1035 })
1036 974
1037 const names2 = await getPlaylistNames() 975 const names2 = await getPlaylistNames()
1038 expect(names2[0]).to.equal('playlist 2') 976 expect(names2[0]).to.equal('playlist 2')
1039 expect(names2[1]).to.equal('playlist 3 updated') 977 expect(names2[1]).to.equal('playlist 3 updated')
1040 978
1041 await removeVideoFromPlaylist({ 979 await server.playlistsCommand.removeElement({ playlistId: playlistServer2Id2, elementId: element2.id })
1042 url: server.url,
1043 token: server.accessToken,
1044 playlistId: playlistServer2Id2,
1045 playlistElementId: element2
1046 })
1047 980
1048 const names3 = await getPlaylistNames() 981 const names3 = await getPlaylistNames()
1049 expect(names3[0]).to.equal('playlist 3 updated') 982 expect(names3[0]).to.equal('playlist 3 updated')
@@ -1053,28 +986,16 @@ describe('Test video playlists', function () {
1053 it('Should delete some elements', async function () { 986 it('Should delete some elements', async function () {
1054 this.timeout(30000) 987 this.timeout(30000)
1055 988
1056 await removeVideoFromPlaylist({ 989 await commands[0].removeElement({ playlistId: playlistServer1Id, elementId: playlistElementServer1Video4 })
1057 url: servers[0].url, 990 await commands[0].removeElement({ playlistId: playlistServer1Id, elementId: playlistElementNSFW })
1058 token: servers[0].accessToken,
1059 playlistId: playlistServer1Id,
1060 playlistElementId: playlistElementServer1Video4
1061 })
1062
1063 await removeVideoFromPlaylist({
1064 url: servers[0].url,
1065 token: servers[0].accessToken,
1066 playlistId: playlistServer1Id,
1067 playlistElementId: playlistElementNSFW
1068 })
1069 991
1070 await waitJobs(servers) 992 await waitJobs(servers)
1071 993
1072 for (const server of servers) { 994 for (const server of servers) {
1073 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) 995 const body = await server.playlistsCommand.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
1074 996 expect(body.total).to.equal(6)
1075 expect(res.body.total).to.equal(6)
1076 997
1077 const elements: VideoPlaylistElement[] = res.body.data 998 const elements = body.data
1078 expect(elements).to.have.lengthOf(6) 999 expect(elements).to.have.lengthOf(6)
1079 1000
1080 expect(elements[0].video.name).to.equal('video 0 server 1') 1001 expect(elements[0].video.name).to.equal('video 0 server 1')
@@ -1100,34 +1021,31 @@ describe('Test video playlists', function () {
1100 it('Should be able to create a public playlist, and set it to private', async function () { 1021 it('Should be able to create a public playlist, and set it to private', async function () {
1101 this.timeout(30000) 1022 this.timeout(30000)
1102 1023
1103 const res = await createVideoPlaylist({ 1024 const videoPlaylistIds = await commands[0].create({
1104 url: servers[0].url, 1025 attributes: {
1105 token: servers[0].accessToken,
1106 playlistAttrs: {
1107 displayName: 'my super public playlist', 1026 displayName: 'my super public playlist',
1108 privacy: VideoPlaylistPrivacy.PUBLIC, 1027 privacy: VideoPlaylistPrivacy.PUBLIC,
1109 videoChannelId: servers[0].videoChannel.id 1028 videoChannelId: servers[0].videoChannel.id
1110 } 1029 }
1111 }) 1030 })
1112 const videoPlaylistIds = res.body.videoPlaylist
1113 1031
1114 await waitJobs(servers) 1032 await waitJobs(servers)
1115 1033
1116 for (const server of servers) { 1034 for (const server of servers) {
1117 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.OK_200) 1035 await server.playlistsCommand.get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.OK_200 })
1118 } 1036 }
1119 1037
1120 const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE } 1038 const attributes = { privacy: VideoPlaylistPrivacy.PRIVATE }
1121 await updateVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: videoPlaylistIds.id, playlistAttrs }) 1039 await commands[0].update({ playlistId: videoPlaylistIds.id, attributes })
1122 1040
1123 await waitJobs(servers) 1041 await waitJobs(servers)
1124 1042
1125 for (const server of [ servers[1], servers[2] ]) { 1043 for (const server of [ servers[1], servers[2] ]) {
1126 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.NOT_FOUND_404) 1044 await server.playlistsCommand.get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
1127 } 1045 }
1128 await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, HttpStatusCode.UNAUTHORIZED_401)
1129 1046
1130 await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, HttpStatusCode.OK_200) 1047 await commands[0].get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
1048 await commands[0].get({ token: servers[0].accessToken, playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.OK_200 })
1131 }) 1049 })
1132 }) 1050 })
1133 1051
@@ -1136,12 +1054,12 @@ describe('Test video playlists', function () {
1136 it('Should delete the playlist on server 1 and delete on server 2 and 3', async function () { 1054 it('Should delete the playlist on server 1 and delete on server 2 and 3', async function () {
1137 this.timeout(30000) 1055 this.timeout(30000)
1138 1056
1139 await deleteVideoPlaylist(servers[0].url, servers[0].accessToken, playlistServer1Id) 1057 await commands[0].delete({ playlistId: playlistServer1Id })
1140 1058
1141 await waitJobs(servers) 1059 await waitJobs(servers)
1142 1060
1143 for (const server of servers) { 1061 for (const server of servers) {
1144 await getVideoPlaylist(server.url, playlistServer1UUID, HttpStatusCode.NOT_FOUND_404) 1062 await server.playlistsCommand.get({ playlistId: playlistServer1UUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
1145 } 1063 }
1146 }) 1064 })
1147 1065
@@ -1156,21 +1074,22 @@ describe('Test video playlists', function () {
1156 it('Should unfollow servers 1 and 2 and hide their playlists', async function () { 1074 it('Should unfollow servers 1 and 2 and hide their playlists', async function () {
1157 this.timeout(30000) 1075 this.timeout(30000)
1158 1076
1159 const finder = data => data.find(p => p.displayName === 'my super playlist') 1077 const finder = (data: VideoPlaylist[]) => data.find(p => p.displayName === 'my super playlist')
1160 1078
1161 { 1079 {
1162 const res = await getVideoPlaylistsList(servers[2].url, 0, 5) 1080 const body = await servers[2].playlistsCommand.list({ start: 0, count: 5 })
1163 expect(res.body.total).to.equal(3) 1081 expect(body.total).to.equal(3)
1164 expect(finder(res.body.data)).to.not.be.undefined 1082
1083 expect(finder(body.data)).to.not.be.undefined
1165 } 1084 }
1166 1085
1167 await servers[2].followsCommand.unfollow({ target: servers[0] }) 1086 await servers[2].followsCommand.unfollow({ target: servers[0] })
1168 1087
1169 { 1088 {
1170 const res = await getVideoPlaylistsList(servers[2].url, 0, 5) 1089 const body = await servers[2].playlistsCommand.list({ start: 0, count: 5 })
1171 expect(res.body.total).to.equal(1) 1090 expect(body.total).to.equal(1)
1172 1091
1173 expect(finder(res.body.data)).to.be.undefined 1092 expect(finder(body.data)).to.be.undefined
1174 } 1093 }
1175 }) 1094 })
1176 1095
@@ -1180,16 +1099,13 @@ describe('Test video playlists', function () {
1180 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, { name: 'super_channel', displayName: 'super channel' }) 1099 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, { name: 'super_channel', displayName: 'super channel' })
1181 const videoChannelId = res.body.videoChannel.id 1100 const videoChannelId = res.body.videoChannel.id
1182 1101
1183 const res2 = await createVideoPlaylist({ 1102 const playlistCreated = await commands[0].create({
1184 url: servers[0].url, 1103 attributes: {
1185 token: servers[0].accessToken,
1186 playlistAttrs: {
1187 displayName: 'channel playlist', 1104 displayName: 'channel playlist',
1188 privacy: VideoPlaylistPrivacy.PUBLIC, 1105 privacy: VideoPlaylistPrivacy.PUBLIC,
1189 videoChannelId 1106 videoChannelId
1190 } 1107 }
1191 }) 1108 })
1192 const videoPlaylistUUID = res2.body.videoPlaylist.uuid
1193 1109
1194 await waitJobs(servers) 1110 await waitJobs(servers)
1195 1111
@@ -1197,11 +1113,11 @@ describe('Test video playlists', function () {
1197 1113
1198 await waitJobs(servers) 1114 await waitJobs(servers)
1199 1115
1200 const res3 = await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistUUID) 1116 const body = await commands[0].get({ token: servers[0].accessToken, playlistId: playlistCreated.uuid })
1201 expect(res3.body.displayName).to.equal('channel playlist') 1117 expect(body.displayName).to.equal('channel playlist')
1202 expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE) 1118 expect(body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
1203 1119
1204 await getVideoPlaylist(servers[1].url, videoPlaylistUUID, HttpStatusCode.NOT_FOUND_404) 1120 await servers[1].playlistsCommand.get({ playlistId: playlistCreated.uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
1205 }) 1121 })
1206 1122
1207 it('Should delete an account and delete its playlists', async function () { 1123 it('Should delete an account and delete its playlists', async function () {
@@ -1221,10 +1137,8 @@ describe('Test video playlists', function () {
1221 const resChannel = await getMyUserInformation(servers[0].url, userAccessToken) 1137 const resChannel = await getMyUserInformation(servers[0].url, userAccessToken)
1222 const userChannel = (resChannel.body as User).videoChannels[0] 1138 const userChannel = (resChannel.body as User).videoChannels[0]
1223 1139
1224 await createVideoPlaylist({ 1140 await commands[0].create({
1225 url: servers[0].url, 1141 attributes: {
1226 token: userAccessToken,
1227 playlistAttrs: {
1228 displayName: 'playlist to be deleted', 1142 displayName: 'playlist to be deleted',
1229 privacy: VideoPlaylistPrivacy.PUBLIC, 1143 privacy: VideoPlaylistPrivacy.PUBLIC,
1230 videoChannelId: userChannel.id 1144 videoChannelId: userChannel.id
@@ -1233,12 +1147,13 @@ describe('Test video playlists', function () {
1233 1147
1234 await waitJobs(servers) 1148 await waitJobs(servers)
1235 1149
1236 const finder = data => data.find(p => p.displayName === 'playlist to be deleted') 1150 const finder = (data: VideoPlaylist[]) => data.find(p => p.displayName === 'playlist to be deleted')
1237 1151
1238 { 1152 {
1239 for (const server of [ servers[0], servers[1] ]) { 1153 for (const server of [ servers[0], servers[1] ]) {
1240 const res = await getVideoPlaylistsList(server.url, 0, 15) 1154 const body = await server.playlistsCommand.list({ start: 0, count: 15 })
1241 expect(finder(res.body.data)).to.not.be.undefined 1155
1156 expect(finder(body.data)).to.not.be.undefined
1242 } 1157 }
1243 } 1158 }
1244 1159
@@ -1247,8 +1162,9 @@ describe('Test video playlists', function () {
1247 1162
1248 { 1163 {
1249 for (const server of [ servers[0], servers[1] ]) { 1164 for (const server of [ servers[0], servers[1] ]) {
1250 const res = await getVideoPlaylistsList(server.url, 0, 15) 1165 const body = await server.playlistsCommand.list({ start: 0, count: 15 })
1251 expect(finder(res.body.data)).to.be.undefined 1166
1167 expect(finder(body.data)).to.be.undefined
1252 } 1168 }
1253 } 1169 }
1254 }) 1170 })
diff --git a/server/tests/cli/prune-storage.ts b/server/tests/cli/prune-storage.ts
index 95f573e50..fa1df65a9 100644
--- a/server/tests/cli/prune-storage.ts
+++ b/server/tests/cli/prune-storage.ts
@@ -10,7 +10,6 @@ import {
10 buildServerDirectory, 10 buildServerDirectory,
11 cleanupTests, 11 cleanupTests,
12 CLICommand, 12 CLICommand,
13 createVideoPlaylist,
14 doubleFollow, 13 doubleFollow,
15 flushAndRunMultipleServers, 14 flushAndRunMultipleServers,
16 killallServers, 15 killallServers,
@@ -77,10 +76,8 @@ describe('Test prune storage scripts', function () {
77 76
78 await updateMyAvatar({ url: server.url, accessToken: server.accessToken, fixture: 'avatar.png' }) 77 await updateMyAvatar({ url: server.url, accessToken: server.accessToken, fixture: 'avatar.png' })
79 78
80 await createVideoPlaylist({ 79 await server.playlistsCommand.create({
81 url: server.url, 80 attributes: {
82 token: server.accessToken,
83 playlistAttrs: {
84 displayName: 'playlist', 81 displayName: 'playlist',
85 privacy: VideoPlaylistPrivacy.PUBLIC, 82 privacy: VideoPlaylistPrivacy.PUBLIC,
86 videoChannelId: server.videoChannel.id, 83 videoChannelId: server.videoChannel.id,
diff --git a/server/tests/client.ts b/server/tests/client.ts
index 60df878d7..129f1e1c0 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -6,9 +6,7 @@ import { omit } from 'lodash'
6import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' 6import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
7import { Account, HTMLServerConfig, ServerConfig, VideoPlaylistCreateResult, VideoPlaylistPrivacy } from '@shared/models' 7import { Account, HTMLServerConfig, ServerConfig, VideoPlaylistCreateResult, VideoPlaylistPrivacy } from '@shared/models'
8import { 8import {
9 addVideoInPlaylist,
10 cleanupTests, 9 cleanupTests,
11 createVideoPlaylist,
12 doubleFollow, 10 doubleFollow,
13 flushAndRunMultipleServers, 11 flushAndRunMultipleServers,
14 getVideosList, 12 getVideosList,
@@ -82,23 +80,17 @@ describe('Test a client controllers', function () {
82 80
83 // Playlist 81 // Playlist
84 82
85 const playlistAttrs = { 83 const attributes = {
86 displayName: playlistName, 84 displayName: playlistName,
87 description: playlistDescription, 85 description: playlistDescription,
88 privacy: VideoPlaylistPrivacy.PUBLIC, 86 privacy: VideoPlaylistPrivacy.PUBLIC,
89 videoChannelId: servers[0].videoChannel.id 87 videoChannelId: servers[0].videoChannel.id
90 } 88 }
91 89
92 const resVideoPlaylistRequest = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs }) 90 playlist = await servers[0].playlistsCommand.create({ attributes })
93 playlist = resVideoPlaylistRequest.body.videoPlaylist
94 playlistIds = [ playlist.id, playlist.shortUUID, playlist.uuid ] 91 playlistIds = [ playlist.id, playlist.shortUUID, playlist.uuid ]
95 92
96 await addVideoInPlaylist({ 93 await servers[0].playlistsCommand.addElement({ playlistId: playlist.shortUUID, attributes: { videoId: video.id } })
97 url: servers[0].url,
98 token: servers[0].accessToken,
99 playlistId: playlist.shortUUID,
100 elementAttrs: { videoId: video.id }
101 })
102 94
103 // Account 95 // Account
104 96
diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts
index 5e9dc3515..fd83bf2ac 100644
--- a/server/tests/plugins/action-hooks.ts
+++ b/server/tests/plugins/action-hooks.ts
@@ -5,10 +5,8 @@ import { ServerHookName, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/mode
5import { 5import {
6 addVideoCommentReply, 6 addVideoCommentReply,
7 addVideoCommentThread, 7 addVideoCommentThread,
8 addVideoInPlaylist,
9 blockUser, 8 blockUser,
10 createUser, 9 createUser,
11 createVideoPlaylist,
12 deleteVideoComment, 10 deleteVideoComment,
13 PluginsCommand, 11 PluginsCommand,
14 registerUser, 12 registerUser,
@@ -180,15 +178,13 @@ describe('Test plugin action hooks', function () {
180 178
181 before(async function () { 179 before(async function () {
182 { 180 {
183 const res = await createVideoPlaylist({ 181 const { id } = await servers[0].playlistsCommand.create({
184 url: servers[0].url, 182 attributes: {
185 token: servers[0].accessToken,
186 playlistAttrs: {
187 displayName: 'My playlist', 183 displayName: 'My playlist',
188 privacy: VideoPlaylistPrivacy.PRIVATE 184 privacy: VideoPlaylistPrivacy.PRIVATE
189 } 185 }
190 }) 186 })
191 playlistId = res.body.videoPlaylist.id 187 playlistId = id
192 } 188 }
193 189
194 { 190 {
@@ -198,12 +194,7 @@ describe('Test plugin action hooks', function () {
198 }) 194 })
199 195
200 it('Should run action:api.video-playlist-element.created', async function () { 196 it('Should run action:api.video-playlist-element.created', async function () {
201 await addVideoInPlaylist({ 197 await servers[0].playlistsCommand.addElement({ playlistId, attributes: { videoId } })
202 url: servers[0].url,
203 token: servers[0].accessToken,
204 playlistId,
205 elementAttrs: { videoId }
206 })
207 198
208 await checkHook('action:api.video-playlist-element.created') 199 await checkHook('action:api.video-playlist-element.created')
209 }) 200 })
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index e938663da..203642d8d 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -7,7 +7,6 @@ import {
7 addVideoCommentReply, 7 addVideoCommentReply,
8 addVideoCommentThread, 8 addVideoCommentThread,
9 cleanupTests, 9 cleanupTests,
10 createVideoPlaylist,
11 doubleFollow, 10 doubleFollow,
12 flushAndRunMultipleServers, 11 flushAndRunMultipleServers,
13 getAccountVideos, 12 getAccountVideos,
@@ -15,7 +14,6 @@ import {
15 getVideo, 14 getVideo,
16 getVideoChannelVideos, 15 getVideoChannelVideos,
17 getVideoCommentThreads, 16 getVideoCommentThreads,
18 getVideoPlaylist,
19 getVideosList, 17 getVideosList,
20 getVideosListPagination, 18 getVideosListPagination,
21 getVideoThreadComments, 19 getVideoThreadComments,
@@ -443,11 +441,11 @@ describe('Test plugin filter hooks', function () {
443 } 441 }
444 442
445 { 443 {
446 const playlistAttrs = { displayName: name, videoChannelId: servers[0].videoChannel.id, privacy: VideoPlaylistPrivacy.PUBLIC } 444 const attributes = { displayName: name, videoChannelId: servers[0].videoChannel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
447 const res = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs }) 445 const { id } = await servers[0].playlistsCommand.create({ attributes })
448 446
449 const resPlaylist = await getVideoPlaylist(servers[0].url, res.body.videoPlaylist.id) 447 const playlist = await servers[0].playlistsCommand.get({ playlistId: id })
450 embedPlaylists.push(resPlaylist.body) 448 embedPlaylists.push(playlist)
451 } 449 }
452 } 450 }
453 }) 451 })
diff --git a/server/tests/plugins/video-constants.ts b/server/tests/plugins/video-constants.ts
index 4124e8a52..4a05af042 100644
--- a/server/tests/plugins/video-constants.ts
+++ b/server/tests/plugins/video-constants.ts
@@ -5,13 +5,11 @@ import * as chai from 'chai'
5import { HttpStatusCode } from '@shared/core-utils' 5import { HttpStatusCode } from '@shared/core-utils'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
8 createVideoPlaylist,
9 flushAndRunServer, 8 flushAndRunServer,
10 getVideo, 9 getVideo,
11 getVideoCategories, 10 getVideoCategories,
12 getVideoLanguages, 11 getVideoLanguages,
13 getVideoLicences, 12 getVideoLicences,
14 getVideoPlaylistPrivacies,
15 getVideoPrivacies, 13 getVideoPrivacies,
16 PluginsCommand, 14 PluginsCommand,
17 ServerInfo, 15 ServerInfo,
@@ -79,8 +77,7 @@ describe('Test plugin altering video constants', function () {
79 }) 77 })
80 78
81 it('Should have updated playlist privacies', async function () { 79 it('Should have updated playlist privacies', async function () {
82 const res = await getVideoPlaylistPrivacies(server.url) 80 const playlistPrivacies = await server.playlistsCommand.getPrivacies()
83 const playlistPrivacies = res.body
84 81
85 expect(playlistPrivacies[1]).to.exist 82 expect(playlistPrivacies[1]).to.exist
86 expect(playlistPrivacies[2]).to.exist 83 expect(playlistPrivacies[2]).to.exist
@@ -93,13 +90,8 @@ describe('Test plugin altering video constants', function () {
93 }) 90 })
94 91
95 it('Should not be able to create a video with this privacy', async function () { 92 it('Should not be able to create a video with this privacy', async function () {
96 const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE } 93 const attributes = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
97 await createVideoPlaylist({ 94 await server.playlistsCommand.create({ attributes, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
98 url: server.url,
99 token: server.accessToken,
100 playlistAttrs: attrs,
101 expectedStatus: HttpStatusCode.BAD_REQUEST_400
102 })
103 }) 95 })
104 96
105 it('Should be able to upload a video with these values', async function () { 97 it('Should be able to upload a video with these values', async function () {
@@ -162,8 +154,7 @@ describe('Test plugin altering video constants', function () {
162 } 154 }
163 155
164 { 156 {
165 const res = await getVideoPlaylistPrivacies(server.url) 157 const playlistPrivacies = await server.playlistsCommand.getPrivacies()
166 const playlistPrivacies = res.body
167 158
168 expect(playlistPrivacies[1]).to.exist 159 expect(playlistPrivacies[1]).to.exist
169 expect(playlistPrivacies[2]).to.exist 160 expect(playlistPrivacies[2]).to.exist
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index 33f558414..78b3be9c7 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -18,7 +18,7 @@ import { makeGetRequest } from '../requests/requests'
18import { SearchCommand } from '../search' 18import { SearchCommand } from '../search'
19import { SocketIOCommand } from '../socket' 19import { SocketIOCommand } from '../socket'
20import { AccountsCommand, BlocklistCommand, SubscriptionsCommand } from '../users' 20import { AccountsCommand, BlocklistCommand, SubscriptionsCommand } from '../users'
21import { BlacklistCommand, CaptionsCommand, ChangeOwnershipCommand, LiveCommand, ServicesCommand } from '../videos' 21import { BlacklistCommand, CaptionsCommand, ChangeOwnershipCommand, LiveCommand, PlaylistsCommand, ServicesCommand } from '../videos'
22import { ConfigCommand } from './config-command' 22import { ConfigCommand } from './config-command'
23import { ContactFormCommand } from './contact-form-command' 23import { ContactFormCommand } from './contact-form-command'
24import { DebugCommand } from './debug-command' 24import { DebugCommand } from './debug-command'
@@ -105,6 +105,7 @@ interface ServerInfo {
105 blacklistCommand?: BlacklistCommand 105 blacklistCommand?: BlacklistCommand
106 captionsCommand?: CaptionsCommand 106 captionsCommand?: CaptionsCommand
107 changeOwnershipCommand?: ChangeOwnershipCommand 107 changeOwnershipCommand?: ChangeOwnershipCommand
108 playlistsCommand?: PlaylistsCommand
108} 109}
109 110
110function parallelTests () { 111function parallelTests () {
@@ -335,6 +336,7 @@ async function runServer (server: ServerInfo, configOverrideArg?: any, args = []
335 server.blacklistCommand = new BlacklistCommand(server) 336 server.blacklistCommand = new BlacklistCommand(server)
336 server.captionsCommand = new CaptionsCommand(server) 337 server.captionsCommand = new CaptionsCommand(server)
337 server.changeOwnershipCommand = new ChangeOwnershipCommand(server) 338 server.changeOwnershipCommand = new ChangeOwnershipCommand(server)
339 server.playlistsCommand = new PlaylistsCommand(server)
338 340
339 res(server) 341 res(server)
340 }) 342 })
diff --git a/shared/extra-utils/videos/index.ts b/shared/extra-utils/videos/index.ts
index 815c7f944..1f6241d7e 100644
--- a/shared/extra-utils/videos/index.ts
+++ b/shared/extra-utils/videos/index.ts
@@ -4,11 +4,12 @@ export * from './captions-command'
4export * from './change-ownership-command' 4export * from './change-ownership-command'
5export * from './live-command' 5export * from './live-command'
6export * from './live' 6export * from './live'
7export * from './playlists-command'
8export * from './playlists'
7export * from './services-command' 9export * from './services-command'
8export * from './video-channels' 10export * from './video-channels'
9export * from './video-comments' 11export * from './video-comments'
10export * from './video-history' 12export * from './video-history'
11export * from './video-imports' 13export * from './video-imports'
12export * from './video-playlists'
13export * from './video-streaming-playlists' 14export * from './video-streaming-playlists'
14export * from './videos' 15export * from './videos'
diff --git a/shared/extra-utils/videos/playlists-command.ts b/shared/extra-utils/videos/playlists-command.ts
new file mode 100644
index 000000000..f77decc1a
--- /dev/null
+++ b/shared/extra-utils/videos/playlists-command.ts
@@ -0,0 +1,280 @@
1import { omit, pick } from 'lodash'
2import {
3 BooleanBothQuery,
4 ResultList,
5 VideoExistInPlaylist,
6 VideoPlaylist,
7 VideoPlaylistCreateResult,
8 VideoPlaylistElement,
9 VideoPlaylistElementCreateResult,
10 VideoPlaylistReorder
11} from '@shared/models'
12import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
13import { VideoPlaylistCreate } from '../../models/videos/playlist/video-playlist-create.model'
14import { VideoPlaylistElementCreate } from '../../models/videos/playlist/video-playlist-element-create.model'
15import { VideoPlaylistElementUpdate } from '../../models/videos/playlist/video-playlist-element-update.model'
16import { VideoPlaylistType } from '../../models/videos/playlist/video-playlist-type.model'
17import { VideoPlaylistUpdate } from '../../models/videos/playlist/video-playlist-update.model'
18import { unwrapBody } from '../requests'
19import { AbstractCommand, OverrideCommandOptions } from '../shared'
20import { videoUUIDToId } from './videos'
21
22export class PlaylistsCommand extends AbstractCommand {
23
24 list (options: OverrideCommandOptions & {
25 start?: number
26 count?: number
27 sort?: string
28 }) {
29 const path = '/api/v1/video-playlists'
30 const query = pick(options, [ 'start', 'count', 'sort' ])
31
32 return this.getRequestBody<ResultList<VideoPlaylist>>({
33 ...options,
34
35 path,
36 query,
37 implicitToken: false,
38 defaultExpectedStatus: HttpStatusCode.OK_200
39 })
40 }
41
42 listByChannel (options: OverrideCommandOptions & {
43 handle: string
44 start?: number
45 count?: number
46 sort?: string
47 }) {
48 const path = '/api/v1/video-channels/' + options.handle + '/video-playlists'
49 const query = pick(options, [ 'start', 'count', 'sort' ])
50
51 return this.getRequestBody<ResultList<VideoPlaylist>>({
52 ...options,
53
54 path,
55 query,
56 implicitToken: false,
57 defaultExpectedStatus: HttpStatusCode.OK_200
58 })
59 }
60
61 listByAccount (options: OverrideCommandOptions & {
62 handle: string
63 start?: number
64 count?: number
65 sort?: string
66 search?: string
67 playlistType?: VideoPlaylistType
68 }) {
69 const path = '/api/v1/accounts/' + options.handle + '/video-playlists'
70 const query = pick(options, [ 'start', 'count', 'sort', 'search', 'playlistType' ])
71
72 return this.getRequestBody<ResultList<VideoPlaylist>>({
73 ...options,
74
75 path,
76 query,
77 implicitToken: false,
78 defaultExpectedStatus: HttpStatusCode.OK_200
79 })
80 }
81
82 get (options: OverrideCommandOptions & {
83 playlistId: number | string
84 }) {
85 const { playlistId } = options
86 const path = '/api/v1/video-playlists/' + playlistId
87
88 return this.getRequestBody<VideoPlaylist>({
89 ...options,
90
91 path,
92 implicitToken: false,
93 defaultExpectedStatus: HttpStatusCode.OK_200
94 })
95 }
96
97 listVideos (options: OverrideCommandOptions & {
98 playlistId: number | string
99 start?: number
100 count?: number
101 query?: { nsfw?: BooleanBothQuery }
102 }) {
103 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
104 const query = options.query ?? {}
105
106 return this.getRequestBody<ResultList<VideoPlaylistElement>>({
107 ...options,
108
109 path,
110 query: {
111 ...query,
112 start: options.start,
113 count: options.count
114 },
115 implicitToken: true,
116 defaultExpectedStatus: HttpStatusCode.OK_200
117 })
118 }
119
120 delete (options: OverrideCommandOptions & {
121 playlistId: number | string
122 }) {
123 const path = '/api/v1/video-playlists/' + options.playlistId
124
125 return this.deleteRequest({
126 ...options,
127
128 path,
129 implicitToken: true,
130 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
131 })
132 }
133
134 async create (options: OverrideCommandOptions & {
135 attributes: VideoPlaylistCreate
136 }) {
137 const path = '/api/v1/video-playlists'
138
139 const fields = omit(options.attributes, 'thumbnailfile')
140
141 const attaches = options.attributes.thumbnailfile
142 ? { thumbnailfile: options.attributes.thumbnailfile }
143 : {}
144
145 const body = await unwrapBody<{ videoPlaylist: VideoPlaylistCreateResult }>(this.postUploadRequest({
146 ...options,
147
148 path,
149 fields,
150 attaches,
151 implicitToken: true,
152 defaultExpectedStatus: HttpStatusCode.OK_200
153 }))
154
155 return body.videoPlaylist
156 }
157
158 update (options: OverrideCommandOptions & {
159 attributes: VideoPlaylistUpdate
160 playlistId: number | string
161 }) {
162 const path = '/api/v1/video-playlists/' + options.playlistId
163
164 const fields = omit(options.attributes, 'thumbnailfile')
165
166 const attaches = options.attributes.thumbnailfile
167 ? { thumbnailfile: options.attributes.thumbnailfile }
168 : {}
169
170 return this.putUploadRequest({
171 ...options,
172
173 path,
174 fields,
175 attaches,
176 implicitToken: true,
177 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
178 })
179 }
180
181 async addElement (options: OverrideCommandOptions & {
182 playlistId: number | string
183 attributes: VideoPlaylistElementCreate | { videoId: string }
184 }) {
185 const attributes = {
186 ...options.attributes,
187
188 videoId: await videoUUIDToId(this.server.url, options.attributes.videoId)
189 }
190
191 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
192
193 const body = await unwrapBody<{ videoPlaylistElement: VideoPlaylistElementCreateResult }>(this.postBodyRequest({
194 ...options,
195
196 path,
197 fields: attributes,
198 implicitToken: true,
199 defaultExpectedStatus: HttpStatusCode.OK_200
200 }))
201
202 return body.videoPlaylistElement
203 }
204
205 updateElement (options: OverrideCommandOptions & {
206 playlistId: number | string
207 elementId: number | string
208 attributes: VideoPlaylistElementUpdate
209 }) {
210 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.elementId
211
212 return this.putBodyRequest({
213 ...options,
214
215 path,
216 fields: options.attributes,
217 implicitToken: true,
218 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
219 })
220 }
221
222 removeElement (options: OverrideCommandOptions & {
223 playlistId: number | string
224 elementId: number
225 }) {
226 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.elementId
227
228 return this.deleteRequest({
229 ...options,
230
231 path,
232 implicitToken: true,
233 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
234 })
235 }
236
237 reorderElements (options: OverrideCommandOptions & {
238 playlistId: number | string
239 attributes: VideoPlaylistReorder
240 }) {
241 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/reorder'
242
243 return this.postBodyRequest({
244 ...options,
245
246 path,
247 fields: options.attributes,
248 implicitToken: true,
249 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
250 })
251 }
252
253 getPrivacies (options: OverrideCommandOptions = {}) {
254 const path = '/api/v1/video-playlists/privacies'
255
256 return this.getRequestBody<{ [ id: number ]: string }>({
257 ...options,
258
259 path,
260 implicitToken: false,
261 defaultExpectedStatus: HttpStatusCode.OK_200
262 })
263 }
264
265 videosExist (options: OverrideCommandOptions & {
266 videoIds: number[]
267 }) {
268 const { videoIds } = options
269 const path = '/api/v1/users/me/video-playlists/videos-exist'
270
271 return this.getRequestBody<VideoExistInPlaylist>({
272 ...options,
273
274 path,
275 query: { videoIds },
276 implicitToken: true,
277 defaultExpectedStatus: HttpStatusCode.OK_200
278 })
279 }
280}
diff --git a/shared/extra-utils/videos/playlists.ts b/shared/extra-utils/videos/playlists.ts
new file mode 100644
index 000000000..023333c87
--- /dev/null
+++ b/shared/extra-utils/videos/playlists.ts
@@ -0,0 +1,25 @@
1import { expect } from 'chai'
2import { readdir } from 'fs-extra'
3import { join } from 'path'
4import { root } from '../'
5
6async function checkPlaylistFilesWereRemoved (
7 playlistUUID: string,
8 internalServerNumber: number,
9 directories = [ 'thumbnails' ]
10) {
11 const testDirectory = 'test' + internalServerNumber
12
13 for (const directory of directories) {
14 const directoryPath = join(root(), testDirectory, directory)
15
16 const files = await readdir(directoryPath)
17 for (const file of files) {
18 expect(file).to.not.contain(playlistUUID)
19 }
20 }
21}
22
23export {
24 checkPlaylistFilesWereRemoved
25}
diff --git a/shared/extra-utils/videos/video-playlists.ts b/shared/extra-utils/videos/video-playlists.ts
deleted file mode 100644
index c6f799e5d..000000000
--- a/shared/extra-utils/videos/video-playlists.ts
+++ /dev/null
@@ -1,320 +0,0 @@
1import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests'
2import { VideoPlaylistCreate } from '../../models/videos/playlist/video-playlist-create.model'
3import { omit } from 'lodash'
4import { VideoPlaylistUpdate } from '../../models/videos/playlist/video-playlist-update.model'
5import { VideoPlaylistElementCreate } from '../../models/videos/playlist/video-playlist-element-create.model'
6import { VideoPlaylistElementUpdate } from '../../models/videos/playlist/video-playlist-element-update.model'
7import { videoUUIDToId } from './videos'
8import { join } from 'path'
9import { root } from '..'
10import { readdir } from 'fs-extra'
11import { expect } from 'chai'
12import { VideoPlaylistType } from '../../models/videos/playlist/video-playlist-type.model'
13import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
14
15function getVideoPlaylistsList (url: string, start: number, count: number, sort?: string) {
16 const path = '/api/v1/video-playlists'
17
18 const query = {
19 start,
20 count,
21 sort
22 }
23
24 return makeGetRequest({
25 url,
26 path,
27 query,
28 statusCodeExpected: HttpStatusCode.OK_200
29 })
30}
31
32function getVideoChannelPlaylistsList (url: string, videoChannelName: string, start: number, count: number, sort?: string) {
33 const path = '/api/v1/video-channels/' + videoChannelName + '/video-playlists'
34
35 const query = {
36 start,
37 count,
38 sort
39 }
40
41 return makeGetRequest({
42 url,
43 path,
44 query,
45 statusCodeExpected: HttpStatusCode.OK_200
46 })
47}
48
49function getAccountPlaylistsList (url: string, accountName: string, start: number, count: number, sort?: string, search?: string) {
50 const path = '/api/v1/accounts/' + accountName + '/video-playlists'
51
52 const query = {
53 start,
54 count,
55 sort,
56 search
57 }
58
59 return makeGetRequest({
60 url,
61 path,
62 query,
63 statusCodeExpected: HttpStatusCode.OK_200
64 })
65}
66
67function getAccountPlaylistsListWithToken (
68 url: string,
69 token: string,
70 accountName: string,
71 start: number,
72 count: number,
73 playlistType?: VideoPlaylistType,
74 sort?: string
75) {
76 const path = '/api/v1/accounts/' + accountName + '/video-playlists'
77
78 const query = {
79 start,
80 count,
81 playlistType,
82 sort
83 }
84
85 return makeGetRequest({
86 url,
87 token,
88 path,
89 query,
90 statusCodeExpected: HttpStatusCode.OK_200
91 })
92}
93
94function getVideoPlaylist (url: string, playlistId: number | string, statusCodeExpected = HttpStatusCode.OK_200) {
95 const path = '/api/v1/video-playlists/' + playlistId
96
97 return makeGetRequest({
98 url,
99 path,
100 statusCodeExpected
101 })
102}
103
104function getVideoPlaylistWithToken (url: string, token: string, playlistId: number | string, statusCodeExpected = HttpStatusCode.OK_200) {
105 const path = '/api/v1/video-playlists/' + playlistId
106
107 return makeGetRequest({
108 url,
109 token,
110 path,
111 statusCodeExpected
112 })
113}
114
115function deleteVideoPlaylist (url: string, token: string, playlistId: number | string, statusCodeExpected = HttpStatusCode.NO_CONTENT_204) {
116 const path = '/api/v1/video-playlists/' + playlistId
117
118 return makeDeleteRequest({
119 url,
120 path,
121 token,
122 statusCodeExpected
123 })
124}
125
126function createVideoPlaylist (options: {
127 url: string
128 token: string
129 playlistAttrs: VideoPlaylistCreate
130 expectedStatus?: number
131}) {
132 const path = '/api/v1/video-playlists'
133
134 const fields = omit(options.playlistAttrs, 'thumbnailfile')
135
136 const attaches = options.playlistAttrs.thumbnailfile
137 ? { thumbnailfile: options.playlistAttrs.thumbnailfile }
138 : {}
139
140 return makeUploadRequest({
141 method: 'POST',
142 url: options.url,
143 path,
144 token: options.token,
145 fields,
146 attaches,
147 statusCodeExpected: options.expectedStatus || HttpStatusCode.OK_200
148 })
149}
150
151function updateVideoPlaylist (options: {
152 url: string
153 token: string
154 playlistAttrs: VideoPlaylistUpdate
155 playlistId: number | string
156 expectedStatus?: number
157}) {
158 const path = '/api/v1/video-playlists/' + options.playlistId
159
160 const fields = omit(options.playlistAttrs, 'thumbnailfile')
161
162 const attaches = options.playlistAttrs.thumbnailfile
163 ? { thumbnailfile: options.playlistAttrs.thumbnailfile }
164 : {}
165
166 return makeUploadRequest({
167 method: 'PUT',
168 url: options.url,
169 path,
170 token: options.token,
171 fields,
172 attaches,
173 statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
174 })
175}
176
177async function addVideoInPlaylist (options: {
178 url: string
179 token: string
180 playlistId: number | string
181 elementAttrs: VideoPlaylistElementCreate | { videoId: string }
182 expectedStatus?: number
183}) {
184 options.elementAttrs.videoId = await videoUUIDToId(options.url, options.elementAttrs.videoId)
185
186 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
187
188 return makePostBodyRequest({
189 url: options.url,
190 path,
191 token: options.token,
192 fields: options.elementAttrs,
193 statusCodeExpected: options.expectedStatus || HttpStatusCode.OK_200
194 })
195}
196
197function updateVideoPlaylistElement (options: {
198 url: string
199 token: string
200 playlistId: number | string
201 playlistElementId: number | string
202 elementAttrs: VideoPlaylistElementUpdate
203 expectedStatus?: number
204}) {
205 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.playlistElementId
206
207 return makePutBodyRequest({
208 url: options.url,
209 path,
210 token: options.token,
211 fields: options.elementAttrs,
212 statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
213 })
214}
215
216function removeVideoFromPlaylist (options: {
217 url: string
218 token: string
219 playlistId: number | string
220 playlistElementId: number
221 expectedStatus?: number
222}) {
223 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.playlistElementId
224
225 return makeDeleteRequest({
226 url: options.url,
227 path,
228 token: options.token,
229 statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
230 })
231}
232
233function reorderVideosPlaylist (options: {
234 url: string
235 token: string
236 playlistId: number | string
237 elementAttrs: {
238 startPosition: number
239 insertAfterPosition: number
240 reorderLength?: number
241 }
242 expectedStatus?: number
243}) {
244 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/reorder'
245
246 return makePostBodyRequest({
247 url: options.url,
248 path,
249 token: options.token,
250 fields: options.elementAttrs,
251 statusCodeExpected: options.expectedStatus || HttpStatusCode.NO_CONTENT_204
252 })
253}
254
255async function checkPlaylistFilesWereRemoved (
256 playlistUUID: string,
257 internalServerNumber: number,
258 directories = [ 'thumbnails' ]
259) {
260 const testDirectory = 'test' + internalServerNumber
261
262 for (const directory of directories) {
263 const directoryPath = join(root(), testDirectory, directory)
264
265 const files = await readdir(directoryPath)
266 for (const file of files) {
267 expect(file).to.not.contain(playlistUUID)
268 }
269 }
270}
271
272function getVideoPlaylistPrivacies (url: string) {
273 const path = '/api/v1/video-playlists/privacies'
274
275 return makeGetRequest({
276 url,
277 path,
278 statusCodeExpected: HttpStatusCode.OK_200
279 })
280}
281
282function doVideosExistInMyPlaylist (url: string, token: string, videoIds: number[]) {
283 const path = '/api/v1/users/me/video-playlists/videos-exist'
284
285 return makeGetRequest({
286 url,
287 token,
288 path,
289 query: { videoIds },
290 statusCodeExpected: HttpStatusCode.OK_200
291 })
292}
293
294// ---------------------------------------------------------------------------
295
296export {
297 getVideoPlaylistPrivacies,
298
299 getVideoPlaylistsList,
300 getVideoChannelPlaylistsList,
301 getAccountPlaylistsList,
302 getAccountPlaylistsListWithToken,
303
304 getVideoPlaylist,
305 getVideoPlaylistWithToken,
306
307 createVideoPlaylist,
308 updateVideoPlaylist,
309 deleteVideoPlaylist,
310
311 addVideoInPlaylist,
312 updateVideoPlaylistElement,
313 removeVideoFromPlaylist,
314
315 reorderVideosPlaylist,
316
317 checkPlaylistFilesWereRemoved,
318
319 doVideosExistInMyPlaylist
320}
diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts
index a45c0402a..920c93072 100644
--- a/shared/extra-utils/videos/videos.ts
+++ b/shared/extra-utils/videos/videos.ts
@@ -262,28 +262,6 @@ function getVideoChannelVideos (
262 }) 262 })
263} 263}
264 264
265function getPlaylistVideos (
266 url: string,
267 accessToken: string,
268 playlistId: number | string,
269 start: number,
270 count: number,
271 query: { nsfw?: boolean } = {}
272) {
273 const path = '/api/v1/video-playlists/' + playlistId + '/videos'
274
275 return makeGetRequest({
276 url,
277 path,
278 query: immutableAssign(query, {
279 start,
280 count
281 }),
282 token: accessToken,
283 statusCodeExpected: HttpStatusCode.OK_200
284 })
285}
286
287function getVideosListPagination (url: string, start: number, count: number, sort?: string, skipCount?: boolean) { 265function getVideosListPagination (url: string, start: number, count: number, sort?: string, skipCount?: boolean) {
288 const path = '/api/v1/videos' 266 const path = '/api/v1/videos'
289 267
@@ -871,7 +849,6 @@ export {
871 getLocalVideos, 849 getLocalVideos,
872 completeVideoCheck, 850 completeVideoCheck,
873 checkVideoFilesWereRemoved, 851 checkVideoFilesWereRemoved,
874 getPlaylistVideos,
875 getMyVideosWithFilter, 852 getMyVideosWithFilter,
876 uploadVideoAndGetId, 853 uploadVideoAndGetId,
877 getLocalIdByUUID, 854 getLocalIdByUUID,
diff --git a/shared/models/videos/playlist/index.ts b/shared/models/videos/playlist/index.ts
index f11a4bd28..a9e8ce496 100644
--- a/shared/models/videos/playlist/index.ts
+++ b/shared/models/videos/playlist/index.ts
@@ -1,6 +1,7 @@
1export * from './video-exist-in-playlist.model' 1export * from './video-exist-in-playlist.model'
2export * from './video-playlist-create-result.model' 2export * from './video-playlist-create-result.model'
3export * from './video-playlist-create.model' 3export * from './video-playlist-create.model'
4export * from './video-playlist-element-create-result.model'
4export * from './video-playlist-element-create.model' 5export * from './video-playlist-element-create.model'
5export * from './video-playlist-element-update.model' 6export * from './video-playlist-element-update.model'
6export * from './video-playlist-element.model' 7export * from './video-playlist-element.model'
diff --git a/shared/models/videos/playlist/video-playlist-element-create-result.model.ts b/shared/models/videos/playlist/video-playlist-element-create-result.model.ts
new file mode 100644
index 000000000..dc475e7d8
--- /dev/null
+++ b/shared/models/videos/playlist/video-playlist-element-create-result.model.ts
@@ -0,0 +1,3 @@
1export interface VideoPlaylistElementCreateResult {
2 id: number
3}