1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { HttpStatusCode, VideoDetails, VideoImportState, VideoPlaylist, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
13 setAccessTokensToServers,
14 setDefaultVideoChannel,
16 } from '@shared/server-commands'
17 import { FIXTURE_URLS } from '../shared'
19 const expect = chai.expect
21 describe('Test plugin filter hooks', function () {
22 let servers: PeerTubeServer[]
25 let videoPlaylistUUID: string
27 before(async function () {
30 servers = await createMultipleServers(2)
31 await setAccessTokensToServers(servers)
32 await setDefaultVideoChannel(servers)
33 await doubleFollow(servers[0], servers[1])
35 await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
36 await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
38 ({ uuid: videoPlaylistUUID } = await servers[0].playlists.create({
40 displayName: 'my super playlist',
41 privacy: VideoPlaylistPrivacy.PUBLIC,
42 description: 'my super description',
43 videoChannelId: servers[0].store.channel.id
48 for (let i = 0; i < 10; i++) {
49 const video = await servers[0].videos.upload({ attributes: { name: 'default video ' + i } })
50 await servers[0].playlists.addElement({ playlistId: videoPlaylistUUID, attributes: { videoId: video.id } })
53 const { data } = await servers[0].videos.list()
54 videoUUID = data[0].uuid
56 await servers[0].config.updateCustomSubConfig({
58 live: { enabled: true },
59 signup: { enabled: true },
62 http: { enabled: true },
63 torrent: { enabled: true }
70 it('Should run filter:api.videos.list.params', async function () {
71 const { data } = await servers[0].videos.list({ start: 0, count: 2 })
73 // 2 plugins do +1 to the count parameter
74 expect(data).to.have.lengthOf(4)
77 it('Should run filter:api.videos.list.result', async function () {
78 const { total } = await servers[0].videos.list({ start: 0, count: 0 })
80 // Plugin do +1 to the total result
81 expect(total).to.equal(11)
84 it('Should run filter:api.video-playlist.videos.list.params', async function () {
85 const { data } = await servers[0].playlists.listVideos({
87 playlistId: videoPlaylistUUID
90 // 1 plugin do +1 to the count parameter
91 expect(data).to.have.lengthOf(3)
94 it('Should run filter:api.video-playlist.videos.list.result', async function () {
95 const { total } = await servers[0].playlists.listVideos({
97 playlistId: videoPlaylistUUID
100 // Plugin do +1 to the total result
101 expect(total).to.equal(11)
104 it('Should run filter:api.accounts.videos.list.params', async function () {
105 const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
107 // 1 plugin do +1 to the count parameter
108 expect(data).to.have.lengthOf(3)
111 it('Should run filter:api.accounts.videos.list.result', async function () {
112 const { total } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
114 // Plugin do +2 to the total result
115 expect(total).to.equal(12)
118 it('Should run filter:api.video-channels.videos.list.params', async function () {
119 const { data } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
121 // 1 plugin do +3 to the count parameter
122 expect(data).to.have.lengthOf(5)
125 it('Should run filter:api.video-channels.videos.list.result', async function () {
126 const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
128 // Plugin do +3 to the total result
129 expect(total).to.equal(13)
132 it('Should run filter:api.user.me.videos.list.params', async function () {
133 const { data } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
135 // 1 plugin do +4 to the count parameter
136 expect(data).to.have.lengthOf(6)
139 it('Should run filter:api.user.me.videos.list.result', async function () {
140 const { total } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
142 // Plugin do +4 to the total result
143 expect(total).to.equal(14)
146 it('Should run filter:api.video.get.result', async function () {
147 const video = await servers[0].videos.get({ id: videoUUID })
148 expect(video.name).to.contain('<3')
151 it('Should run filter:api.video.upload.accept.result', async function () {
152 await servers[0].videos.upload({ attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
155 it('Should run filter:api.live-video.create.accept.result', async function () {
157 name: 'video with bad word',
158 privacy: VideoPrivacy.PUBLIC,
159 channelId: servers[0].store.channel.id
162 await servers[0].live.create({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
165 it('Should run filter:api.video.pre-import-url.accept.result', async function () {
167 name: 'normal title',
168 privacy: VideoPrivacy.PUBLIC,
169 channelId: servers[0].store.channel.id,
170 targetUrl: FIXTURE_URLS.goodVideo + 'bad'
172 await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
175 it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
178 privacy: VideoPrivacy.PUBLIC,
179 channelId: servers[0].store.channel.id,
180 torrentfile: 'video-720p.torrent' as any
182 await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
185 it('Should run filter:api.video.post-import-url.accept.result', async function () {
188 let videoImportId: number
192 name: 'title with bad word',
193 privacy: VideoPrivacy.PUBLIC,
194 channelId: servers[0].store.channel.id,
195 targetUrl: FIXTURE_URLS.goodVideo
197 const body = await servers[0].imports.importVideo({ attributes })
198 videoImportId = body.id
201 await waitJobs(servers)
204 const body = await servers[0].imports.getMyVideoImports()
205 const videoImports = body.data
207 const videoImport = videoImports.find(i => i.id === videoImportId)
209 expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
210 expect(videoImport.state.label).to.equal('Rejected')
214 it('Should run filter:api.video.post-import-torrent.accept.result', async function () {
217 let videoImportId: number
221 name: 'title with bad word',
222 privacy: VideoPrivacy.PUBLIC,
223 channelId: servers[0].store.channel.id,
224 torrentfile: 'video-720p.torrent' as any
226 const body = await servers[0].imports.importVideo({ attributes })
227 videoImportId = body.id
230 await waitJobs(servers)
233 const { data: videoImports } = await servers[0].imports.getMyVideoImports()
235 const videoImport = videoImports.find(i => i.id === videoImportId)
237 expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
238 expect(videoImport.state.label).to.equal('Rejected')
242 it('Should run filter:api.video-thread.create.accept.result', async function () {
243 await servers[0].comments.createThread({
245 text: 'comment with bad word',
246 expectedStatus: HttpStatusCode.FORBIDDEN_403
250 it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
251 const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
252 threadId = created.id
254 await servers[0].comments.addReply({
256 toCommentId: threadId,
257 text: 'comment with bad word',
258 expectedStatus: HttpStatusCode.FORBIDDEN_403
260 await servers[0].comments.addReply({
262 toCommentId: threadId,
263 text: 'comment with good word',
264 expectedStatus: HttpStatusCode.OK_200
268 it('Should run filter:api.video-threads.list.params', async function () {
269 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
271 // our plugin do +1 to the count parameter
272 expect(data).to.have.lengthOf(1)
275 it('Should run filter:api.video-threads.list.result', async function () {
276 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
278 // Plugin do +1 to the total result
279 expect(total).to.equal(2)
282 it('Should run filter:api.video-thread-comments.list.params')
284 it('Should run filter:api.video-thread-comments.list.result', async function () {
285 const thread = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
287 expect(thread.comment.text.endsWith(' <3')).to.be.true
290 it('Should run filter:api.overviews.videos.list.{params,result}', async function () {
291 await servers[0].overviews.getVideos({ page: 1 })
293 // 3 because we get 3 samples per page
294 await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.params', 3)
295 await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.result', 3)
298 describe('Should run filter:video.auto-blacklist.result', function () {
300 async function checkIsBlacklisted (id: number | string, value: boolean) {
301 const video = await servers[0].videos.getWithToken({ id })
302 expect(video.blacklisted).to.equal(value)
305 it('Should blacklist on upload', async function () {
306 const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video please blacklist me' } })
307 await checkIsBlacklisted(uuid, true)
310 it('Should blacklist on import', async function () {
314 name: 'video please blacklist me',
315 targetUrl: FIXTURE_URLS.goodVideo,
316 channelId: servers[0].store.channel.id
318 const body = await servers[0].imports.importVideo({ attributes })
319 await checkIsBlacklisted(body.video.uuid, true)
322 it('Should blacklist on update', async function () {
323 const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' } })
324 await checkIsBlacklisted(uuid, false)
326 await servers[0].videos.update({ id: uuid, attributes: { name: 'please blacklist me' } })
327 await checkIsBlacklisted(uuid, true)
330 it('Should blacklist on remote upload', async function () {
333 const { uuid } = await servers[1].videos.upload({ attributes: { name: 'remote please blacklist me' } })
334 await waitJobs(servers)
336 await checkIsBlacklisted(uuid, true)
339 it('Should blacklist on remote update', async function () {
342 const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video' } })
343 await waitJobs(servers)
345 await checkIsBlacklisted(uuid, false)
347 await servers[1].videos.update({ id: uuid, attributes: { name: 'please blacklist me' } })
348 await waitJobs(servers)
350 await checkIsBlacklisted(uuid, true)
354 describe('Should run filter:api.user.signup.allowed.result', function () {
356 it('Should run on config endpoint', async function () {
357 const body = await servers[0].config.getConfig()
358 expect(body.signup.allowed).to.be.true
361 it('Should allow a signup', async function () {
362 await servers[0].users.register({ username: 'john', password: 'password' })
365 it('Should not allow a signup', async function () {
366 const res = await servers[0].users.register({
368 password: 'password',
369 expectedStatus: HttpStatusCode.FORBIDDEN_403
372 expect(res.body.error).to.equal('No jma')
376 describe('Download hooks', function () {
377 const downloadVideos: VideoDetails[] = []
379 before(async function () {
382 await servers[0].config.updateCustomSubConfig({
395 const uuids: string[] = []
397 for (const name of [ 'bad torrent', 'bad file', 'bad playlist file' ]) {
398 const uuid = (await servers[0].videos.quickUpload({ name: name })).uuid
402 await waitJobs(servers)
404 for (const uuid of uuids) {
405 downloadVideos.push(await servers[0].videos.get({ id: uuid }))
409 it('Should run filter:api.download.torrent.allowed.result', async function () {
410 const res = await makeRawRequest(downloadVideos[0].files[0].torrentDownloadUrl, 403)
411 expect(res.body.error).to.equal('Liu Bei')
413 await makeRawRequest(downloadVideos[1].files[0].torrentDownloadUrl, 200)
414 await makeRawRequest(downloadVideos[2].files[0].torrentDownloadUrl, 200)
417 it('Should run filter:api.download.video.allowed.result', async function () {
419 const res = await makeRawRequest(downloadVideos[1].files[0].fileDownloadUrl, 403)
420 expect(res.body.error).to.equal('Cao Cao')
422 await makeRawRequest(downloadVideos[0].files[0].fileDownloadUrl, 200)
423 await makeRawRequest(downloadVideos[2].files[0].fileDownloadUrl, 200)
427 const res = await makeRawRequest(downloadVideos[2].streamingPlaylists[0].files[0].fileDownloadUrl, 403)
428 expect(res.body.error).to.equal('Sun Jian')
430 await makeRawRequest(downloadVideos[2].files[0].fileDownloadUrl, 200)
432 await makeRawRequest(downloadVideos[0].streamingPlaylists[0].files[0].fileDownloadUrl, 200)
433 await makeRawRequest(downloadVideos[1].streamingPlaylists[0].files[0].fileDownloadUrl, 200)
438 describe('Embed filters', function () {
439 const embedVideos: VideoDetails[] = []
440 const embedPlaylists: VideoPlaylist[] = []
442 before(async function () {
445 await servers[0].config.disableTranscoding()
447 for (const name of [ 'bad embed', 'good embed' ]) {
449 const uuid = (await servers[0].videos.quickUpload({ name: name })).uuid
450 embedVideos.push(await servers[0].videos.get({ id: uuid }))
454 const attributes = { displayName: name, videoChannelId: servers[0].store.channel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
455 const { id } = await servers[0].playlists.create({ attributes })
457 const playlist = await servers[0].playlists.get({ playlistId: id })
458 embedPlaylists.push(playlist)
463 it('Should run filter:html.embed.video.allowed.result', async function () {
464 const res = await makeRawRequest(servers[0].url + embedVideos[0].embedPath, 200)
465 expect(res.text).to.equal('Lu Bu')
468 it('Should run filter:html.embed.video-playlist.allowed.result', async function () {
469 const res = await makeRawRequest(servers[0].url + embedPlaylists[0].embedPath, 200)
470 expect(res.text).to.equal('Diao Chan')
474 describe('Search filters', function () {
476 before(async function () {
477 await servers[0].config.updateCustomSubConfig({
482 isDefaultSearch: false,
483 disableLocalSearch: false
490 it('Should run filter:api.search.videos.local.list.{params,result}', async function () {
491 await servers[0].search.advancedVideoSearch({
497 await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.params', 1)
498 await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.result', 1)
501 it('Should run filter:api.search.videos.index.list.{params,result}', async function () {
502 await servers[0].search.advancedVideoSearch({
505 searchTarget: 'search-index'
509 await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.params', 1)
510 await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.result', 1)
511 await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.index.list.params', 1)
512 await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.index.list.result', 1)
515 it('Should run filter:api.search.video-channels.local.list.{params,result}', async function () {
516 await servers[0].search.advancedChannelSearch({
522 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.params', 1)
523 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.result', 1)
526 it('Should run filter:api.search.video-channels.index.list.{params,result}', async function () {
527 await servers[0].search.advancedChannelSearch({
530 searchTarget: 'search-index'
534 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.params', 1)
535 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.result', 1)
536 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.index.list.params', 1)
537 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.index.list.result', 1)
540 it('Should run filter:api.search.video-playlists.local.list.{params,result}', async function () {
541 await servers[0].search.advancedPlaylistSearch({
547 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.params', 1)
548 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.result', 1)
551 it('Should run filter:api.search.video-playlists.index.list.{params,result}', async function () {
552 await servers[0].search.advancedPlaylistSearch({
555 searchTarget: 'search-index'
559 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.params', 1)
560 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.result', 1)
561 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.index.list.params', 1)
562 await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.index.list.result', 1)
566 describe('Upload/import/live attributes filters', function () {
568 before(async function () {
569 await servers[0].config.enableLive({ transcoding: false, allowReplay: false })
570 await servers[0].config.enableImports()
571 await servers[0].config.disableTranscoding()
574 it('Should run filter:api.video.upload.video-attribute.result', async function () {
575 for (const mode of [ 'legacy' as 'legacy', 'resumable' as 'resumable' ]) {
576 const { id } = await servers[0].videos.upload({ attributes: { name: 'video', description: 'upload' }, mode })
578 const video = await servers[0].videos.get({ id })
579 expect(video.description).to.equal('upload - filter:api.video.upload.video-attribute.result')
583 it('Should run filter:api.video.import-url.video-attribute.result', async function () {
586 description: 'import url',
587 channelId: servers[0].store.channel.id,
588 targetUrl: FIXTURE_URLS.goodVideo,
589 privacy: VideoPrivacy.PUBLIC
591 const { video: { id } } = await servers[0].imports.importVideo({ attributes })
593 const video = await servers[0].videos.get({ id })
594 expect(video.description).to.equal('import url - filter:api.video.import-url.video-attribute.result')
597 it('Should run filter:api.video.import-torrent.video-attribute.result', async function () {
600 description: 'import torrent',
601 channelId: servers[0].store.channel.id,
602 magnetUri: FIXTURE_URLS.magnet,
603 privacy: VideoPrivacy.PUBLIC
605 const { video: { id } } = await servers[0].imports.importVideo({ attributes })
607 const video = await servers[0].videos.get({ id })
608 expect(video.description).to.equal('import torrent - filter:api.video.import-torrent.video-attribute.result')
611 it('Should run filter:api.video.live.video-attribute.result', async function () {
615 channelId: servers[0].store.channel.id,
616 privacy: VideoPrivacy.PUBLIC
618 const { id } = await servers[0].live.create({ fields })
620 const video = await servers[0].videos.get({ id })
621 expect(video.description).to.equal('live - filter:api.video.live.video-attribute.result')
625 describe('Stats filters', function () {
627 it('Should run filter:api.server.stats.get.result', async function () {
628 const data = await servers[0].stats.get()
630 expect((data as any).customStats).to.equal(14)
635 after(async function () {
636 await cleanupTests(servers)