]>
Commit | Line | Data |
---|---|---|
1 | import * as Sequelize from 'sequelize' | |
2 | ||
3 | import { database as db } from '../../initializers' | |
4 | import { | |
5 | AccountInstance, | |
6 | VideoInstance, | |
7 | VideoChannelInstance | |
8 | } from '../../models' | |
9 | import { httpRequestJobScheduler } from '../jobs' | |
10 | import { signObject, activityPubContextify } from '../../helpers' | |
11 | import { Activity } from '../../../shared' | |
12 | import { VideoAbuseInstance } from '../../models/video/video-abuse-interface' | |
13 | import { getActivityPubUrl } from '../../helpers/activitypub' | |
14 | import { logger } from '../../helpers/logger' | |
15 | ||
16 | async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) { | |
17 | const videoChannelObject = videoChannel.toActivityPubObject() | |
18 | const data = await createActivityData(videoChannel.url, videoChannel.Account, videoChannelObject) | |
19 | ||
20 | return broadcastToFollowers(data, [ videoChannel.Account ], t) | |
21 | } | |
22 | ||
23 | async function sendUpdateVideoChannel (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) { | |
24 | const videoChannelObject = videoChannel.toActivityPubObject() | |
25 | const data = await updateActivityData(videoChannel.url, videoChannel.Account, videoChannelObject) | |
26 | ||
27 | return broadcastToFollowers(data, [ videoChannel.Account ], t) | |
28 | } | |
29 | ||
30 | async function sendDeleteVideoChannel (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) { | |
31 | const data = await deleteActivityData(videoChannel.url, videoChannel.Account) | |
32 | ||
33 | return broadcastToFollowers(data, [ videoChannel.Account ], t) | |
34 | } | |
35 | ||
36 | async function sendAddVideo (video: VideoInstance, t: Sequelize.Transaction) { | |
37 | const videoObject = video.toActivityPubObject() | |
38 | const data = await addActivityData(video.url, video.VideoChannel.Account, video.VideoChannel.url, videoObject) | |
39 | ||
40 | return broadcastToFollowers(data, [ video.VideoChannel.Account ], t) | |
41 | } | |
42 | ||
43 | async function sendUpdateVideo (video: VideoInstance, t: Sequelize.Transaction) { | |
44 | const videoObject = video.toActivityPubObject() | |
45 | const data = await updateActivityData(video.url, video.VideoChannel.Account, videoObject) | |
46 | ||
47 | return broadcastToFollowers(data, [ video.VideoChannel.Account ], t) | |
48 | } | |
49 | ||
50 | async function sendDeleteVideo (video: VideoInstance, t: Sequelize.Transaction) { | |
51 | const data = await deleteActivityData(video.url, video.VideoChannel.Account) | |
52 | ||
53 | return broadcastToFollowers(data, [ video.VideoChannel.Account ], t) | |
54 | } | |
55 | ||
56 | async function sendDeleteAccount (account: AccountInstance, t: Sequelize.Transaction) { | |
57 | const data = await deleteActivityData(account.url, account) | |
58 | ||
59 | return broadcastToFollowers(data, [ account ], t) | |
60 | } | |
61 | ||
62 | async function sendVideoChannelAnnounce (byAccount: AccountInstance, videoChannel: VideoChannelInstance, t: Sequelize.Transaction) { | |
63 | const url = getActivityPubUrl('videoChannel', videoChannel.uuid) + '#announce' | |
64 | const announcedActivity = await createActivityData(url, videoChannel.Account, videoChannel.toActivityPubObject(), true) | |
65 | ||
66 | const data = await announceActivityData(url, byAccount, announcedActivity) | |
67 | return broadcastToFollowers(data, [ byAccount ], t) | |
68 | } | |
69 | ||
70 | async function sendVideoAnnounce (byAccount: AccountInstance, video: VideoInstance, t: Sequelize.Transaction) { | |
71 | const url = getActivityPubUrl('video', video.uuid) + '#announce' | |
72 | ||
73 | const videoChannel = video.VideoChannel | |
74 | const announcedActivity = await addActivityData(url, videoChannel.Account, videoChannel.url, video.toActivityPubObject(), true) | |
75 | ||
76 | const data = await announceActivityData(url, byAccount, announcedActivity) | |
77 | return broadcastToFollowers(data, [ byAccount ], t) | |
78 | } | |
79 | ||
80 | async function sendVideoAbuse ( | |
81 | fromAccount: AccountInstance, | |
82 | videoAbuse: VideoAbuseInstance, | |
83 | video: VideoInstance, | |
84 | t: Sequelize.Transaction | |
85 | ) { | |
86 | const url = getActivityPubUrl('videoAbuse', videoAbuse.id.toString()) | |
87 | const data = await createActivityData(url, fromAccount, video.url) | |
88 | ||
89 | return unicastTo(data, video.VideoChannel.Account.sharedInboxUrl, t) | |
90 | } | |
91 | ||
92 | async function sendAccept (fromAccount: AccountInstance, toAccount: AccountInstance, t: Sequelize.Transaction) { | |
93 | const data = await acceptActivityData(fromAccount) | |
94 | ||
95 | return unicastTo(data, toAccount.inboxUrl, t) | |
96 | } | |
97 | ||
98 | async function sendFollow (fromAccount: AccountInstance, toAccount: AccountInstance, t: Sequelize.Transaction) { | |
99 | const data = await followActivityData(toAccount.url, fromAccount) | |
100 | ||
101 | return unicastTo(data, toAccount.inboxUrl, t) | |
102 | } | |
103 | ||
104 | // --------------------------------------------------------------------------- | |
105 | ||
106 | export { | |
107 | sendCreateVideoChannel, | |
108 | sendUpdateVideoChannel, | |
109 | sendDeleteVideoChannel, | |
110 | sendAddVideo, | |
111 | sendUpdateVideo, | |
112 | sendDeleteVideo, | |
113 | sendDeleteAccount, | |
114 | sendAccept, | |
115 | sendFollow, | |
116 | sendVideoAbuse, | |
117 | sendVideoChannelAnnounce, | |
118 | sendVideoAnnounce | |
119 | } | |
120 | ||
121 | // --------------------------------------------------------------------------- | |
122 | ||
123 | async function broadcastToFollowers (data: any, toAccountFollowers: AccountInstance[], t: Sequelize.Transaction) { | |
124 | const toAccountFollowerIds = toAccountFollowers.map(a => a.id) | |
125 | const result = await db.AccountFollow.listAcceptedFollowerSharedInboxUrls(toAccountFollowerIds) | |
126 | if (result.data.length === 0) { | |
127 | logger.info('Not broadcast because of 0 followers for %s.', toAccountFollowerIds.join(', ')) | |
128 | return | |
129 | } | |
130 | ||
131 | const jobPayload = { | |
132 | uris: result.data, | |
133 | body: data | |
134 | } | |
135 | ||
136 | return httpRequestJobScheduler.createJob(t, 'httpRequestBroadcastHandler', jobPayload) | |
137 | } | |
138 | ||
139 | async function unicastTo (data: any, toAccountUrl: string, t: Sequelize.Transaction) { | |
140 | const jobPayload = { | |
141 | uris: [ toAccountUrl ], | |
142 | body: data | |
143 | } | |
144 | ||
145 | return httpRequestJobScheduler.createJob(t, 'httpRequestUnicastHandler', jobPayload) | |
146 | } | |
147 | ||
148 | function buildSignedActivity (byAccount: AccountInstance, data: Object) { | |
149 | const activity = activityPubContextify(data) | |
150 | ||
151 | return signObject(byAccount, activity) as Promise<Activity> | |
152 | } | |
153 | ||
154 | async function getPublicActivityTo (account: AccountInstance) { | |
155 | const inboxUrls = await account.getFollowerSharedInboxUrls() | |
156 | ||
157 | return inboxUrls.concat('https://www.w3.org/ns/activitystreams#Public') | |
158 | } | |
159 | ||
160 | async function createActivityData (url: string, byAccount: AccountInstance, object: any, raw = false) { | |
161 | const to = await getPublicActivityTo(byAccount) | |
162 | const base = { | |
163 | type: 'Create', | |
164 | id: url, | |
165 | actor: byAccount.url, | |
166 | to, | |
167 | object | |
168 | } | |
169 | ||
170 | if (raw === true) return base | |
171 | ||
172 | return buildSignedActivity(byAccount, base) | |
173 | } | |
174 | ||
175 | async function updateActivityData (url: string, byAccount: AccountInstance, object: any) { | |
176 | const to = await getPublicActivityTo(byAccount) | |
177 | const base = { | |
178 | type: 'Update', | |
179 | id: url, | |
180 | actor: byAccount.url, | |
181 | to, | |
182 | object | |
183 | } | |
184 | ||
185 | return buildSignedActivity(byAccount, base) | |
186 | } | |
187 | ||
188 | async function deleteActivityData (url: string, byAccount: AccountInstance) { | |
189 | const base = { | |
190 | type: 'Delete', | |
191 | id: url, | |
192 | actor: byAccount.url | |
193 | } | |
194 | ||
195 | return buildSignedActivity(byAccount, base) | |
196 | } | |
197 | ||
198 | async function addActivityData (url: string, byAccount: AccountInstance, target: string, object: any, raw = false) { | |
199 | const to = await getPublicActivityTo(byAccount) | |
200 | const base = { | |
201 | type: 'Add', | |
202 | id: url, | |
203 | actor: byAccount.url, | |
204 | to, | |
205 | object, | |
206 | target | |
207 | } | |
208 | ||
209 | if (raw === true) return base | |
210 | ||
211 | return buildSignedActivity(byAccount, base) | |
212 | } | |
213 | ||
214 | async function announceActivityData (url: string, byAccount: AccountInstance, object: any) { | |
215 | const base = { | |
216 | type: 'Announce', | |
217 | id: url, | |
218 | actor: byAccount.url, | |
219 | object | |
220 | } | |
221 | ||
222 | return buildSignedActivity(byAccount, base) | |
223 | } | |
224 | ||
225 | async function followActivityData (url: string, byAccount: AccountInstance) { | |
226 | const base = { | |
227 | type: 'Follow', | |
228 | id: byAccount.url, | |
229 | actor: byAccount.url, | |
230 | object: url | |
231 | } | |
232 | ||
233 | return buildSignedActivity(byAccount, base) | |
234 | } | |
235 | ||
236 | async function acceptActivityData (byAccount: AccountInstance) { | |
237 | const base = { | |
238 | type: 'Accept', | |
239 | id: byAccount.url, | |
240 | actor: byAccount.url | |
241 | } | |
242 | ||
243 | return buildSignedActivity(byAccount, base) | |
244 | } |