diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-11-27 14:44:51 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-11-27 19:40:53 +0100 |
commit | 4e50b6a1c9a3eb261e04ede73241648e6edf21d6 (patch) | |
tree | e1c6c121d561ffc1cf2996daec03a1e7f27f0a25 /server/lib/activitypub/process | |
parent | 74bb2cb8348d6794ed3a0e2ec94c8c9abdde82cf (diff) | |
download | PeerTube-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/process')
-rw-r--r-- | server/lib/activitypub/process/misc.ts | 57 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-add.ts | 16 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-announce.ts | 100 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-create.ts | 12 |
4 files changed, 155 insertions, 30 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 @@ | |||
1 | import * as magnetUtil from 'magnet-uri' | 1 | import * as magnetUtil from 'magnet-uri' |
2 | import { VideoTorrentObject } from '../../../../shared' | 2 | import { VideoTorrentObject } from '../../../../shared' |
3 | import { VideoChannelObject } from '../../../../shared/models/activitypub/objects/video-channel-object' | 3 | import { VideoChannelObject } from '../../../../shared/models/activitypub/objects/video-channel-object' |
4 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' | ||
4 | import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos' | 5 | import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos' |
6 | import { doRequest } from '../../../helpers/requests' | ||
7 | import { database as db } from '../../../initializers' | ||
5 | import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers/constants' | 8 | import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers/constants' |
6 | import { AccountInstance } from '../../../models/account/account-interface' | 9 | import { AccountInstance } from '../../../models/account/account-interface' |
7 | import { VideoChannelInstance } from '../../../models/video/video-channel-interface' | 10 | import { VideoChannelInstance } from '../../../models/video/video-channel-interface' |
8 | import { VideoFileAttributes } from '../../../models/video/video-file-interface' | 11 | import { VideoFileAttributes } from '../../../models/video/video-file-interface' |
9 | import { VideoAttributes, VideoInstance } from '../../../models/video/video-interface' | 12 | import { VideoAttributes, VideoInstance } from '../../../models/video/video-interface' |
10 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' | 13 | import { getOrCreateAccountAndServer } from '../account' |
11 | 14 | ||
12 | function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountInstance) { | 15 | function 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 | ||
103 | async 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 | |||
127 | async 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 | ||
102 | export { | 153 | export { |
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' | |||
11 | import { getOrCreateAccountAndServer } from '../account' | 11 | import { getOrCreateAccountAndServer } from '../account' |
12 | import { getOrCreateVideoChannel } from '../video-channels' | 12 | import { getOrCreateVideoChannel } from '../video-channels' |
13 | import { generateThumbnailFromUrl } from '../videos' | 13 | import { generateThumbnailFromUrl } from '../videos' |
14 | import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' | 14 | import { addVideoShares, videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' |
15 | 15 | ||
16 | async function processAddActivity (activity: ActivityAdd) { | 16 | async 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 | ||
40 | async function processAddVideo ( | 40 | async 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 @@ | |||
1 | import { ActivityAnnounce } from '../../../../shared/models/activitypub/activity' | 1 | import { ActivityAdd, ActivityAnnounce, ActivityCreate } from '../../../../shared/models/activitypub/activity' |
2 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | ||
2 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
3 | import { database as db } from '../../../initializers/index' | 4 | import { database as db } from '../../../initializers/index' |
5 | import { AccountInstance } from '../../../models/account/account-interface' | ||
4 | import { VideoInstance } from '../../../models/index' | 6 | import { VideoInstance } from '../../../models/index' |
5 | import { VideoChannelInstance } from '../../../models/video/video-channel-interface' | 7 | import { VideoChannelInstance } from '../../../models/video/video-channel-interface' |
8 | import { getOrCreateAccountAndServer } from '../account' | ||
9 | import { forwardActivity } from '../send/misc' | ||
6 | import { processAddActivity } from './process-add' | 10 | import { processAddActivity } from './process-add' |
7 | import { processCreateActivity } from './process-create' | 11 | import { processCreateActivity } from './process-create' |
8 | import { getOrCreateAccountAndServer } from '../account' | ||
9 | 12 | ||
10 | async function processAnnounceActivity (activity: ActivityAnnounce) { | 13 | async 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) { | |||
44 | export { | 33 | export { |
45 | processAnnounceActivity | 34 | processAnnounceActivity |
46 | } | 35 | } |
36 | |||
37 | // --------------------------------------------------------------------------- | ||
38 | |||
39 | function 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 | |||
48 | async 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 | |||
75 | function 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 | |||
84 | function 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' | |||
8 | import { getOrCreateAccountAndServer } from '../account' | 8 | import { getOrCreateAccountAndServer } from '../account' |
9 | import { forwardActivity } from '../send/misc' | 9 | import { forwardActivity } from '../send/misc' |
10 | import { getVideoChannelActivityPubUrl } from '../url' | 10 | import { getVideoChannelActivityPubUrl } from '../url' |
11 | import { videoChannelActivityObjectToDBAttributes } from './misc' | 11 | import { addVideoChannelShares, videoChannelActivityObjectToDBAttributes } from './misc' |
12 | 12 | ||
13 | async function processCreateActivity (activity: ActivityCreate) { | 13 | async 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 | ||
95 | function processCreateVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) { | 95 | async 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 | ||
104 | function addRemoteVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) { | 110 | function addRemoteVideoChannel (account: AccountInstance, videoChannelToCreateData: VideoChannelObject) { |