From 304a84d59c3a800b7f7aef48cf55f307534c0926 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 2 Jun 2021 15:47:05 +0200 Subject: Refactor getOrCreateAPVideo --- server/lib/activitypub/videos/get.ts | 109 +++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 server/lib/activitypub/videos/get.ts (limited to 'server/lib/activitypub/videos/get.ts') diff --git a/server/lib/activitypub/videos/get.ts b/server/lib/activitypub/videos/get.ts new file mode 100644 index 000000000..a8c41e178 --- /dev/null +++ b/server/lib/activitypub/videos/get.ts @@ -0,0 +1,109 @@ +import { getAPId } from '@server/helpers/activitypub' +import { retryTransactionWrapper } from '@server/helpers/database-utils' +import { fetchVideoByUrl, VideoFetchByUrlType } from '@server/helpers/video' +import { JobQueue } from '@server/lib/job-queue' +import { MVideoAccountLightBlacklistAllFiles, MVideoImmutable, MVideoThumbnail } from '@server/types/models' +import { refreshVideoIfNeeded } from './refresh' +import { APVideoCreator, fetchRemoteVideo, SyncParam, syncVideoExternalAttributes } from './shared' + +type GetVideoResult = Promise<{ + video: T + created: boolean + autoBlacklisted?: boolean +}> + +type GetVideoParamAll = { + videoObject: { id: string } | string + syncParam?: SyncParam + fetchType?: 'all' + allowRefresh?: boolean +} + +type GetVideoParamImmutable = { + videoObject: { id: string } | string + syncParam?: SyncParam + fetchType: 'only-immutable-attributes' + allowRefresh: false +} + +type GetVideoParamOther = { + videoObject: { id: string } | string + syncParam?: SyncParam + fetchType?: 'all' | 'only-video' + allowRefresh?: boolean +} + +function getOrCreateAPVideo (options: GetVideoParamAll): GetVideoResult +function getOrCreateAPVideo (options: GetVideoParamImmutable): GetVideoResult +function getOrCreateAPVideo (options: GetVideoParamOther): GetVideoResult + +async function getOrCreateAPVideo ( + options: GetVideoParamAll | GetVideoParamImmutable | GetVideoParamOther +): GetVideoResult { + // Default params + const syncParam = options.syncParam || { likes: true, dislikes: true, shares: true, comments: true, thumbnail: true, refreshVideo: false } + const fetchType = options.fetchType || 'all' + const allowRefresh = options.allowRefresh !== false + + // Get video url + const videoUrl = getAPId(options.videoObject) + let videoFromDatabase = await fetchVideoByUrl(videoUrl, fetchType) + + if (videoFromDatabase) { + if (allowRefresh === true) { + // Typings ensure allowRefresh === false in only-immutable-attributes fetch type + videoFromDatabase = await scheduleRefresh(videoFromDatabase as MVideoThumbnail, fetchType, syncParam) + } + + return { video: videoFromDatabase, created: false } + } + + const { videoObject } = await fetchRemoteVideo(videoUrl) + if (!videoObject) throw new Error('Cannot fetch remote video with url: ' + videoUrl) + + try { + const creator = new APVideoCreator(videoObject) + const { autoBlacklisted, videoCreated } = await retryTransactionWrapper(creator.create.bind(creator), syncParam.thumbnail) + + await syncVideoExternalAttributes(videoCreated, videoObject, syncParam) + + return { video: videoCreated, created: true, autoBlacklisted } + } catch (err) { + // Maybe a concurrent getOrCreateAPVideo call created this video + if (err.name === 'SequelizeUniqueConstraintError') { + const alreadyCreatedVideo = await fetchVideoByUrl(videoUrl, fetchType) + if (alreadyCreatedVideo) return { video: alreadyCreatedVideo, created: false } + } + + throw err + } +} + +// --------------------------------------------------------------------------- + +export { + getOrCreateAPVideo +} + +// --------------------------------------------------------------------------- + +async function scheduleRefresh (video: MVideoThumbnail, fetchType: VideoFetchByUrlType, syncParam: SyncParam) { + if (!video.isOutdated()) return video + + const refreshOptions = { + video, + fetchedType: fetchType, + syncParam + } + + if (syncParam.refreshVideo === true) { + return refreshVideoIfNeeded(refreshOptions) + } + + await JobQueue.Instance.createJobWithPromise({ + type: 'activitypub-refresher', + payload: { type: 'video', url: video.url } + }) + + return video +} -- cgit v1.2.3