1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 01:39:37 +02:00

Better thumbnail error handling

* Had to upgrade to es2022 to use `cause` error
 * Had to declare class attributes with declare for sequelize models, so
   it still works as before
This commit is contained in:
Chocobozzz 2025-07-25 17:01:36 +02:00
parent 29a88c0dde
commit 13bceb5f40
No known key found for this signature in database
GPG key ID: 583A612D890159BE
77 changed files with 919 additions and 912 deletions

View file

@ -1,19 +1,20 @@
import express from 'express'
import { move } from 'fs-extra/esm'
import { readFile } from 'fs/promises'
import { decode } from 'magnet-uri'
import parseTorrent, { Instance } from 'parse-torrent'
import { join } from 'path'
import { buildVideoFromImport, buildYoutubeDLImport, insertFromImportIntoDB, YoutubeDlImportError } from '@server/lib/video-pre-import.js'
import { MThumbnail, MVideoThumbnail } from '@server/types/models/index.js'
import {
HttpStatusCode,
HttpStatusCodeType,
ServerErrorCode,
ThumbnailType,
VideoImportCreate,
VideoImportPayload,
VideoImportState
} from '@peertube/peertube-models'
import { buildVideoFromImport, buildYoutubeDLImport, insertFromImportIntoDB, YoutubeDlImportError } from '@server/lib/video-pre-import.js'
import { MThumbnail, MVideoThumbnail } from '@server/types/models/index.js'
import express from 'express'
import { move } from 'fs-extra/esm'
import { readFile } from 'fs/promises'
import { decode } from 'magnet-uri'
import parseTorrent, { Instance } from 'parse-torrent'
import { join } from 'path'
import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger.js'
import { isArray } from '../../../helpers/custom-validators/misc.js'
import { cleanUpReqFiles, createReqFiles } from '../../../helpers/express-utils.js'
@ -40,20 +41,23 @@ const reqVideoFileImport = createReqFiles(
{ ...MIMETYPES.TORRENT.MIMETYPE_EXT, ...MIMETYPES.IMAGE.MIMETYPE_EXT }
)
videoImportsRouter.post('/imports',
videoImportsRouter.post(
'/imports',
authenticate,
reqVideoFileImport,
asyncMiddleware(videoImportAddValidator),
asyncRetryTransactionMiddleware(handleVideoImport)
)
videoImportsRouter.post('/imports/:id/cancel',
videoImportsRouter.post(
'/imports/:id/cancel',
authenticate,
asyncMiddleware(videoImportCancelValidator),
asyncRetryTransactionMiddleware(cancelVideoImport)
)
videoImportsRouter.delete('/imports/:id',
videoImportsRouter.delete(
'/imports/:id',
authenticate,
asyncMiddleware(videoImportDeleteValidator),
asyncRetryTransactionMiddleware(deleteVideoImport)
@ -152,7 +156,7 @@ async function handleTorrentImport (req: express.Request, res: express.Response,
return res.json(videoImport.toFormattedJSON()).end()
}
function statusFromYtDlImportError (err: YoutubeDlImportError): number {
function statusFromYtDlImportError (err: YoutubeDlImportError): HttpStatusCodeType {
switch (err.code) {
case YoutubeDlImportError.CODE.NOT_ONLY_UNICAST_URL:
return HttpStatusCode.FORBIDDEN_403

View file

@ -1,5 +1,5 @@
import { ffprobePromise, getChaptersFromContainer } from '@peertube/peertube-ffmpeg'
import { ThumbnailType, VideoCreate } from '@peertube/peertube-models'
import { isPeerTubeError, ThumbnailType, VideoCreate } from '@peertube/peertube-models'
import { uuidToShort } from '@peertube/peertube-node-utils'
import { getResumableUploadPath } from '@server/helpers/upload.js'
import { LocalVideoCreator } from '@server/lib/local-video-creator.js'
@ -38,7 +38,8 @@ const reqVideoFileAddResumable = createReqFiles(
getResumableUploadPath()
)
uploadRouter.post('/upload',
uploadRouter.post(
'/upload',
openapiOperationDoc({ operationId: 'uploadLegacy' }),
authenticate,
setReqTimeout(1000 * 60 * 10), // Uploading the video could be long
@ -90,11 +91,14 @@ async function addVideoResumable (req: express.Request, res: express.Response) {
const videoInfo = videoPhysicalFile.metadata
const files = { previewfile: videoInfo.previewfile, thumbnailfile: videoInfo.thumbnailfile }
const response = await addVideo({ req, res, videoPhysicalFile, videoInfo, files })
await Redis.Instance.deleteUploadSession(req.query.upload_id)
await uploadx.storage.delete(res.locals.uploadVideoFileResumable)
try {
const response = await addVideo({ req, res, videoPhysicalFile, videoInfo, files })
return res.json(response)
return res.json(response)
} finally {
await Redis.Instance.deleteUploadSession(req.query.upload_id)
await uploadx.storage.delete(res.locals.uploadVideoFileResumable)
}
}
async function addVideo (options: {
@ -157,19 +161,31 @@ async function addVideo (options: {
thumbnails
})
const { video } = await localVideoCreator.create()
try {
const { video } = await localVideoCreator.create()
auditLogger.create(getAuditIdFromRes(res), new VideoAuditView(video.toFormattedDetailsJSON()))
logger.info('Video with name %s and uuid %s created.', videoInfo.name, video.uuid, lTags(video.uuid))
auditLogger.create(getAuditIdFromRes(res), new VideoAuditView(video.toFormattedDetailsJSON()))
logger.info('Video with name %s and uuid %s created.', videoInfo.name, video.uuid, lTags(video.uuid))
Hooks.runAction('action:api.video.uploaded', { video, req, res })
Hooks.runAction('action:api.video.uploaded', { video, req, res })
return {
video: {
id: video.id,
shortUUID: uuidToShort(video.uuid),
uuid: video.uuid
return {
video: {
id: video.id,
shortUUID: uuidToShort(video.uuid),
uuid: video.uuid
}
}
} catch (err) {
if (isPeerTubeError(err) && err.code === 'INVALID_IMAGE_FILE') {
logger.warn('Invalid thumbnail file provided for video upload.', { err, ...lTags() })
return res.fail({
message: req.t('The provided thumbnail file is invalid.')
})
}
throw err
}
}