import { ActivityAnnounce } from '@peertube/peertube-models'
import { getAPId } from '@server/lib/activitypub/activity.js'
import { retryTransactionWrapper } from '../../../helpers/database-utils.js'
-import { logger } from '../../../helpers/logger.js'
import { sequelizeTypescript } from '../../../initializers/database.js'
import { VideoShareModel } from '../../../models/video/video-share.js'
import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
-import { MActorSignature, MVideoAccountLightBlacklistAllFiles } from '../../../types/models/index.js'
+import { MActorSignature } from '../../../types/models/index.js'
import { Notifier } from '../../notifier/index.js'
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
-import { getOrCreateAPVideo } from '../videos/index.js'
+import { maybeGetOrCreateAPVideo } from '../videos/index.js'
async function processAnnounceActivity (options: APProcessorOptions<ActivityAnnounce>) {
const { activity, byActor: actorAnnouncer } = options
async function processVideoShare (actorAnnouncer: MActorSignature, activity: ActivityAnnounce, notify: boolean) {
const objectUri = getAPId(activity.object)
- let video: MVideoAccountLightBlacklistAllFiles
- let videoCreated: boolean
-
- try {
- const result = await getOrCreateAPVideo({ videoObject: objectUri })
- video = result.video
- videoCreated = result.created
- } catch (err) {
- logger.debug('Cannot process share of %s. Maybe this is not a video object, so just skipping.', objectUri, { err })
- return
- }
+ const { video, created: videoCreated } = await maybeGetOrCreateAPVideo({ videoObject: objectUri })
+ if (!video) return
await sequelizeTypescript.transaction(async t => {
// Add share entry
import { AccountVideoRateModel } from '../../../models/account/account-video-rate.js'
import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
import { MActorSignature } from '../../../types/models/index.js'
-import { federateVideoIfNeeded, getOrCreateAPVideo } from '../videos/index.js'
+import { federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
async function processDislikeActivity (options: APProcessorOptions<ActivityDislike>) {
const { activity, byActor } = options
if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url)
- const { video: onlyVideo } = await getOrCreateAPVideo({ videoObject: dislikeObject, fetchType: 'only-video' })
-
- // We don't care about dislikes of remote videos
- if (!onlyVideo.isOwned()) return
+ const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: dislikeObject, fetchType: 'only-video' })
+ if (!onlyVideo?.isOwned()) return
return sequelizeTypescript.transaction(async t => {
const video = await VideoModel.loadFull(onlyVideo.id, t)
import { AccountVideoRateModel } from '../../../models/account/account-video-rate.js'
import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
import { MActorSignature } from '../../../types/models/index.js'
-import { federateVideoIfNeeded, getOrCreateAPVideo } from '../videos/index.js'
+import { federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
async function processLikeActivity (options: APProcessorOptions<ActivityLike>) {
const { activity, byActor } = options
const byAccount = byActor.Account
if (!byAccount) throw new Error('Cannot create like with the non account actor ' + byActor.url)
- const { video: onlyVideo } = await getOrCreateAPVideo({ videoObject: videoUrl, fetchType: 'only-video' })
-
- // We don't care about likes of remote videos
- if (!onlyVideo.isOwned()) return
+ const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: videoUrl, fetchType: 'only-video' })
+ if (!onlyVideo?.isOwned()) return
return sequelizeTypescript.transaction(async t => {
const video = await VideoModel.loadFull(onlyVideo.id, t)
import { MActorSignature } from '../../../types/models/index.js'
import { fetchAPObjectIfNeeded } from '../activity.js'
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
-import { federateVideoIfNeeded, getOrCreateAPVideo } from '../videos/index.js'
+import { federateVideoIfNeeded, getOrCreateAPVideo, maybeGetOrCreateAPVideo } from '../videos/index.js'
async function processUndoActivity (options: APProcessorOptions<ActivityUndo<ActivityUndoObject>>) {
const { activity, byActor } = options
async function processUndoLike (byActor: MActorSignature, activity: ActivityUndo<ActivityLike>) {
const likeActivity = activity.object
- const { video: onlyVideo } = await getOrCreateAPVideo({ videoObject: likeActivity.object })
- // We don't care about likes of remote videos
- if (!onlyVideo.isOwned()) return
+ const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: likeActivity.object })
+ if (!onlyVideo?.isOwned()) return
return sequelizeTypescript.transaction(async t => {
if (!byActor.Account) throw new Error('Unknown account ' + byActor.url)
async function processUndoDislike (byActor: MActorSignature, activity: ActivityUndo<ActivityDislike>) {
const dislikeActivity = activity.object
- const { video: onlyVideo } = await getOrCreateAPVideo({ videoObject: dislikeActivity.object })
- // We don't care about likes of remote videos
- if (!onlyVideo.isOwned()) return
+ const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: dislikeActivity.object })
+ if (!onlyVideo?.isOwned()) return
return sequelizeTypescript.transaction(async t => {
if (!byActor.Account) throw new Error('Unknown account ' + byActor.url)
allowRefresh?: boolean
}
-function getOrCreateAPVideo (options: GetVideoParamAll): GetVideoResult<MVideoAccountLightBlacklistAllFiles>
-function getOrCreateAPVideo (options: GetVideoParamImmutable): GetVideoResult<MVideoImmutable>
-function getOrCreateAPVideo (options: GetVideoParamOther): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
-
-async function getOrCreateAPVideo (
+export function getOrCreateAPVideo (options: GetVideoParamAll): GetVideoResult<MVideoAccountLightBlacklistAllFiles>
+export function getOrCreateAPVideo (options: GetVideoParamImmutable): GetVideoResult<MVideoImmutable>
+export function getOrCreateAPVideo (options: GetVideoParamOther): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
+export async function getOrCreateAPVideo (
options: GetVideoParamAll | GetVideoParamImmutable | GetVideoParamOther
): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
// Default params
}
}
-// ---------------------------------------------------------------------------
+export function maybeGetOrCreateAPVideo (options: GetVideoParamAll): GetVideoResult<MVideoAccountLightBlacklistAllFiles>
+export function maybeGetOrCreateAPVideo (options: GetVideoParamImmutable): GetVideoResult<MVideoImmutable>
+export function maybeGetOrCreateAPVideo (options: GetVideoParamOther): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
+export async function maybeGetOrCreateAPVideo (options: GetVideoParamAll | GetVideoParamImmutable | GetVideoParamOther) {
+ try {
+ const result = await getOrCreateAPVideo(options as any)
-export {
- getOrCreateAPVideo
+ return result
+ } catch (err) {
+ logger.debug('Cannot fetch remote video ' + options.videoObject + ': maybe not a video object?', { err })
+ return { video: undefined, created: false }
+ }
}
+// ---------------------------------------------------------------------------
+// Private
// ---------------------------------------------------------------------------
async function scheduleRefresh (video: MVideoThumbnail, fetchType: VideoLoadByUrlType, syncParam: SyncParam) {