aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/process
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/process
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/process')
-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
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 @@
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) {