PeerTube/server/lib/activitypub/actors/updater.ts

99 lines
3.9 KiB
TypeScript
Raw Normal View History

2021-06-08 10:29:45 -05:00
import { resetSequelizeInstance, runInReadCommittedTransaction } from '@server/helpers/database-utils'
2021-06-03 09:02:29 -05:00
import { logger } from '@server/helpers/logger'
import { AccountModel } from '@server/models/account/account'
2021-06-03 09:02:29 -05:00
import { VideoChannelModel } from '@server/models/video/video-channel'
import { MAccount, MActor, MActorFull, MChannel } from '@server/types/models'
import { ActivityPubActor, ActorImageType } from '@shared/models'
import { getOrCreateAPOwner } from './get'
import { updateActorImages } from './image'
2021-06-03 09:02:29 -05:00
import { fetchActorFollowsCount } from './shared'
import { getImagesInfoFromObject } from './shared/object-to-model-attributes'
2021-06-03 09:02:29 -05:00
export class APActorUpdater {
private accountOrChannel: MAccount | MChannel
private readonly actorFieldsSave: object
private readonly accountOrChannelFieldsSave: object
constructor (
private readonly actorObject: ActivityPubActor,
private readonly actor: MActorFull
) {
this.actorFieldsSave = this.actor.toJSON()
if (this.actorObject.type === 'Group') this.accountOrChannel = this.actor.VideoChannel
else this.accountOrChannel = this.actor.Account
this.accountOrChannelFieldsSave = this.accountOrChannel.toJSON()
}
async update () {
const avatarsInfo = getImagesInfoFromObject(this.actorObject, ActorImageType.AVATAR)
const bannersInfo = getImagesInfoFromObject(this.actorObject, ActorImageType.BANNER)
2021-06-03 09:02:29 -05:00
try {
2021-06-08 10:29:45 -05:00
await this.updateActorInstance(this.actor, this.actorObject)
2021-06-03 09:02:29 -05:00
2021-06-08 10:29:45 -05:00
this.accountOrChannel.name = this.actorObject.name || this.actorObject.preferredUsername
this.accountOrChannel.description = this.actorObject.summary
2021-06-03 09:02:29 -05:00
if (this.accountOrChannel instanceof VideoChannelModel) {
const owner = await getOrCreateAPOwner(this.actorObject, this.actorObject.url)
this.accountOrChannel.accountId = owner.Account.id
this.accountOrChannel.Account = owner.Account as AccountModel
this.accountOrChannel.support = this.actorObject.support
}
2021-06-03 09:02:29 -05:00
2021-06-08 10:29:45 -05:00
await runInReadCommittedTransaction(async t => {
await updateActorImages(this.actor, ActorImageType.BANNER, bannersInfo, t)
await updateActorImages(this.actor, ActorImageType.AVATAR, avatarsInfo, t)
2021-06-03 09:02:29 -05:00
})
2021-06-08 10:29:45 -05:00
await runInReadCommittedTransaction(async t => {
2021-06-08 11:12:49 -05:00
await this.actor.save({ transaction: t })
await this.accountOrChannel.save({ transaction: t })
2021-06-08 10:29:45 -05:00
})
2021-06-03 09:02:29 -05:00
logger.info('Remote account %s updated', this.actorObject.url)
} catch (err) {
if (this.actor !== undefined && this.actorFieldsSave !== undefined) {
resetSequelizeInstance(this.actor, this.actorFieldsSave)
}
if (this.accountOrChannel !== undefined && this.accountOrChannelFieldsSave !== undefined) {
resetSequelizeInstance(this.accountOrChannel, this.accountOrChannelFieldsSave)
}
// This is just a debug because we will retry the insert
logger.debug('Cannot update the remote account.', { err })
throw err
}
}
private async updateActorInstance (actorInstance: MActor, actorObject: ActivityPubActor) {
const { followersCount, followingCount } = await fetchActorFollowsCount(actorObject)
actorInstance.type = actorObject.type
actorInstance.preferredUsername = actorObject.preferredUsername
actorInstance.url = actorObject.id
actorInstance.publicKey = actorObject.publicKey.publicKeyPem
actorInstance.followersCount = followersCount
actorInstance.followingCount = followingCount
actorInstance.inboxUrl = actorObject.inbox
actorInstance.outboxUrl = actorObject.outbox
actorInstance.followersUrl = actorObject.followers
actorInstance.followingUrl = actorObject.following
if (actorObject.published) actorInstance.remoteCreatedAt = new Date(actorObject.published)
if (actorObject.endpoints?.sharedInbox) {
actorInstance.sharedInboxUrl = actorObject.endpoints.sharedInbox
}
// Force actor update
actorInstance.changed('updatedAt', true)
}
}