diff options
Diffstat (limited to 'server/lib/activitypub/send/utils.ts')
-rw-r--r-- | server/lib/activitypub/send/utils.ts | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts new file mode 100644 index 000000000..80d4463ff --- /dev/null +++ b/server/lib/activitypub/send/utils.ts | |||
@@ -0,0 +1,113 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { Activity } from '../../../../shared/models/activitypub' | ||
3 | import { logger } from '../../../helpers/logger' | ||
4 | import { ActorModel } from '../../../models/activitypub/actor' | ||
5 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | ||
6 | import { JobQueue } from '../../job-queue' | ||
7 | |||
8 | async function forwardActivity ( | ||
9 | activity: Activity, | ||
10 | t: Transaction, | ||
11 | followersException: ActorModel[] = [], | ||
12 | additionalFollowerUrls: string[] = [] | ||
13 | ) { | ||
14 | const to = activity.to || [] | ||
15 | const cc = activity.cc || [] | ||
16 | |||
17 | const followersUrls = additionalFollowerUrls | ||
18 | for (const dest of to.concat(cc)) { | ||
19 | if (dest.endsWith('/followers')) { | ||
20 | followersUrls.push(dest) | ||
21 | } | ||
22 | } | ||
23 | |||
24 | const toActorFollowers = await ActorModel.listByFollowersUrls(followersUrls, t) | ||
25 | const uris = await computeFollowerUris(toActorFollowers, followersException, t) | ||
26 | |||
27 | if (uris.length === 0) { | ||
28 | logger.info('0 followers for %s, no forwarding.', toActorFollowers.map(a => a.id).join(', ')) | ||
29 | return undefined | ||
30 | } | ||
31 | |||
32 | logger.debug('Creating forwarding job.', { uris }) | ||
33 | |||
34 | const payload = { | ||
35 | uris, | ||
36 | body: activity | ||
37 | } | ||
38 | return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) | ||
39 | } | ||
40 | |||
41 | async function broadcastToFollowers ( | ||
42 | data: any, | ||
43 | byActor: ActorModel, | ||
44 | toActorFollowers: ActorModel[], | ||
45 | t: Transaction, | ||
46 | actorsException: ActorModel[] = [] | ||
47 | ) { | ||
48 | const uris = await computeFollowerUris(toActorFollowers, actorsException, t) | ||
49 | return broadcastTo(uris, data, byActor) | ||
50 | } | ||
51 | |||
52 | async function broadcastToActors ( | ||
53 | data: any, | ||
54 | byActor: ActorModel, | ||
55 | toActors: ActorModel[], | ||
56 | actorsException: ActorModel[] = [] | ||
57 | ) { | ||
58 | const uris = await computeUris(toActors, actorsException) | ||
59 | return broadcastTo(uris, data, byActor) | ||
60 | } | ||
61 | |||
62 | async function broadcastTo (uris: string[], data: any, byActor: ActorModel) { | ||
63 | if (uris.length === 0) return undefined | ||
64 | |||
65 | logger.debug('Creating broadcast job.', { uris }) | ||
66 | |||
67 | const payload = { | ||
68 | uris, | ||
69 | signatureActorId: byActor.id, | ||
70 | body: data | ||
71 | } | ||
72 | |||
73 | return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) | ||
74 | } | ||
75 | |||
76 | async function unicastTo (data: any, byActor: ActorModel, toActorUrl: string) { | ||
77 | logger.debug('Creating unicast job.', { uri: toActorUrl }) | ||
78 | |||
79 | const payload = { | ||
80 | uri: toActorUrl, | ||
81 | signatureActorId: byActor.id, | ||
82 | body: data | ||
83 | } | ||
84 | |||
85 | return JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload }) | ||
86 | } | ||
87 | |||
88 | // --------------------------------------------------------------------------- | ||
89 | |||
90 | export { | ||
91 | broadcastToFollowers, | ||
92 | unicastTo, | ||
93 | forwardActivity, | ||
94 | broadcastToActors | ||
95 | } | ||
96 | |||
97 | // --------------------------------------------------------------------------- | ||
98 | |||
99 | async function computeFollowerUris (toActorFollower: ActorModel[], actorsException: ActorModel[], t: Transaction) { | ||
100 | const toActorFollowerIds = toActorFollower.map(a => a.id) | ||
101 | |||
102 | const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) | ||
103 | const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl) | ||
104 | return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) | ||
105 | } | ||
106 | |||
107 | async function computeUris (toActors: ActorModel[], actorsException: ActorModel[] = []) { | ||
108 | const toActorSharedInboxesSet = new Set(toActors.map(a => a.sharedInboxUrl || a.inboxUrl)) | ||
109 | |||
110 | const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl) | ||
111 | return Array.from(toActorSharedInboxesSet) | ||
112 | .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) | ||
113 | } | ||