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