]>
Commit | Line | Data |
---|---|---|
54141398 | 1 | import { Transaction } from 'sequelize' |
3fd3ab2d C |
2 | import { Activity } from '../../../../shared/models/activitypub' |
3 | import { logger } from '../../../helpers' | |
4 | import { ACTIVITY_PUB } from '../../../initializers' | |
50d6de9c C |
5 | import { ActorModel } from '../../../models/activitypub/actor' |
6 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | |
3fd3ab2d | 7 | import { VideoModel } from '../../../models/video/video' |
3fd3ab2d C |
8 | import { VideoShareModel } from '../../../models/video/video-share' |
9 | import { activitypubHttpJobScheduler, ActivityPubHttpPayload } from '../../jobs/activitypub-http-job-scheduler' | |
63c93323 C |
10 | |
11 | async function forwardActivity ( | |
12 | activity: Activity, | |
13 | t: Transaction, | |
50d6de9c | 14 | followersException: ActorModel[] = [] |
63c93323 C |
15 | ) { |
16 | const to = activity.to || [] | |
17 | const cc = activity.cc || [] | |
18 | ||
19 | const followersUrls: string[] = [] | |
20 | for (const dest of to.concat(cc)) { | |
21 | if (dest.endsWith('/followers')) { | |
22 | followersUrls.push(dest) | |
23 | } | |
24 | } | |
25 | ||
50d6de9c C |
26 | const toActorFollowers = await ActorModel.listByFollowersUrls(followersUrls, t) |
27 | const uris = await computeFollowerUris(toActorFollowers, followersException, t) | |
63c93323 C |
28 | |
29 | if (uris.length === 0) { | |
50d6de9c | 30 | logger.info('0 followers for %s, no forwarding.', toActorFollowers.map(a => a.id).join(', ')) |
df1966c9 | 31 | return undefined |
63c93323 C |
32 | } |
33 | ||
34 | logger.debug('Creating forwarding job.', { uris }) | |
35 | ||
36 | const jobPayload: ActivityPubHttpPayload = { | |
37 | uris, | |
38 | body: activity | |
39 | } | |
40 | ||
41 | return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpBroadcastHandler', jobPayload) | |
42 | } | |
54141398 | 43 | |
40ff5707 C |
44 | async function broadcastToFollowers ( |
45 | data: any, | |
50d6de9c C |
46 | byActor: ActorModel, |
47 | toActorFollowers: ActorModel[], | |
40ff5707 | 48 | t: Transaction, |
50d6de9c | 49 | followersException: ActorModel[] = [] |
40ff5707 | 50 | ) { |
50d6de9c | 51 | const uris = await computeFollowerUris(toActorFollowers, followersException, t) |
63c93323 | 52 | if (uris.length === 0) { |
50d6de9c | 53 | logger.info('0 followers for %s, no broadcasting.', toActorFollowers.map(a => a.id).join(', ')) |
df1966c9 | 54 | return undefined |
54141398 C |
55 | } |
56 | ||
63c93323 | 57 | logger.debug('Creating broadcast job.', { uris }) |
40ff5707 | 58 | |
63c93323 | 59 | const jobPayload: ActivityPubHttpPayload = { |
40ff5707 | 60 | uris, |
50d6de9c | 61 | signatureActorId: byActor.id, |
54141398 C |
62 | body: data |
63 | } | |
64 | ||
65 | return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpBroadcastHandler', jobPayload) | |
66 | } | |
67 | ||
50d6de9c C |
68 | async function unicastTo (data: any, byActor: ActorModel, toActorUrl: string, t: Transaction) { |
69 | logger.debug('Creating unicast job.', { uri: toActorUrl }) | |
63c93323 C |
70 | |
71 | const jobPayload: ActivityPubHttpPayload = { | |
50d6de9c C |
72 | uris: [ toActorUrl ], |
73 | signatureActorId: byActor.id, | |
54141398 C |
74 | body: data |
75 | } | |
76 | ||
77 | return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpUnicastHandler', jobPayload) | |
78 | } | |
79 | ||
50d6de9c | 80 | function getOriginVideoAudience (video: VideoModel, actorsInvolvedInVideo: ActorModel[]) { |
0032ebe9 | 81 | return { |
50d6de9c C |
82 | to: [ video.VideoChannel.Account.Actor.url ], |
83 | cc: actorsInvolvedInVideo.map(a => a.followersUrl) | |
0032ebe9 C |
84 | } |
85 | } | |
86 | ||
50d6de9c | 87 | function getObjectFollowersAudience (actorsInvolvedInObject: ActorModel[]) { |
4e50b6a1 | 88 | return { |
50d6de9c | 89 | to: actorsInvolvedInObject.map(a => a.followersUrl), |
0032ebe9 C |
90 | cc: [] |
91 | } | |
92 | } | |
93 | ||
50d6de9c C |
94 | async function getActorsInvolvedInVideo (video: VideoModel, t: Transaction) { |
95 | const actorsToForwardView = await VideoShareModel.loadActorsByShare(video.id, t) | |
96 | actorsToForwardView.push(video.VideoChannel.Account.Actor) | |
4e50b6a1 | 97 | |
50d6de9c | 98 | return actorsToForwardView |
4e50b6a1 C |
99 | } |
100 | ||
50d6de9c C |
101 | async function getAudience (actorSender: ActorModel, t: Transaction, isPublic = true) { |
102 | const followerInboxUrls = await actorSender.getFollowerSharedInboxUrls(t) | |
54141398 C |
103 | |
104 | // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47 | |
105 | let to = [] | |
106 | let cc = [] | |
107 | ||
108 | if (isPublic) { | |
109 | to = [ ACTIVITY_PUB.PUBLIC ] | |
110 | cc = followerInboxUrls | |
111 | } else { // Unlisted | |
112 | to = followerInboxUrls | |
113 | cc = [ ACTIVITY_PUB.PUBLIC ] | |
114 | } | |
115 | ||
116 | return { to, cc } | |
117 | } | |
118 | ||
50d6de9c C |
119 | async function computeFollowerUris (toActorFollower: ActorModel[], followersException: ActorModel[], t: Transaction) { |
120 | const toActorFollowerIds = toActorFollower.map(a => a.id) | |
63c93323 | 121 | |
50d6de9c | 122 | const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) |
63c93323 | 123 | const followersSharedInboxException = followersException.map(f => f.sharedInboxUrl) |
3fd3ab2d | 124 | return result.data.filter(sharedInbox => followersSharedInboxException.indexOf(sharedInbox) === -1) |
63c93323 C |
125 | } |
126 | ||
54141398 C |
127 | // --------------------------------------------------------------------------- |
128 | ||
129 | export { | |
130 | broadcastToFollowers, | |
131 | unicastTo, | |
0032ebe9 C |
132 | getAudience, |
133 | getOriginVideoAudience, | |
50d6de9c | 134 | getActorsInvolvedInVideo, |
4e50b6a1 | 135 | getObjectFollowersAudience, |
63c93323 | 136 | forwardActivity |
54141398 | 137 | } |