videoChannelRouter.get('/:nameWithHost',
asyncMiddleware(videoChannelsNameWithHostValidator),
- getVideoChannel
+ asyncMiddleware(getVideoChannel)
)
videoChannelRouter.get('/:nameWithHost/video-playlists',
async function listVideoChannels (req: express.Request, res: express.Response) {
const serverActor = await getServerActor()
- const resultList = await VideoChannelModel.listForApi({
+
+ const apiOptions = await Hooks.wrapObject({
actorId: serverActor.id,
start: req.query.start,
count: req.query.count,
sort: req.query.sort
- })
+ }, 'filter:api.video-channels.list.params')
+
+ const resultList = await Hooks.wrapPromiseFun(
+ VideoChannelModel.listForApi,
+ apiOptions,
+ 'filter:api.video-channels.list.result'
+ )
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
auditLogger.create(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelCreated.toFormattedJSON()))
logger.info('Video channel %s created.', videoChannelCreated.Actor.url)
+ Hooks.runAction('action:api.video-channel.created', { videoChannel: videoChannelCreated, req, res })
+
return res.json({
videoChannel: {
id: videoChannelCreated.id
oldVideoChannelAuditKeys
)
+ Hooks.runAction('action:api.video-channel.updated', { videoChannel: videoChannelInstanceUpdated, req, res })
+
logger.info('Video channel %s updated.', videoChannelInstance.Actor.url)
})
} catch (err) {
await videoChannelInstance.destroy({ transaction: t })
+ Hooks.runAction('action:api.video-channel.deleted', { videoChannel: videoChannelInstance, req, res })
+
auditLogger.delete(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelInstance.toFormattedJSON()))
logger.info('Video channel %s deleted.', videoChannelInstance.Actor.url)
})
return res.type('json').status(HttpStatusCode.NO_CONTENT_204).end()
}
-function getVideoChannel (req: express.Request, res: express.Response) {
- const videoChannel = res.locals.videoChannel
+async function getVideoChannel (req: express.Request, res: express.Response) {
+ const id = res.locals.videoChannel.id
+ const videoChannel = await Hooks.wrapObject(res.locals.videoChannel, 'filter:api.video-channel.get.result', { id })
if (videoChannel.isOutdated()) {
JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'actor', url: videoChannel.Actor.url } })
optionalAuthenticate,
asyncMiddleware(videosCustomGetValidator('for-api')),
asyncMiddleware(checkVideoFollowConstraints),
- getVideo
+ asyncMiddleware(getVideo)
)
videosRouter.delete('/:id',
res.json(VIDEO_PRIVACIES)
}
-function getVideo (_req: express.Request, res: express.Response) {
- const video = res.locals.videoAPI
+async function getVideo (_req: express.Request, res: express.Response) {
+ const videoId = res.locals.videoAPI.id
+ const userId = res.locals.oauth?.token.User.id
+
+ const video = await Hooks.wrapObject(res.locals.videoAPI, 'filter:api.video.get.result', { id: videoId, userId })
if (video.isOutdated()) {
JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', url: video.url } })
MVideoImmutable,
MVideoThumbnail
} from '@server/types/models'
-import { Hooks } from '../plugins/hooks'
+
type VideoLoadType = 'for-api' | 'all' | 'only-video' | 'id' | 'none' | 'only-immutable-attributes'
userId?: number
): Promise<MVideoFullLight | MVideoThumbnail | MVideoId | MVideoImmutable> {
- if (fetchType === 'for-api') {
- return Hooks.wrapPromiseFun(
- VideoModel.loadForGetAPI,
- { id, userId },
- 'filter:api.video.get.result'
- )
- }
+ if (fetchType === 'for-api') return VideoModel.loadForGetAPI({ id, userId })
if (fetchType === 'all') return VideoModel.loadFull(id, undefined, userId)
'action:api.video.uploaded',
'action:api.video.viewed',
+ 'action:api.video-channel.created',
+ 'action:api.video-channel.updated',
+ 'action:api.video-channel.deleted',
+
'action:api.live-video.created',
'action:api.video-thread.created',
}
})
+ // ---------------------------------------------------------------------------
+
+ registerHook({
+ target: 'filter:api.video-channels.list.params',
+ handler: obj => addToCount(obj, 1)
+ })
+
+ registerHook({
+ target: 'filter:api.video-channels.list.result',
+ handler: obj => addToTotal(obj, 1)
+ })
+
+ registerHook({
+ target: 'filter:api.video-channel.get.result',
+ handler: channel => {
+ channel.name += ' <3'
+
+ return channel
+ }
+ })
+
+ // ---------------------------------------------------------------------------
+
for (const hook of [ 'filter:api.video.upload.accept.result', 'filter:api.live-video.create.accept.result' ]) {
registerHook({
target: hook,
await checkHook('action:api.video.viewed')
})
+
+ it('Should run action:api.video.deleted', async function () {
+ await servers[0].videos.remove({ id: videoUUID })
+
+ await checkHook('action:api.video.deleted')
+ })
+
+ after(async function () {
+ const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
+ videoUUID = uuid
+ })
+ })
+
+ describe('Video channel hooks', function () {
+ const channelName = 'my_super_channel'
+
+ it('Should run action:api.video-channel.created', async function () {
+ await servers[0].channels.create({ attributes: { name: channelName } })
+
+ await checkHook('action:api.video-channel.created')
+ })
+
+ it('Should run action:api.video-channel.updated', async function () {
+ await servers[0].channels.update({ channelName, attributes: { displayName: 'my display name' } })
+
+ await checkHook('action:api.video-channel.updated')
+ })
+
+ it('Should run action:api.video-channel.deleted', async function () {
+ await servers[0].channels.delete({ channelName })
+
+ await checkHook('action:api.video-channel.deleted')
+ })
})
describe('Live hooks', function () {
await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.result', 3)
})
- describe('Should run filter:video.auto-blacklist.result', function () {
+ describe('filter:video.auto-blacklist.result', function () {
async function checkIsBlacklisted (id: number | string, value: boolean) {
const video = await servers[0].videos.getWithToken({ id })
})
})
+ describe('Video channel filters', async function () {
+
+ it('Should run filter:api.video-channels.list.params', async function () {
+ const { data } = await servers[0].channels.list({ start: 0, count: 0 })
+
+ // plugin do +1 to the count parameter
+ expect(data).to.have.lengthOf(1)
+ })
+
+ it('Should run filter:api.video-channels.list.result', async function () {
+ const { total } = await servers[0].channels.list({ start: 0, count: 1 })
+
+ // plugin do +1 to the total parameter
+ expect(total).to.equal(4)
+ })
+
+ it('Should run filter:api.video-channel.get.result', async function () {
+ const channel = await servers[0].channels.get({ channelName: 'root_channel' })
+ expect(channel.displayName).to.equal('Main root channel <3')
+ })
+ })
+
after(async function () {
await cleanupTests(servers)
})
// Used to get detailed video information (video watch page for example)
'filter:api.video.get.result': true,
+ // Filter params/results when listing video channels
+ 'filter:api.video-channels.list.params': true,
+ 'filter:api.video-channels.list.result': true,
+
+ // Filter the result when getting a video channel
+ 'filter:api.video-channel.get.result': true,
+
// Filter the result of the accept upload/live, import via torrent/url functions
// If this function returns false then the upload is aborted with an error
'filter:api.video.upload.accept.result': true,
// Fired when a local video is viewed
'action:api.video.viewed': true,
+ // Fired when a video channel is created
+ 'action:api.video-channel.created': true,
+ // Fired when a video channel is updated
+ 'action:api.video-channel.updated': true,
+ // Fired when a video channel is deleted
+ 'action:api.video-channel.deleted': true,
+
// Fired when a live video is created
'action:api.live-video.created': true,