X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Flib%2Fjob-queue%2Fhandlers%2Fvideo-import.ts;h=4de901c0c1f55236e7ff1018955e3aeb5e532cdc;hb=dbe6aa698eaacf9125d2c4232dee6e3e1f0d7ba1;hp=c457b71fc8d21294f06839d4ffdeebf175d26176;hpb=ce33919c24e7402d92d81f3cd8e545df52d98240;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index c457b71fc..4de901c0c 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts @@ -6,14 +6,15 @@ import { VideoImportState } from '../../../../shared/models/videos' import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' import { extname, join } from 'path' import { VideoFileModel } from '../../../models/video/video-file' -import { renamePromise, statPromise, unlinkPromise } from '../../../helpers/core-utils' -import { CONFIG, sequelizeTypescript } from '../../../initializers' -import { doRequestAndSaveToFile } from '../../../helpers/requests' +import { CONFIG, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_IMPORT_TIMEOUT } from '../../../initializers' +import { doRequestAndSaveToFile, downloadImage } from '../../../helpers/requests' import { VideoState } from '../../../../shared' import { JobQueue } from '../index' import { federateVideoIfNeeded } from '../../activitypub' import { VideoModel } from '../../../models/video/video' import { downloadWebTorrentVideo } from '../../../helpers/webtorrent' +import { getSecureTorrentName } from '../../../helpers/utils' +import { remove, rename, stat } from 'fs-extra' type VideoImportYoutubeDLPayload = { type: 'youtube-dl' @@ -25,7 +26,7 @@ type VideoImportYoutubeDLPayload = { } type VideoImportTorrentPayload = { - type: 'magnet-uri' + type: 'magnet-uri' | 'torrent-file' videoImportId: number } @@ -35,7 +36,7 @@ async function processVideoImport (job: Bull.Job) { const payload = job.data as VideoImportPayload if (payload.type === 'youtube-dl') return processYoutubeDLImport(job, payload) - if (payload.type === 'magnet-uri') return processTorrentImport(job, payload) + if (payload.type === 'magnet-uri' || payload.type === 'torrent-file') return processTorrentImport(job, payload) } // --------------------------------------------------------------------------- @@ -50,6 +51,7 @@ async function processTorrentImport (job: Bull.Job, payload: VideoImportTorrentP logger.info('Processing torrent video import in job %d.', job.id) const videoImport = await getVideoImportOrDie(payload.videoImportId) + const options = { videoImportId: payload.videoImportId, @@ -59,7 +61,11 @@ async function processTorrentImport (job: Bull.Job, payload: VideoImportTorrentP generateThumbnail: true, generatePreview: true } - return processFile(() => downloadWebTorrentVideo(videoImport.magnetUri), videoImport, options) + const target = { + torrentName: videoImport.torrentName ? getSecureTorrentName(videoImport.torrentName) : undefined, + magnetUri: videoImport.magnetUri + } + return processFile(() => downloadWebTorrentVideo(target, VIDEO_IMPORT_TIMEOUT), videoImport, options) } async function processYoutubeDLImport (job: Bull.Job, payload: VideoImportYoutubeDLPayload) { @@ -77,7 +83,7 @@ async function processYoutubeDLImport (job: Bull.Job, payload: VideoImportYoutub generatePreview: false } - return processFile(() => downloadYoutubeDLVideo(videoImport.targetUrl), videoImport, options) + return processFile(() => downloadYoutubeDLVideo(videoImport.targetUrl, VIDEO_IMPORT_TIMEOUT), videoImport, options) } async function getVideoImportOrDie (videoImportId: number) { @@ -108,9 +114,14 @@ async function processFile (downloader: () => Promise, videoImport: Vide tempVideoPath = await downloader() // Get information about this video + const stats = await stat(tempVideoPath) + const isAble = await videoImport.User.isAbleToUploadVideo({ size: stats.size }) + if (isAble === false) { + throw new Error('The user video quota is exceeded with this video to import.') + } + const { videoFileResolution } = await getVideoFileResolution(tempVideoPath) const fps = await getVideoFileFPS(tempVideoPath) - const stats = await statPromise(tempVideoPath) const duration = await getDurationFromVideoFile(tempVideoPath) // Create video file object in database @@ -122,19 +133,19 @@ async function processFile (downloader: () => Promise, videoImport: Vide videoId: videoImport.videoId } videoFile = new VideoFileModel(videoFileData) - // Import if the import fails, to clean files + // To clean files if the import fails videoImport.Video.VideoFiles = [ videoFile ] // Move file videoDestFile = join(CONFIG.STORAGE.VIDEOS_DIR, videoImport.Video.getVideoFilename(videoFile)) - await renamePromise(tempVideoPath, videoDestFile) + await rename(tempVideoPath, videoDestFile) tempVideoPath = null // This path is not used anymore // Process thumbnail if (options.downloadThumbnail) { if (options.thumbnailUrl) { const destThumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, videoImport.Video.getThumbnailName()) - await doRequestAndSaveToFile({ method: 'GET', uri: options.thumbnailUrl }, destThumbnailPath) + await downloadImage(options.thumbnailUrl, destThumbnailPath, THUMBNAILS_SIZE) } else { await videoImport.Video.createThumbnail(videoFile) } @@ -146,7 +157,7 @@ async function processFile (downloader: () => Promise, videoImport: Vide if (options.downloadPreview) { if (options.thumbnailUrl) { const destPreviewPath = join(CONFIG.STORAGE.PREVIEWS_DIR, videoImport.Video.getPreviewName()) - await doRequestAndSaveToFile({ method: 'GET', uri: options.thumbnailUrl }, destPreviewPath) + await downloadImage(options.thumbnailUrl, destPreviewPath, PREVIEWS_SIZE) } else { await videoImport.Video.createPreview(videoFile) } @@ -172,14 +183,14 @@ async function processFile (downloader: () => Promise, videoImport: Vide const videoUpdated = await video.save({ transaction: t }) // Now we can federate the video (reload from database, we need more attributes) - const videoForFederation = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(video.uuid, t) + const videoForFederation = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) await federateVideoIfNeeded(videoForFederation, true, t) // Update video import object videoImport.state = VideoImportState.SUCCESS const videoImportUpdated = await videoImport.save({ transaction: t }) - logger.info('Video %s imported.', videoImport.targetUrl) + logger.info('Video %s imported.', video.uuid) videoImportUpdated.Video = videoUpdated return videoImportUpdated @@ -198,7 +209,7 @@ async function processFile (downloader: () => Promise, videoImport: Vide } catch (err) { try { - if (tempVideoPath) await unlinkPromise(tempVideoPath) + if (tempVideoPath) await remove(tempVideoPath) } catch (errUnlink) { logger.warn('Cannot cleanup files after a video import error.', { err: errUnlink }) }