import { getAPId } from '@server/helpers/activitypub' ; import { retryTransactionWrapper } from '@server/helpers/database-utils' ; import { JobQueue } from '@server/lib/job-queue' ; import { loadVideoByUrl , VideoLoadByUrlType } from '@server/lib/model-loaders' ; import { MVideoAccountLightBlacklistAllFiles , MVideoImmutable , MVideoThumbnail } from '@server/types/models' ; import { APObject } from '@shared/models' ; import { refreshVideoIfNeeded } from './refresh' ; import { APVideoCreator , fetchRemoteVideo , SyncParam , syncVideoExternalAttributes } from './shared' ; type GetVideoResult < T > = Promise < { video : T ; created : boolean ; autoBlacklisted ? : boolean ; } > ; type GetVideoParamAll = { videoObject : APObject ; syncParam ? : SyncParam ; fetchType ? : 'all' ; allowRefresh ? : boolean ; } ; type GetVideoParamImmutable = { videoObject : APObject ; syncParam ? : SyncParam ; fetchType : 'only-immutable-attributes' ; allowRefresh : false ; } ; type GetVideoParamOther = { videoObject : APObject ; syncParam ? : SyncParam ; fetchType ? : 'all' | 'only-video' ; allowRefresh ? : boolean ; } ; function getOrCreateAPVideo ( options ) ; function getOrCreateAPVideo ( options ) ; function getOrCreateAPVideo ( options ) ; async function getOrCreateAPVideo ( options ) { 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 ; const videoUrl = getAPId ( options . videoObject ) ; let videoFromDatabase = await loadVideoByUrl ( videoUrl , fetchType ) ; if ( videoFromDatabase ) { if ( allowRefresh === true ) { 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 ) ; if ( videoObject . id !== videoUrl ) return getOrCreateAPVideo ( { ... options , fetchType : 'all' , videoObject } ) ; 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 ) { if ( err . name === 'SequelizeUniqueConstraintError' ) { const alreadyCreatedVideo = await loadVideoByUrl ( videoUrl , fetchType ) ; if ( alreadyCreatedVideo ) return { video : alreadyCreatedVideo , created : false } ; } throw err ; } } export { getOrCreateAPVideo } ; async function scheduleRefresh ( video , fetchType , 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 ; }