]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/activitypub/actors/updater.ts
5a92e7a2241cc6c8fbfc129ce7f50e66f244d7be
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / actors / updater.ts
1 import { resetSequelizeInstance, runInReadCommittedTransaction } from '@server/helpers/database-utils'
2 import { logger } from '@server/helpers/logger'
3 import { AccountModel } from '@server/models/account/account'
4 import { VideoChannelModel } from '@server/models/video/video-channel'
5 import { MAccount, MActor, MActorFull, MChannel } from '@server/types/models'
6 import { ActivityPubActor, ActorImageType } from '@shared/models'
7 import { getOrCreateAPOwner } from './get'
8 import { updateActorImages } from './image'
9 import { fetchActorFollowsCount } from './shared'
10 import { getImagesInfoFromObject } from './shared/object-to-model-attributes'
11
12 export class APActorUpdater {
13
14 private readonly accountOrChannel: MAccount | MChannel
15
16 constructor (
17 private readonly actorObject: ActivityPubActor,
18 private readonly actor: MActorFull
19 ) {
20 if (this.actorObject.type === 'Group') this.accountOrChannel = this.actor.VideoChannel
21 else this.accountOrChannel = this.actor.Account
22 }
23
24 async update () {
25 const avatarsInfo = getImagesInfoFromObject(this.actorObject, ActorImageType.AVATAR)
26 const bannersInfo = getImagesInfoFromObject(this.actorObject, ActorImageType.BANNER)
27
28 try {
29 await this.updateActorInstance(this.actor, this.actorObject)
30
31 this.accountOrChannel.name = this.actorObject.name || this.actorObject.preferredUsername
32 this.accountOrChannel.description = this.actorObject.summary
33
34 if (this.accountOrChannel instanceof VideoChannelModel) {
35 const owner = await getOrCreateAPOwner(this.actorObject, this.actorObject.url)
36 this.accountOrChannel.accountId = owner.Account.id
37 this.accountOrChannel.Account = owner.Account as AccountModel
38
39 this.accountOrChannel.support = this.actorObject.support
40 }
41
42 await runInReadCommittedTransaction(async t => {
43 await updateActorImages(this.actor, ActorImageType.BANNER, bannersInfo, t)
44 await updateActorImages(this.actor, ActorImageType.AVATAR, avatarsInfo, t)
45 })
46
47 await runInReadCommittedTransaction(async t => {
48 await this.actor.save({ transaction: t })
49 await this.accountOrChannel.save({ transaction: t })
50 })
51
52 logger.info('Remote account %s updated', this.actorObject.url)
53 } catch (err) {
54 if (this.actor !== undefined) {
55 await resetSequelizeInstance(this.actor)
56 }
57
58 if (this.accountOrChannel !== undefined) {
59 await resetSequelizeInstance(this.accountOrChannel)
60 }
61
62 // This is just a debug because we will retry the insert
63 logger.debug('Cannot update the remote account.', { err })
64 throw err
65 }
66 }
67
68 private async updateActorInstance (actorInstance: MActor, actorObject: ActivityPubActor) {
69 const { followersCount, followingCount } = await fetchActorFollowsCount(actorObject)
70
71 actorInstance.type = actorObject.type
72 actorInstance.preferredUsername = actorObject.preferredUsername
73 actorInstance.url = actorObject.id
74 actorInstance.publicKey = actorObject.publicKey.publicKeyPem
75 actorInstance.followersCount = followersCount
76 actorInstance.followingCount = followingCount
77 actorInstance.inboxUrl = actorObject.inbox
78 actorInstance.outboxUrl = actorObject.outbox
79 actorInstance.followersUrl = actorObject.followers
80 actorInstance.followingUrl = actorObject.following
81
82 if (actorObject.published) actorInstance.remoteCreatedAt = new Date(actorObject.published)
83
84 if (actorObject.endpoints?.sharedInbox) {
85 actorInstance.sharedInboxUrl = actorObject.endpoints.sharedInbox
86 }
87
88 // Force actor update
89 actorInstance.changed('updatedAt', true)
90 }
91 }