aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/actor.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/activitypub/actor.ts')
-rw-r--r--server/lib/activitypub/actor.ts80
1 files changed, 77 insertions, 3 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index b6ba2cc22..0882ab843 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -7,10 +7,11 @@ import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/a
7import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' 7import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects'
8import { isActorObjectValid } from '../../helpers/custom-validators/activitypub/actor' 8import { isActorObjectValid } from '../../helpers/custom-validators/activitypub/actor'
9import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 9import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
10import { retryTransactionWrapper } from '../../helpers/database-utils' 10import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils'
11import { logger } from '../../helpers/logger' 11import { logger } from '../../helpers/logger'
12import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' 12import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
13import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' 13import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
14import { getUrlFromWebfinger } from '../../helpers/webfinger'
14import { AVATAR_MIMETYPE_EXT, CONFIG, sequelizeTypescript } from '../../initializers' 15import { AVATAR_MIMETYPE_EXT, CONFIG, sequelizeTypescript } from '../../initializers'
15import { AccountModel } from '../../models/account/account' 16import { AccountModel } from '../../models/account/account'
16import { ActorModel } from '../../models/activitypub/actor' 17import { ActorModel } from '../../models/activitypub/actor'
@@ -63,7 +64,7 @@ async function getOrCreateActorAndServerAndModel (actorUrl: string, recurseIfNee
63 actor = await retryTransactionWrapper(saveActorAndServerAndModelIfNotExist, options) 64 actor = await retryTransactionWrapper(saveActorAndServerAndModelIfNotExist, options)
64 } 65 }
65 66
66 return actor 67 return refreshActorIfNeeded(actor)
67} 68}
68 69
69function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) { 70function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) {
@@ -84,6 +85,45 @@ function buildActorInstance (type: ActivityPubActorType, url: string, preferredU
84 }) 85 })
85} 86}
86 87
88async function updateActorInstance (actorInstance: ActorModel, attributes: ActivityPubActor) {
89 const followersCount = await fetchActorTotalItems(attributes.followers)
90 const followingCount = await fetchActorTotalItems(attributes.following)
91
92 actorInstance.set('type', attributes.type)
93 actorInstance.set('uuid', attributes.uuid)
94 actorInstance.set('preferredUsername', attributes.preferredUsername)
95 actorInstance.set('url', attributes.id)
96 actorInstance.set('publicKey', attributes.publicKey.publicKeyPem)
97 actorInstance.set('followersCount', followersCount)
98 actorInstance.set('followingCount', followingCount)
99 actorInstance.set('inboxUrl', attributes.inbox)
100 actorInstance.set('outboxUrl', attributes.outbox)
101 actorInstance.set('sharedInboxUrl', attributes.endpoints.sharedInbox)
102 actorInstance.set('followersUrl', attributes.followers)
103 actorInstance.set('followingUrl', attributes.following)
104}
105
106async function updateActorAvatarInstance (actorInstance: ActorModel, avatarName: string, t: Transaction) {
107 if (avatarName !== undefined) {
108 if (actorInstance.avatarId) {
109 try {
110 await actorInstance.Avatar.destroy({ transaction: t })
111 } catch (err) {
112 logger.error('Cannot remove old avatar of actor %s.', actorInstance.url, err)
113 }
114 }
115
116 const avatar = await AvatarModel.create({
117 filename: avatarName
118 }, { transaction: t })
119
120 actorInstance.set('avatarId', avatar.id)
121 actorInstance.Avatar = avatar
122 }
123
124 return actorInstance
125}
126
87async function fetchActorTotalItems (url: string) { 127async function fetchActorTotalItems (url: string) {
88 const options = { 128 const options = {
89 uri: url, 129 uri: url,
@@ -129,7 +169,9 @@ export {
129 buildActorInstance, 169 buildActorInstance,
130 setAsyncActorKeys, 170 setAsyncActorKeys,
131 fetchActorTotalItems, 171 fetchActorTotalItems,
132 fetchAvatarIfExists 172 fetchAvatarIfExists,
173 updateActorInstance,
174 updateActorAvatarInstance
133} 175}
134 176
135// --------------------------------------------------------------------------- 177// ---------------------------------------------------------------------------
@@ -263,3 +305,35 @@ async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResu
263 305
264 return videoChannel.save({ transaction: t }) 306 return videoChannel.save({ transaction: t })
265} 307}
308
309async function refreshActorIfNeeded (actor: ActorModel) {
310 if (!actor.isOutdated()) return actor
311
312 const actorUrl = await getUrlFromWebfinger(actor.preferredUsername, actor.getHost())
313 const result = await fetchRemoteActor(actorUrl)
314 if (result === undefined) throw new Error('Cannot fetch remote actor in refresh actor.')
315
316 return sequelizeTypescript.transaction(async t => {
317 updateInstanceWithAnother(actor, result.actor)
318
319 if (result.avatarName !== undefined) {
320 await updateActorAvatarInstance(actor, result.avatarName, t)
321 }
322
323 await actor.save({ transaction: t })
324
325 if (actor.Account) {
326 await actor.save({ transaction: t })
327
328 actor.Account.set('name', result.name)
329 await actor.Account.save({ transaction: t })
330 } else if (actor.VideoChannel) {
331 await actor.save({ transaction: t })
332
333 actor.VideoChannel.set('name', result.name)
334 await actor.VideoChannel.save({ transaction: t })
335 }
336
337 return actor
338 })
339}