aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-05-14 11:10:26 +0200
committerGitHub <noreply@github.com>2020-05-14 11:10:26 +0200
commit2158ac90341dc3fcae958540de65032da25c8d6e (patch)
treea780923d701f3daa130996768e38c1e1b6a0646c /server/lib
parent7405b6ba897dbce1b4fd50c92174f1df5ac15adc (diff)
downloadPeerTube-2158ac90341dc3fcae958540de65032da25c8d6e.tar.gz
PeerTube-2158ac90341dc3fcae958540de65032da25c8d6e.tar.zst
PeerTube-2158ac90341dc3fcae958540de65032da25c8d6e.zip
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 <me@florianbigard.com>
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/job-queue/handlers/video-import.ts76
-rw-r--r--server/lib/moderation.ts24
2 files changed, 79 insertions, 21 deletions
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 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import { logger } from '../../../helpers/logger' 2import { move, remove, stat } from 'fs-extra'
3import { downloadYoutubeDLVideo } from '../../../helpers/youtube-dl' 3import { extname } from 'path'
4import { VideoImportModel } from '../../../models/video/video-import' 4import { addOptimizeOrMergeAudioJob } from '@server/helpers/video'
5import { isPostImportVideoAccepted } from '@server/lib/moderation'
6import { Hooks } from '@server/lib/plugins/hooks'
7import { getVideoFilePath } from '@server/lib/video-paths'
8import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/typings/models/video/video-import'
9import {
10 VideoImportPayload,
11 VideoImportTorrentPayload,
12 VideoImportTorrentPayloadType,
13 VideoImportYoutubeDLPayload,
14 VideoImportYoutubeDLPayloadType,
15 VideoState
16} from '../../../../shared'
5import { VideoImportState } from '../../../../shared/models/videos' 17import { VideoImportState } from '../../../../shared/models/videos'
18import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
6import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' 19import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
7import { extname } from 'path' 20import { logger } from '../../../helpers/logger'
8import { VideoFileModel } from '../../../models/video/video-file'
9import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants'
10import { VideoImportPayload, VideoImportTorrentPayload, VideoImportYoutubeDLPayload, VideoState } from '../../../../shared'
11import { federateVideoIfNeeded } from '../../activitypub/videos'
12import { VideoModel } from '../../../models/video/video'
13import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent'
14import { getSecureTorrentName } from '../../../helpers/utils' 21import { getSecureTorrentName } from '../../../helpers/utils'
15import { move, remove, stat } from 'fs-extra' 22import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent'
16import { Notifier } from '../../notifier' 23import { downloadYoutubeDLVideo } from '../../../helpers/youtube-dl'
17import { CONFIG } from '../../../initializers/config' 24import { CONFIG } from '../../../initializers/config'
25import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants'
18import { sequelizeTypescript } from '../../../initializers/database' 26import { sequelizeTypescript } from '../../../initializers/database'
19import { generateVideoMiniature } from '../../thumbnail' 27import { VideoModel } from '../../../models/video/video'
20import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' 28import { VideoFileModel } from '../../../models/video/video-file'
29import { VideoImportModel } from '../../../models/video/video-import'
21import { MThumbnail } from '../../../typings/models/video/thumbnail' 30import { MThumbnail } from '../../../typings/models/video/thumbnail'
22import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/typings/models/video/video-import' 31import { federateVideoIfNeeded } from '../../activitypub/videos'
23import { getVideoFilePath } from '@server/lib/video-paths' 32import { Notifier } from '../../notifier'
24import { addOptimizeOrMergeAudioJob } from '@server/helpers/video' 33import { generateVideoMiniature } from '../../thumbnail'
25 34
26async function processVideoImport (job: Bull.Job) { 35async function processVideoImport (job: Bull.Job) {
27 const payload = job.data as VideoImportPayload 36 const payload = job.data as VideoImportPayload
@@ -44,6 +53,7 @@ async function processTorrentImport (job: Bull.Job, payload: VideoImportTorrentP
44 const videoImport = await getVideoImportOrDie(payload.videoImportId) 53 const videoImport = await getVideoImportOrDie(payload.videoImportId)
45 54
46 const options = { 55 const options = {
56 type: payload.type,
47 videoImportId: payload.videoImportId, 57 videoImportId: payload.videoImportId,
48 58
49 generateThumbnail: true, 59 generateThumbnail: true,
@@ -61,6 +71,7 @@ async function processYoutubeDLImport (job: Bull.Job, payload: VideoImportYoutub
61 71
62 const videoImport = await getVideoImportOrDie(payload.videoImportId) 72 const videoImport = await getVideoImportOrDie(payload.videoImportId)
63 const options = { 73 const options = {
74 type: payload.type,
64 videoImportId: videoImport.id, 75 videoImportId: videoImport.id,
65 76
66 generateThumbnail: payload.generateThumbnail, 77 generateThumbnail: payload.generateThumbnail,
@@ -80,6 +91,7 @@ async function getVideoImportOrDie (videoImportId: number) {
80} 91}
81 92
82type ProcessFileOptions = { 93type ProcessFileOptions = {
94 type: VideoImportYoutubeDLPayloadType | VideoImportTorrentPayloadType
83 videoImportId: number 95 videoImportId: number
84 96
85 generateThumbnail: boolean 97 generateThumbnail: boolean
@@ -105,7 +117,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid
105 const fps = await getVideoFileFPS(tempVideoPath) 117 const fps = await getVideoFileFPS(tempVideoPath)
106 const duration = await getDurationFromVideoFile(tempVideoPath) 118 const duration = await getDurationFromVideoFile(tempVideoPath)
107 119
108 // Create video file object in database 120 // Prepare video file object for creation in database
109 const videoFileData = { 121 const videoFileData = {
110 extname: extname(tempVideoPath), 122 extname: extname(tempVideoPath),
111 resolution: videoFileResolution, 123 resolution: videoFileResolution,
@@ -115,6 +127,30 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid
115 } 127 }
116 videoFile = new VideoFileModel(videoFileData) 128 videoFile = new VideoFileModel(videoFileData)
117 129
130 const hookName = options.type === 'youtube-dl'
131 ? 'filter:api.video.post-import-url.accept.result'
132 : 'filter:api.video.post-import-torrent.accept.result'
133
134 // Check we accept this video
135 const acceptParameters = {
136 videoImport,
137 video: videoImport.Video,
138 videoFilePath: tempVideoPath,
139 videoFile,
140 user: videoImport.User
141 }
142 const acceptedResult = await Hooks.wrapFun(isPostImportVideoAccepted, acceptParameters, hookName)
143
144 if (acceptedResult.accepted !== true) {
145 logger.info('Refused imported video.', { acceptedResult, acceptParameters })
146
147 videoImport.state = VideoImportState.REJECTED
148 await videoImport.save()
149
150 throw new Error(acceptedResult.errorMessage)
151 }
152
153 // Video is accepted, resuming preparation
118 const videoWithFiles = Object.assign(videoImport.Video, { VideoFiles: [ videoFile ], VideoStreamingPlaylists: [] }) 154 const videoWithFiles = Object.assign(videoImport.Video, { VideoFiles: [ videoFile ], VideoStreamingPlaylists: [] })
119 // To clean files if the import fails 155 // To clean files if the import fails
120 const videoImportWithFiles: MVideoImportDefaultFiles = Object.assign(videoImport, { Video: videoWithFiles }) 156 const videoImportWithFiles: MVideoImportDefaultFiles = Object.assign(videoImport, { Video: videoWithFiles })
@@ -194,7 +230,9 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid
194 } 230 }
195 231
196 videoImport.error = err.message 232 videoImport.error = err.message
197 videoImport.state = VideoImportState.FAILED 233 if (videoImport.state !== VideoImportState.REJECTED) {
234 videoImport.state = VideoImportState.FAILED
235 }
198 await videoImport.save() 236 await videoImport.save()
199 237
200 Notifier.Instance.notifyOnFinishedVideoImport(videoImport, false) 238 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 @@
1import { VideoModel } from '../models/video/video' 1import { VideoModel } from '../models/video/video'
2import { VideoCommentModel } from '../models/video/video-comment' 2import { VideoCommentModel } from '../models/video/video-comment'
3import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' 3import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model'
4import { VideoCreate } from '../../shared/models/videos' 4import { VideoCreate, VideoImportCreate } from '../../shared/models/videos'
5import { UserModel } from '../models/account/user' 5import { UserModel } from '../models/account/user'
6import { VideoTorrentObject } from '../../shared/models/activitypub/objects' 6import { VideoTorrentObject } from '../../shared/models/activitypub/objects'
7import { ActivityCreate } from '../../shared/models/activitypub' 7import { ActivityCreate } from '../../shared/models/activitypub'
8import { ActorModel } from '../models/activitypub/actor' 8import { ActorModel } from '../models/activitypub/actor'
9import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' 9import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
10import { VideoFileModel } from '@server/models/video/video-file'
11import { PathLike } from 'fs-extra'
12import { MUser } from '@server/typings/models'
10 13
11export type AcceptResult = { 14export type AcceptResult = {
12 accepted: boolean 15 accepted: boolean
@@ -55,10 +58,27 @@ function isRemoteVideoCommentAccepted (_object: {
55 return { accepted: true } 58 return { accepted: true }
56} 59}
57 60
61function isPreImportVideoAccepted (object: {
62 videoImportBody: VideoImportCreate
63 user: MUser
64}): AcceptResult {
65 return { accepted: true }
66}
67
68function isPostImportVideoAccepted (object: {
69 videoFilePath: PathLike
70 videoFile: VideoFileModel
71 user: MUser
72}): AcceptResult {
73 return { accepted: true }
74}
75
58export { 76export {
59 isLocalVideoAccepted, 77 isLocalVideoAccepted,
60 isLocalVideoThreadAccepted, 78 isLocalVideoThreadAccepted,
61 isRemoteVideoAccepted, 79 isRemoteVideoAccepted,
62 isRemoteVideoCommentAccepted, 80 isRemoteVideoCommentAccepted,
63 isLocalVideoCommentReplyAccepted 81 isLocalVideoCommentReplyAccepted,
82 isPreImportVideoAccepted,
83 isPostImportVideoAccepted
64} 84}