Support refusing remote comments

This commit is contained in:
Chocobozzz 2022-09-23 11:38:18 +02:00
parent b569b2c607
commit b2a70e3ca2
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
6 changed files with 311 additions and 202 deletions

View File

@ -109,8 +109,10 @@ async function processCreateVideoComment (activity: ActivityCreate, byActor: MAc
let video: MVideoAccountLightBlacklistAllFiles let video: MVideoAccountLightBlacklistAllFiles
let created: boolean let created: boolean
let comment: MCommentOwnerVideo let comment: MCommentOwnerVideo
try { try {
const resolveThreadResult = await resolveThread({ url: commentObject.id, isVideo: false }) const resolveThreadResult = await resolveThread({ url: commentObject.id, isVideo: false })
if (!resolveThreadResult) return // Comment not accepted
video = resolveThreadResult.video video = resolveThreadResult.video
created = resolveThreadResult.commentCreated created = resolveThreadResult.commentCreated

View File

@ -4,7 +4,9 @@ import { logger } from '../../helpers/logger'
import { doJSONRequest } from '../../helpers/requests' import { doJSONRequest } from '../../helpers/requests'
import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
import { VideoCommentModel } from '../../models/video/video-comment' import { VideoCommentModel } from '../../models/video/video-comment'
import { MCommentOwner, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../types/models/video' import { MComment, MCommentOwner, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../types/models/video'
import { isRemoteVideoCommentAccepted } from '../moderation'
import { Hooks } from '../plugins/hooks'
import { getOrCreateAPActor } from './actors' import { getOrCreateAPActor } from './actors'
import { checkUrlsSameHost } from './url' import { checkUrlsSameHost } from './url'
import { getOrCreateAPVideo } from './videos' import { getOrCreateAPVideo } from './videos'
@ -103,6 +105,10 @@ async function tryToResolveThreadFromVideo (params: ResolveThreadParams) {
firstReply.changed('updatedAt', true) firstReply.changed('updatedAt', true)
firstReply.Video = video firstReply.Video = video
if (await isRemoteCommentAccepted(firstReply) !== true) {
return undefined
}
comments[comments.length - 1] = await firstReply.save() comments[comments.length - 1] = await firstReply.save()
for (let i = comments.length - 2; i >= 0; i--) { for (let i = comments.length - 2; i >= 0; i--) {
@ -113,6 +119,10 @@ async function tryToResolveThreadFromVideo (params: ResolveThreadParams) {
comment.changed('updatedAt', true) comment.changed('updatedAt', true)
comment.Video = video comment.Video = video
if (await isRemoteCommentAccepted(comment) !== true) {
return undefined
}
comments[i] = await comment.save() comments[i] = await comment.save()
} }
@ -169,3 +179,26 @@ async function resolveRemoteParentComment (params: ResolveThreadParams) {
commentCreated: true commentCreated: true
}) })
} }
async function isRemoteCommentAccepted (comment: MComment) {
// Already created
if (comment.id) return true
const acceptParameters = {
comment
}
const acceptedResult = await Hooks.wrapFun(
isRemoteVideoCommentAccepted,
acceptParameters,
'filter:activity-pub.remote-video-comment.create.accept.result'
)
if (!acceptedResult || acceptedResult.accepted !== true) {
logger.info('Refused to create a remote comment.', { acceptedResult, acceptParameters })
return false
}
return true
}

View File

@ -13,18 +13,15 @@ import {
MAbuseFull, MAbuseFull,
MAccountDefault, MAccountDefault,
MAccountLight, MAccountLight,
MComment,
MCommentAbuseAccountVideo, MCommentAbuseAccountVideo,
MCommentOwnerVideo, MCommentOwnerVideo,
MUser, MUser,
MVideoAbuseVideoFull, MVideoAbuseVideoFull,
MVideoAccountLightBlacklistAllFiles MVideoAccountLightBlacklistAllFiles
} from '@server/types/models' } from '@server/types/models'
import { ActivityCreate } from '../../shared/models/activitypub'
import { VideoObject } from '../../shared/models/activitypub/objects'
import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos' import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos'
import { VideoCommentCreate } from '../../shared/models/videos/comment' import { VideoCommentCreate } from '../../shared/models/videos/comment'
import { ActorModel } from '../models/actor/actor'
import { UserModel } from '../models/user/user' import { UserModel } from '../models/user/user'
import { VideoModel } from '../models/video/video' import { VideoModel } from '../models/video/video'
import { VideoCommentModel } from '../models/video/video-comment' import { VideoCommentModel } from '../models/video/video-comment'
@ -36,7 +33,9 @@ export type AcceptResult = {
errorMessage?: string errorMessage?: string
} }
// Can be filtered by plugins // ---------------------------------------------------------------------------
// Stub function that can be filtered by plugins
function isLocalVideoAccepted (object: { function isLocalVideoAccepted (object: {
videoBody: VideoCreate videoBody: VideoCreate
videoFile: VideoUploadFile videoFile: VideoUploadFile
@ -45,6 +44,9 @@ function isLocalVideoAccepted (object: {
return { accepted: true } return { accepted: true }
} }
// ---------------------------------------------------------------------------
// Stub function that can be filtered by plugins
function isLocalLiveVideoAccepted (object: { function isLocalLiveVideoAccepted (object: {
liveVideoBody: LiveVideoCreate liveVideoBody: LiveVideoCreate
user: UserModel user: UserModel
@ -52,6 +54,9 @@ function isLocalLiveVideoAccepted (object: {
return { accepted: true } return { accepted: true }
} }
// ---------------------------------------------------------------------------
// Stub function that can be filtered by plugins
function isLocalVideoThreadAccepted (_object: { function isLocalVideoThreadAccepted (_object: {
commentBody: VideoCommentCreate commentBody: VideoCommentCreate
video: VideoModel video: VideoModel
@ -60,6 +65,7 @@ function isLocalVideoThreadAccepted (_object: {
return { accepted: true } return { accepted: true }
} }
// Stub function that can be filtered by plugins
function isLocalVideoCommentReplyAccepted (_object: { function isLocalVideoCommentReplyAccepted (_object: {
commentBody: VideoCommentCreate commentBody: VideoCommentCreate
parentComment: VideoCommentModel parentComment: VideoCommentModel
@ -69,22 +75,18 @@ function isLocalVideoCommentReplyAccepted (_object: {
return { accepted: true } return { accepted: true }
} }
function isRemoteVideoAccepted (_object: { // ---------------------------------------------------------------------------
activity: ActivityCreate
videoAP: VideoObject
byActor: ActorModel
}): AcceptResult {
return { accepted: true }
}
// Stub function that can be filtered by plugins
function isRemoteVideoCommentAccepted (_object: { function isRemoteVideoCommentAccepted (_object: {
activity: ActivityCreate comment: MComment
commentAP: VideoCommentObject
byActor: ActorModel
}): AcceptResult { }): AcceptResult {
return { accepted: true } return { accepted: true }
} }
// ---------------------------------------------------------------------------
// Stub function that can be filtered by plugins
function isPreImportVideoAccepted (object: { function isPreImportVideoAccepted (object: {
videoImportBody: VideoImportCreate videoImportBody: VideoImportCreate
user: MUser user: MUser
@ -92,6 +94,7 @@ function isPreImportVideoAccepted (object: {
return { accepted: true } return { accepted: true }
} }
// Stub function that can be filtered by plugins
function isPostImportVideoAccepted (object: { function isPostImportVideoAccepted (object: {
videoFilePath: PathLike videoFilePath: PathLike
videoFile: VideoFileModel videoFile: VideoFileModel
@ -100,6 +103,8 @@ function isPostImportVideoAccepted (object: {
return { accepted: true } return { accepted: true }
} }
// ---------------------------------------------------------------------------
async function createVideoAbuse (options: { async function createVideoAbuse (options: {
baseAbuse: FilteredModelAttributes<AbuseModel> baseAbuse: FilteredModelAttributes<AbuseModel>
videoInstance: MVideoAccountLightBlacklistAllFiles videoInstance: MVideoAccountLightBlacklistAllFiles
@ -189,12 +194,13 @@ function createAccountAbuse (options: {
}) })
} }
// ---------------------------------------------------------------------------
export { export {
isLocalLiveVideoAccepted, isLocalLiveVideoAccepted,
isLocalVideoAccepted, isLocalVideoAccepted,
isLocalVideoThreadAccepted, isLocalVideoThreadAccepted,
isRemoteVideoAccepted,
isRemoteVideoCommentAccepted, isRemoteVideoCommentAccepted,
isLocalVideoCommentReplyAccepted, isLocalVideoCommentReplyAccepted,
isPreImportVideoAccepted, isPreImportVideoAccepted,

View File

@ -178,6 +178,8 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
} }
}) })
// ---------------------------------------------------------------------------
registerHook({ registerHook({
target: 'filter:api.video-thread.create.accept.result', target: 'filter:api.video-thread.create.accept.result',
handler: ({ accepted }, { commentBody }) => checkCommentBadWord(accepted, commentBody) handler: ({ accepted }, { commentBody }) => checkCommentBadWord(accepted, commentBody)
@ -188,6 +190,13 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
handler: ({ accepted }, { commentBody }) => checkCommentBadWord(accepted, commentBody) handler: ({ accepted }, { commentBody }) => checkCommentBadWord(accepted, commentBody)
}) })
registerHook({
target: 'filter:activity-pub.remote-video-comment.create.accept.result',
handler: ({ accepted }, { comment }) => checkCommentBadWord(accepted, comment)
})
// ---------------------------------------------------------------------------
registerHook({ registerHook({
target: 'filter:api.video-threads.list.params', target: 'filter:api.video-threads.list.params',
handler: obj => addToCount(obj) handler: obj => addToCount(obj)

View File

@ -64,232 +64,289 @@ describe('Test plugin filter hooks', function () {
}) })
}) })
it('Should run filter:api.videos.list.params', async function () { describe('Videos', function () {
const { data } = await servers[0].videos.list({ start: 0, count: 2 })
// 2 plugins do +1 to the count parameter it('Should run filter:api.videos.list.params', async function () {
expect(data).to.have.lengthOf(4) const { data } = await servers[0].videos.list({ start: 0, count: 2 })
})
it('Should run filter:api.videos.list.result', async function () { // 2 plugins do +1 to the count parameter
const { total } = await servers[0].videos.list({ start: 0, count: 0 }) expect(data).to.have.lengthOf(4)
// Plugin do +1 to the total result
expect(total).to.equal(11)
})
it('Should run filter:api.video-playlist.videos.list.params', async function () {
const { data } = await servers[0].playlists.listVideos({
count: 2,
playlistId: videoPlaylistUUID
}) })
// 1 plugin do +1 to the count parameter it('Should run filter:api.videos.list.result', async function () {
expect(data).to.have.lengthOf(3) const { total } = await servers[0].videos.list({ start: 0, count: 0 })
})
it('Should run filter:api.video-playlist.videos.list.result', async function () { // Plugin do +1 to the total result
const { total } = await servers[0].playlists.listVideos({ expect(total).to.equal(11)
count: 0,
playlistId: videoPlaylistUUID
}) })
// Plugin do +1 to the total result it('Should run filter:api.video-playlist.videos.list.params', async function () {
expect(total).to.equal(11) const { data } = await servers[0].playlists.listVideos({
count: 2,
playlistId: videoPlaylistUUID
})
// 1 plugin do +1 to the count parameter
expect(data).to.have.lengthOf(3)
})
it('Should run filter:api.video-playlist.videos.list.result', async function () {
const { total } = await servers[0].playlists.listVideos({
count: 0,
playlistId: videoPlaylistUUID
})
// Plugin do +1 to the total result
expect(total).to.equal(11)
})
it('Should run filter:api.accounts.videos.list.params', async function () {
const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
// 1 plugin do +1 to the count parameter
expect(data).to.have.lengthOf(3)
})
it('Should run filter:api.accounts.videos.list.result', async function () {
const { total } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
// Plugin do +2 to the total result
expect(total).to.equal(12)
})
it('Should run filter:api.video-channels.videos.list.params', async function () {
const { data } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
// 1 plugin do +3 to the count parameter
expect(data).to.have.lengthOf(5)
})
it('Should run filter:api.video-channels.videos.list.result', async function () {
const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
// Plugin do +3 to the total result
expect(total).to.equal(13)
})
it('Should run filter:api.user.me.videos.list.params', async function () {
const { data } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
// 1 plugin do +4 to the count parameter
expect(data).to.have.lengthOf(6)
})
it('Should run filter:api.user.me.videos.list.result', async function () {
const { total } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
// Plugin do +4 to the total result
expect(total).to.equal(14)
})
it('Should run filter:api.video.get.result', async function () {
const video = await servers[0].videos.get({ id: videoUUID })
expect(video.name).to.contain('<3')
})
}) })
it('Should run filter:api.accounts.videos.list.params', async function () { describe('Video/live/import accept', function () {
const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
// 1 plugin do +1 to the count parameter it('Should run filter:api.video.upload.accept.result', async function () {
expect(data).to.have.lengthOf(3) await servers[0].videos.upload({ attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
}) })
it('Should run filter:api.accounts.videos.list.result', async function () { it('Should run filter:api.live-video.create.accept.result', async function () {
const { total } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
// Plugin do +2 to the total result
expect(total).to.equal(12)
})
it('Should run filter:api.video-channels.videos.list.params', async function () {
const { data } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
// 1 plugin do +3 to the count parameter
expect(data).to.have.lengthOf(5)
})
it('Should run filter:api.video-channels.videos.list.result', async function () {
const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
// Plugin do +3 to the total result
expect(total).to.equal(13)
})
it('Should run filter:api.user.me.videos.list.params', async function () {
const { data } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
// 1 plugin do +4 to the count parameter
expect(data).to.have.lengthOf(6)
})
it('Should run filter:api.user.me.videos.list.result', async function () {
const { total } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
// Plugin do +4 to the total result
expect(total).to.equal(14)
})
it('Should run filter:api.video.get.result', async function () {
const video = await servers[0].videos.get({ id: videoUUID })
expect(video.name).to.contain('<3')
})
it('Should run filter:api.video.upload.accept.result', async function () {
await servers[0].videos.upload({ attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.live-video.create.accept.result', async function () {
const attributes = {
name: 'video with bad word',
privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id
}
await servers[0].live.create({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
const attributes = {
name: 'normal title',
privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id,
targetUrl: FIXTURE_URLS.goodVideo + 'bad'
}
await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
const attributes = {
name: 'bad torrent',
privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id,
torrentfile: 'video-720p.torrent' as any
}
await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.post-import-url.accept.result', async function () {
this.timeout(60000)
let videoImportId: number
{
const attributes = { const attributes = {
name: 'title with bad word', name: 'video with bad word',
privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id
}
await servers[0].live.create({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
})
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
const attributes = {
name: 'normal title',
privacy: VideoPrivacy.PUBLIC, privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id, channelId: servers[0].store.channel.id,
targetUrl: FIXTURE_URLS.goodVideo targetUrl: FIXTURE_URLS.goodVideo + 'bad'
} }
const body = await servers[0].imports.importVideo({ attributes }) await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
videoImportId = body.id })
}
await waitJobs(servers) it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
{
const body = await servers[0].imports.getMyVideoImports()
const videoImports = body.data
const videoImport = videoImports.find(i => i.id === videoImportId)
expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
expect(videoImport.state.label).to.equal('Rejected')
}
})
it('Should run filter:api.video.post-import-torrent.accept.result', async function () {
this.timeout(60000)
let videoImportId: number
{
const attributes = { const attributes = {
name: 'title with bad word', name: 'bad torrent',
privacy: VideoPrivacy.PUBLIC, privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id, channelId: servers[0].store.channel.id,
torrentfile: 'video-720p.torrent' as any torrentfile: 'video-720p.torrent' as any
} }
const body = await servers[0].imports.importVideo({ attributes }) await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
videoImportId = body.id })
}
await waitJobs(servers) it('Should run filter:api.video.post-import-url.accept.result', async function () {
this.timeout(60000)
{ let videoImportId: number
const { data: videoImports } = await servers[0].imports.getMyVideoImports()
const videoImport = videoImports.find(i => i.id === videoImportId) {
const attributes = {
name: 'title with bad word',
privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id,
targetUrl: FIXTURE_URLS.goodVideo
}
const body = await servers[0].imports.importVideo({ attributes })
videoImportId = body.id
}
expect(videoImport.state.id).to.equal(VideoImportState.REJECTED) await waitJobs(servers)
expect(videoImport.state.label).to.equal('Rejected')
}
})
it('Should run filter:api.video-thread.create.accept.result', async function () { {
await servers[0].comments.createThread({ const body = await servers[0].imports.getMyVideoImports()
videoId: videoUUID, const videoImports = body.data
text: 'comment with bad word',
expectedStatus: HttpStatusCode.FORBIDDEN_403 const videoImport = videoImports.find(i => i.id === videoImportId)
expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
expect(videoImport.state.label).to.equal('Rejected')
}
})
it('Should run filter:api.video.post-import-torrent.accept.result', async function () {
this.timeout(60000)
let videoImportId: number
{
const attributes = {
name: 'title with bad word',
privacy: VideoPrivacy.PUBLIC,
channelId: servers[0].store.channel.id,
torrentfile: 'video-720p.torrent' as any
}
const body = await servers[0].imports.importVideo({ attributes })
videoImportId = body.id
}
await waitJobs(servers)
{
const { data: videoImports } = await servers[0].imports.getMyVideoImports()
const videoImport = videoImports.find(i => i.id === videoImportId)
expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
expect(videoImport.state.label).to.equal('Rejected')
}
}) })
}) })
it('Should run filter:api.video-comment-reply.create.accept.result', async function () { describe('Video comments accept', function () {
const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
threadId = created.id
await servers[0].comments.addReply({ it('Should run filter:api.video-thread.create.accept.result', async function () {
videoId: videoUUID, await servers[0].comments.createThread({
toCommentId: threadId, videoId: videoUUID,
text: 'comment with bad word', text: 'comment with bad word',
expectedStatus: HttpStatusCode.FORBIDDEN_403 expectedStatus: HttpStatusCode.FORBIDDEN_403
})
}) })
await servers[0].comments.addReply({
videoId: videoUUID, it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
toCommentId: threadId, const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
text: 'comment with good word', threadId = created.id
expectedStatus: HttpStatusCode.OK_200
await servers[0].comments.addReply({
videoId: videoUUID,
toCommentId: threadId,
text: 'comment with bad word',
expectedStatus: HttpStatusCode.FORBIDDEN_403
})
await servers[0].comments.addReply({
videoId: videoUUID,
toCommentId: threadId,
text: 'comment with good word',
expectedStatus: HttpStatusCode.OK_200
})
})
it('Should run filter:activity-pub.remote-video-comment.create.accept.result on a thread creation', async function () {
this.timeout(30000)
await servers[1].comments.createThread({ videoId: videoUUID, text: 'comment with bad word' })
await waitJobs(servers)
{
const thread = await servers[0].comments.listThreads({ videoId: videoUUID })
expect(thread.data).to.have.lengthOf(1)
expect(thread.data[0].text).to.not.include(' bad ')
}
{
const thread = await servers[1].comments.listThreads({ videoId: videoUUID })
expect(thread.data).to.have.lengthOf(2)
}
})
it('Should run filter:activity-pub.remote-video-comment.create.accept.result on a reply creation', async function () {
this.timeout(30000)
const { data } = await servers[1].comments.listThreads({ videoId: videoUUID })
const threadIdServer2 = data.find(t => t.text === 'thread').id
await servers[1].comments.addReply({
videoId: videoUUID,
toCommentId: threadIdServer2,
text: 'comment with bad word'
})
await waitJobs(servers)
{
const tree = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
expect(tree.children).to.have.lengthOf(1)
expect(tree.children[0].comment.text).to.not.include(' bad ')
}
{
const tree = await servers[1].comments.getThread({ videoId: videoUUID, threadId: threadIdServer2 })
expect(tree.children).to.have.lengthOf(2)
}
}) })
}) })
it('Should run filter:api.video-threads.list.params', async function () { describe('Video comments', function () {
const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
// our plugin do +1 to the count parameter it('Should run filter:api.video-threads.list.params', async function () {
expect(data).to.have.lengthOf(1) const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
})
it('Should run filter:api.video-threads.list.result', async function () { // our plugin do +1 to the count parameter
const { total } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 }) expect(data).to.have.lengthOf(1)
})
// Plugin do +1 to the total result it('Should run filter:api.video-threads.list.result', async function () {
expect(total).to.equal(2) const { total } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
})
it('Should run filter:api.video-thread-comments.list.params') // Plugin do +1 to the total result
expect(total).to.equal(2)
})
it('Should run filter:api.video-thread-comments.list.result', async function () { it('Should run filter:api.video-thread-comments.list.params')
const thread = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
expect(thread.comment.text.endsWith(' <3')).to.be.true it('Should run filter:api.video-thread-comments.list.result', async function () {
}) const thread = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
it('Should run filter:api.overviews.videos.list.{params,result}', async function () { expect(thread.comment.text.endsWith(' <3')).to.be.true
await servers[0].overviews.getVideos({ page: 1 }) })
// 3 because we get 3 samples per page it('Should run filter:api.overviews.videos.list.{params,result}', async function () {
await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.params', 3) await servers[0].overviews.getVideos({ page: 1 })
await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.result', 3)
// 3 because we get 3 samples per page
await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.params', 3)
await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.result', 3)
})
}) })
describe('filter:video.auto-blacklist.result', function () { describe('filter:video.auto-blacklist.result', function () {

View File

@ -103,7 +103,9 @@ export const serverFilterHookObject = {
'filter:job-queue.process.result': true, 'filter:job-queue.process.result': true,
'filter:transcoding.manual.resolutions-to-transcode.result': true, 'filter:transcoding.manual.resolutions-to-transcode.result': true,
'filter:transcoding.auto.resolutions-to-transcode.result': true 'filter:transcoding.auto.resolutions-to-transcode.result': true,
'filter:activity-pub.remote-video-comment.create.accept.result': true
} }
export type ServerFilterHookName = keyof typeof serverFilterHookObject export type ServerFilterHookName = keyof typeof serverFilterHookObject