]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/activitypub/send/misc.ts
fe137464eb57ec587589bf010379ccfa001f4c78
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / send / misc.ts
1 import { Transaction } from 'sequelize'
2 import { logger } from '../../../helpers/logger'
3 import { ACTIVITY_PUB, database as db } from '../../../initializers'
4 import { AccountInstance } from '../../../models/account/account-interface'
5 import {
6 activitypubHttpJobScheduler,
7 ActivityPubHttpPayload
8 } from '../../jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler'
9 import { VideoInstance } from '../../../models/video/video-interface'
10 import { Activity } from '../../../../shared/models/activitypub/activity'
11
12 async function forwardActivity (
13 activity: Activity,
14 t: Transaction,
15 followersException: AccountInstance[] = []
16 ) {
17 const to = activity.to || []
18 const cc = activity.cc || []
19
20 const followersUrls: string[] = []
21 for (const dest of to.concat(cc)) {
22 if (dest.endsWith('/followers')) {
23 followersUrls.push(dest)
24 }
25 }
26
27 const toAccountFollowers = await db.Account.listByFollowersUrls(followersUrls)
28 const uris = await computeFollowerUris(toAccountFollowers, followersException)
29
30 if (uris.length === 0) {
31 logger.info('0 followers for %s, no forwarding.', toAccountFollowers.map(a => a.id).join(', '))
32 return
33 }
34
35 logger.debug('Creating forwarding job.', { uris })
36
37 const jobPayload: ActivityPubHttpPayload = {
38 uris,
39 body: activity
40 }
41
42 return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpBroadcastHandler', jobPayload)
43 }
44
45 async function broadcastToFollowers (
46 data: any,
47 byAccount: AccountInstance,
48 toAccountFollowers: AccountInstance[],
49 t: Transaction,
50 followersException: AccountInstance[] = []
51 ) {
52 const uris = await computeFollowerUris(toAccountFollowers, followersException)
53 if (uris.length === 0) {
54 logger.info('0 followers for %s, no broadcasting.', toAccountFollowers.map(a => a.id).join(', '))
55 return
56 }
57
58 logger.debug('Creating broadcast job.', { uris })
59
60 const jobPayload: ActivityPubHttpPayload = {
61 uris,
62 signatureAccountId: byAccount.id,
63 body: data
64 }
65
66 return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpBroadcastHandler', jobPayload)
67 }
68
69 async function unicastTo (data: any, byAccount: AccountInstance, toAccountUrl: string, t: Transaction) {
70 logger.debug('Creating unicast job.', { uri: toAccountUrl })
71
72 const jobPayload: ActivityPubHttpPayload = {
73 uris: [ toAccountUrl ],
74 signatureAccountId: byAccount.id,
75 body: data
76 }
77
78 return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpUnicastHandler', jobPayload)
79 }
80
81 function getOriginVideoAudience (video: VideoInstance, accountsInvolvedInVideo: AccountInstance[]) {
82 return {
83 to: [ video.VideoChannel.Account.url ],
84 cc: accountsInvolvedInVideo.map(a => a.followersUrl)
85 }
86 }
87
88 function getVideoFollowersAudience (accountsInvolvedInVideo: AccountInstance[]) {
89 return {
90 to: accountsInvolvedInVideo.map(a => a.followersUrl),
91 cc: []
92 }
93 }
94
95 async function getAccountsInvolvedInVideo (video: VideoInstance) {
96 const accountsToForwardView = await db.VideoShare.loadAccountsByShare(video.id)
97 accountsToForwardView.push(video.VideoChannel.Account)
98
99 return accountsToForwardView
100 }
101
102 async function getAudience (accountSender: AccountInstance, isPublic = true) {
103 const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls()
104
105 // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47
106 let to = []
107 let cc = []
108
109 if (isPublic) {
110 to = [ ACTIVITY_PUB.PUBLIC ]
111 cc = followerInboxUrls
112 } else { // Unlisted
113 to = followerInboxUrls
114 cc = [ ACTIVITY_PUB.PUBLIC ]
115 }
116
117 return { to, cc }
118 }
119
120 async function computeFollowerUris (toAccountFollower: AccountInstance[], followersException: AccountInstance[]) {
121 const toAccountFollowerIds = toAccountFollower.map(a => a.id)
122
123 const result = await db.AccountFollow.listAcceptedFollowerSharedInboxUrls(toAccountFollowerIds)
124 const followersSharedInboxException = followersException.map(f => f.sharedInboxUrl)
125 const uris = result.data.filter(sharedInbox => followersSharedInboxException.indexOf(sharedInbox) === -1)
126
127 return uris
128 }
129
130 // ---------------------------------------------------------------------------
131
132 export {
133 broadcastToFollowers,
134 unicastTo,
135 getAudience,
136 getOriginVideoAudience,
137 getAccountsInvolvedInVideo,
138 getVideoFollowersAudience,
139 forwardActivity
140 }