X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fcontrollers%2Fapi%2Fvideos%2Fimport.ts;h=28ced58368b2939f0957d09cb0f69f0723793646;hb=d7a25329f9e607894d29ab342b9cb66638b56dc0;hp=94dafcdbdc28707699f0a6a714f6b3a89962ca78;hpb=a84b8fa5cf6e4cafb841af3db9bdfcc9531c09a4;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts index 94dafcdbd..28ced5836 100644 --- a/server/controllers/api/videos/import.ts +++ b/server/controllers/api/videos/import.ts @@ -1,16 +1,8 @@ import * as express from 'express' import * as magnetUtil from 'magnet-uri' -import 'multer' -import { auditLoggerFactory, VideoImportAuditView } from '../../../helpers/audit-logger' +import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger' import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoImportAddValidator } from '../../../middlewares' -import { - CONFIG, - IMAGE_MIMETYPE_EXT, - PREVIEWS_SIZE, - sequelizeTypescript, - THUMBNAILS_SIZE, - TORRENT_MIMETYPE_EXT -} from '../../../initializers' +import { MIMETYPES } from '../../../initializers/constants' import { getYoutubeDLInfo, YoutubeDLInfo } from '../../../helpers/youtube-dl' import { createReqFiles } from '../../../helpers/express-utils' import { logger } from '../../../helpers/logger' @@ -20,26 +12,38 @@ import { getVideoActivityPubUrl } from '../../../lib/activitypub' import { TagModel } from '../../../models/video/tag' import { VideoImportModel } from '../../../models/video/video-import' import { JobQueue } from '../../../lib/job-queue/job-queue' -import { processImage } from '../../../helpers/image-utils' import { join } from 'path' import { isArray } from '../../../helpers/custom-validators/misc' -import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model' -import { VideoChannelModel } from '../../../models/video/video-channel' import * as Bluebird from 'bluebird' import * as parseTorrent from 'parse-torrent' -import { readFileBufferPromise, renamePromise } from '../../../helpers/core-utils' import { getSecureTorrentName } from '../../../helpers/utils' +import { move, readFile } from 'fs-extra' +import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' +import { CONFIG } from '../../../initializers/config' +import { sequelizeTypescript } from '../../../initializers/database' +import { createVideoMiniatureFromExisting } from '../../../lib/thumbnail' +import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' +import { + MChannelAccountDefault, + MThumbnail, + MUser, + MVideoAccountDefault, + MVideoTag, + MVideoThumbnailAccountDefault, + MVideoWithBlacklistLight +} from '@server/typings/models' +import { MVideoImport, MVideoImportFormattable } from '@server/typings/models/video/video-import' const auditLogger = auditLoggerFactory('video-imports') const videoImportsRouter = express.Router() const reqVideoFileImport = createReqFiles( [ 'thumbnailfile', 'previewfile', 'torrentfile' ], - Object.assign({}, TORRENT_MIMETYPE_EXT, IMAGE_MIMETYPE_EXT), + Object.assign({}, MIMETYPES.TORRENT.MIMETYPE_EXT, MIMETYPES.IMAGE.MIMETYPE_EXT), { - thumbnailfile: CONFIG.STORAGE.THUMBNAILS_DIR, - previewfile: CONFIG.STORAGE.PREVIEWS_DIR, - torrentfile: CONFIG.STORAGE.TORRENTS_DIR + thumbnailfile: CONFIG.STORAGE.TMP_DIR, + previewfile: CONFIG.STORAGE.TMP_DIR, + torrentfile: CONFIG.STORAGE.TMP_DIR } ) @@ -78,10 +82,10 @@ async function addTorrentImport (req: express.Request, res: express.Response, to // Rename the torrent to a secured name const newTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, getSecureTorrentName(torrentName)) - await renamePromise(torrentfile.path, newTorrentPath) + await move(torrentfile.path, newTorrentPath) torrentfile.path = newTorrentPath - const buf = await readFileBufferPromise(torrentfile.path) + const buf = await readFile(torrentfile.path) const parsedTorrent = parseTorrent(buf) videoName = isArray(parsedTorrent.name) ? parsedTorrent.name[ 0 ] : parsedTorrent.name as string @@ -94,17 +98,25 @@ async function addTorrentImport (req: express.Request, res: express.Response, to const video = buildVideo(res.locals.videoChannel.id, body, { name: videoName }) - await processThumbnail(req, video) - await processPreview(req, video) + const thumbnailModel = await processThumbnail(req, video) + const previewModel = await processPreview(req, video) - const tags = null + const tags = body.tags || undefined const videoImportAttributes = { magnetUri, torrentName, state: VideoImportState.PENDING, userId: user.id } - const videoImport: VideoImportModel = await insertIntoDB(video, res.locals.videoChannel, tags, videoImportAttributes) + const videoImport = await insertIntoDB({ + video, + thumbnailModel, + previewModel, + videoChannel: res.locals.videoChannel, + tags, + videoImportAttributes, + user + }) // Create job to import the video const payload = { @@ -114,7 +126,7 @@ async function addTorrentImport (req: express.Request, res: express.Response, to } await JobQueue.Instance.createJob({ type: 'video-import', payload }) - auditLogger.create(res.locals.oauth.token.User.Account.Actor.getIdentifier(), new VideoImportAuditView(videoImport.toFormattedJSON())) + auditLogger.create(getAuditIdFromRes(res), new VideoImportAuditView(videoImport.toFormattedJSON())) return res.json(videoImport.toFormattedJSON()).end() } @@ -137,8 +149,8 @@ async function addYoutubeDLImport (req: express.Request, res: express.Response) const video = buildVideo(res.locals.videoChannel.id, body, youtubeDLInfo) - const downloadThumbnail = !await processThumbnail(req, video) - const downloadPreview = !await processPreview(req, video) + const thumbnailModel = await processThumbnail(req, video) + const previewModel = await processPreview(req, video) const tags = body.tags || youtubeDLInfo.tags const videoImportAttributes = { @@ -146,19 +158,27 @@ async function addYoutubeDLImport (req: express.Request, res: express.Response) state: VideoImportState.PENDING, userId: user.id } - const videoImport: VideoImportModel = await insertIntoDB(video, res.locals.videoChannel, tags, videoImportAttributes) + const videoImport = await insertIntoDB({ + video, + thumbnailModel, + previewModel, + videoChannel: res.locals.videoChannel, + tags, + videoImportAttributes, + user + }) // Create job to import the video const payload = { type: 'youtube-dl' as 'youtube-dl', videoImportId: videoImport.id, thumbnailUrl: youtubeDLInfo.thumbnailUrl, - downloadThumbnail, - downloadPreview + downloadThumbnail: !thumbnailModel, + downloadPreview: !previewModel } await JobQueue.Instance.createJob({ type: 'video-import', payload }) - auditLogger.create(res.locals.oauth.token.User.Account.Actor.getIdentifier(), new VideoImportAuditView(videoImport.toFormattedJSON())) + auditLogger.create(getAuditIdFromRes(res), new VideoImportAuditView(videoImport.toFormattedJSON())) return res.json(videoImport.toFormattedJSON()).end() } @@ -170,7 +190,8 @@ function buildVideo (channelId: number, body: VideoImportCreate, importData: You category: body.category || importData.category, licence: body.licence || importData.licence, language: body.language || undefined, - commentsEnabled: body.commentsEnabled || true, + commentsEnabled: body.commentsEnabled !== false, // If the value is not "false", the default is "true" + downloadEnabled: body.downloadEnabled !== false, waitTranscoding: body.waitTranscoding || false, state: VideoState.TO_IMPORT, nsfw: body.nsfw || importData.nsfw || false, @@ -178,7 +199,8 @@ function buildVideo (channelId: number, body: VideoImportCreate, importData: You support: body.support || null, privacy: body.privacy || VideoPrivacy.PRIVATE, duration: 0, // duration will be set by the import job - channelId: channelId + channelId: channelId, + originallyPublishedAt: importData.originallyPublishedAt } const video = new VideoModel(videoData) video.url = getVideoActivityPubUrl(video) @@ -190,52 +212,69 @@ async function processThumbnail (req: express.Request, video: VideoModel) { const thumbnailField = req.files ? req.files['thumbnailfile'] : undefined if (thumbnailField) { const thumbnailPhysicalFile = thumbnailField[ 0 ] - await processImage(thumbnailPhysicalFile, join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName()), THUMBNAILS_SIZE) - return true + return createVideoMiniatureFromExisting(thumbnailPhysicalFile.path, video, ThumbnailType.MINIATURE, false) } - return false + return undefined } async function processPreview (req: express.Request, video: VideoModel) { const previewField = req.files ? req.files['previewfile'] : undefined if (previewField) { const previewPhysicalFile = previewField[0] - await processImage(previewPhysicalFile, join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName()), PREVIEWS_SIZE) - return true + return createVideoMiniatureFromExisting(previewPhysicalFile.path, video, ThumbnailType.PREVIEW, false) } - return false + return undefined } -function insertIntoDB ( - video: VideoModel, - videoChannel: VideoChannelModel, +function insertIntoDB (parameters: { + video: MVideoThumbnailAccountDefault, + thumbnailModel: MThumbnail, + previewModel: MThumbnail, + videoChannel: MChannelAccountDefault, tags: string[], - videoImportAttributes: FilteredModelAttributes -): Bluebird { + videoImportAttributes: Partial, + user: MUser +}): Bluebird { + const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters + return sequelizeTypescript.transaction(async t => { const sequelizeOptions = { transaction: t } // Save video object in database - const videoCreated = await video.save(sequelizeOptions) + const videoCreated = await video.save(sequelizeOptions) as (MVideoAccountDefault & MVideoWithBlacklistLight & MVideoTag) videoCreated.VideoChannel = videoChannel + if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t) + if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t) + + await autoBlacklistVideoIfNeeded({ + video: videoCreated, + user, + notify: false, + isRemote: false, + isNew: true, + transaction: t + }) + // Set tags to the video - if (tags !== undefined) { + if (tags) { const tagInstances = await TagModel.findOrCreateTags(tags, t) await videoCreated.$set('Tags', tagInstances, sequelizeOptions) videoCreated.Tags = tagInstances + } else { + videoCreated.Tags = [] } // Create video import object in database const videoImport = await VideoImportModel.create( Object.assign({ videoId: videoCreated.id }, videoImportAttributes), sequelizeOptions - ) + ) as MVideoImportFormattable videoImport.Video = videoCreated return videoImport