aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/videos/import.ts21
-rw-r--r--server/helpers/youtube-dl.ts2
-rw-r--r--server/lib/job-queue/handlers/video-import.ts34
-rw-r--r--server/middlewares/validators/video-imports.ts29
-rw-r--r--server/models/video/video.ts6
5 files changed, 34 insertions, 58 deletions
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts
index 680d8665f..ca7a5f9ca 100644
--- a/server/controllers/api/videos/import.ts
+++ b/server/controllers/api/videos/import.ts
@@ -4,8 +4,7 @@ import {
4 asyncMiddleware, 4 asyncMiddleware,
5 asyncRetryTransactionMiddleware, 5 asyncRetryTransactionMiddleware,
6 authenticate, 6 authenticate,
7 videoImportAddValidator, 7 videoImportAddValidator
8 videoImportDeleteValidator
9} from '../../../middlewares' 8} from '../../../middlewares'
10import { CONFIG, IMAGE_MIMETYPE_EXT, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE } from '../../../initializers' 9import { CONFIG, IMAGE_MIMETYPE_EXT, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE } from '../../../initializers'
11import { getYoutubeDLInfo, YoutubeDLInfo } from '../../../helpers/youtube-dl' 10import { getYoutubeDLInfo, YoutubeDLInfo } from '../../../helpers/youtube-dl'
@@ -39,12 +38,6 @@ videoImportsRouter.post('/imports',
39 asyncRetryTransactionMiddleware(addVideoImport) 38 asyncRetryTransactionMiddleware(addVideoImport)
40) 39)
41 40
42videoImportsRouter.delete('/imports/:id',
43 authenticate,
44 asyncMiddleware(videoImportDeleteValidator),
45 asyncRetryTransactionMiddleware(deleteVideoImport)
46)
47
48// --------------------------------------------------------------------------- 41// ---------------------------------------------------------------------------
49 42
50export { 43export {
@@ -145,15 +138,3 @@ async function addVideoImport (req: express.Request, res: express.Response) {
145 138
146 return res.json(videoImport.toFormattedJSON()) 139 return res.json(videoImport.toFormattedJSON())
147} 140}
148
149async function deleteVideoImport (req: express.Request, res: express.Response) {
150 await sequelizeTypescript.transaction(async t => {
151 const videoImport = res.locals.videoImport
152 const video = videoImport.Video
153
154 await videoImport.destroy({ transaction: t })
155 await video.destroy({ transaction: t })
156 })
157
158 return res.status(204).end()
159}
diff --git a/server/helpers/youtube-dl.ts b/server/helpers/youtube-dl.ts
index 43156bb22..ff1fbf59f 100644
--- a/server/helpers/youtube-dl.ts
+++ b/server/helpers/youtube-dl.ts
@@ -30,7 +30,7 @@ function getYoutubeDLInfo (url: string): Promise<YoutubeDLInfo> {
30} 30}
31 31
32function downloadYoutubeDLVideo (url: string) { 32function downloadYoutubeDLVideo (url: string) {
33 const hash = crypto.createHash('sha256').update(url).digest('base64') 33 const hash = crypto.createHash('sha256').update(url).digest('hex')
34 const path = join(CONFIG.STORAGE.VIDEOS_DIR, hash + '-import.mp4') 34 const path = join(CONFIG.STORAGE.VIDEOS_DIR, hash + '-import.mp4')
35 35
36 logger.info('Importing video %s', url) 36 logger.info('Importing video %s', url)
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts
index 4f2faab7d..3b9d08d3b 100644
--- a/server/lib/job-queue/handlers/video-import.ts
+++ b/server/lib/job-queue/handlers/video-import.ts
@@ -12,6 +12,7 @@ import { doRequestAndSaveToFile } from '../../../helpers/requests'
12import { VideoState } from '../../../../shared' 12import { VideoState } from '../../../../shared'
13import { JobQueue } from '../index' 13import { JobQueue } from '../index'
14import { federateVideoIfNeeded } from '../../activitypub' 14import { federateVideoIfNeeded } from '../../activitypub'
15import { VideoModel } from '../../../models/video/video'
15 16
16export type VideoImportPayload = { 17export type VideoImportPayload = {
17 type: 'youtube-dl' 18 type: 'youtube-dl'
@@ -26,9 +27,13 @@ async function processVideoImport (job: Bull.Job) {
26 logger.info('Processing video import in job %d.', job.id) 27 logger.info('Processing video import in job %d.', job.id)
27 28
28 const videoImport = await VideoImportModel.loadAndPopulateVideo(payload.videoImportId) 29 const videoImport = await VideoImportModel.loadAndPopulateVideo(payload.videoImportId)
29 if (!videoImport) throw new Error('Cannot import video %s: the video import entry does not exist anymore.') 30 if (!videoImport || !videoImport.Video) {
31 throw new Error('Cannot import video %s: the video import or video linked to this import does not exist anymore.')
32 }
30 33
31 let tempVideoPath: string 34 let tempVideoPath: string
35 let videoDestFile: string
36 let videoFile: VideoFileModel
32 try { 37 try {
33 // Download video from youtubeDL 38 // Download video from youtubeDL
34 tempVideoPath = await downloadYoutubeDLVideo(videoImport.targetUrl) 39 tempVideoPath = await downloadYoutubeDLVideo(videoImport.targetUrl)
@@ -47,11 +52,14 @@ async function processVideoImport (job: Bull.Job) {
47 fps, 52 fps,
48 videoId: videoImport.videoId 53 videoId: videoImport.videoId
49 } 54 }
50 const videoFile = new VideoFileModel(videoFileData) 55 videoFile = new VideoFileModel(videoFileData)
56 // Import if the import fails, to clean files
57 videoImport.Video.VideoFiles = [ videoFile ]
51 58
52 // Move file 59 // Move file
53 const destination = join(CONFIG.STORAGE.VIDEOS_DIR, videoImport.Video.getVideoFilename(videoFile)) 60 videoDestFile = join(CONFIG.STORAGE.VIDEOS_DIR, videoImport.Video.getVideoFilename(videoFile))
54 await renamePromise(tempVideoPath, destination) 61 await renamePromise(tempVideoPath, videoDestFile)
62 tempVideoPath = null // This path is not used anymore
55 63
56 // Process thumbnail 64 // Process thumbnail
57 if (payload.downloadThumbnail) { 65 if (payload.downloadThumbnail) {
@@ -77,15 +85,21 @@ async function processVideoImport (job: Bull.Job) {
77 await videoImport.Video.createTorrentAndSetInfoHash(videoFile) 85 await videoImport.Video.createTorrentAndSetInfoHash(videoFile)
78 86
79 const videoImportUpdated: VideoImportModel = await sequelizeTypescript.transaction(async t => { 87 const videoImportUpdated: VideoImportModel = await sequelizeTypescript.transaction(async t => {
80 await videoFile.save({ transaction: t }) 88 // Refresh video
89 const video = await VideoModel.load(videoImport.videoId, t)
90 if (!video) throw new Error('Video linked to import ' + videoImport.videoId + ' does not exist anymore.')
91 videoImport.Video = video
92
93 const videoFileCreated = await videoFile.save({ transaction: t })
94 video.VideoFiles = [ videoFileCreated ]
81 95
82 // Update video DB object 96 // Update video DB object
83 videoImport.Video.duration = duration 97 video.duration = duration
84 videoImport.Video.state = CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED 98 video.state = CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED
85 const videoUpdated = await videoImport.Video.save({ transaction: t }) 99 const videoUpdated = await video.save({ transaction: t })
86 100
87 // Now we can federate the video 101 // Now we can federate the video
88 await federateVideoIfNeeded(videoImport.Video, true, t) 102 await federateVideoIfNeeded(video, true, t)
89 103
90 // Update video import object 104 // Update video import object
91 videoImport.state = VideoImportState.SUCCESS 105 videoImport.state = VideoImportState.SUCCESS
@@ -112,7 +126,7 @@ async function processVideoImport (job: Bull.Job) {
112 try { 126 try {
113 if (tempVideoPath) await unlinkPromise(tempVideoPath) 127 if (tempVideoPath) await unlinkPromise(tempVideoPath)
114 } catch (errUnlink) { 128 } catch (errUnlink) {
115 logger.error('Cannot cleanup files after a video import error.', { err: errUnlink }) 129 logger.warn('Cannot cleanup files after a video import error.', { err: errUnlink })
116 } 130 }
117 131
118 videoImport.error = err.message 132 videoImport.error = err.message
diff --git a/server/middlewares/validators/video-imports.ts b/server/middlewares/validators/video-imports.ts
index 0dedcf803..e0a552976 100644
--- a/server/middlewares/validators/video-imports.ts
+++ b/server/middlewares/validators/video-imports.ts
@@ -1,14 +1,12 @@
1import * as express from 'express' 1import * as express from 'express'
2import { body, param } from 'express-validator/check' 2import { body } from 'express-validator/check'
3import { isIdValid } from '../../helpers/custom-validators/misc' 3import { isIdValid } from '../../helpers/custom-validators/misc'
4import { logger } from '../../helpers/logger' 4import { logger } from '../../helpers/logger'
5import { areValidationErrors } from './utils' 5import { areValidationErrors } from './utils'
6import { getCommonVideoAttributes } from './videos' 6import { getCommonVideoAttributes } from './videos'
7import { isVideoImportTargetUrlValid, isVideoImportExist } from '../../helpers/custom-validators/video-imports' 7import { isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
8import { cleanUpReqFiles } from '../../helpers/utils' 8import { cleanUpReqFiles } from '../../helpers/utils'
9import { isVideoChannelOfAccountExist, isVideoNameValid, checkUserCanManageVideo } from '../../helpers/custom-validators/videos' 9import { isVideoChannelOfAccountExist, isVideoNameValid } from '../../helpers/custom-validators/videos'
10import { VideoImportModel } from '../../models/video/video-import'
11import { UserRight } from '../../../shared'
12 10
13const videoImportAddValidator = getCommonVideoAttributes().concat([ 11const videoImportAddValidator = getCommonVideoAttributes().concat([
14 body('targetUrl').custom(isVideoImportTargetUrlValid).withMessage('Should have a valid video import target URL'), 12 body('targetUrl').custom(isVideoImportTargetUrlValid).withMessage('Should have a valid video import target URL'),
@@ -31,29 +29,10 @@ const videoImportAddValidator = getCommonVideoAttributes().concat([
31 } 29 }
32]) 30])
33 31
34const videoImportDeleteValidator = [
35 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
36
37 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
38 logger.debug('Checking videoImportDeleteValidator parameters', { parameters: req.body })
39
40 if (areValidationErrors(req, res)) return
41 if (!await isVideoImportExist(req.params.id, res)) return
42
43 const user = res.locals.oauth.token.User
44 const videoImport: VideoImportModel = res.locals.videoImport
45
46 if (!await checkUserCanManageVideo(user, videoImport.Video, UserRight.UPDATE_ANY_VIDEO, res)) return
47
48 return next()
49 }
50]
51
52// --------------------------------------------------------------------------- 32// ---------------------------------------------------------------------------
53 33
54export { 34export {
55 videoImportAddValidator, 35 videoImportAddValidator
56 videoImportDeleteValidator
57} 36}
58 37
59// --------------------------------------------------------------------------- 38// ---------------------------------------------------------------------------
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index f32010014..67711b102 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -957,8 +957,10 @@ export class VideoModel extends Model<VideoModel> {
957 }) 957 })
958 } 958 }
959 959
960 static load (id: number) { 960 static load (id: number, t?: Sequelize.Transaction) {
961 return VideoModel.findById(id) 961 const options = t ? { transaction: t } : undefined
962
963 return VideoModel.findById(id, options)
962 } 964 }
963 965
964 static loadByUrlAndPopulateAccount (url: string, t?: Sequelize.Transaction) { 966 static loadByUrlAndPopulateAccount (url: string, t?: Sequelize.Transaction) {