X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Flib%2Factivitypub%2Fvideos.ts;h=62f589272e8fdfdfbdda3767bbe9e74a5753d1ad;hb=652c64165b3d8d1c5d5fc646c29e5cd1c82a3330;hp=7d8296e45e75b38267c02eec29616178feb62aea;hpb=a3b7421abb4192e215aa280418b62e96958c5e42;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 7d8296e45..62f589272 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts @@ -14,7 +14,7 @@ import { } from '../../../shared/index' import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' import { VideoPrivacy } from '../../../shared/models/videos' -import { sanitizeAndCheckVideoTorrentObject } from '../../helpers/custom-validators/activitypub/videos' +import { isAPVideoFileMetadataObject, sanitizeAndCheckVideoTorrentObject } from '../../helpers/custom-validators/activitypub/videos' import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' import { deleteNonExistingModels, resetSequelizeInstance, retryTransactionWrapper } from '../../helpers/database-utils' import { logger } from '../../helpers/logger' @@ -25,7 +25,8 @@ import { P2P_MEDIA_LOADER_PEER_VERSION, PREVIEWS_SIZE, REMOTE_SCHEME, - STATIC_PATHS, THUMBNAILS_SIZE + STATIC_PATHS, + THUMBNAILS_SIZE } from '../../initializers/constants' import { TagModel } from '../../models/video/tag' import { VideoModel } from '../../models/video/video' @@ -68,7 +69,8 @@ import { MVideoAPWithoutCaption, MVideoFile, MVideoFullLight, - MVideoId, MVideoImmutable, + MVideoId, + MVideoImmutable, MVideoThumbnail } from '../../typings/models' import { MThumbnail } from '../../typings/models/video/thumbnail' @@ -111,7 +113,7 @@ async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request. logger.info('Fetching remote video %s.', videoUrl) - const { response, body } = await doRequest(options) + const { response, body } = await doRequest(options) if (sanitizeAndCheckVideoTorrentObject(body) === false || checkUrlsSameHost(body.id, videoUrl) !== true) { logger.debug('Remote video JSON is not valid.', { body }) @@ -129,7 +131,7 @@ async function fetchRemoteVideoDescription (video: MVideoAccountLight) { json: true } - const { body } = await doRequest(options) + const { body } = await doRequest(options) return body.description ? body.description : '' } @@ -340,9 +342,11 @@ async function updateVideoFromAP (options: { if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel, t) - const previewUrl = videoUpdated.getPreview().getFileUrl(videoUpdated) - const previewModel = createPlaceholderThumbnail(previewUrl, video, ThumbnailType.PREVIEW, PREVIEWS_SIZE) - await videoUpdated.addAndSaveThumbnail(previewModel, t) + if (videoUpdated.getPreview()) { + const previewUrl = videoUpdated.getPreview().getFileUrl(videoUpdated) + const previewModel = createPlaceholderThumbnail(previewUrl, video, ThumbnailType.PREVIEW, PREVIEWS_SIZE) + await videoUpdated.addAndSaveThumbnail(previewModel, t) + } { const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoUpdated, videoObject.url) @@ -505,7 +509,7 @@ function isAPVideoUrlObject (url: any): url is ActivityVideoUrlObject { const mimeTypes = Object.keys(MIMETYPES.VIDEO.MIMETYPE_EXT) const urlMediaType = url.mediaType - return mimeTypes.indexOf(urlMediaType) !== -1 && urlMediaType.startsWith('video/') + return mimeTypes.includes(urlMediaType) && urlMediaType.startsWith('video/') } function isAPStreamingPlaylistUrlObject (url: ActivityUrlObject): url is ActivityPlaylistUrlObject { @@ -531,6 +535,10 @@ async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAc const video = VideoModel.build(videoData) as MVideoThumbnail const promiseThumbnail = createVideoMiniatureFromUrl(getThumbnailFromIcons(videoObject).url, video, ThumbnailType.MINIATURE) + .catch(err => { + logger.error('Cannot create miniature from url.', { err }) + return undefined + }) let thumbnailModel: MThumbnail if (waitThumbnail === true) { @@ -602,34 +610,35 @@ async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAc }) if (waitThumbnail === false) { + // Error is already caught above + // eslint-disable-next-line @typescript-eslint/no-floating-promises promiseThumbnail.then(thumbnailModel => { + if (!thumbnailModel) return + thumbnailModel = videoCreated.id return thumbnailModel.save() - }).catch(err => logger.error('Cannot create miniature from url.', { err })) + }) } return { autoBlacklisted, videoCreated } } function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoTorrentObject, to: string[] = []) { - const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED - const duration = videoObject.duration.replace(/[^\d]+/, '') + const privacy = to.includes(ACTIVITY_PUB.PUBLIC) + ? VideoPrivacy.PUBLIC + : VideoPrivacy.UNLISTED - let language: string | undefined - if (videoObject.language) { - language = videoObject.language.identifier - } + const duration = videoObject.duration.replace(/[^\d]+/, '') + const language = videoObject.language?.identifier - let category: number | undefined - if (videoObject.category) { - category = parseInt(videoObject.category.identifier, 10) - } + const category = videoObject.category + ? parseInt(videoObject.category.identifier, 10) + : undefined - let licence: number | undefined - if (videoObject.licence) { - licence = parseInt(videoObject.licence.identifier, 10) - } + const licence = videoObject.licence + ? parseInt(videoObject.licence.identifier, 10) + : undefined const description = videoObject.content || null const support = videoObject.support || null @@ -652,7 +661,11 @@ function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObjec duration: parseInt(duration, 10), createdAt: new Date(videoObject.published), publishedAt: new Date(videoObject.published), - originallyPublishedAt: videoObject.originallyPublishedAt ? new Date(videoObject.originallyPublishedAt) : null, + + originallyPublishedAt: videoObject.originallyPublishedAt + ? new Date(videoObject.originallyPublishedAt) + : null, + updatedAt: new Date(videoObject.updated), views: videoObject.views, likes: 0, @@ -683,6 +696,14 @@ function videoFileActivityUrlToDBAttributes ( throw new Error('Cannot parse magnet URI ' + magnet.href) } + // Fetch associated metadata url, if any + const metadata = urls.filter(isAPVideoFileMetadataObject) + .find(u => { + return u.height === fileUrl.height && + u.fps === fileUrl.fps && + u.rel.includes(fileUrl.mediaType) + }) + const mediaType = fileUrl.mediaType const attribute = { extname: MIMETYPES.VIDEO.MIMETYPE_EXT[mediaType], @@ -690,6 +711,7 @@ function videoFileActivityUrlToDBAttributes ( resolution: fileUrl.height, size: fileUrl.size, fps: fileUrl.fps || -1, + metadataUrl: metadata?.href, // This is a video file owned by a video or by a streaming playlist videoId: (videoOrPlaylist as MStreamingPlaylist).playlistUrl ? null : videoOrPlaylist.id,