diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-11-20 09:43:39 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-11-27 19:40:52 +0100 |
commit | 54141398354e6e7b94aa3065a705a1251390111c (patch) | |
tree | 8d30d1b9ea8acbe04f6d404125b04fc0c9897b70 /server/lib/activitypub/send | |
parent | eb8b27c93e61a896a08923dc1ca3c87ba8cf4948 (diff) | |
download | PeerTube-54141398354e6e7b94aa3065a705a1251390111c.tar.gz PeerTube-54141398354e6e7b94aa3065a705a1251390111c.tar.zst PeerTube-54141398354e6e7b94aa3065a705a1251390111c.zip |
Refractor activity pub lib/helpers
Diffstat (limited to 'server/lib/activitypub/send')
-rw-r--r-- | server/lib/activitypub/send/index.ts | 7 | ||||
-rw-r--r-- | server/lib/activitypub/send/misc.ts | 58 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-accept.ts | 34 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-add.ts | 38 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-announce.ts | 45 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-create.ts | 44 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-delete.ts | 53 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-follow.ts | 34 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-undo.ts | 39 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-update.ts | 55 |
10 files changed, 407 insertions, 0 deletions
diff --git a/server/lib/activitypub/send/index.ts b/server/lib/activitypub/send/index.ts new file mode 100644 index 000000000..5f15dd4b5 --- /dev/null +++ b/server/lib/activitypub/send/index.ts | |||
@@ -0,0 +1,7 @@ | |||
1 | export * from './send-accept' | ||
2 | export * from './send-add' | ||
3 | export * from './send-announce' | ||
4 | export * from './send-create' | ||
5 | export * from './send-delete' | ||
6 | export * from './send-follow' | ||
7 | export * from './send-update' | ||
diff --git a/server/lib/activitypub/send/misc.ts b/server/lib/activitypub/send/misc.ts new file mode 100644 index 000000000..bea955b67 --- /dev/null +++ b/server/lib/activitypub/send/misc.ts | |||
@@ -0,0 +1,58 @@ | |||
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 { activitypubHttpJobScheduler } from '../../jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler' | ||
6 | |||
7 | async function broadcastToFollowers (data: any, byAccount: AccountInstance, toAccountFollowers: AccountInstance[], t: Transaction) { | ||
8 | const toAccountFollowerIds = toAccountFollowers.map(a => a.id) | ||
9 | const result = await db.AccountFollow.listAcceptedFollowerSharedInboxUrls(toAccountFollowerIds) | ||
10 | if (result.data.length === 0) { | ||
11 | logger.info('Not broadcast because of 0 followers for %s.', toAccountFollowerIds.join(', ')) | ||
12 | return undefined | ||
13 | } | ||
14 | |||
15 | const jobPayload = { | ||
16 | uris: result.data, | ||
17 | signatureAccountId: byAccount.id, | ||
18 | body: data | ||
19 | } | ||
20 | |||
21 | return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpBroadcastHandler', jobPayload) | ||
22 | } | ||
23 | |||
24 | async function unicastTo (data: any, byAccount: AccountInstance, toAccountUrl: string, t: Transaction) { | ||
25 | const jobPayload = { | ||
26 | uris: [ toAccountUrl ], | ||
27 | signatureAccountId: byAccount.id, | ||
28 | body: data | ||
29 | } | ||
30 | |||
31 | return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpUnicastHandler', jobPayload) | ||
32 | } | ||
33 | |||
34 | async function getAudience (accountSender: AccountInstance, isPublic = true) { | ||
35 | const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls() | ||
36 | |||
37 | // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47 | ||
38 | let to = [] | ||
39 | let cc = [] | ||
40 | |||
41 | if (isPublic) { | ||
42 | to = [ ACTIVITY_PUB.PUBLIC ] | ||
43 | cc = followerInboxUrls | ||
44 | } else { // Unlisted | ||
45 | to = followerInboxUrls | ||
46 | cc = [ ACTIVITY_PUB.PUBLIC ] | ||
47 | } | ||
48 | |||
49 | return { to, cc } | ||
50 | } | ||
51 | |||
52 | // --------------------------------------------------------------------------- | ||
53 | |||
54 | export { | ||
55 | broadcastToFollowers, | ||
56 | unicastTo, | ||
57 | getAudience | ||
58 | } | ||
diff --git a/server/lib/activitypub/send/send-accept.ts b/server/lib/activitypub/send/send-accept.ts new file mode 100644 index 000000000..0324a30fa --- /dev/null +++ b/server/lib/activitypub/send/send-accept.ts | |||
@@ -0,0 +1,34 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityAccept } from '../../../../shared/models/activitypub/activity' | ||
3 | import { AccountInstance } from '../../../models' | ||
4 | import { AccountFollowInstance } from '../../../models/account/account-follow-interface' | ||
5 | import { unicastTo } from './misc' | ||
6 | import { getAccountFollowAcceptActivityPubUrl } from '../../../helpers/activitypub' | ||
7 | |||
8 | async function sendAccept (accountFollow: AccountFollowInstance, t: Transaction) { | ||
9 | const follower = accountFollow.AccountFollower | ||
10 | const me = accountFollow.AccountFollowing | ||
11 | |||
12 | const url = getAccountFollowAcceptActivityPubUrl(accountFollow) | ||
13 | const data = await acceptActivityData(url, me) | ||
14 | |||
15 | return unicastTo(data, me, follower.inboxUrl, t) | ||
16 | } | ||
17 | |||
18 | // --------------------------------------------------------------------------- | ||
19 | |||
20 | export { | ||
21 | sendAccept | ||
22 | } | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
25 | |||
26 | async function acceptActivityData (url: string, byAccount: AccountInstance) { | ||
27 | const activity: ActivityAccept = { | ||
28 | type: 'Accept', | ||
29 | id: url, | ||
30 | actor: byAccount.url | ||
31 | } | ||
32 | |||
33 | return activity | ||
34 | } | ||
diff --git a/server/lib/activitypub/send/send-add.ts b/server/lib/activitypub/send/send-add.ts new file mode 100644 index 000000000..3012b7533 --- /dev/null +++ b/server/lib/activitypub/send/send-add.ts | |||
@@ -0,0 +1,38 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityAdd } from '../../../../shared/models/activitypub/activity' | ||
3 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' | ||
4 | import { AccountInstance, VideoInstance } from '../../../models' | ||
5 | import { broadcastToFollowers, getAudience } from './misc' | ||
6 | |||
7 | async function sendAddVideo (video: VideoInstance, t: Transaction) { | ||
8 | const byAccount = video.VideoChannel.Account | ||
9 | |||
10 | const videoObject = video.toActivityPubObject() | ||
11 | const data = await addActivityData(video.url, byAccount, video, video.VideoChannel.url, videoObject) | ||
12 | |||
13 | return broadcastToFollowers(data, byAccount, [ byAccount ], t) | ||
14 | } | ||
15 | |||
16 | async function addActivityData (url: string, byAccount: AccountInstance, video: VideoInstance, target: string, object: any) { | ||
17 | const videoPublic = video.privacy === VideoPrivacy.PUBLIC | ||
18 | |||
19 | const { to, cc } = await getAudience(byAccount, videoPublic) | ||
20 | const activity: ActivityAdd = { | ||
21 | type: 'Add', | ||
22 | id: url, | ||
23 | actor: byAccount.url, | ||
24 | to, | ||
25 | cc, | ||
26 | object, | ||
27 | target | ||
28 | } | ||
29 | |||
30 | return activity | ||
31 | } | ||
32 | |||
33 | // --------------------------------------------------------------------------- | ||
34 | |||
35 | export { | ||
36 | addActivityData, | ||
37 | sendAddVideo | ||
38 | } | ||
diff --git a/server/lib/activitypub/send/send-announce.ts b/server/lib/activitypub/send/send-announce.ts new file mode 100644 index 000000000..b9217e4f6 --- /dev/null +++ b/server/lib/activitypub/send/send-announce.ts | |||
@@ -0,0 +1,45 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { AccountInstance, VideoInstance } from '../../../models' | ||
3 | import { VideoChannelInstance } from '../../../models/video/video-channel-interface' | ||
4 | import { broadcastToFollowers } from './misc' | ||
5 | import { addActivityData } from './send-add' | ||
6 | import { createActivityData } from './send-create' | ||
7 | import { getAnnounceActivityPubUrl } from '../../../helpers/activitypub' | ||
8 | |||
9 | async function sendVideoAnnounce (byAccount: AccountInstance, video: VideoInstance, t: Transaction) { | ||
10 | const url = getAnnounceActivityPubUrl(video.url, byAccount) | ||
11 | |||
12 | const videoChannel = video.VideoChannel | ||
13 | const announcedActivity = await addActivityData(url, videoChannel.Account, video, videoChannel.url, video.toActivityPubObject()) | ||
14 | |||
15 | const data = await announceActivityData(url, byAccount, announcedActivity) | ||
16 | return broadcastToFollowers(data, byAccount, [ byAccount ], t) | ||
17 | } | ||
18 | |||
19 | async function sendVideoChannelAnnounce (byAccount: AccountInstance, videoChannel: VideoChannelInstance, t: Transaction) { | ||
20 | const url = getAnnounceActivityPubUrl(videoChannel.url, byAccount) | ||
21 | const announcedActivity = await createActivityData(url, videoChannel.Account, videoChannel.toActivityPubObject()) | ||
22 | |||
23 | const data = await announceActivityData(url, byAccount, announcedActivity) | ||
24 | return broadcastToFollowers(data, byAccount, [ byAccount ], t) | ||
25 | } | ||
26 | |||
27 | // --------------------------------------------------------------------------- | ||
28 | |||
29 | export { | ||
30 | sendVideoAnnounce, | ||
31 | sendVideoChannelAnnounce | ||
32 | } | ||
33 | |||
34 | // --------------------------------------------------------------------------- | ||
35 | |||
36 | async function announceActivityData (url: string, byAccount: AccountInstance, object: any) { | ||
37 | const activity = { | ||
38 | type: 'Announce', | ||
39 | id: url, | ||
40 | actor: byAccount.url, | ||
41 | object | ||
42 | } | ||
43 | |||
44 | return activity | ||
45 | } | ||
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts new file mode 100644 index 000000000..66bfeee89 --- /dev/null +++ b/server/lib/activitypub/send/send-create.ts | |||
@@ -0,0 +1,44 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityCreate } from '../../../../shared/models/activitypub/activity' | ||
3 | import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models' | ||
4 | import { VideoAbuseInstance } from '../../../models/video/video-abuse-interface' | ||
5 | import { broadcastToFollowers, getAudience, unicastTo } from './misc' | ||
6 | import { getVideoAbuseActivityPubUrl } from '../../../helpers/activitypub' | ||
7 | |||
8 | async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) { | ||
9 | const byAccount = videoChannel.Account | ||
10 | |||
11 | const videoChannelObject = videoChannel.toActivityPubObject() | ||
12 | const data = await createActivityData(videoChannel.url, byAccount, videoChannelObject) | ||
13 | |||
14 | return broadcastToFollowers(data, byAccount, [ byAccount ], t) | ||
15 | } | ||
16 | |||
17 | async function sendVideoAbuse (byAccount: AccountInstance, videoAbuse: VideoAbuseInstance, video: VideoInstance, t: Transaction) { | ||
18 | const url = getVideoAbuseActivityPubUrl(videoAbuse) | ||
19 | const data = await createActivityData(url, byAccount, videoAbuse.toActivityPubObject()) | ||
20 | |||
21 | return unicastTo(data, byAccount, video.VideoChannel.Account.sharedInboxUrl, t) | ||
22 | } | ||
23 | |||
24 | async function createActivityData (url: string, byAccount: AccountInstance, object: any) { | ||
25 | const { to, cc } = await getAudience(byAccount) | ||
26 | const activity: ActivityCreate = { | ||
27 | type: 'Create', | ||
28 | id: url, | ||
29 | actor: byAccount.url, | ||
30 | to, | ||
31 | cc, | ||
32 | object | ||
33 | } | ||
34 | |||
35 | return activity | ||
36 | } | ||
37 | |||
38 | // --------------------------------------------------------------------------- | ||
39 | |||
40 | export { | ||
41 | sendCreateVideoChannel, | ||
42 | sendVideoAbuse, | ||
43 | createActivityData | ||
44 | } | ||
diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts new file mode 100644 index 000000000..5be0e2d24 --- /dev/null +++ b/server/lib/activitypub/send/send-delete.ts | |||
@@ -0,0 +1,53 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityDelete } from '../../../../shared/models/activitypub/activity' | ||
3 | import { database as db } from '../../../initializers' | ||
4 | import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models' | ||
5 | import { broadcastToFollowers } from './misc' | ||
6 | |||
7 | async function sendDeleteVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) { | ||
8 | const byAccount = videoChannel.Account | ||
9 | |||
10 | const data = await deleteActivityData(videoChannel.url, byAccount) | ||
11 | |||
12 | const accountsInvolved = await db.VideoChannelShare.loadAccountsByShare(videoChannel.id) | ||
13 | accountsInvolved.push(byAccount) | ||
14 | |||
15 | return broadcastToFollowers(data, byAccount, accountsInvolved, t) | ||
16 | } | ||
17 | |||
18 | async function sendDeleteVideo (video: VideoInstance, t: Transaction) { | ||
19 | const byAccount = video.VideoChannel.Account | ||
20 | |||
21 | const data = await deleteActivityData(video.url, byAccount) | ||
22 | |||
23 | const accountsInvolved = await db.VideoShare.loadAccountsByShare(video.id) | ||
24 | accountsInvolved.push(byAccount) | ||
25 | |||
26 | return broadcastToFollowers(data, byAccount, accountsInvolved, t) | ||
27 | } | ||
28 | |||
29 | async function sendDeleteAccount (account: AccountInstance, t: Transaction) { | ||
30 | const data = await deleteActivityData(account.url, account) | ||
31 | |||
32 | return broadcastToFollowers(data, account, [ account ], t) | ||
33 | } | ||
34 | |||
35 | // --------------------------------------------------------------------------- | ||
36 | |||
37 | export { | ||
38 | sendDeleteVideoChannel, | ||
39 | sendDeleteVideo, | ||
40 | sendDeleteAccount | ||
41 | } | ||
42 | |||
43 | // --------------------------------------------------------------------------- | ||
44 | |||
45 | async function deleteActivityData (url: string, byAccount: AccountInstance) { | ||
46 | const activity: ActivityDelete = { | ||
47 | type: 'Delete', | ||
48 | id: url, | ||
49 | actor: byAccount.url | ||
50 | } | ||
51 | |||
52 | return activity | ||
53 | } | ||
diff --git a/server/lib/activitypub/send/send-follow.ts b/server/lib/activitypub/send/send-follow.ts new file mode 100644 index 000000000..48d641c22 --- /dev/null +++ b/server/lib/activitypub/send/send-follow.ts | |||
@@ -0,0 +1,34 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityFollow } from '../../../../shared/models/activitypub/activity' | ||
3 | import { AccountInstance } from '../../../models' | ||
4 | import { AccountFollowInstance } from '../../../models/account/account-follow-interface' | ||
5 | import { unicastTo } from './misc' | ||
6 | import { getAccountFollowActivityPubUrl } from '../../../helpers/activitypub' | ||
7 | |||
8 | async function sendFollow (accountFollow: AccountFollowInstance, t: Transaction) { | ||
9 | const me = accountFollow.AccountFollower | ||
10 | const following = accountFollow.AccountFollowing | ||
11 | |||
12 | const url = getAccountFollowActivityPubUrl(accountFollow) | ||
13 | const data = await followActivityData(url, me, following) | ||
14 | |||
15 | return unicastTo(data, me, following.inboxUrl, t) | ||
16 | } | ||
17 | |||
18 | async function followActivityData (url: string, byAccount: AccountInstance, targetAccount: AccountInstance) { | ||
19 | const activity: ActivityFollow = { | ||
20 | type: 'Follow', | ||
21 | id: url, | ||
22 | actor: byAccount.url, | ||
23 | object: targetAccount.url | ||
24 | } | ||
25 | |||
26 | return activity | ||
27 | } | ||
28 | |||
29 | // --------------------------------------------------------------------------- | ||
30 | |||
31 | export { | ||
32 | sendFollow, | ||
33 | followActivityData | ||
34 | } | ||
diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts new file mode 100644 index 000000000..39da824f3 --- /dev/null +++ b/server/lib/activitypub/send/send-undo.ts | |||
@@ -0,0 +1,39 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityFollow, ActivityUndo } from '../../../../shared/models/activitypub/activity' | ||
3 | import { AccountInstance } from '../../../models' | ||
4 | import { AccountFollowInstance } from '../../../models/account/account-follow-interface' | ||
5 | import { unicastTo } from './misc' | ||
6 | import { getAccountFollowActivityPubUrl, getUndoActivityPubUrl } from '../../../helpers/activitypub' | ||
7 | import { followActivityData } from './send-follow' | ||
8 | |||
9 | async function sendUndoFollow (accountFollow: AccountFollowInstance, t: Transaction) { | ||
10 | const me = accountFollow.AccountFollower | ||
11 | const following = accountFollow.AccountFollowing | ||
12 | |||
13 | const followUrl = getAccountFollowActivityPubUrl(accountFollow) | ||
14 | const undoUrl = getUndoActivityPubUrl(followUrl) | ||
15 | |||
16 | const object = await followActivityData(followUrl, me, following) | ||
17 | const data = await undoActivityData(undoUrl, me, object) | ||
18 | |||
19 | return unicastTo(data, me, following.inboxUrl, t) | ||
20 | } | ||
21 | |||
22 | // --------------------------------------------------------------------------- | ||
23 | |||
24 | export { | ||
25 | sendUndoFollow | ||
26 | } | ||
27 | |||
28 | // --------------------------------------------------------------------------- | ||
29 | |||
30 | async function undoActivityData (url: string, byAccount: AccountInstance, object: ActivityFollow) { | ||
31 | const activity: ActivityUndo = { | ||
32 | type: 'Undo', | ||
33 | id: url, | ||
34 | actor: byAccount.url, | ||
35 | object | ||
36 | } | ||
37 | |||
38 | return activity | ||
39 | } | ||
diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts new file mode 100644 index 000000000..42738f973 --- /dev/null +++ b/server/lib/activitypub/send/send-update.ts | |||
@@ -0,0 +1,55 @@ | |||
1 | import { Transaction } from 'sequelize' | ||
2 | import { ActivityUpdate } from '../../../../shared/models/activitypub/activity' | ||
3 | import { getUpdateActivityPubUrl } from '../../../helpers/activitypub' | ||
4 | import { database as db } from '../../../initializers' | ||
5 | import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../../models' | ||
6 | import { broadcastToFollowers, getAudience } from './misc' | ||
7 | |||
8 | async function sendUpdateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) { | ||
9 | const byAccount = videoChannel.Account | ||
10 | |||
11 | const url = getUpdateActivityPubUrl(videoChannel.url, videoChannel.updatedAt.toISOString()) | ||
12 | const videoChannelObject = videoChannel.toActivityPubObject() | ||
13 | const data = await updateActivityData(url, byAccount, videoChannelObject) | ||
14 | |||
15 | const accountsInvolved = await db.VideoChannelShare.loadAccountsByShare(videoChannel.id) | ||
16 | accountsInvolved.push(byAccount) | ||
17 | |||
18 | return broadcastToFollowers(data, byAccount, accountsInvolved, t) | ||
19 | } | ||
20 | |||
21 | async function sendUpdateVideo (video: VideoInstance, t: Transaction) { | ||
22 | const byAccount = video.VideoChannel.Account | ||
23 | |||
24 | const url = getUpdateActivityPubUrl(video.url, video.updatedAt.toISOString()) | ||
25 | const videoObject = video.toActivityPubObject() | ||
26 | const data = await updateActivityData(url, byAccount, videoObject) | ||
27 | |||
28 | const accountsInvolved = await db.VideoShare.loadAccountsByShare(video.id) | ||
29 | accountsInvolved.push(byAccount) | ||
30 | |||
31 | return broadcastToFollowers(data, byAccount, accountsInvolved, t) | ||
32 | } | ||
33 | |||
34 | // --------------------------------------------------------------------------- | ||
35 | |||
36 | export { | ||
37 | sendUpdateVideoChannel, | ||
38 | sendUpdateVideo | ||
39 | } | ||
40 | |||
41 | // --------------------------------------------------------------------------- | ||
42 | |||
43 | async function updateActivityData (url: string, byAccount: AccountInstance, object: any) { | ||
44 | const { to, cc } = await getAudience(byAccount) | ||
45 | const activity: ActivityUpdate = { | ||
46 | type: 'Update', | ||
47 | id: url, | ||
48 | actor: byAccount.url, | ||
49 | to, | ||
50 | cc, | ||
51 | object | ||
52 | } | ||
53 | |||
54 | return activity | ||
55 | } | ||