Add live server hooks
This commit is contained in:
parent
c8f3cfeba7
commit
3cabf3532b
|
@ -262,7 +262,7 @@ live:
|
|||
# PeerTube will transcode segments in a video file
|
||||
# If the user daily/total quota is reached, PeerTube will stop the live
|
||||
# /!\ transcoding.enabled (and not live.transcoding.enabled) has to be true to create a replay
|
||||
allow_replay: true
|
||||
allow_replay: false
|
||||
|
||||
rtmp:
|
||||
port: 1935
|
||||
|
|
|
@ -5,6 +5,7 @@ import { CONFIG } from '@server/initializers/config'
|
|||
import { ASSETS_PATH, MIMETYPES } from '@server/initializers/constants'
|
||||
import { getVideoActivityPubUrl } from '@server/lib/activitypub/url'
|
||||
import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
|
||||
import { videoLiveAddValidator, videoLiveGetValidator, videoLiveUpdateValidator } from '@server/middlewares/validators/videos/video-live'
|
||||
import { VideoLiveModel } from '@server/models/video/video-live'
|
||||
|
@ -128,6 +129,8 @@ async function addLiveVideo (req: express.Request, res: express.Response) {
|
|||
return { videoCreated }
|
||||
})
|
||||
|
||||
Hooks.runAction('action:api.live-video.created', { video: videoCreated })
|
||||
|
||||
return res.json({
|
||||
video: {
|
||||
id: videoCreated.id,
|
||||
|
|
|
@ -118,7 +118,7 @@ class LiveManager {
|
|||
}
|
||||
|
||||
run () {
|
||||
logger.info('Running RTMP server.')
|
||||
logger.info('Running RTMP server on port %d', config.rtmp.port)
|
||||
|
||||
this.rtmpServer = new NodeRtmpServer(config)
|
||||
this.rtmpServer.run()
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
import { ActivityCreate } from '../../shared/models/activitypub'
|
||||
import { VideoObject } from '../../shared/models/activitypub/objects'
|
||||
import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
|
||||
import { VideoCreate, VideoImportCreate } from '../../shared/models/videos'
|
||||
import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos'
|
||||
import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model'
|
||||
import { UserModel } from '../models/account/user'
|
||||
import { ActorModel } from '../models/activitypub/actor'
|
||||
|
@ -43,6 +43,13 @@ function isLocalVideoAccepted (object: {
|
|||
return { accepted: true }
|
||||
}
|
||||
|
||||
function isLocalLiveVideoAccepted (object: {
|
||||
liveVideoBody: LiveVideoCreate
|
||||
user: UserModel
|
||||
}): AcceptResult {
|
||||
return { accepted: true }
|
||||
}
|
||||
|
||||
function isLocalVideoThreadAccepted (_object: {
|
||||
commentBody: VideoCommentCreate
|
||||
video: VideoModel
|
||||
|
@ -175,6 +182,8 @@ function createAccountAbuse (options: {
|
|||
}
|
||||
|
||||
export {
|
||||
isLocalLiveVideoAccepted,
|
||||
|
||||
isLocalVideoAccepted,
|
||||
isLocalVideoThreadAccepted,
|
||||
isRemoteVideoAccepted,
|
||||
|
|
|
@ -11,6 +11,8 @@ import { CONFIG } from '../../../initializers/config'
|
|||
import { areValidationErrors } from '../utils'
|
||||
import { getCommonVideoEditAttributes } from './videos'
|
||||
import { VideoModel } from '@server/models/video/video'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { isLocalLiveVideoAccepted } from '@server/lib/moderation'
|
||||
|
||||
const videoLiveGetValidator = [
|
||||
param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
|
||||
|
@ -97,6 +99,8 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
|
|||
}
|
||||
}
|
||||
|
||||
if (!await isLiveVideoAccepted(req, res)) return cleanUpReqFiles(req)
|
||||
|
||||
return next()
|
||||
}
|
||||
])
|
||||
|
@ -137,3 +141,29 @@ export {
|
|||
videoLiveUpdateValidator,
|
||||
videoLiveGetValidator
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function isLiveVideoAccepted (req: express.Request, res: express.Response) {
|
||||
// Check we accept this video
|
||||
const acceptParameters = {
|
||||
liveVideoBody: req.body,
|
||||
user: res.locals.oauth.token.User
|
||||
}
|
||||
const acceptedResult = await Hooks.wrapFun(
|
||||
isLocalLiveVideoAccepted,
|
||||
acceptParameters,
|
||||
'filter:api.live-video.create.accept.result'
|
||||
)
|
||||
|
||||
if (!acceptedResult || acceptedResult.accepted !== true) {
|
||||
logger.info('Refused local live video.', { acceptedResult, acceptParameters })
|
||||
|
||||
res.status(403)
|
||||
.json({ error: acceptedResult.errorMessage || 'Refused local live video' })
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
|
|||
'action:api.video.uploaded',
|
||||
'action:api.video.viewed',
|
||||
|
||||
'action:api.live-video.created',
|
||||
|
||||
'action:api.video-thread.created',
|
||||
'action:api.video-comment-reply.created',
|
||||
'action:api.video-comment.deleted',
|
||||
|
@ -46,15 +48,22 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
|
|||
}
|
||||
})
|
||||
|
||||
for (const hook of [ 'filter:api.video.upload.accept.result', 'filter:api.live-video.create.accept.result' ]) {
|
||||
registerHook({
|
||||
target: 'filter:api.video.upload.accept.result',
|
||||
handler: ({ accepted }, { videoBody }) => {
|
||||
target: hook,
|
||||
handler: ({ accepted }, { videoBody, liveVideoBody }) => {
|
||||
if (!accepted) return { accepted: false }
|
||||
if (videoBody.name.indexOf('bad word') !== -1) return { accepted: false, errorMessage: 'bad word' }
|
||||
|
||||
const name = videoBody
|
||||
? videoBody.name
|
||||
: liveVideoBody.name
|
||||
|
||||
if (name.indexOf('bad word') !== -1) return { accepted: false, errorMessage: 'bad word' }
|
||||
|
||||
return { accepted: true }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
registerHook({
|
||||
target: 'filter:api.video.pre-import-url.accept.result',
|
||||
|
|
|
@ -1,6 +1,27 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import 'mocha'
|
||||
import { ServerHookName, VideoPrivacy } from '@shared/models'
|
||||
import {
|
||||
addVideoCommentReply,
|
||||
addVideoCommentThread,
|
||||
blockUser,
|
||||
createLive,
|
||||
createUser,
|
||||
deleteVideoComment,
|
||||
getPluginTestPath,
|
||||
installPlugin,
|
||||
registerUser,
|
||||
removeUser,
|
||||
setAccessTokensToServers,
|
||||
setDefaultVideoChannel,
|
||||
unblockUser,
|
||||
updateUser,
|
||||
updateVideo,
|
||||
uploadVideo,
|
||||
userLogin,
|
||||
viewVideo
|
||||
} from '../../../shared/extra-utils'
|
||||
import {
|
||||
cleanupTests,
|
||||
flushAndRunMultipleServers,
|
||||
|
@ -9,31 +30,13 @@ import {
|
|||
ServerInfo,
|
||||
waitUntilLog
|
||||
} from '../../../shared/extra-utils/server/servers'
|
||||
import {
|
||||
addVideoCommentReply,
|
||||
addVideoCommentThread,
|
||||
blockUser,
|
||||
createUser,
|
||||
deleteVideoComment,
|
||||
getPluginTestPath,
|
||||
installPlugin,
|
||||
registerUser,
|
||||
removeUser,
|
||||
setAccessTokensToServers,
|
||||
unblockUser,
|
||||
updateUser,
|
||||
updateVideo,
|
||||
uploadVideo,
|
||||
userLogin,
|
||||
viewVideo
|
||||
} from '../../../shared/extra-utils'
|
||||
|
||||
describe('Test plugin action hooks', function () {
|
||||
let servers: ServerInfo[]
|
||||
let videoUUID: string
|
||||
let threadId: number
|
||||
|
||||
function checkHook (hook: string) {
|
||||
function checkHook (hook: ServerHookName) {
|
||||
return waitUntilLog(servers[0], 'Run hook ' + hook)
|
||||
}
|
||||
|
||||
|
@ -42,6 +45,7 @@ describe('Test plugin action hooks', function () {
|
|||
|
||||
servers = await flushAndRunMultipleServers(2)
|
||||
await setAccessTokensToServers(servers)
|
||||
await setDefaultVideoChannel(servers)
|
||||
|
||||
await installPlugin({
|
||||
url: servers[0].url,
|
||||
|
@ -51,7 +55,11 @@ describe('Test plugin action hooks', function () {
|
|||
|
||||
killallServers([ servers[0] ])
|
||||
|
||||
await reRunServer(servers[0])
|
||||
await reRunServer(servers[0], {
|
||||
live: {
|
||||
enabled: true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Application hooks', function () {
|
||||
|
@ -81,6 +89,21 @@ describe('Test plugin action hooks', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('Live hooks', function () {
|
||||
|
||||
it('Should run action:api.live-video.created', async function () {
|
||||
const attributes = {
|
||||
name: 'live',
|
||||
privacy: VideoPrivacy.PUBLIC,
|
||||
channelId: servers[0].videoChannel.id
|
||||
}
|
||||
|
||||
await createLive(servers[0].url, servers[0].accessToken, attributes)
|
||||
|
||||
await checkHook('action:api.live-video.created')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Comments hooks', function () {
|
||||
it('Should run action:api.video-thread.created', async function () {
|
||||
const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
|
||||
|
|
|
@ -6,6 +6,7 @@ import { ServerConfig } from '@shared/models'
|
|||
import {
|
||||
addVideoCommentReply,
|
||||
addVideoCommentThread,
|
||||
createLive,
|
||||
doubleFollow,
|
||||
getConfig,
|
||||
getPluginTestPath,
|
||||
|
@ -19,6 +20,7 @@ import {
|
|||
registerUser,
|
||||
setAccessTokensToServers,
|
||||
setDefaultVideoChannel,
|
||||
updateCustomSubConfig,
|
||||
updateVideo,
|
||||
uploadVideo,
|
||||
waitJobs
|
||||
|
@ -61,6 +63,17 @@ describe('Test plugin filter hooks', function () {
|
|||
|
||||
const res = await getVideosList(servers[0].url)
|
||||
videoUUID = res.body.data[0].uuid
|
||||
|
||||
await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
|
||||
live: { enabled: true },
|
||||
signup: { enabled: true },
|
||||
import: {
|
||||
videos: {
|
||||
http: { enabled: true },
|
||||
torrent: { enabled: true }
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('Should run filter:api.videos.list.params', async function () {
|
||||
|
@ -87,6 +100,16 @@ describe('Test plugin filter hooks', function () {
|
|||
await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, 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].videoChannel.id
|
||||
}
|
||||
|
||||
await createLive(servers[0].url, servers[0].accessToken, attributes, 403)
|
||||
})
|
||||
|
||||
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
|
||||
const baseAttributes = {
|
||||
name: 'normal title',
|
||||
|
|
|
@ -9,9 +9,10 @@ export const serverFilterHookObject = {
|
|||
// Used to get detailed video information (video watch page for example)
|
||||
'filter:api.video.get.result': true,
|
||||
|
||||
// Filter the result of the accept upload, import via torrent or url functions
|
||||
// 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,
|
||||
'filter:api.live-video.create.accept.result': true,
|
||||
'filter:api.video.pre-import-url.accept.result': true,
|
||||
'filter:api.video.pre-import-torrent.accept.result': true,
|
||||
'filter:api.video.post-import-url.accept.result': true,
|
||||
|
@ -54,6 +55,9 @@ export const serverActionHookObject = {
|
|||
// Fired when a local video is viewed
|
||||
'action:api.video.viewed': true,
|
||||
|
||||
// Fired when a live video is created
|
||||
'action:api.live-video.created': true,
|
||||
|
||||
// Fired when a thread is created
|
||||
'action:api.video-thread.created': true,
|
||||
// Fired when a reply to a thread is created
|
||||
|
|
Loading…
Reference in New Issue