Correctly forward like/dislikes and undo
[oweals/peertube.git] / server / lib / activitypub / send / send-create.ts
1 import { Transaction } from 'sequelize'
2 import { ActivityAudience, ActivityCreate } from '../../../../shared/models/activitypub/activity'
3 import { getServerAccount } from '../../../helpers/utils'
4 import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models'
5 import { VideoAbuseInstance } from '../../../models/video/video-abuse-interface'
6 import { getVideoAbuseActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoViewActivityPubUrl } from '../url'
7 import {
8   broadcastToFollowers,
9   getAccountsInvolvedInVideo,
10   getAudience,
11   getOriginVideoAudience,
12   getVideoFollowersAudience,
13   unicastTo
14 } from './misc'
15
16 async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) {
17   const byAccount = videoChannel.Account
18
19   const videoChannelObject = videoChannel.toActivityPubObject()
20   const data = await createActivityData(videoChannel.url, byAccount, videoChannelObject)
21
22   return broadcastToFollowers(data, byAccount, [ byAccount ], t)
23 }
24
25 async function sendVideoAbuse (byAccount: AccountInstance, videoAbuse: VideoAbuseInstance, video: VideoInstance, t: Transaction) {
26   const url = getVideoAbuseActivityPubUrl(videoAbuse)
27
28   const audience = { to: [ video.VideoChannel.Account.url ], cc: [] }
29   const data = await createActivityData(url, byAccount, videoAbuse.toActivityPubObject(), audience)
30
31   return unicastTo(data, byAccount, video.VideoChannel.Account.sharedInboxUrl, t)
32 }
33
34 async function sendCreateViewToOrigin (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
35   const url = getVideoViewActivityPubUrl(byAccount, video)
36   const viewActivity = createViewActivityData(byAccount, video)
37
38   const accountsInvolvedInVideo = await getAccountsInvolvedInVideo(video)
39   const audience = getOriginVideoAudience(video, accountsInvolvedInVideo)
40   const data = await createActivityData(url, byAccount, viewActivity, audience)
41
42   return unicastTo(data, byAccount, video.VideoChannel.Account.sharedInboxUrl, t)
43 }
44
45 async function sendCreateViewToVideoFollowers (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
46   const url = getVideoViewActivityPubUrl(byAccount, video)
47   const viewActivity = createViewActivityData(byAccount, video)
48
49   const accountsToForwardView = await getAccountsInvolvedInVideo(video)
50   const audience = getVideoFollowersAudience(accountsToForwardView)
51   const data = await createActivityData(url, byAccount, viewActivity, audience)
52
53   // Use the server account to send the view, because it could be an unregistered account
54   const serverAccount = await getServerAccount()
55   const followersException = [ byAccount ]
56   return broadcastToFollowers(data, serverAccount, accountsToForwardView, t, followersException)
57 }
58
59 async function sendCreateDislikeToOrigin (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
60   const url = getVideoDislikeActivityPubUrl(byAccount, video)
61   const dislikeActivity = createDislikeActivityData(byAccount, video)
62
63   const accountsInvolvedInVideo = await getAccountsInvolvedInVideo(video)
64   const audience = getOriginVideoAudience(video, accountsInvolvedInVideo)
65   const data = await createActivityData(url, byAccount, dislikeActivity, audience)
66
67   return unicastTo(data, byAccount, video.VideoChannel.Account.sharedInboxUrl, t)
68 }
69
70 async function sendCreateDislikeToVideoFollowers (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
71   const url = getVideoDislikeActivityPubUrl(byAccount, video)
72   const dislikeActivity = createDislikeActivityData(byAccount, video)
73
74   const accountsToForwardView = await getAccountsInvolvedInVideo(video)
75   const audience = getVideoFollowersAudience(accountsToForwardView)
76   const data = await createActivityData(url, byAccount, dislikeActivity, audience)
77
78   const followersException = [ byAccount ]
79   return broadcastToFollowers(data, byAccount, accountsToForwardView, t, followersException)
80 }
81
82 async function createActivityData (url: string, byAccount: AccountInstance, object: any, audience?: ActivityAudience) {
83   if (!audience) {
84     audience = await getAudience(byAccount)
85   }
86
87   const activity: ActivityCreate = {
88     type: 'Create',
89     id: url,
90     actor: byAccount.url,
91     to: audience.to,
92     cc: audience.cc,
93     object
94   }
95
96   return activity
97 }
98
99 function createDislikeActivityData (byAccount: AccountInstance, video: VideoInstance) {
100   const obj = {
101     type: 'Dislike',
102     actor: byAccount.url,
103     object: video.url
104   }
105
106   return obj
107 }
108
109 // ---------------------------------------------------------------------------
110
111 export {
112   sendCreateVideoChannel,
113   sendVideoAbuse,
114   createActivityData,
115   sendCreateViewToOrigin,
116   sendCreateViewToVideoFollowers,
117   sendCreateDislikeToOrigin,
118   sendCreateDislikeToVideoFollowers,
119   createDislikeActivityData
120 }
121
122 // ---------------------------------------------------------------------------
123
124 function createViewActivityData (byAccount: AccountInstance, video: VideoInstance) {
125   const obj = {
126     type: 'View',
127     actor: byAccount.url,
128     object: video.url
129   }
130
131   return obj
132 }