aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-11-27 14:44:51 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-11-27 19:40:53 +0100
commit4e50b6a1c9a3eb261e04ede73241648e6edf21d6 (patch)
treee1c6c121d561ffc1cf2996daec03a1e7f27f0a25 /server/lib/activitypub
parent74bb2cb8348d6794ed3a0e2ec94c8c9abdde82cf (diff)
downloadPeerTube-4e50b6a1c9a3eb261e04ede73241648e6edf21d6.tar.gz
PeerTube-4e50b6a1c9a3eb261e04ede73241648e6edf21d6.tar.zst
PeerTube-4e50b6a1c9a3eb261e04ede73241648e6edf21d6.zip
Add shares forward and collection on videos/video channels
Diffstat (limited to 'server/lib/activitypub')
-rw-r--r--server/lib/activitypub/process/misc.ts57
-rw-r--r--server/lib/activitypub/process/process-add.ts16
-rw-r--r--server/lib/activitypub/process/process-announce.ts100
-rw-r--r--server/lib/activitypub/process/process-create.ts12
-rw-r--r--server/lib/activitypub/send/misc.ts27
-rw-r--r--server/lib/activitypub/send/send-announce.ts86
-rw-r--r--server/lib/activitypub/send/send-create.ts6
-rw-r--r--server/lib/activitypub/send/send-like.ts4
-rw-r--r--server/lib/activitypub/send/send-undo.ts4
-rw-r--r--server/lib/activitypub/share.ts6
-rw-r--r--server/lib/activitypub/url.ts14
11 files changed, 270 insertions, 62 deletions
diff --git a/server/lib/activitypub/process/misc.ts b/server/lib/activitypub/process/misc.ts
index eefbe2884..f20e588ab 100644
--- a/server/lib/activitypub/process/misc.ts
+++ b/server/lib/activitypub/process/misc.ts
@@ -1,13 +1,16 @@
1import * as magnetUtil from 'magnet-uri' 1import * as magnetUtil from 'magnet-uri'
2import { VideoTorrentObject } from '../../../../shared' 2import { VideoTorrentObject } from '../../../../shared'
3import { VideoChannelObject } from '../../../../shared/models/activitypub/objects/video-channel-object' 3import { VideoChannelObject } from '../../../../shared/models/activitypub/objects/video-channel-object'
4import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
4import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos' 5import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos'
6import { doRequest } from '../../../helpers/requests'
7import { database as db } from '../../../initializers'
5import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers/constants' 8import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers/constants'
6import { AccountInstance } from '../../../models/account/account-interface' 9import { AccountInstance } from '../../../models/account/account-interface'
7import { VideoChannelInstance } from '../../../models/video/video-channel-interface' 10import { VideoChannelInstance } from '../../../models/video/video-channel-interface'
8import { VideoFileAttributes } from '../../../models/video/video-file-interface' 11import { VideoFileAttributes } from '../../../models/video/video-file-interface'
9import { VideoAttributes, VideoInstance } from '../../../models/video/video-interface' 12import { VideoAttributes, VideoInstance } from '../../../models/video/video-interface'
10import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' 13import { getOrCreateAccountAndServer } from '../account'
11 14
12function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountInstance) { 15function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountInstance) {
13 return { 16 return {
@@ -97,10 +100,60 @@ function videoFileActivityUrlToDBAttributes (videoCreated: VideoInstance, videoO
97 return attributes 100 return attributes
98} 101}
99 102
103async function addVideoShares (instance: VideoInstance, shares: string[]) {
104 for (const share of shares) {
105 // Fetch url
106 const json = await doRequest({
107 uri: share,
108 json: true
109 })
110 const actor = json['actor']
111 if (!actor) continue
112
113 const account = await getOrCreateAccountAndServer(actor)
114
115 const entry = {
116 accountId: account.id,
117 videoId: instance.id
118 }
119
120 await db.VideoShare.findOrCreate({
121 where: entry,
122 defaults: entry
123 })
124 }
125}
126
127async function addVideoChannelShares (instance: VideoChannelInstance, shares: string[]) {
128 for (const share of shares) {
129 // Fetch url
130 const json = await doRequest({
131 uri: share,
132 json: true
133 })
134 const actor = json['actor']
135 if (!actor) continue
136
137 const account = await getOrCreateAccountAndServer(actor)
138
139 const entry = {
140 accountId: account.id,
141 videoChannelId: instance.id
142 }
143
144 await db.VideoChannelShare.findOrCreate({
145 where: entry,
146 defaults: entry
147 })
148 }
149}
150
100// --------------------------------------------------------------------------- 151// ---------------------------------------------------------------------------
101 152
102export { 153export {
103 videoFileActivityUrlToDBAttributes, 154 videoFileActivityUrlToDBAttributes,
104 videoActivityObjectToDBAttributes, 155 videoActivityObjectToDBAttributes,
105 videoChannelActivityObjectToDBAttributes 156 videoChannelActivityObjectToDBAttributes,
157 addVideoChannelShares,
158 addVideoShares
106} 159}
diff --git a/server/lib/activitypub/process/process-add.ts b/server/lib/activitypub/process/process-add.ts
index 98280b9f0..e6bf63eb2 100644
--- a/server/lib/activitypub/process/process-add.ts
+++ b/server/lib/activitypub/process/process-add.ts
@@ -11,7 +11,7 @@ import { VideoInstance } from '../../../models/video/video-interface'
11import { getOrCreateAccountAndServer } from '../account' 11import { getOrCreateAccountAndServer } from '../account'
12import { getOrCreateVideoChannel } from '../video-channels' 12import { getOrCreateVideoChannel } from '../video-channels'
13import { generateThumbnailFromUrl } from '../videos' 13import { generateThumbnailFromUrl } from '../videos'
14import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' 14import { addVideoShares, videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc'
15 15
16async function processAddActivity (activity: ActivityAdd) { 16async function processAddActivity (activity: ActivityAdd) {
17 const activityObject = activity.object 17 const activityObject = activity.object
@@ -37,12 +37,10 @@ export {
37 37
38// --------------------------------------------------------------------------- 38// ---------------------------------------------------------------------------
39 39
40async function processAddVideo ( 40async function processAddVideo (account: AccountInstance,
41 account: AccountInstance, 41 activity: ActivityAdd,
42 activity: ActivityAdd, 42 videoChannel: VideoChannelInstance,
43 videoChannel: VideoChannelInstance, 43 videoToCreateData: VideoTorrentObject) {
44 videoToCreateData: VideoTorrentObject
45) {
46 const options = { 44 const options = {
47 arguments: [ account, activity, videoChannel, videoToCreateData ], 45 arguments: [ account, activity, videoChannel, videoToCreateData ],
48 errorMessage: 'Cannot insert the remote video with many retries.' 46 errorMessage: 'Cannot insert the remote video with many retries.'
@@ -59,6 +57,10 @@ async function processAddVideo (
59 await createRates(videoToCreateData.dislikes.orderedItems, video, 'dislike') 57 await createRates(videoToCreateData.dislikes.orderedItems, video, 'dislike')
60 } 58 }
61 59
60 if (videoToCreateData.shares && Array.isArray(videoToCreateData.shares.orderedItems)) {
61 await addVideoShares(video, videoToCreateData.shares.orderedItems)
62 }
63
62 return video 64 return video
63} 65}
64 66
diff --git a/server/lib/activitypub/process/process-announce.ts b/server/lib/activitypub/process/process-announce.ts
index d8532d3a1..2aa9ad5c7 100644
--- a/server/lib/activitypub/process/process-announce.ts
+++ b/server/lib/activitypub/process/process-announce.ts
@@ -1,34 +1,23 @@
1import { ActivityAnnounce } from '../../../../shared/models/activitypub/activity' 1import { ActivityAdd, ActivityAnnounce, ActivityCreate } from '../../../../shared/models/activitypub/activity'
2import { retryTransactionWrapper } from '../../../helpers/database-utils'
2import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
3import { database as db } from '../../../initializers/index' 4import { database as db } from '../../../initializers/index'
5import { AccountInstance } from '../../../models/account/account-interface'
4import { VideoInstance } from '../../../models/index' 6import { VideoInstance } from '../../../models/index'
5import { VideoChannelInstance } from '../../../models/video/video-channel-interface' 7import { VideoChannelInstance } from '../../../models/video/video-channel-interface'
8import { getOrCreateAccountAndServer } from '../account'
9import { forwardActivity } from '../send/misc'
6import { processAddActivity } from './process-add' 10import { processAddActivity } from './process-add'
7import { processCreateActivity } from './process-create' 11import { processCreateActivity } from './process-create'
8import { getOrCreateAccountAndServer } from '../account'
9 12
10async function processAnnounceActivity (activity: ActivityAnnounce) { 13async function processAnnounceActivity (activity: ActivityAnnounce) {
11 const announcedActivity = activity.object 14 const announcedActivity = activity.object
12 const accountAnnouncer = await getOrCreateAccountAndServer(activity.actor) 15 const accountAnnouncer = await getOrCreateAccountAndServer(activity.actor)
13 16
14 if (announcedActivity.type === 'Create' && announcedActivity.object.type === 'VideoChannel') { 17 if (announcedActivity.type === 'Create' && announcedActivity.object.type === 'VideoChannel') {
15 // Add share entry 18 return processVideoChannelShare(accountAnnouncer, activity)
16 const videoChannel: VideoChannelInstance = await processCreateActivity(announcedActivity)
17 await db.VideoChannelShare.create({
18 accountId: accountAnnouncer.id,
19 videoChannelId: videoChannel.id
20 })
21
22 return undefined
23 } else if (announcedActivity.type === 'Add' && announcedActivity.object.type === 'Video') { 19 } else if (announcedActivity.type === 'Add' && announcedActivity.object.type === 'Video') {
24 // Add share entry 20 return processVideoShare(accountAnnouncer, activity)
25 const video: VideoInstance = await processAddActivity(announcedActivity)
26 await db.VideoShare.create({
27 accountId: accountAnnouncer.id,
28 videoId: video.id
29 })
30
31 return undefined
32 } 21 }
33 22
34 logger.warn( 23 logger.warn(
@@ -44,3 +33,78 @@ async function processAnnounceActivity (activity: ActivityAnnounce) {
44export { 33export {
45 processAnnounceActivity 34 processAnnounceActivity
46} 35}
36
37// ---------------------------------------------------------------------------
38
39function processVideoChannelShare (accountAnnouncer: AccountInstance, activity: ActivityAnnounce) {
40 const options = {
41 arguments: [ accountAnnouncer, activity ],
42 errorMessage: 'Cannot share the video channel with many retries.'
43 }
44
45 return retryTransactionWrapper(shareVideoChannel, options)
46}
47
48async function shareVideoChannel (accountAnnouncer: AccountInstance, activity: ActivityAnnounce) {
49 const announcedActivity = activity.object as ActivityCreate
50
51 return db.sequelize.transaction(async t => {
52 // Add share entry
53 const videoChannel: VideoChannelInstance = await processCreateActivity(announcedActivity)
54 const share = {
55 accountId: accountAnnouncer.id,
56 videoChannelId: videoChannel.id
57 }
58
59 const [ , created ] = await db.VideoChannelShare.findOrCreate({
60 where: share,
61 defaults: share,
62 transaction: t
63 })
64
65 if (videoChannel.isOwned() && created === true) {
66 // Don't resend the activity to the sender
67 const exceptions = [ accountAnnouncer ]
68 await forwardActivity(activity, t, exceptions)
69 }
70
71 return undefined
72 })
73}
74
75function processVideoShare (accountAnnouncer: AccountInstance, activity: ActivityAnnounce) {
76 const options = {
77 arguments: [ accountAnnouncer, activity ],
78 errorMessage: 'Cannot share the video with many retries.'
79 }
80
81 return retryTransactionWrapper(shareVideo, options)
82}
83
84function shareVideo (accountAnnouncer: AccountInstance, activity: ActivityAnnounce) {
85 const announcedActivity = activity.object as ActivityAdd
86
87 return db.sequelize.transaction(async t => {
88 // Add share entry
89 const video: VideoInstance = await processAddActivity(announcedActivity)
90
91 const share = {
92 accountId: accountAnnouncer.id,
93 videoId: video.id
94 }
95
96 const [ , created ] = await db.VideoShare.findOrCreate({
97 where: share,
98 defaults: share,
99 transaction: t
100 })
101
102 if (video.isOwned() && created === true) {
103 // Don't resend the activity to the sender
104 const exceptions = [ accountAnnouncer ]
105 await forwardActivity(activity, t, exceptions)
106 }
107
108 return undefined
109 })
110}
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index 1f982598b..c88082bbf 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -8,7 +8,7 @@ import { AccountInstance } from '../../../models/account/account-interface'
8import { getOrCreateAccountAndServer } from '../account' 8import { getOrCreateAccountAndServer } from '../account'
9import { forwardActivity } from '../send/misc' 9import { forwardActivity } from '../send/misc'
10import { getVideoChannelActivityPubUrl } from '../url' 10import { getVideoChannelActivityPubUrl } from '../url'
11import { videoChannelActivityObjectToDBAttributes } from './misc' 11import { addVideoChannelShares, videoChannelActivityObjectToDBAttributes } from './misc'
12 12
13async function processCreateActivity (activity: ActivityCreate) { 13async function processCreateActivity (activity: ActivityCreate) {
14 const activityObject = activity.object 14 const activityObject = activity.object
@@ -92,13 +92,19 @@ async function processCreateView (byAccount: AccountInstance, activity: Activity
92 } 92 }
93} 93}
94 94
95function processCreateVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) { 95async function processCreateVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) {
96 const options = { 96 const options = {
97 arguments: [ account, videoChannelToCreateData ], 97 arguments: [ account, videoChannelToCreateData ],
98 errorMessage: 'Cannot insert the remote video channel with many retries.' 98 errorMessage: 'Cannot insert the remote video channel with many retries.'
99 } 99 }
100 100
101 return retryTransactionWrapper(addRemoteVideoChannel, options) 101 const videoChannel = await retryTransactionWrapper(addRemoteVideoChannel, options)
102
103 if (videoChannelToCreateData.shares && Array.isArray(videoChannelToCreateData.shares.orderedItems)) {
104 await addVideoChannelShares(videoChannel, videoChannelToCreateData.shares.orderedItems)
105 }
106
107 return videoChannel
102} 108}
103 109
104function addRemoteVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) { 110function addRemoteVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) {
diff --git a/server/lib/activitypub/send/misc.ts b/server/lib/activitypub/send/misc.ts
index 444c1cbd6..fd1add68e 100644
--- a/server/lib/activitypub/send/misc.ts
+++ b/server/lib/activitypub/send/misc.ts
@@ -1,13 +1,14 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { Activity } from '../../../../shared/models/activitypub/activity'
2import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
3import { ACTIVITY_PUB, database as db } from '../../../initializers' 4import { ACTIVITY_PUB, database as db } from '../../../initializers'
4import { AccountInstance } from '../../../models/account/account-interface' 5import { AccountInstance } from '../../../models/account/account-interface'
6import { VideoChannelInstance } from '../../../models/index'
7import { VideoInstance } from '../../../models/video/video-interface'
5import { 8import {
6 activitypubHttpJobScheduler, 9 activitypubHttpJobScheduler,
7 ActivityPubHttpPayload 10 ActivityPubHttpPayload
8} from '../../jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler' 11} from '../../jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler'
9import { VideoInstance } from '../../../models/video/video-interface'
10import { Activity } from '../../../../shared/models/activitypub/activity'
11 12
12async function forwardActivity ( 13async function forwardActivity (
13 activity: Activity, 14 activity: Activity,
@@ -85,9 +86,16 @@ function getOriginVideoAudience (video: VideoInstance, accountsInvolvedInVideo:
85 } 86 }
86} 87}
87 88
88function getVideoFollowersAudience (accountsInvolvedInVideo: AccountInstance[]) { 89function getOriginVideoChannelAudience (videoChannel: VideoChannelInstance, accountsInvolved: AccountInstance[]) {
90 return {
91 to: [ videoChannel.Account.url ],
92 cc: accountsInvolved.map(a => a.followersUrl)
93 }
94}
95
96function getObjectFollowersAudience (accountsInvolvedInObject: AccountInstance[]) {
89 return { 97 return {
90 to: accountsInvolvedInVideo.map(a => a.followersUrl), 98 to: accountsInvolvedInObject.map(a => a.followersUrl),
91 cc: [] 99 cc: []
92 } 100 }
93} 101}
@@ -99,6 +107,13 @@ async function getAccountsInvolvedInVideo (video: VideoInstance) {
99 return accountsToForwardView 107 return accountsToForwardView
100} 108}
101 109
110async function getAccountsInvolvedInVideoChannel (videoChannel: VideoChannelInstance) {
111 const accountsToForwardView = await db.VideoChannelShare.loadAccountsByShare(videoChannel.id)
112 accountsToForwardView.push(videoChannel.Account)
113
114 return accountsToForwardView
115}
116
102async function getAudience (accountSender: AccountInstance, isPublic = true) { 117async function getAudience (accountSender: AccountInstance, isPublic = true) {
103 const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls() 118 const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls()
104 119
@@ -131,10 +146,12 @@ async function computeFollowerUris (toAccountFollower: AccountInstance[], follow
131 146
132export { 147export {
133 broadcastToFollowers, 148 broadcastToFollowers,
149 getOriginVideoChannelAudience,
134 unicastTo, 150 unicastTo,
135 getAudience, 151 getAudience,
136 getOriginVideoAudience, 152 getOriginVideoAudience,
137 getAccountsInvolvedInVideo, 153 getAccountsInvolvedInVideo,
138 getVideoFollowersAudience, 154 getAccountsInvolvedInVideoChannel,
155 getObjectFollowersAudience,
139 forwardActivity 156 forwardActivity
140} 157}
diff --git a/server/lib/activitypub/send/send-announce.ts b/server/lib/activitypub/send/send-announce.ts
index b8ea51bc0..efc23af46 100644
--- a/server/lib/activitypub/send/send-announce.ts
+++ b/server/lib/activitypub/send/send-announce.ts
@@ -1,34 +1,96 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { ActivityAdd } from '../../../../shared/index' 2import { ActivityAdd } from '../../../../shared/index'
3import { ActivityAnnounce, ActivityCreate } from '../../../../shared/models/activitypub/activity' 3import { ActivityAnnounce, ActivityAudience, ActivityCreate } from '../../../../shared/models/activitypub/activity'
4import { AccountInstance, VideoInstance } from '../../../models' 4import { AccountInstance, VideoInstance } from '../../../models'
5import { VideoChannelInstance } from '../../../models/video/video-channel-interface' 5import { VideoChannelInstance } from '../../../models/video/video-channel-interface'
6import { getAnnounceActivityPubUrl } from '../url' 6import { getAnnounceActivityPubUrl } from '../url'
7import { broadcastToFollowers } from './misc' 7import {
8 broadcastToFollowers,
9 getAccountsInvolvedInVideo,
10 getAccountsInvolvedInVideoChannel,
11 getAudience,
12 getObjectFollowersAudience,
13 getOriginVideoAudience,
14 getOriginVideoChannelAudience,
15 unicastTo
16} from './misc'
8import { addActivityData } from './send-add' 17import { addActivityData } from './send-add'
9import { createActivityData } from './send-create' 18import { createActivityData } from './send-create'
10 19
11async function sendVideoAnnounce (byAccount: AccountInstance, video: VideoInstance, t: Transaction) { 20async function buildVideoAnnounceToFollowers (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
12 const url = getAnnounceActivityPubUrl(video.url, byAccount) 21 const url = getAnnounceActivityPubUrl(video.url, byAccount)
13 22
14 const videoChannel = video.VideoChannel 23 const videoChannel = video.VideoChannel
15 const announcedActivity = await addActivityData(url, videoChannel.Account, video, videoChannel.url, video.toActivityPubObject()) 24 const announcedActivity = await addActivityData(url, videoChannel.Account, video, videoChannel.url, video.toActivityPubObject())
16 25
17 const data = await announceActivityData(url, byAccount, announcedActivity) 26 const accountsToForwardView = await getAccountsInvolvedInVideo(video)
27 const audience = getObjectFollowersAudience(accountsToForwardView)
28 const data = await announceActivityData(url, byAccount, announcedActivity, audience)
29
30 return data
31}
32
33async function sendVideoAnnounceToFollowers (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
34 const data = await buildVideoAnnounceToFollowers(byAccount, video, t)
35
18 return broadcastToFollowers(data, byAccount, [ byAccount ], t) 36 return broadcastToFollowers(data, byAccount, [ byAccount ], t)
19} 37}
20 38
21async function sendVideoChannelAnnounce (byAccount: AccountInstance, videoChannel: VideoChannelInstance, t: Transaction) { 39async function sendVideoAnnounceToOrigin (byAccount: AccountInstance, video: VideoInstance, t: Transaction) {
40 const url = getAnnounceActivityPubUrl(video.url, byAccount)
41
42 const videoChannel = video.VideoChannel
43 const announcedActivity = await addActivityData(url, videoChannel.Account, video, videoChannel.url, video.toActivityPubObject())
44
45 const accountsInvolvedInVideo = await getAccountsInvolvedInVideo(video)
46 const audience = getOriginVideoAudience(video, accountsInvolvedInVideo)
47 const data = await createActivityData(url, byAccount, announcedActivity, audience)
48
49 return unicastTo(data, byAccount, videoChannel.Account.sharedInboxUrl, t)
50}
51
52async function buildVideoChannelAnnounceToFollowers (byAccount: AccountInstance, videoChannel: VideoChannelInstance, t: Transaction) {
22 const url = getAnnounceActivityPubUrl(videoChannel.url, byAccount) 53 const url = getAnnounceActivityPubUrl(videoChannel.url, byAccount)
23 const announcedActivity = await createActivityData(url, videoChannel.Account, videoChannel.toActivityPubObject()) 54 const announcedActivity = await createActivityData(url, videoChannel.Account, videoChannel.toActivityPubObject())
24 55
25 const data = await announceActivityData(url, byAccount, announcedActivity) 56 const accountsToForwardView = await getAccountsInvolvedInVideoChannel(videoChannel)
57 const audience = getObjectFollowersAudience(accountsToForwardView)
58 const data = await announceActivityData(url, byAccount, announcedActivity, audience)
59
60 return data
61}
62
63async function sendVideoChannelAnnounceToFollowers (byAccount: AccountInstance, videoChannel: VideoChannelInstance, t: Transaction) {
64 const data = await buildVideoChannelAnnounceToFollowers(byAccount, videoChannel, t)
65
26 return broadcastToFollowers(data, byAccount, [ byAccount ], t) 66 return broadcastToFollowers(data, byAccount, [ byAccount ], t)
27} 67}
28 68
29async function announceActivityData (url: string, byAccount: AccountInstance, object: ActivityCreate | ActivityAdd) { 69async function sendVideoChannelAnnounceToOrigin (byAccount: AccountInstance, videoChannel: VideoChannelInstance, t: Transaction) {
70 const url = getAnnounceActivityPubUrl(videoChannel.url, byAccount)
71 const announcedActivity = await createActivityData(url, videoChannel.Account, videoChannel.toActivityPubObject())
72
73 const accountsInvolvedInVideo = await getAccountsInvolvedInVideoChannel(videoChannel)
74 const audience = getOriginVideoChannelAudience(videoChannel, accountsInvolvedInVideo)
75 const data = await createActivityData(url, byAccount, announcedActivity, audience)
76
77 return unicastTo(data, byAccount, videoChannel.Account.sharedInboxUrl, t)
78}
79
80async function announceActivityData (
81 url: string,
82 byAccount: AccountInstance,
83 object: ActivityCreate | ActivityAdd,
84 audience?: ActivityAudience
85) {
86 if (!audience) {
87 audience = await getAudience(byAccount)
88 }
89
30 const activity: ActivityAnnounce = { 90 const activity: ActivityAnnounce = {
31 type: 'Announce', 91 type: 'Announce',
92 to: audience.to,
93 cc: audience.cc,
32 id: url, 94 id: url,
33 actor: byAccount.url, 95 actor: byAccount.url,
34 object 96 object
@@ -40,7 +102,11 @@ async function announceActivityData (url: string, byAccount: AccountInstance, ob
40// --------------------------------------------------------------------------- 102// ---------------------------------------------------------------------------
41 103
42export { 104export {
43 sendVideoAnnounce, 105 sendVideoAnnounceToFollowers,
44 sendVideoChannelAnnounce, 106 sendVideoChannelAnnounceToFollowers,
45 announceActivityData 107 sendVideoAnnounceToOrigin,
108 sendVideoChannelAnnounceToOrigin,
109 announceActivityData,
110 buildVideoAnnounceToFollowers,
111 buildVideoChannelAnnounceToFollowers
46} 112}
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts
index 113d89233..bf66606c1 100644
--- a/server/lib/activitypub/send/send-create.ts
+++ b/server/lib/activitypub/send/send-create.ts
@@ -9,7 +9,7 @@ import {
9 getAccountsInvolvedInVideo, 9 getAccountsInvolvedInVideo,
10 getAudience, 10 getAudience,
11 getOriginVideoAudience, 11 getOriginVideoAudience,
12 getVideoFollowersAudience, 12 getObjectFollowersAudience,
13 unicastTo 13 unicastTo
14} from './misc' 14} from './misc'
15 15
@@ -47,7 +47,7 @@ async function sendCreateViewToVideoFollowers (byAccount: AccountInstance, video
47 const viewActivity = createViewActivityData(byAccount, video) 47 const viewActivity = createViewActivityData(byAccount, video)
48 48
49 const accountsToForwardView = await getAccountsInvolvedInVideo(video) 49 const accountsToForwardView = await getAccountsInvolvedInVideo(video)
50 const audience = getVideoFollowersAudience(accountsToForwardView) 50 const audience = getObjectFollowersAudience(accountsToForwardView)
51 const data = await createActivityData(url, byAccount, viewActivity, audience) 51 const data = await createActivityData(url, byAccount, viewActivity, audience)
52 52
53 // Use the server account to send the view, because it could be an unregistered account 53 // Use the server account to send the view, because it could be an unregistered account
@@ -72,7 +72,7 @@ async function sendCreateDislikeToVideoFollowers (byAccount: AccountInstance, vi
72 const dislikeActivity = createDislikeActivityData(byAccount, video) 72 const dislikeActivity = createDislikeActivityData(byAccount, video)
73 73
74 const accountsToForwardView = await getAccountsInvolvedInVideo(video) 74 const accountsToForwardView = await getAccountsInvolvedInVideo(video)
75 const audience = getVideoFollowersAudience(accountsToForwardView) 75 const audience = getObjectFollowersAudience(accountsToForwardView)
76 const data = await createActivityData(url, byAccount, dislikeActivity, audience) 76 const data = await createActivityData(url, byAccount, dislikeActivity, audience)
77 77
78 const followersException = [ byAccount ] 78 const followersException = [ byAccount ]
diff --git a/server/lib/activitypub/send/send-like.ts b/server/lib/activitypub/send/send-like.ts
index 8ca775bf3..41b879b8a 100644
--- a/server/lib/activitypub/send/send-like.ts
+++ b/server/lib/activitypub/send/send-like.ts
@@ -7,7 +7,7 @@ import {
7 getAccountsInvolvedInVideo, 7 getAccountsInvolvedInVideo,
8 getAudience, 8 getAudience,
9 getOriginVideoAudience, 9 getOriginVideoAudience,
10 getVideoFollowersAudience, 10 getObjectFollowersAudience,
11 unicastTo 11 unicastTo
12} from './misc' 12} from './misc'
13 13
@@ -25,7 +25,7 @@ async function sendLikeToVideoFollowers (byAccount: AccountInstance, video: Vide
25 const url = getVideoLikeActivityPubUrl(byAccount, video) 25 const url = getVideoLikeActivityPubUrl(byAccount, video)
26 26
27 const accountsInvolvedInVideo = await getAccountsInvolvedInVideo(video) 27 const accountsInvolvedInVideo = await getAccountsInvolvedInVideo(video)
28 const audience = getVideoFollowersAudience(accountsInvolvedInVideo) 28 const audience = getObjectFollowersAudience(accountsInvolvedInVideo)
29 const data = await likeActivityData(url, byAccount, video, audience) 29 const data = await likeActivityData(url, byAccount, video, audience)
30 30
31 const toAccountsFollowers = await getAccountsInvolvedInVideo(video) 31 const toAccountsFollowers = await getAccountsInvolvedInVideo(video)
diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts
index 79fc113f0..9b732df40 100644
--- a/server/lib/activitypub/send/send-undo.ts
+++ b/server/lib/activitypub/send/send-undo.ts
@@ -10,7 +10,7 @@ import { AccountInstance } from '../../../models'
10import { AccountFollowInstance } from '../../../models/account/account-follow-interface' 10import { AccountFollowInstance } from '../../../models/account/account-follow-interface'
11import { VideoInstance } from '../../../models/video/video-interface' 11import { VideoInstance } from '../../../models/video/video-interface'
12import { getAccountFollowActivityPubUrl, getUndoActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from '../url' 12import { getAccountFollowActivityPubUrl, getUndoActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from '../url'
13import { broadcastToFollowers, getAccountsInvolvedInVideo, getAudience, getVideoFollowersAudience, unicastTo } from './misc' 13import { broadcastToFollowers, getAccountsInvolvedInVideo, getAudience, getObjectFollowersAudience, unicastTo } from './misc'
14import { createActivityData, createDislikeActivityData } from './send-create' 14import { createActivityData, createDislikeActivityData } from './send-create'
15import { followActivityData } from './send-follow' 15import { followActivityData } from './send-follow'
16import { likeActivityData } from './send-like' 16import { likeActivityData } from './send-like'
@@ -43,7 +43,7 @@ async function sendUndoLikeToVideoFollowers (byAccount: AccountInstance, video:
43 const undoUrl = getUndoActivityPubUrl(likeUrl) 43 const undoUrl = getUndoActivityPubUrl(likeUrl)
44 44
45 const toAccountsFollowers = await getAccountsInvolvedInVideo(video) 45 const toAccountsFollowers = await getAccountsInvolvedInVideo(video)
46 const audience = getVideoFollowersAudience(toAccountsFollowers) 46 const audience = getObjectFollowersAudience(toAccountsFollowers)
47 const object = await likeActivityData(likeUrl, byAccount, video) 47 const object = await likeActivityData(likeUrl, byAccount, video)
48 const data = await undoActivityData(undoUrl, byAccount, object, audience) 48 const data = await undoActivityData(undoUrl, byAccount, object, audience)
49 49
diff --git a/server/lib/activitypub/share.ts b/server/lib/activitypub/share.ts
index 689e200a6..e14b0f50c 100644
--- a/server/lib/activitypub/share.ts
+++ b/server/lib/activitypub/share.ts
@@ -3,7 +3,7 @@ import { getServerAccount } from '../../helpers/utils'
3import { database as db } from '../../initializers' 3import { database as db } from '../../initializers'
4import { VideoChannelInstance } from '../../models/index' 4import { VideoChannelInstance } from '../../models/index'
5import { VideoInstance } from '../../models/video/video-interface' 5import { VideoInstance } from '../../models/video/video-interface'
6import { sendVideoAnnounce, sendVideoChannelAnnounce } from './send/send-announce' 6import { sendVideoAnnounceToFollowers, sendVideoChannelAnnounceToFollowers } from './send/send-announce'
7 7
8async function shareVideoChannelByServer (videoChannel: VideoChannelInstance, t: Transaction) { 8async function shareVideoChannelByServer (videoChannel: VideoChannelInstance, t: Transaction) {
9 const serverAccount = await getServerAccount() 9 const serverAccount = await getServerAccount()
@@ -13,7 +13,7 @@ async function shareVideoChannelByServer (videoChannel: VideoChannelInstance, t:
13 videoChannelId: videoChannel.id 13 videoChannelId: videoChannel.id
14 }, { transaction: t }) 14 }, { transaction: t })
15 15
16 return sendVideoChannelAnnounce(serverAccount, videoChannel, t) 16 return sendVideoChannelAnnounceToFollowers(serverAccount, videoChannel, t)
17} 17}
18 18
19async function shareVideoByServer (video: VideoInstance, t: Transaction) { 19async function shareVideoByServer (video: VideoInstance, t: Transaction) {
@@ -24,7 +24,7 @@ async function shareVideoByServer (video: VideoInstance, t: Transaction) {
24 videoId: video.id 24 videoId: video.id
25 }, { transaction: t }) 25 }, { transaction: t })
26 26
27 return sendVideoAnnounce(serverAccount, video, t) 27 return sendVideoAnnounceToFollowers(serverAccount, video, t)
28} 28}
29 29
30export { 30export {
diff --git a/server/lib/activitypub/url.ts b/server/lib/activitypub/url.ts
index 17395a99b..6475c4218 100644
--- a/server/lib/activitypub/url.ts
+++ b/server/lib/activitypub/url.ts
@@ -22,37 +22,37 @@ function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseInstance) {
22} 22}
23 23
24function getVideoViewActivityPubUrl (byAccount: AccountInstance, video: VideoInstance) { 24function getVideoViewActivityPubUrl (byAccount: AccountInstance, video: VideoInstance) {
25 return video.url + '#views/' + byAccount.uuid + '/' + new Date().toISOString() 25 return video.url + '/views/' + byAccount.uuid + '/' + new Date().toISOString()
26} 26}
27 27
28function getVideoLikeActivityPubUrl (byAccount: AccountInstance, video: VideoInstance) { 28function getVideoLikeActivityPubUrl (byAccount: AccountInstance, video: VideoInstance) {
29 return byAccount.url + '#likes/' + video.id 29 return byAccount.url + '/likes/' + video.id
30} 30}
31 31
32function getVideoDislikeActivityPubUrl (byAccount: AccountInstance, video: VideoInstance) { 32function getVideoDislikeActivityPubUrl (byAccount: AccountInstance, video: VideoInstance) {
33 return byAccount.url + '#dislikes/' + video.id 33 return byAccount.url + '/dislikes/' + video.id
34} 34}
35 35
36function getAccountFollowActivityPubUrl (accountFollow: AccountFollowInstance) { 36function getAccountFollowActivityPubUrl (accountFollow: AccountFollowInstance) {
37 const me = accountFollow.AccountFollower 37 const me = accountFollow.AccountFollower
38 const following = accountFollow.AccountFollowing 38 const following = accountFollow.AccountFollowing
39 39
40 return me.url + '#follows/' + following.id 40 return me.url + '/follows/' + following.id
41} 41}
42 42
43function getAccountFollowAcceptActivityPubUrl (accountFollow: AccountFollowInstance) { 43function getAccountFollowAcceptActivityPubUrl (accountFollow: AccountFollowInstance) {
44 const follower = accountFollow.AccountFollower 44 const follower = accountFollow.AccountFollower
45 const me = accountFollow.AccountFollowing 45 const me = accountFollow.AccountFollowing
46 46
47 return follower.url + '#accepts/follows/' + me.id 47 return follower.url + '/accepts/follows/' + me.id
48} 48}
49 49
50function getAnnounceActivityPubUrl (originalUrl: string, byAccount: AccountInstance) { 50function getAnnounceActivityPubUrl (originalUrl: string, byAccount: AccountInstance) {
51 return originalUrl + '#announces/' + byAccount.id 51 return originalUrl + '/announces/' + byAccount.id
52} 52}
53 53
54function getUpdateActivityPubUrl (originalUrl: string, updatedAt: string) { 54function getUpdateActivityPubUrl (originalUrl: string, updatedAt: string) {
55 return originalUrl + '#updates/' + updatedAt 55 return originalUrl + '/updates/' + updatedAt
56} 56}
57 57
58function getUndoActivityPubUrl (originalUrl: string) { 58function getUndoActivityPubUrl (originalUrl: string) {