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