]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/videos/video-studio.ts
Merge branch 'release/5.0.0' into develop
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / videos / video-studio.ts
1 import express from 'express'
2 import { body, param } from 'express-validator'
3 import { isIdOrUUIDValid } from '@server/helpers/custom-validators/misc'
4 import {
5 isStudioCutTaskValid,
6 isStudioTaskAddIntroOutroValid,
7 isStudioTaskAddWatermarkValid,
8 isValidStudioTasksArray
9 } from '@server/helpers/custom-validators/video-studio'
10 import { cleanUpReqFiles } from '@server/helpers/express-utils'
11 import { CONFIG } from '@server/initializers/config'
12 import { approximateIntroOutroAdditionalSize, getTaskFile } from '@server/lib/video-studio'
13 import { isAudioFile } from '@shared/extra-utils'
14 import { HttpStatusCode, UserRight, VideoState, VideoStudioCreateEdition, VideoStudioTask } from '@shared/models'
15 import { areValidationErrors, checkUserCanManageVideo, checkUserQuota, doesVideoExist } from '../shared'
16
17 const videoStudioAddEditionValidator = [
18 param('videoId')
19 .custom(isIdOrUUIDValid).withMessage('Should have a valid video id/uuid/short uuid'),
20
21 body('tasks')
22 .custom(isValidStudioTasksArray).withMessage('Should have a valid array of tasks'),
23
24 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
25 if (CONFIG.VIDEO_STUDIO.ENABLED !== true) {
26 res.fail({
27 status: HttpStatusCode.BAD_REQUEST_400,
28 message: 'Video studio is disabled on this instance'
29 })
30
31 return cleanUpReqFiles(req)
32 }
33
34 if (areValidationErrors(req, res)) return cleanUpReqFiles(req)
35
36 const body: VideoStudioCreateEdition = req.body
37 const files = req.files as Express.Multer.File[]
38
39 for (let i = 0; i < body.tasks.length; i++) {
40 const task = body.tasks[i]
41
42 if (!checkTask(req, task, i)) {
43 res.fail({
44 status: HttpStatusCode.BAD_REQUEST_400,
45 message: `Task ${task.name} is invalid`
46 })
47
48 return cleanUpReqFiles(req)
49 }
50
51 if (task.name === 'add-intro' || task.name === 'add-outro') {
52 const filePath = getTaskFile(files, i).path
53
54 // Our concat filter needs a video stream
55 if (await isAudioFile(filePath)) {
56 res.fail({
57 status: HttpStatusCode.BAD_REQUEST_400,
58 message: `Task ${task.name} is invalid: file does not contain a video stream`
59 })
60
61 return cleanUpReqFiles(req)
62 }
63 }
64 }
65
66 if (!await doesVideoExist(req.params.videoId, res)) return cleanUpReqFiles(req)
67
68 const video = res.locals.videoAll
69 if (video.state === VideoState.TO_TRANSCODE || video.state === VideoState.TO_EDIT) {
70 res.fail({
71 status: HttpStatusCode.CONFLICT_409,
72 message: 'Cannot edit video that is already waiting for transcoding/edition'
73 })
74
75 return cleanUpReqFiles(req)
76 }
77
78 const user = res.locals.oauth.token.User
79 if (!checkUserCanManageVideo(user, video, UserRight.UPDATE_ANY_VIDEO, res)) return cleanUpReqFiles(req)
80
81 // Try to make an approximation of bytes added by the intro/outro
82 const additionalBytes = await approximateIntroOutroAdditionalSize(video, body.tasks, i => getTaskFile(files, i).path)
83 if (await checkUserQuota(user, additionalBytes, res) === false) return cleanUpReqFiles(req)
84
85 return next()
86 }
87 ]
88
89 // ---------------------------------------------------------------------------
90
91 export {
92 videoStudioAddEditionValidator
93 }
94
95 // ---------------------------------------------------------------------------
96
97 const taskCheckers: {
98 [id in VideoStudioTask['name']]: (task: VideoStudioTask, indice?: number, files?: Express.Multer.File[]) => boolean
99 } = {
100 'cut': isStudioCutTaskValid,
101 'add-intro': isStudioTaskAddIntroOutroValid,
102 'add-outro': isStudioTaskAddIntroOutroValid,
103 'add-watermark': isStudioTaskAddWatermarkValid
104 }
105
106 function checkTask (req: express.Request, task: VideoStudioTask, indice?: number) {
107 const checker = taskCheckers[task.name]
108 if (!checker) return false
109
110 return checker(task, indice, req.files as Express.Multer.File[])
111 }