From 2158ac90341dc3fcae958540de65032da25c8d6e Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Thu, 14 May 2020 11:10:26 +0200 Subject: Add server plugin filter hooks for import with torrent and url (#2621) * Add server plugin filter hooks for import with torrent and url * WIP: pre and post-import filter hooks * Rebased * Cleanup filters to accept imports Co-authored-by: Chocobozzz --- server/lib/job-queue/handlers/video-import.ts | 76 ++++++++++++++++++++------- server/lib/moderation.ts | 24 ++++++++- 2 files changed, 79 insertions(+), 21 deletions(-) (limited to 'server/lib') diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index ad549c6fc..a197ef629 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts @@ -1,27 +1,36 @@ import * as Bull from 'bull' -import { logger } from '../../../helpers/logger' -import { downloadYoutubeDLVideo } from '../../../helpers/youtube-dl' -import { VideoImportModel } from '../../../models/video/video-import' +import { move, remove, stat } from 'fs-extra' +import { extname } from 'path' +import { addOptimizeOrMergeAudioJob } from '@server/helpers/video' +import { isPostImportVideoAccepted } from '@server/lib/moderation' +import { Hooks } from '@server/lib/plugins/hooks' +import { getVideoFilePath } from '@server/lib/video-paths' +import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/typings/models/video/video-import' +import { + VideoImportPayload, + VideoImportTorrentPayload, + VideoImportTorrentPayloadType, + VideoImportYoutubeDLPayload, + VideoImportYoutubeDLPayloadType, + VideoState +} from '../../../../shared' import { VideoImportState } from '../../../../shared/models/videos' +import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' -import { extname } from 'path' -import { VideoFileModel } from '../../../models/video/video-file' -import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants' -import { VideoImportPayload, VideoImportTorrentPayload, VideoImportYoutubeDLPayload, VideoState } from '../../../../shared' -import { federateVideoIfNeeded } from '../../activitypub/videos' -import { VideoModel } from '../../../models/video/video' -import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' +import { logger } from '../../../helpers/logger' import { getSecureTorrentName } from '../../../helpers/utils' -import { move, remove, stat } from 'fs-extra' -import { Notifier } from '../../notifier' +import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' +import { downloadYoutubeDLVideo } from '../../../helpers/youtube-dl' import { CONFIG } from '../../../initializers/config' +import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants' import { sequelizeTypescript } from '../../../initializers/database' -import { generateVideoMiniature } from '../../thumbnail' -import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' +import { VideoModel } from '../../../models/video/video' +import { VideoFileModel } from '../../../models/video/video-file' +import { VideoImportModel } from '../../../models/video/video-import' import { MThumbnail } from '../../../typings/models/video/thumbnail' -import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/typings/models/video/video-import' -import { getVideoFilePath } from '@server/lib/video-paths' -import { addOptimizeOrMergeAudioJob } from '@server/helpers/video' +import { federateVideoIfNeeded } from '../../activitypub/videos' +import { Notifier } from '../../notifier' +import { generateVideoMiniature } from '../../thumbnail' async function processVideoImport (job: Bull.Job) { const payload = job.data as VideoImportPayload @@ -44,6 +53,7 @@ async function processTorrentImport (job: Bull.Job, payload: VideoImportTorrentP const videoImport = await getVideoImportOrDie(payload.videoImportId) const options = { + type: payload.type, videoImportId: payload.videoImportId, generateThumbnail: true, @@ -61,6 +71,7 @@ async function processYoutubeDLImport (job: Bull.Job, payload: VideoImportYoutub const videoImport = await getVideoImportOrDie(payload.videoImportId) const options = { + type: payload.type, videoImportId: videoImport.id, generateThumbnail: payload.generateThumbnail, @@ -80,6 +91,7 @@ async function getVideoImportOrDie (videoImportId: number) { } type ProcessFileOptions = { + type: VideoImportYoutubeDLPayloadType | VideoImportTorrentPayloadType videoImportId: number generateThumbnail: boolean @@ -105,7 +117,7 @@ async function processFile (downloader: () => Promise, videoImport: MVid const fps = await getVideoFileFPS(tempVideoPath) const duration = await getDurationFromVideoFile(tempVideoPath) - // Create video file object in database + // Prepare video file object for creation in database const videoFileData = { extname: extname(tempVideoPath), resolution: videoFileResolution, @@ -115,6 +127,30 @@ async function processFile (downloader: () => Promise, videoImport: MVid } videoFile = new VideoFileModel(videoFileData) + const hookName = options.type === 'youtube-dl' + ? 'filter:api.video.post-import-url.accept.result' + : 'filter:api.video.post-import-torrent.accept.result' + + // Check we accept this video + const acceptParameters = { + videoImport, + video: videoImport.Video, + videoFilePath: tempVideoPath, + videoFile, + user: videoImport.User + } + const acceptedResult = await Hooks.wrapFun(isPostImportVideoAccepted, acceptParameters, hookName) + + if (acceptedResult.accepted !== true) { + logger.info('Refused imported video.', { acceptedResult, acceptParameters }) + + videoImport.state = VideoImportState.REJECTED + await videoImport.save() + + throw new Error(acceptedResult.errorMessage) + } + + // Video is accepted, resuming preparation const videoWithFiles = Object.assign(videoImport.Video, { VideoFiles: [ videoFile ], VideoStreamingPlaylists: [] }) // To clean files if the import fails const videoImportWithFiles: MVideoImportDefaultFiles = Object.assign(videoImport, { Video: videoWithFiles }) @@ -194,7 +230,9 @@ async function processFile (downloader: () => Promise, videoImport: MVid } videoImport.error = err.message - videoImport.state = VideoImportState.FAILED + if (videoImport.state !== VideoImportState.REJECTED) { + videoImport.state = VideoImportState.FAILED + } await videoImport.save() Notifier.Instance.notifyOnFinishedVideoImport(videoImport, false) diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts index 55f7a985d..4afebb32a 100644 --- a/server/lib/moderation.ts +++ b/server/lib/moderation.ts @@ -1,12 +1,15 @@ import { VideoModel } from '../models/video/video' import { VideoCommentModel } from '../models/video/video-comment' import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' -import { VideoCreate } from '../../shared/models/videos' +import { VideoCreate, VideoImportCreate } from '../../shared/models/videos' import { UserModel } from '../models/account/user' import { VideoTorrentObject } from '../../shared/models/activitypub/objects' import { ActivityCreate } from '../../shared/models/activitypub' import { ActorModel } from '../models/activitypub/actor' import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' +import { VideoFileModel } from '@server/models/video/video-file' +import { PathLike } from 'fs-extra' +import { MUser } from '@server/typings/models' export type AcceptResult = { accepted: boolean @@ -55,10 +58,27 @@ function isRemoteVideoCommentAccepted (_object: { return { accepted: true } } +function isPreImportVideoAccepted (object: { + videoImportBody: VideoImportCreate + user: MUser +}): AcceptResult { + return { accepted: true } +} + +function isPostImportVideoAccepted (object: { + videoFilePath: PathLike + videoFile: VideoFileModel + user: MUser +}): AcceptResult { + return { accepted: true } +} + export { isLocalVideoAccepted, isLocalVideoThreadAccepted, isRemoteVideoAccepted, isRemoteVideoCommentAccepted, - isLocalVideoCommentReplyAccepted + isLocalVideoCommentReplyAccepted, + isPreImportVideoAccepted, + isPostImportVideoAccepted } -- cgit v1.2.3