123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- import { ActivityUpdate, CacheFileObject, VideoTorrentObject } from '../../../../shared/models/activitypub'
- import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor'
- import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils'
- import { logger } from '../../../helpers/logger'
- import { sequelizeTypescript } from '../../../initializers'
- import { AccountModel } from '../../../models/account/account'
- import { ActorModel } from '../../../models/activitypub/actor'
- import { VideoChannelModel } from '../../../models/video/video-channel'
- import { fetchAvatarIfExists, updateActorAvatarInstance, updateActorInstance } from '../actor'
- import { getOrCreateVideoAndAccountAndChannel, getOrCreateVideoChannelFromVideoObject, updateVideoFromAP } from '../videos'
- import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos'
- import { isCacheFileObjectValid } from '../../../helpers/custom-validators/activitypub/cache-file'
- import { createOrUpdateCacheFile } from '../cache-file'
- import { forwardVideoRelatedActivity } from '../send/utils'
- import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
- import { createOrUpdateVideoPlaylist } from '../playlist'
- async function processUpdateActivity (activity: ActivityUpdate, byActor: ActorModel) {
- const objectType = activity.object.type
- if (objectType === 'Video') {
- return retryTransactionWrapper(processUpdateVideo, byActor, activity)
- }
- if (objectType === 'Person' || objectType === 'Application' || objectType === 'Group') {
- // We need more attributes
- const byActorFull = await ActorModel.loadByUrlAndPopulateAccountAndChannel(byActor.url)
- return retryTransactionWrapper(processUpdateActor, byActorFull, activity)
- }
- if (objectType === 'CacheFile') {
- // We need more attributes
- const byActorFull = await ActorModel.loadByUrlAndPopulateAccountAndChannel(byActor.url)
- return retryTransactionWrapper(processUpdateCacheFile, byActorFull, activity)
- }
- if (objectType === 'Playlist') {
- return retryTransactionWrapper(processUpdatePlaylist, byActor, activity)
- }
- return undefined
- }
- // ---------------------------------------------------------------------------
- export {
- processUpdateActivity
- }
- // ---------------------------------------------------------------------------
- async function processUpdateVideo (actor: ActorModel, activity: ActivityUpdate) {
- const videoObject = activity.object as VideoTorrentObject
- if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) {
- logger.debug('Video sent by update is not valid.', { videoObject })
- return undefined
- }
- const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoObject.id, allowRefresh: false })
- const channelActor = await getOrCreateVideoChannelFromVideoObject(videoObject)
- const updateOptions = {
- video,
- videoObject,
- account: actor.Account,
- channel: channelActor.VideoChannel,
- overrideTo: activity.to
- }
- return updateVideoFromAP(updateOptions)
- }
- async function processUpdateCacheFile (byActor: ActorModel, activity: ActivityUpdate) {
- const cacheFileObject = activity.object as CacheFileObject
- if (!isCacheFileObjectValid(cacheFileObject)) {
- logger.debug('Cache file object sent by update is not valid.', { cacheFileObject })
- return undefined
- }
- const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: cacheFileObject.object })
- await sequelizeTypescript.transaction(async t => {
- await createOrUpdateCacheFile(cacheFileObject, video, byActor, t)
- })
- if (video.isOwned()) {
- // Don't resend the activity to the sender
- const exceptions = [ byActor ]
- await forwardVideoRelatedActivity(activity, undefined, exceptions, video)
- }
- }
- async function processUpdateActor (actor: ActorModel, activity: ActivityUpdate) {
- const actorAttributesToUpdate = activity.object as ActivityPubActor
- logger.debug('Updating remote account "%s".', actorAttributesToUpdate.url)
- let accountOrChannelInstance: AccountModel | VideoChannelModel
- let actorFieldsSave: object
- let accountOrChannelFieldsSave: object
- // Fetch icon?
- const avatarName = await fetchAvatarIfExists(actorAttributesToUpdate)
- try {
- await sequelizeTypescript.transaction(async t => {
- actorFieldsSave = actor.toJSON()
- if (actorAttributesToUpdate.type === 'Group') accountOrChannelInstance = actor.VideoChannel
- else accountOrChannelInstance = actor.Account
- accountOrChannelFieldsSave = accountOrChannelInstance.toJSON()
- await updateActorInstance(actor, actorAttributesToUpdate)
- if (avatarName !== undefined) {
- await updateActorAvatarInstance(actor, avatarName, t)
- }
- await actor.save({ transaction: t })
- accountOrChannelInstance.name = actorAttributesToUpdate.name || actorAttributesToUpdate.preferredUsername
- accountOrChannelInstance.description = actorAttributesToUpdate.summary
- if (accountOrChannelInstance instanceof VideoChannelModel) accountOrChannelInstance.support = actorAttributesToUpdate.support
- await accountOrChannelInstance.save({ transaction: t })
- })
- logger.info('Remote account %s updated', actorAttributesToUpdate.url)
- } catch (err) {
- if (actor !== undefined && actorFieldsSave !== undefined) {
- resetSequelizeInstance(actor, actorFieldsSave)
- }
- if (accountOrChannelInstance !== undefined && accountOrChannelFieldsSave !== undefined) {
- resetSequelizeInstance(accountOrChannelInstance, accountOrChannelFieldsSave)
- }
- // This is just a debug because we will retry the insert
- logger.debug('Cannot update the remote account.', { err })
- throw err
- }
- }
- async function processUpdatePlaylist (byActor: ActorModel, activity: ActivityUpdate) {
- const playlistObject = activity.object as PlaylistObject
- const byAccount = byActor.Account
- if (!byAccount) throw new Error('Cannot update video playlist with the non account actor ' + byActor.url)
- await createOrUpdateVideoPlaylist(playlistObject, byAccount, activity.to)
- }
|