diff options
author | Chocobozzz <me@florianbigard.com> | 2017-12-14 17:38:41 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2017-12-19 10:53:16 +0100 |
commit | 50d6de9c286abcb34ff4234d56d9cbb803db7665 (patch) | |
tree | f1732b27edcd05c7877a8358b8312f1e38c287ed /server/lib/activitypub/process | |
parent | fadf619ad61a016c1c7fc53de5a8f398a4f77519 (diff) | |
download | PeerTube-50d6de9c286abcb34ff4234d56d9cbb803db7665.tar.gz PeerTube-50d6de9c286abcb34ff4234d56d9cbb803db7665.tar.zst PeerTube-50d6de9c286abcb34ff4234d56d9cbb803db7665.zip |
Begin moving video channel to actor
Diffstat (limited to 'server/lib/activitypub/process')
-rw-r--r-- | server/lib/activitypub/process/index.ts | 1 | ||||
-rw-r--r-- | server/lib/activitypub/process/misc.ts | 52 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-accept.ts | 18 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-add.ts | 137 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-announce.ts | 67 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-create.ts | 187 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-delete.ts | 72 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-follow.ts | 48 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-like.ts | 19 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-undo.ts | 43 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-update.ts | 63 | ||||
-rw-r--r-- | server/lib/activitypub/process/process.ts | 14 |
12 files changed, 272 insertions, 449 deletions
diff --git a/server/lib/activitypub/process/index.ts b/server/lib/activitypub/process/index.ts index e25c261cc..db4980a72 100644 --- a/server/lib/activitypub/process/index.ts +++ b/server/lib/activitypub/process/index.ts | |||
@@ -1,6 +1,5 @@ | |||
1 | export * from './process' | 1 | export * from './process' |
2 | export * from './process-accept' | 2 | export * from './process-accept' |
3 | export * from './process-add' | ||
4 | export * from './process-announce' | 3 | export * from './process-announce' |
5 | export * from './process-create' | 4 | export * from './process-create' |
6 | export * from './process-delete' | 5 | export * from './process-delete' |
diff --git a/server/lib/activitypub/process/misc.ts b/server/lib/activitypub/process/misc.ts index a775c858a..a9c6f913c 100644 --- a/server/lib/activitypub/process/misc.ts +++ b/server/lib/activitypub/process/misc.ts | |||
@@ -1,29 +1,13 @@ | |||
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' | ||
4 | import { VideoPrivacy } from '../../../../shared/models/videos' | 3 | import { VideoPrivacy } from '../../../../shared/models/videos' |
5 | import { doRequest } from '../../../helpers' | 4 | import { doRequest } from '../../../helpers' |
6 | import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos' | 5 | import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos' |
7 | import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers' | 6 | import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers' |
8 | import { AccountModel } from '../../../models/account/account' | ||
9 | import { VideoModel } from '../../../models/video/video' | 7 | import { VideoModel } from '../../../models/video/video' |
10 | import { VideoChannelModel } from '../../../models/video/video-channel' | 8 | import { VideoChannelModel } from '../../../models/video/video-channel' |
11 | import { VideoChannelShareModel } from '../../../models/video/video-channel-share' | ||
12 | import { VideoShareModel } from '../../../models/video/video-share' | 9 | import { VideoShareModel } from '../../../models/video/video-share' |
13 | import { getOrCreateAccountAndServer } from '../account' | 10 | import { getOrCreateActorAndServerAndModel } from '../actor' |
14 | |||
15 | function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountModel) { | ||
16 | return { | ||
17 | name: videoChannelObject.name, | ||
18 | description: videoChannelObject.content, | ||
19 | uuid: videoChannelObject.uuid, | ||
20 | url: videoChannelObject.id, | ||
21 | createdAt: new Date(videoChannelObject.published), | ||
22 | updatedAt: new Date(videoChannelObject.updated), | ||
23 | remote: true, | ||
24 | accountId: account.id | ||
25 | } | ||
26 | } | ||
27 | 11 | ||
28 | async function videoActivityObjectToDBAttributes ( | 12 | async function videoActivityObjectToDBAttributes ( |
29 | videoChannel: VideoChannelModel, | 13 | videoChannel: VideoChannelModel, |
@@ -120,13 +104,13 @@ async function addVideoShares (instance: VideoModel, shares: string[]) { | |||
120 | uri: share, | 104 | uri: share, |
121 | json: true | 105 | json: true |
122 | }) | 106 | }) |
123 | const actor = json['actor'] | 107 | const actorUrl = json['actor'] |
124 | if (!actor) continue | 108 | if (!actorUrl) continue |
125 | 109 | ||
126 | const account = await getOrCreateAccountAndServer(actor) | 110 | const actor = await getOrCreateActorAndServerAndModel(actorUrl) |
127 | 111 | ||
128 | const entry = { | 112 | const entry = { |
129 | accountId: account.id, | 113 | actorId: actor.id, |
130 | videoId: instance.id | 114 | videoId: instance.id |
131 | } | 115 | } |
132 | 116 | ||
@@ -137,36 +121,10 @@ async function addVideoShares (instance: VideoModel, shares: string[]) { | |||
137 | } | 121 | } |
138 | } | 122 | } |
139 | 123 | ||
140 | async function addVideoChannelShares (instance: VideoChannelModel, shares: string[]) { | ||
141 | for (const share of shares) { | ||
142 | // Fetch url | ||
143 | const json = await doRequest({ | ||
144 | uri: share, | ||
145 | json: true | ||
146 | }) | ||
147 | const actor = json['actor'] | ||
148 | if (!actor) continue | ||
149 | |||
150 | const account = await getOrCreateAccountAndServer(actor) | ||
151 | |||
152 | const entry = { | ||
153 | accountId: account.id, | ||
154 | videoChannelId: instance.id | ||
155 | } | ||
156 | |||
157 | await VideoChannelShareModel.findOrCreate({ | ||
158 | where: entry, | ||
159 | defaults: entry | ||
160 | }) | ||
161 | } | ||
162 | } | ||
163 | |||
164 | // --------------------------------------------------------------------------- | 124 | // --------------------------------------------------------------------------- |
165 | 125 | ||
166 | export { | 126 | export { |
167 | videoFileActivityUrlToDBAttributes, | 127 | videoFileActivityUrlToDBAttributes, |
168 | videoActivityObjectToDBAttributes, | 128 | videoActivityObjectToDBAttributes, |
169 | videoChannelActivityObjectToDBAttributes, | ||
170 | addVideoChannelShares, | ||
171 | addVideoShares | 129 | addVideoShares |
172 | } | 130 | } |
diff --git a/server/lib/activitypub/process/process-accept.ts b/server/lib/activitypub/process/process-accept.ts index 5b321f771..b9d906ec9 100644 --- a/server/lib/activitypub/process/process-accept.ts +++ b/server/lib/activitypub/process/process-accept.ts | |||
@@ -1,14 +1,14 @@ | |||
1 | import { ActivityAccept } from '../../../../shared/models/activitypub' | 1 | import { ActivityAccept } from '../../../../shared/models/activitypub' |
2 | import { AccountModel } from '../../../models/account/account' | 2 | import { ActorModel } from '../../../models/activitypub/actor' |
3 | import { AccountFollowModel } from '../../../models/account/account-follow' | 3 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' |
4 | import { addFetchOutboxJob } from '../fetch' | 4 | import { addFetchOutboxJob } from '../fetch' |
5 | 5 | ||
6 | async function processAcceptActivity (activity: ActivityAccept, inboxAccount?: AccountModel) { | 6 | async function processAcceptActivity (activity: ActivityAccept, inboxActor?: ActorModel) { |
7 | if (inboxAccount === undefined) throw new Error('Need to accept on explicit inbox.') | 7 | if (inboxActor === undefined) throw new Error('Need to accept on explicit inbox.') |
8 | 8 | ||
9 | const targetAccount = await AccountModel.loadByUrl(activity.actor) | 9 | const targetActor = await ActorModel.loadByUrl(activity.actor) |
10 | 10 | ||
11 | return processAccept(inboxAccount, targetAccount) | 11 | return processAccept(inboxActor, targetActor) |
12 | } | 12 | } |
13 | 13 | ||
14 | // --------------------------------------------------------------------------- | 14 | // --------------------------------------------------------------------------- |
@@ -19,11 +19,11 @@ export { | |||
19 | 19 | ||
20 | // --------------------------------------------------------------------------- | 20 | // --------------------------------------------------------------------------- |
21 | 21 | ||
22 | async function processAccept (account: AccountModel, targetAccount: AccountModel) { | 22 | async function processAccept (actor: ActorModel, targetActor: ActorModel) { |
23 | const follow = await AccountFollowModel.loadByAccountAndTarget(account.id, targetAccount.id) | 23 | const follow = await ActorFollowModel.loadByActorAndTarget(actor.id, targetActor.id) |
24 | if (!follow) throw new Error('Cannot find associated follow.') | 24 | if (!follow) throw new Error('Cannot find associated follow.') |
25 | 25 | ||
26 | follow.set('state', 'accepted') | 26 | follow.set('state', 'accepted') |
27 | await follow.save() | 27 | await follow.save() |
28 | await addFetchOutboxJob(targetAccount, undefined) | 28 | await addFetchOutboxJob(targetActor, undefined) |
29 | } | 29 | } |
diff --git a/server/lib/activitypub/process/process-add.ts b/server/lib/activitypub/process/process-add.ts deleted file mode 100644 index 550593eab..000000000 --- a/server/lib/activitypub/process/process-add.ts +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | import * as Bluebird from 'bluebird' | ||
2 | import { VideoTorrentObject } from '../../../../shared' | ||
3 | import { ActivityAdd } from '../../../../shared/models/activitypub' | ||
4 | import { VideoRateType } from '../../../../shared/models/videos' | ||
5 | import { logger, retryTransactionWrapper } from '../../../helpers' | ||
6 | import { sequelizeTypescript } from '../../../initializers' | ||
7 | import { AccountModel } from '../../../models/account/account' | ||
8 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | ||
9 | import { TagModel } from '../../../models/video/tag' | ||
10 | import { VideoModel } from '../../../models/video/video' | ||
11 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
12 | import { VideoFileModel } from '../../../models/video/video-file' | ||
13 | import { getOrCreateAccountAndServer } from '../account' | ||
14 | import { getOrCreateVideoChannel } from '../video-channels' | ||
15 | import { generateThumbnailFromUrl } from '../videos' | ||
16 | import { addVideoShares, videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' | ||
17 | |||
18 | async function processAddActivity (activity: ActivityAdd) { | ||
19 | const activityObject = activity.object | ||
20 | const activityType = activityObject.type | ||
21 | const account = await getOrCreateAccountAndServer(activity.actor) | ||
22 | |||
23 | if (activityType === 'Video') { | ||
24 | const videoChannelUrl = activity.target | ||
25 | const videoChannel = await getOrCreateVideoChannel(account, videoChannelUrl) | ||
26 | |||
27 | return processAddVideo(account, activity, videoChannel, activityObject) | ||
28 | } | ||
29 | |||
30 | logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id }) | ||
31 | return Promise.resolve(undefined) | ||
32 | } | ||
33 | |||
34 | // --------------------------------------------------------------------------- | ||
35 | |||
36 | export { | ||
37 | processAddActivity | ||
38 | } | ||
39 | |||
40 | // --------------------------------------------------------------------------- | ||
41 | |||
42 | async function processAddVideo (account: AccountModel, | ||
43 | activity: ActivityAdd, | ||
44 | videoChannel: VideoChannelModel, | ||
45 | videoToCreateData: VideoTorrentObject) { | ||
46 | const options = { | ||
47 | arguments: [ account, activity, videoChannel, videoToCreateData ], | ||
48 | errorMessage: 'Cannot insert the remote video with many retries.' | ||
49 | } | ||
50 | |||
51 | const video = await retryTransactionWrapper(addRemoteVideo, options) | ||
52 | |||
53 | // Process outside the transaction because we could fetch remote data | ||
54 | if (videoToCreateData.likes && Array.isArray(videoToCreateData.likes.orderedItems)) { | ||
55 | await createRates(videoToCreateData.likes.orderedItems, video, 'like') | ||
56 | } | ||
57 | |||
58 | if (videoToCreateData.dislikes && Array.isArray(videoToCreateData.dislikes.orderedItems)) { | ||
59 | await createRates(videoToCreateData.dislikes.orderedItems, video, 'dislike') | ||
60 | } | ||
61 | |||
62 | if (videoToCreateData.shares && Array.isArray(videoToCreateData.shares.orderedItems)) { | ||
63 | await addVideoShares(video, videoToCreateData.shares.orderedItems) | ||
64 | } | ||
65 | |||
66 | return video | ||
67 | } | ||
68 | |||
69 | function addRemoteVideo (account: AccountModel, | ||
70 | activity: ActivityAdd, | ||
71 | videoChannel: VideoChannelModel, | ||
72 | videoToCreateData: VideoTorrentObject) { | ||
73 | logger.debug('Adding remote video %s.', videoToCreateData.id) | ||
74 | |||
75 | return sequelizeTypescript.transaction(async t => { | ||
76 | const sequelizeOptions = { | ||
77 | transaction: t | ||
78 | } | ||
79 | |||
80 | if (videoChannel.Account.id !== account.id) throw new Error('Video channel is not owned by this account.') | ||
81 | |||
82 | const videoFromDatabase = await VideoModel.loadByUUIDOrURL(videoToCreateData.uuid, videoToCreateData.id, t) | ||
83 | if (videoFromDatabase) return videoFromDatabase | ||
84 | |||
85 | const videoData = await videoActivityObjectToDBAttributes(videoChannel, videoToCreateData, activity.to, activity.cc) | ||
86 | const video = VideoModel.build(videoData) | ||
87 | |||
88 | // Don't block on request | ||
89 | generateThumbnailFromUrl(video, videoToCreateData.icon) | ||
90 | .catch(err => logger.warn('Cannot generate thumbnail of %s.', videoToCreateData.id, err)) | ||
91 | |||
92 | const videoCreated = await video.save(sequelizeOptions) | ||
93 | |||
94 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoToCreateData) | ||
95 | if (videoFileAttributes.length === 0) { | ||
96 | throw new Error('Cannot find valid files for video %s ' + videoToCreateData.url) | ||
97 | } | ||
98 | |||
99 | const tasks: Bluebird<any>[] = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t })) | ||
100 | await Promise.all(tasks) | ||
101 | |||
102 | const tags = videoToCreateData.tag.map(t => t.name) | ||
103 | const tagInstances = await TagModel.findOrCreateTags(tags, t) | ||
104 | await videoCreated.$set('Tags', tagInstances, sequelizeOptions) | ||
105 | |||
106 | logger.info('Remote video with uuid %s inserted.', videoToCreateData.uuid) | ||
107 | |||
108 | return videoCreated | ||
109 | }) | ||
110 | } | ||
111 | |||
112 | async function createRates (accountUrls: string[], video: VideoModel, rate: VideoRateType) { | ||
113 | let rateCounts = 0 | ||
114 | const tasks: Bluebird<any>[] = [] | ||
115 | |||
116 | for (const accountUrl of accountUrls) { | ||
117 | const account = await getOrCreateAccountAndServer(accountUrl) | ||
118 | const p = AccountVideoRateModel | ||
119 | .create({ | ||
120 | videoId: video.id, | ||
121 | accountId: account.id, | ||
122 | type: rate | ||
123 | }) | ||
124 | .then(() => rateCounts += 1) | ||
125 | |||
126 | tasks.push(p) | ||
127 | } | ||
128 | |||
129 | await Promise.all(tasks) | ||
130 | |||
131 | logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid) | ||
132 | |||
133 | // This is "likes" and "dislikes" | ||
134 | await video.increment(rate + 's', { by: rateCounts }) | ||
135 | |||
136 | return | ||
137 | } | ||
diff --git a/server/lib/activitypub/process/process-announce.ts b/server/lib/activitypub/process/process-announce.ts index ff2c6d708..7dfee2f60 100644 --- a/server/lib/activitypub/process/process-announce.ts +++ b/server/lib/activitypub/process/process-announce.ts | |||
@@ -1,24 +1,19 @@ | |||
1 | import { ActivityAdd, ActivityAnnounce, ActivityCreate } from '../../../../shared/models/activitypub' | 1 | import { ActivityAnnounce } from '../../../../shared/models/activitypub' |
2 | import { logger, retryTransactionWrapper } from '../../../helpers' | 2 | import { logger, retryTransactionWrapper } from '../../../helpers' |
3 | import { sequelizeTypescript } from '../../../initializers' | 3 | import { sequelizeTypescript } from '../../../initializers' |
4 | import { AccountModel } from '../../../models/account/account' | 4 | import { ActorModel } from '../../../models/activitypub/actor' |
5 | import { VideoModel } from '../../../models/video/video' | 5 | import { VideoModel } from '../../../models/video/video' |
6 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
7 | import { VideoChannelShareModel } from '../../../models/video/video-channel-share' | ||
8 | import { VideoShareModel } from '../../../models/video/video-share' | 6 | import { VideoShareModel } from '../../../models/video/video-share' |
9 | import { getOrCreateAccountAndServer } from '../account' | 7 | import { getOrCreateActorAndServerAndModel } from '../actor' |
10 | import { forwardActivity } from '../send/misc' | 8 | import { forwardActivity } from '../send/misc' |
11 | import { processAddActivity } from './process-add' | ||
12 | import { processCreateActivity } from './process-create' | 9 | import { processCreateActivity } from './process-create' |
13 | 10 | ||
14 | async function processAnnounceActivity (activity: ActivityAnnounce) { | 11 | async function processAnnounceActivity (activity: ActivityAnnounce) { |
15 | const announcedActivity = activity.object | 12 | const announcedActivity = activity.object |
16 | const accountAnnouncer = await getOrCreateAccountAndServer(activity.actor) | 13 | const actorAnnouncer = await getOrCreateActorAndServerAndModel(activity.actor) |
17 | 14 | ||
18 | if (announcedActivity.type === 'Create' && announcedActivity.object.type === 'VideoChannel') { | 15 | if (announcedActivity.type === 'Create' && announcedActivity.object.type === 'Video') { |
19 | return processVideoChannelShare(accountAnnouncer, activity) | 16 | return processVideoShare(actorAnnouncer, activity) |
20 | } else if (announcedActivity.type === 'Add' && announcedActivity.object.type === 'Video') { | ||
21 | return processVideoShare(accountAnnouncer, activity) | ||
22 | } | 17 | } |
23 | 18 | ||
24 | logger.warn( | 19 | logger.warn( |
@@ -37,60 +32,24 @@ export { | |||
37 | 32 | ||
38 | // --------------------------------------------------------------------------- | 33 | // --------------------------------------------------------------------------- |
39 | 34 | ||
40 | function processVideoChannelShare (accountAnnouncer: AccountModel, activity: ActivityAnnounce) { | 35 | function processVideoShare (actorAnnouncer: ActorModel, activity: ActivityAnnounce) { |
41 | const options = { | 36 | const options = { |
42 | arguments: [ accountAnnouncer, activity ], | 37 | arguments: [ actorAnnouncer, activity ], |
43 | errorMessage: 'Cannot share the video channel with many retries.' | ||
44 | } | ||
45 | |||
46 | return retryTransactionWrapper(shareVideoChannel, options) | ||
47 | } | ||
48 | |||
49 | async function shareVideoChannel (accountAnnouncer: AccountModel, activity: ActivityAnnounce) { | ||
50 | const announcedActivity = activity.object as ActivityCreate | ||
51 | |||
52 | return sequelizeTypescript.transaction(async t => { | ||
53 | // Add share entry | ||
54 | const videoChannel: VideoChannelModel = await processCreateActivity(announcedActivity) | ||
55 | const share = { | ||
56 | accountId: accountAnnouncer.id, | ||
57 | videoChannelId: videoChannel.id | ||
58 | } | ||
59 | |||
60 | const [ , created ] = await VideoChannelShareModel.findOrCreate({ | ||
61 | where: share, | ||
62 | defaults: share, | ||
63 | transaction: t | ||
64 | }) | ||
65 | |||
66 | if (videoChannel.isOwned() && created === true) { | ||
67 | // Don't resend the activity to the sender | ||
68 | const exceptions = [ accountAnnouncer ] | ||
69 | await forwardActivity(activity, t, exceptions) | ||
70 | } | ||
71 | |||
72 | return undefined | ||
73 | }) | ||
74 | } | ||
75 | |||
76 | function processVideoShare (accountAnnouncer: AccountModel, activity: ActivityAnnounce) { | ||
77 | const options = { | ||
78 | arguments: [ accountAnnouncer, activity ], | ||
79 | errorMessage: 'Cannot share the video with many retries.' | 38 | errorMessage: 'Cannot share the video with many retries.' |
80 | } | 39 | } |
81 | 40 | ||
82 | return retryTransactionWrapper(shareVideo, options) | 41 | return retryTransactionWrapper(shareVideo, options) |
83 | } | 42 | } |
84 | 43 | ||
85 | function shareVideo (accountAnnouncer: AccountModel, activity: ActivityAnnounce) { | 44 | function shareVideo (actorAnnouncer: ActorModel, activity: ActivityAnnounce) { |
86 | const announcedActivity = activity.object as ActivityAdd | 45 | const announcedActivity = activity.object |
87 | 46 | ||
88 | return sequelizeTypescript.transaction(async t => { | 47 | return sequelizeTypescript.transaction(async t => { |
89 | // Add share entry | 48 | // Add share entry |
90 | const video: VideoModel = await processAddActivity(announcedActivity) | 49 | const video: VideoModel = await processCreateActivity(announcedActivity) |
91 | 50 | ||
92 | const share = { | 51 | const share = { |
93 | accountId: accountAnnouncer.id, | 52 | actorId: actorAnnouncer.id, |
94 | videoId: video.id | 53 | videoId: video.id |
95 | } | 54 | } |
96 | 55 | ||
@@ -102,7 +61,7 @@ function shareVideo (accountAnnouncer: AccountModel, activity: ActivityAnnounce) | |||
102 | 61 | ||
103 | if (video.isOwned() && created === true) { | 62 | if (video.isOwned() && created === true) { |
104 | // Don't resend the activity to the sender | 63 | // Don't resend the activity to the sender |
105 | const exceptions = [ accountAnnouncer ] | 64 | const exceptions = [ actorAnnouncer ] |
106 | await forwardActivity(activity, t, exceptions) | 65 | await forwardActivity(activity, t, exceptions) |
107 | } | 66 | } |
108 | 67 | ||
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts index c1eb2a8ab..1ddd817db 100644 --- a/server/lib/activitypub/process/process-create.ts +++ b/server/lib/activitypub/process/process-create.ts | |||
@@ -1,30 +1,33 @@ | |||
1 | import { ActivityCreate, VideoChannelObject } from '../../../../shared' | 1 | import * as Bluebird from 'bluebird' |
2 | import { ActivityCreate, VideoTorrentObject } from '../../../../shared' | ||
2 | import { DislikeObject, VideoAbuseObject, ViewObject } from '../../../../shared/models/activitypub/objects' | 3 | import { DislikeObject, VideoAbuseObject, ViewObject } from '../../../../shared/models/activitypub/objects' |
4 | import { VideoRateType } from '../../../../shared/models/videos' | ||
3 | import { logger, retryTransactionWrapper } from '../../../helpers' | 5 | import { logger, retryTransactionWrapper } from '../../../helpers' |
4 | import { sequelizeTypescript } from '../../../initializers' | 6 | import { sequelizeTypescript } from '../../../initializers' |
5 | import { AccountModel } from '../../../models/account/account' | ||
6 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | 7 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' |
8 | import { ActorModel } from '../../../models/activitypub/actor' | ||
9 | import { TagModel } from '../../../models/video/tag' | ||
7 | import { VideoModel } from '../../../models/video/video' | 10 | import { VideoModel } from '../../../models/video/video' |
8 | import { VideoAbuseModel } from '../../../models/video/video-abuse' | 11 | import { VideoAbuseModel } from '../../../models/video/video-abuse' |
9 | import { VideoChannelModel } from '../../../models/video/video-channel' | 12 | import { VideoFileModel } from '../../../models/video/video-file' |
10 | import { getOrCreateAccountAndServer } from '../account' | 13 | import { getOrCreateActorAndServerAndModel } from '../actor' |
11 | import { forwardActivity } from '../send/misc' | 14 | import { forwardActivity } from '../send/misc' |
12 | import { getVideoChannelActivityPubUrl } from '../url' | 15 | import { generateThumbnailFromUrl } from '../videos' |
13 | import { addVideoChannelShares, videoChannelActivityObjectToDBAttributes } from './misc' | 16 | import { addVideoShares, videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' |
14 | 17 | ||
15 | async function processCreateActivity (activity: ActivityCreate) { | 18 | async function processCreateActivity (activity: ActivityCreate) { |
16 | const activityObject = activity.object | 19 | const activityObject = activity.object |
17 | const activityType = activityObject.type | 20 | const activityType = activityObject.type |
18 | const account = await getOrCreateAccountAndServer(activity.actor) | 21 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
19 | 22 | ||
20 | if (activityType === 'View') { | 23 | if (activityType === 'View') { |
21 | return processCreateView(account, activity) | 24 | return processCreateView(actor, activity) |
22 | } else if (activityType === 'Dislike') { | 25 | } else if (activityType === 'Dislike') { |
23 | return processCreateDislike(account, activity) | 26 | return processCreateDislike(actor, activity) |
24 | } else if (activityType === 'VideoChannel') { | 27 | } else if (activityType === 'Video') { |
25 | return processCreateVideoChannel(account, activityObject as VideoChannelObject) | 28 | return processCreateVideo(actor, activity) |
26 | } else if (activityType === 'Flag') { | 29 | } else if (activityType === 'Flag') { |
27 | return processCreateVideoAbuse(account, activityObject as VideoAbuseObject) | 30 | return processCreateVideoAbuse(actor, activityObject as VideoAbuseObject) |
28 | } | 31 | } |
29 | 32 | ||
30 | logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id }) | 33 | logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id }) |
@@ -39,17 +42,123 @@ export { | |||
39 | 42 | ||
40 | // --------------------------------------------------------------------------- | 43 | // --------------------------------------------------------------------------- |
41 | 44 | ||
42 | async function processCreateDislike (byAccount: AccountModel, activity: ActivityCreate) { | 45 | async function processCreateVideo ( |
46 | actor: ActorModel, | ||
47 | activity: ActivityCreate | ||
48 | ) { | ||
49 | const videoToCreateData = activity.object as VideoTorrentObject | ||
50 | |||
51 | const channel = videoToCreateData.attributedTo.find(a => a.type === 'Group') | ||
52 | if (!channel) throw new Error('Cannot find associated video channel to video ' + videoToCreateData.url) | ||
53 | |||
54 | const channelActor = await getOrCreateActorAndServerAndModel(channel.id) | ||
55 | |||
56 | const options = { | ||
57 | arguments: [ actor, activity, videoToCreateData, channelActor ], | ||
58 | errorMessage: 'Cannot insert the remote video with many retries.' | ||
59 | } | ||
60 | |||
61 | const video = await retryTransactionWrapper(createRemoteVideo, options) | ||
62 | |||
63 | // Process outside the transaction because we could fetch remote data | ||
64 | if (videoToCreateData.likes && Array.isArray(videoToCreateData.likes.orderedItems)) { | ||
65 | await createRates(videoToCreateData.likes.orderedItems, video, 'like') | ||
66 | } | ||
67 | |||
68 | if (videoToCreateData.dislikes && Array.isArray(videoToCreateData.dislikes.orderedItems)) { | ||
69 | await createRates(videoToCreateData.dislikes.orderedItems, video, 'dislike') | ||
70 | } | ||
71 | |||
72 | if (videoToCreateData.shares && Array.isArray(videoToCreateData.shares.orderedItems)) { | ||
73 | await addVideoShares(video, videoToCreateData.shares.orderedItems) | ||
74 | } | ||
75 | |||
76 | return video | ||
77 | } | ||
78 | |||
79 | function createRemoteVideo ( | ||
80 | account: ActorModel, | ||
81 | activity: ActivityCreate, | ||
82 | videoToCreateData: VideoTorrentObject, | ||
83 | channelActor: ActorModel | ||
84 | ) { | ||
85 | logger.debug('Adding remote video %s.', videoToCreateData.id) | ||
86 | |||
87 | return sequelizeTypescript.transaction(async t => { | ||
88 | const sequelizeOptions = { | ||
89 | transaction: t | ||
90 | } | ||
91 | const videoFromDatabase = await VideoModel.loadByUUIDOrURL(videoToCreateData.uuid, videoToCreateData.id, t) | ||
92 | if (videoFromDatabase) return videoFromDatabase | ||
93 | |||
94 | const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoToCreateData, activity.to, activity.cc) | ||
95 | const video = VideoModel.build(videoData) | ||
96 | |||
97 | // Don't block on request | ||
98 | generateThumbnailFromUrl(video, videoToCreateData.icon) | ||
99 | .catch(err => logger.warn('Cannot generate thumbnail of %s.', videoToCreateData.id, err)) | ||
100 | |||
101 | const videoCreated = await video.save(sequelizeOptions) | ||
102 | |||
103 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoToCreateData) | ||
104 | if (videoFileAttributes.length === 0) { | ||
105 | throw new Error('Cannot find valid files for video %s ' + videoToCreateData.url) | ||
106 | } | ||
107 | |||
108 | const tasks: Bluebird<any>[] = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t })) | ||
109 | await Promise.all(tasks) | ||
110 | |||
111 | const tags = videoToCreateData.tag.map(t => t.name) | ||
112 | const tagInstances = await TagModel.findOrCreateTags(tags, t) | ||
113 | await videoCreated.$set('Tags', tagInstances, sequelizeOptions) | ||
114 | |||
115 | logger.info('Remote video with uuid %s inserted.', videoToCreateData.uuid) | ||
116 | |||
117 | return videoCreated | ||
118 | }) | ||
119 | } | ||
120 | |||
121 | async function createRates (actorUrls: string[], video: VideoModel, rate: VideoRateType) { | ||
122 | let rateCounts = 0 | ||
123 | const tasks: Bluebird<any>[] = [] | ||
124 | |||
125 | for (const actorUrl of actorUrls) { | ||
126 | const actor = await getOrCreateActorAndServerAndModel(actorUrl) | ||
127 | const p = AccountVideoRateModel | ||
128 | .create({ | ||
129 | videoId: video.id, | ||
130 | accountId: actor.Account.id, | ||
131 | type: rate | ||
132 | }) | ||
133 | .then(() => rateCounts += 1) | ||
134 | |||
135 | tasks.push(p) | ||
136 | } | ||
137 | |||
138 | await Promise.all(tasks) | ||
139 | |||
140 | logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid) | ||
141 | |||
142 | // This is "likes" and "dislikes" | ||
143 | await video.increment(rate + 's', { by: rateCounts }) | ||
144 | |||
145 | return | ||
146 | } | ||
147 | |||
148 | async function processCreateDislike (byActor: ActorModel, activity: ActivityCreate) { | ||
43 | const options = { | 149 | const options = { |
44 | arguments: [ byAccount, activity ], | 150 | arguments: [ byActor, activity ], |
45 | errorMessage: 'Cannot dislike the video with many retries.' | 151 | errorMessage: 'Cannot dislike the video with many retries.' |
46 | } | 152 | } |
47 | 153 | ||
48 | return retryTransactionWrapper(createVideoDislike, options) | 154 | return retryTransactionWrapper(createVideoDislike, options) |
49 | } | 155 | } |
50 | 156 | ||
51 | function createVideoDislike (byAccount: AccountModel, activity: ActivityCreate) { | 157 | function createVideoDislike (byActor: ActorModel, activity: ActivityCreate) { |
52 | const dislike = activity.object as DislikeObject | 158 | const dislike = activity.object as DislikeObject |
159 | const byAccount = byActor.Account | ||
160 | |||
161 | if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url) | ||
53 | 162 | ||
54 | return sequelizeTypescript.transaction(async t => { | 163 | return sequelizeTypescript.transaction(async t => { |
55 | const video = await VideoModel.loadByUrlAndPopulateAccount(dislike.object, t) | 164 | const video = await VideoModel.loadByUrlAndPopulateAccount(dislike.object, t) |
@@ -69,20 +178,20 @@ function createVideoDislike (byAccount: AccountModel, activity: ActivityCreate) | |||
69 | 178 | ||
70 | if (video.isOwned() && created === true) { | 179 | if (video.isOwned() && created === true) { |
71 | // Don't resend the activity to the sender | 180 | // Don't resend the activity to the sender |
72 | const exceptions = [ byAccount ] | 181 | const exceptions = [ byActor ] |
73 | await forwardActivity(activity, t, exceptions) | 182 | await forwardActivity(activity, t, exceptions) |
74 | } | 183 | } |
75 | }) | 184 | }) |
76 | } | 185 | } |
77 | 186 | ||
78 | async function processCreateView (byAccount: AccountModel, activity: ActivityCreate) { | 187 | async function processCreateView (byAccount: ActorModel, activity: ActivityCreate) { |
79 | const view = activity.object as ViewObject | 188 | const view = activity.object as ViewObject |
80 | 189 | ||
81 | const video = await VideoModel.loadByUrlAndPopulateAccount(view.object) | 190 | const video = await VideoModel.loadByUrlAndPopulateAccount(view.object) |
82 | 191 | ||
83 | if (!video) throw new Error('Unknown video ' + view.object) | 192 | if (!video) throw new Error('Unknown video ' + view.object) |
84 | 193 | ||
85 | const account = await AccountModel.loadByUrl(view.actor) | 194 | const account = await ActorModel.loadByUrl(view.actor) |
86 | if (!account) throw new Error('Unknown account ' + view.actor) | 195 | if (!account) throw new Error('Unknown account ' + view.actor) |
87 | 196 | ||
88 | await video.increment('views') | 197 | await video.increment('views') |
@@ -94,51 +203,21 @@ async function processCreateView (byAccount: AccountModel, activity: ActivityCre | |||
94 | } | 203 | } |
95 | } | 204 | } |
96 | 205 | ||
97 | async function processCreateVideoChannel (account: AccountModel, videoChannelToCreateData: VideoChannelObject) { | 206 | function processCreateVideoAbuse (actor: ActorModel, videoAbuseToCreateData: VideoAbuseObject) { |
98 | const options = { | ||
99 | arguments: [ account, videoChannelToCreateData ], | ||
100 | errorMessage: 'Cannot insert the remote video channel with many retries.' | ||
101 | } | ||
102 | |||
103 | const videoChannel = await retryTransactionWrapper(addRemoteVideoChannel, options) | ||
104 | |||
105 | if (videoChannelToCreateData.shares && Array.isArray(videoChannelToCreateData.shares.orderedItems)) { | ||
106 | await addVideoChannelShares(videoChannel, videoChannelToCreateData.shares.orderedItems) | ||
107 | } | ||
108 | |||
109 | return videoChannel | ||
110 | } | ||
111 | |||
112 | function addRemoteVideoChannel (account: AccountModel, videoChannelToCreateData: VideoChannelObject) { | ||
113 | logger.debug('Adding remote video channel "%s".', videoChannelToCreateData.uuid) | ||
114 | |||
115 | return sequelizeTypescript.transaction(async t => { | ||
116 | let videoChannel = await VideoChannelModel.loadByUUIDOrUrl(videoChannelToCreateData.uuid, videoChannelToCreateData.id, t) | ||
117 | if (videoChannel) return videoChannel | ||
118 | |||
119 | const videoChannelData = videoChannelActivityObjectToDBAttributes(videoChannelToCreateData, account) | ||
120 | videoChannel = new VideoChannelModel(videoChannelData) | ||
121 | videoChannel.url = getVideoChannelActivityPubUrl(videoChannel) | ||
122 | |||
123 | videoChannel = await videoChannel.save({ transaction: t }) | ||
124 | logger.info('Remote video channel with uuid %s inserted.', videoChannelToCreateData.uuid) | ||
125 | |||
126 | return videoChannel | ||
127 | }) | ||
128 | } | ||
129 | |||
130 | function processCreateVideoAbuse (account: AccountModel, videoAbuseToCreateData: VideoAbuseObject) { | ||
131 | const options = { | 207 | const options = { |
132 | arguments: [ account, videoAbuseToCreateData ], | 208 | arguments: [ actor, videoAbuseToCreateData ], |
133 | errorMessage: 'Cannot insert the remote video abuse with many retries.' | 209 | errorMessage: 'Cannot insert the remote video abuse with many retries.' |
134 | } | 210 | } |
135 | 211 | ||
136 | return retryTransactionWrapper(addRemoteVideoAbuse, options) | 212 | return retryTransactionWrapper(addRemoteVideoAbuse, options) |
137 | } | 213 | } |
138 | 214 | ||
139 | function addRemoteVideoAbuse (account: AccountModel, videoAbuseToCreateData: VideoAbuseObject) { | 215 | function addRemoteVideoAbuse (actor: ActorModel, videoAbuseToCreateData: VideoAbuseObject) { |
140 | logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object) | 216 | logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object) |
141 | 217 | ||
218 | const account = actor.Account | ||
219 | if (!account) throw new Error('Cannot create dislike with the non account actor ' + actor.url) | ||
220 | |||
142 | return sequelizeTypescript.transaction(async t => { | 221 | return sequelizeTypescript.transaction(async t => { |
143 | const video = await VideoModel.loadByUrlAndPopulateAccount(videoAbuseToCreateData.object, t) | 222 | const video = await VideoModel.loadByUrlAndPopulateAccount(videoAbuseToCreateData.object, t) |
144 | if (!video) { | 223 | if (!video) { |
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts index 8f280d37f..65a4e5bcc 100644 --- a/server/lib/activitypub/process/process-delete.ts +++ b/server/lib/activitypub/process/process-delete.ts | |||
@@ -2,28 +2,30 @@ import { ActivityDelete } from '../../../../shared/models/activitypub' | |||
2 | import { logger, retryTransactionWrapper } from '../../../helpers' | 2 | import { logger, retryTransactionWrapper } from '../../../helpers' |
3 | import { sequelizeTypescript } from '../../../initializers' | 3 | import { sequelizeTypescript } from '../../../initializers' |
4 | import { AccountModel } from '../../../models/account/account' | 4 | import { AccountModel } from '../../../models/account/account' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | ||
5 | import { VideoModel } from '../../../models/video/video' | 6 | import { VideoModel } from '../../../models/video/video' |
6 | import { VideoChannelModel } from '../../../models/video/video-channel' | 7 | import { VideoChannelModel } from '../../../models/video/video-channel' |
7 | import { getOrCreateAccountAndServer } from '../account' | 8 | import { getOrCreateActorAndServerAndModel } from '../actor' |
8 | 9 | ||
9 | async function processDeleteActivity (activity: ActivityDelete) { | 10 | async function processDeleteActivity (activity: ActivityDelete) { |
10 | const account = await getOrCreateAccountAndServer(activity.actor) | 11 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
11 | 12 | ||
12 | if (account.url === activity.id) { | 13 | if (actor.url === activity.id) { |
13 | return processDeleteAccount(account) | 14 | if (actor.type === 'Person') { |
14 | } | 15 | if (!actor.Account) throw new Error('Actor ' + actor.url + ' is a person but we cannot find it in database.') |
15 | 16 | ||
16 | { | 17 | return processDeleteAccount(actor.Account) |
17 | let videoObject = await VideoModel.loadByUrlAndPopulateAccount(activity.id) | 18 | } else if (actor.type === 'Group') { |
18 | if (videoObject !== undefined) { | 19 | if (!actor.VideoChannel) throw new Error('Actor ' + actor.url + ' is a group but we cannot find it in database.') |
19 | return processDeleteVideo(account, videoObject) | 20 | |
21 | return processDeleteVideoChannel(actor.VideoChannel) | ||
20 | } | 22 | } |
21 | } | 23 | } |
22 | 24 | ||
23 | { | 25 | { |
24 | let videoChannelObject = await VideoChannelModel.loadByUrl(activity.id) | 26 | let videoObject = await VideoModel.loadByUrlAndPopulateAccount(activity.id) |
25 | if (videoChannelObject !== undefined) { | 27 | if (videoObject !== undefined) { |
26 | return processDeleteVideoChannel(account, videoChannelObject) | 28 | return processDeleteVideo(actor, videoObject) |
27 | } | 29 | } |
28 | } | 30 | } |
29 | 31 | ||
@@ -38,21 +40,21 @@ export { | |||
38 | 40 | ||
39 | // --------------------------------------------------------------------------- | 41 | // --------------------------------------------------------------------------- |
40 | 42 | ||
41 | async function processDeleteVideo (account: AccountModel, videoToDelete: VideoModel) { | 43 | async function processDeleteVideo (actor: ActorModel, videoToDelete: VideoModel) { |
42 | const options = { | 44 | const options = { |
43 | arguments: [ account, videoToDelete ], | 45 | arguments: [ actor, videoToDelete ], |
44 | errorMessage: 'Cannot remove the remote video with many retries.' | 46 | errorMessage: 'Cannot remove the remote video with many retries.' |
45 | } | 47 | } |
46 | 48 | ||
47 | await retryTransactionWrapper(deleteRemoteVideo, options) | 49 | await retryTransactionWrapper(deleteRemoteVideo, options) |
48 | } | 50 | } |
49 | 51 | ||
50 | async function deleteRemoteVideo (account: AccountModel, videoToDelete: VideoModel) { | 52 | async function deleteRemoteVideo (actor: ActorModel, videoToDelete: VideoModel) { |
51 | logger.debug('Removing remote video "%s".', videoToDelete.uuid) | 53 | logger.debug('Removing remote video "%s".', videoToDelete.uuid) |
52 | 54 | ||
53 | await sequelizeTypescript.transaction(async t => { | 55 | await sequelizeTypescript.transaction(async t => { |
54 | if (videoToDelete.VideoChannel.Account.id !== account.id) { | 56 | if (videoToDelete.VideoChannel.Account.Actor.id !== actor.id) { |
55 | throw new Error('Account ' + account.url + ' does not own video channel ' + videoToDelete.VideoChannel.url) | 57 | throw new Error('Account ' + actor.url + ' does not own video channel ' + videoToDelete.VideoChannel.Actor.url) |
56 | } | 58 | } |
57 | 59 | ||
58 | await videoToDelete.destroy({ transaction: t }) | 60 | await videoToDelete.destroy({ transaction: t }) |
@@ -61,44 +63,40 @@ async function deleteRemoteVideo (account: AccountModel, videoToDelete: VideoMod | |||
61 | logger.info('Remote video with uuid %s removed.', videoToDelete.uuid) | 63 | logger.info('Remote video with uuid %s removed.', videoToDelete.uuid) |
62 | } | 64 | } |
63 | 65 | ||
64 | async function processDeleteVideoChannel (account: AccountModel, videoChannelToRemove: VideoChannelModel) { | 66 | async function processDeleteAccount (accountToRemove: AccountModel) { |
65 | const options = { | 67 | const options = { |
66 | arguments: [ account, videoChannelToRemove ], | 68 | arguments: [ accountToRemove ], |
67 | errorMessage: 'Cannot remove the remote video channel with many retries.' | 69 | errorMessage: 'Cannot remove the remote account with many retries.' |
68 | } | 70 | } |
69 | 71 | ||
70 | await retryTransactionWrapper(deleteRemoteVideoChannel, options) | 72 | await retryTransactionWrapper(deleteRemoteAccount, options) |
71 | } | 73 | } |
72 | 74 | ||
73 | async function deleteRemoteVideoChannel (account: AccountModel, videoChannelToRemove: VideoChannelModel) { | 75 | async function deleteRemoteAccount (accountToRemove: AccountModel) { |
74 | logger.debug('Removing remote video channel "%s".', videoChannelToRemove.uuid) | 76 | logger.debug('Removing remote account "%s".', accountToRemove.Actor.uuid) |
75 | 77 | ||
76 | await sequelizeTypescript.transaction(async t => { | 78 | await sequelizeTypescript.transaction(async t => { |
77 | if (videoChannelToRemove.Account.id !== account.id) { | 79 | await accountToRemove.destroy({ transaction: t }) |
78 | throw new Error('Account ' + account.url + ' does not own video channel ' + videoChannelToRemove.url) | ||
79 | } | ||
80 | |||
81 | await videoChannelToRemove.destroy({ transaction: t }) | ||
82 | }) | 80 | }) |
83 | 81 | ||
84 | logger.info('Remote video channel with uuid %s removed.', videoChannelToRemove.uuid) | 82 | logger.info('Remote account with uuid %s removed.', accountToRemove.Actor.uuid) |
85 | } | 83 | } |
86 | 84 | ||
87 | async function processDeleteAccount (accountToRemove: AccountModel) { | 85 | async function processDeleteVideoChannel (videoChannelToRemove: VideoChannelModel) { |
88 | const options = { | 86 | const options = { |
89 | arguments: [ accountToRemove ], | 87 | arguments: [ videoChannelToRemove ], |
90 | errorMessage: 'Cannot remove the remote account with many retries.' | 88 | errorMessage: 'Cannot remove the remote video channel with many retries.' |
91 | } | 89 | } |
92 | 90 | ||
93 | await retryTransactionWrapper(deleteRemoteAccount, options) | 91 | await retryTransactionWrapper(deleteRemoteVideoChannel, options) |
94 | } | 92 | } |
95 | 93 | ||
96 | async function deleteRemoteAccount (accountToRemove: AccountModel) { | 94 | async function deleteRemoteVideoChannel (videoChannelToRemove: VideoChannelModel) { |
97 | logger.debug('Removing remote account "%s".', accountToRemove.uuid) | 95 | logger.debug('Removing remote video channel "%s".', videoChannelToRemove.Actor.uuid) |
98 | 96 | ||
99 | await sequelizeTypescript.transaction(async t => { | 97 | await sequelizeTypescript.transaction(async t => { |
100 | await accountToRemove.destroy({ transaction: t }) | 98 | await videoChannelToRemove.destroy({ transaction: t }) |
101 | }) | 99 | }) |
102 | 100 | ||
103 | logger.info('Remote account with uuid %s removed.', accountToRemove.uuid) | 101 | logger.info('Remote video channel with uuid %s removed.', videoChannelToRemove.Actor.uuid) |
104 | } | 102 | } |
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts index ccaee43a6..ec7a331f3 100644 --- a/server/lib/activitypub/process/process-follow.ts +++ b/server/lib/activitypub/process/process-follow.ts | |||
@@ -1,16 +1,16 @@ | |||
1 | import { ActivityFollow } from '../../../../shared/models/activitypub' | 1 | import { ActivityFollow } from '../../../../shared/models/activitypub' |
2 | import { logger, retryTransactionWrapper } from '../../../helpers' | 2 | import { logger, retryTransactionWrapper } from '../../../helpers' |
3 | import { sequelizeTypescript } from '../../../initializers' | 3 | import { sequelizeTypescript } from '../../../initializers' |
4 | import { AccountModel } from '../../../models/account/account' | 4 | import { ActorModel } from '../../../models/activitypub/actor' |
5 | import { AccountFollowModel } from '../../../models/account/account-follow' | 5 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' |
6 | import { getOrCreateAccountAndServer } from '../account' | 6 | import { getOrCreateActorAndServerAndModel } from '../actor' |
7 | import { sendAccept } from '../send' | 7 | import { sendAccept } from '../send' |
8 | 8 | ||
9 | async function processFollowActivity (activity: ActivityFollow) { | 9 | async function processFollowActivity (activity: ActivityFollow) { |
10 | const activityObject = activity.object | 10 | const activityObject = activity.object |
11 | const account = await getOrCreateAccountAndServer(activity.actor) | 11 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
12 | 12 | ||
13 | return processFollow(account, activityObject) | 13 | return processFollow(actor, activityObject) |
14 | } | 14 | } |
15 | 15 | ||
16 | // --------------------------------------------------------------------------- | 16 | // --------------------------------------------------------------------------- |
@@ -21,46 +21,46 @@ export { | |||
21 | 21 | ||
22 | // --------------------------------------------------------------------------- | 22 | // --------------------------------------------------------------------------- |
23 | 23 | ||
24 | function processFollow (account: AccountModel, targetAccountURL: string) { | 24 | function processFollow (actor: ActorModel, targetActorURL: string) { |
25 | const options = { | 25 | const options = { |
26 | arguments: [ account, targetAccountURL ], | 26 | arguments: [ actor, targetActorURL ], |
27 | errorMessage: 'Cannot follow with many retries.' | 27 | errorMessage: 'Cannot follow with many retries.' |
28 | } | 28 | } |
29 | 29 | ||
30 | return retryTransactionWrapper(follow, options) | 30 | return retryTransactionWrapper(follow, options) |
31 | } | 31 | } |
32 | 32 | ||
33 | async function follow (account: AccountModel, targetAccountURL: string) { | 33 | async function follow (actor: ActorModel, targetActorURL: string) { |
34 | await sequelizeTypescript.transaction(async t => { | 34 | await sequelizeTypescript.transaction(async t => { |
35 | const targetAccount = await AccountModel.loadByUrl(targetAccountURL, t) | 35 | const targetActor = await ActorModel.loadByUrl(targetActorURL, t) |
36 | 36 | ||
37 | if (!targetAccount) throw new Error('Unknown account') | 37 | if (!targetActor) throw new Error('Unknown actor') |
38 | if (targetAccount.isOwned() === false) throw new Error('This is not a local account.') | 38 | if (targetActor.isOwned() === false) throw new Error('This is not a local actor.') |
39 | 39 | ||
40 | const [ accountFollow ] = await AccountFollowModel.findOrCreate({ | 40 | const [ actorFollow ] = await ActorFollowModel.findOrCreate({ |
41 | where: { | 41 | where: { |
42 | accountId: account.id, | 42 | actorId: actor.id, |
43 | targetAccountId: targetAccount.id | 43 | targetActorId: targetActor.id |
44 | }, | 44 | }, |
45 | defaults: { | 45 | defaults: { |
46 | accountId: account.id, | 46 | actorId: actor.id, |
47 | targetAccountId: targetAccount.id, | 47 | targetActorId: targetActor.id, |
48 | state: 'accepted' | 48 | state: 'accepted' |
49 | }, | 49 | }, |
50 | transaction: t | 50 | transaction: t |
51 | }) | 51 | }) |
52 | 52 | ||
53 | if (accountFollow.state !== 'accepted') { | 53 | if (actorFollow.state !== 'accepted') { |
54 | accountFollow.state = 'accepted' | 54 | actorFollow.state = 'accepted' |
55 | await accountFollow.save({ transaction: t }) | 55 | await actorFollow.save({ transaction: t }) |
56 | } | 56 | } |
57 | 57 | ||
58 | accountFollow.AccountFollower = account | 58 | actorFollow.ActorFollower = actor |
59 | accountFollow.AccountFollowing = targetAccount | 59 | actorFollow.ActorFollowing = targetActor |
60 | 60 | ||
61 | // Target sends to account he accepted the follow request | 61 | // Target sends to actor he accepted the follow request |
62 | return sendAccept(accountFollow, t) | 62 | return sendAccept(actorFollow, t) |
63 | }) | 63 | }) |
64 | 64 | ||
65 | logger.info('Account uuid %s is followed by account %s.', account.url, targetAccountURL) | 65 | logger.info('Actor uuid %s is followed by actor %s.', actor.url, targetActorURL) |
66 | } | 66 | } |
diff --git a/server/lib/activitypub/process/process-like.ts b/server/lib/activitypub/process/process-like.ts index a6e391f1e..a7fcec21c 100644 --- a/server/lib/activitypub/process/process-like.ts +++ b/server/lib/activitypub/process/process-like.ts | |||
@@ -1,16 +1,16 @@ | |||
1 | import { ActivityLike } from '../../../../shared/models/activitypub' | 1 | import { ActivityLike } from '../../../../shared/models/activitypub' |
2 | import { retryTransactionWrapper } from '../../../helpers' | 2 | import { retryTransactionWrapper } from '../../../helpers' |
3 | import { sequelizeTypescript } from '../../../initializers' | 3 | import { sequelizeTypescript } from '../../../initializers' |
4 | import { AccountModel } from '../../../models/account/account' | ||
5 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | 4 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | ||
6 | import { VideoModel } from '../../../models/video/video' | 6 | import { VideoModel } from '../../../models/video/video' |
7 | import { getOrCreateAccountAndServer } from '../account' | 7 | import { getOrCreateActorAndServerAndModel } from '../actor' |
8 | import { forwardActivity } from '../send/misc' | 8 | import { forwardActivity } from '../send/misc' |
9 | 9 | ||
10 | async function processLikeActivity (activity: ActivityLike) { | 10 | async function processLikeActivity (activity: ActivityLike) { |
11 | const account = await getOrCreateAccountAndServer(activity.actor) | 11 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
12 | 12 | ||
13 | return processLikeVideo(account, activity) | 13 | return processLikeVideo(actor, activity) |
14 | } | 14 | } |
15 | 15 | ||
16 | // --------------------------------------------------------------------------- | 16 | // --------------------------------------------------------------------------- |
@@ -21,18 +21,21 @@ export { | |||
21 | 21 | ||
22 | // --------------------------------------------------------------------------- | 22 | // --------------------------------------------------------------------------- |
23 | 23 | ||
24 | async function processLikeVideo (byAccount: AccountModel, activity: ActivityLike) { | 24 | async function processLikeVideo (actor: ActorModel, activity: ActivityLike) { |
25 | const options = { | 25 | const options = { |
26 | arguments: [ byAccount, activity ], | 26 | arguments: [ actor, activity ], |
27 | errorMessage: 'Cannot like the video with many retries.' | 27 | errorMessage: 'Cannot like the video with many retries.' |
28 | } | 28 | } |
29 | 29 | ||
30 | return retryTransactionWrapper(createVideoLike, options) | 30 | return retryTransactionWrapper(createVideoLike, options) |
31 | } | 31 | } |
32 | 32 | ||
33 | function createVideoLike (byAccount: AccountModel, activity: ActivityLike) { | 33 | function createVideoLike (byActor: ActorModel, activity: ActivityLike) { |
34 | const videoUrl = activity.object | 34 | const videoUrl = activity.object |
35 | 35 | ||
36 | const byAccount = byActor.Account | ||
37 | if (!byAccount) throw new Error('Cannot create like with the non account actor ' + byActor.url) | ||
38 | |||
36 | return sequelizeTypescript.transaction(async t => { | 39 | return sequelizeTypescript.transaction(async t => { |
37 | const video = await VideoModel.loadByUrlAndPopulateAccount(videoUrl) | 40 | const video = await VideoModel.loadByUrlAndPopulateAccount(videoUrl) |
38 | 41 | ||
@@ -52,7 +55,7 @@ function createVideoLike (byAccount: AccountModel, activity: ActivityLike) { | |||
52 | 55 | ||
53 | if (video.isOwned() && created === true) { | 56 | if (video.isOwned() && created === true) { |
54 | // Don't resend the activity to the sender | 57 | // Don't resend the activity to the sender |
55 | const exceptions = [ byAccount ] | 58 | const exceptions = [ byActor ] |
56 | await forwardActivity(activity, t, exceptions) | 59 | await forwardActivity(activity, t, exceptions) |
57 | } | 60 | } |
58 | }) | 61 | }) |
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts index efa63122b..4a0181137 100644 --- a/server/lib/activitypub/process/process-undo.ts +++ b/server/lib/activitypub/process/process-undo.ts | |||
@@ -3,8 +3,9 @@ import { DislikeObject } from '../../../../shared/models/activitypub/objects' | |||
3 | import { logger, retryTransactionWrapper } from '../../../helpers' | 3 | import { logger, retryTransactionWrapper } from '../../../helpers' |
4 | import { sequelizeTypescript } from '../../../initializers' | 4 | import { sequelizeTypescript } from '../../../initializers' |
5 | import { AccountModel } from '../../../models/account/account' | 5 | import { AccountModel } from '../../../models/account/account' |
6 | import { AccountFollowModel } from '../../../models/account/account-follow' | ||
7 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | 6 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' |
7 | import { ActorModel } from '../../../models/activitypub/actor' | ||
8 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | ||
8 | import { VideoModel } from '../../../models/video/video' | 9 | import { VideoModel } from '../../../models/video/video' |
9 | import { forwardActivity } from '../send/misc' | 10 | import { forwardActivity } from '../send/misc' |
10 | 11 | ||
@@ -32,21 +33,21 @@ export { | |||
32 | 33 | ||
33 | // --------------------------------------------------------------------------- | 34 | // --------------------------------------------------------------------------- |
34 | 35 | ||
35 | function processUndoLike (actor: string, activity: ActivityUndo) { | 36 | function processUndoLike (actorUrl: string, activity: ActivityUndo) { |
36 | const options = { | 37 | const options = { |
37 | arguments: [ actor, activity ], | 38 | arguments: [ actorUrl, activity ], |
38 | errorMessage: 'Cannot undo like with many retries.' | 39 | errorMessage: 'Cannot undo like with many retries.' |
39 | } | 40 | } |
40 | 41 | ||
41 | return retryTransactionWrapper(undoLike, options) | 42 | return retryTransactionWrapper(undoLike, options) |
42 | } | 43 | } |
43 | 44 | ||
44 | function undoLike (actor: string, activity: ActivityUndo) { | 45 | function undoLike (actorUrl: string, activity: ActivityUndo) { |
45 | const likeActivity = activity.object as ActivityLike | 46 | const likeActivity = activity.object as ActivityLike |
46 | 47 | ||
47 | return sequelizeTypescript.transaction(async t => { | 48 | return sequelizeTypescript.transaction(async t => { |
48 | const byAccount = await AccountModel.loadByUrl(actor, t) | 49 | const byAccount = await AccountModel.loadByUrl(actorUrl, t) |
49 | if (!byAccount) throw new Error('Unknown account ' + actor) | 50 | if (!byAccount) throw new Error('Unknown account ' + actorUrl) |
50 | 51 | ||
51 | const video = await VideoModel.loadByUrlAndPopulateAccount(likeActivity.object, t) | 52 | const video = await VideoModel.loadByUrlAndPopulateAccount(likeActivity.object, t) |
52 | if (!video) throw new Error('Unknown video ' + likeActivity.actor) | 53 | if (!video) throw new Error('Unknown video ' + likeActivity.actor) |
@@ -59,27 +60,27 @@ function undoLike (actor: string, activity: ActivityUndo) { | |||
59 | 60 | ||
60 | if (video.isOwned()) { | 61 | if (video.isOwned()) { |
61 | // Don't resend the activity to the sender | 62 | // Don't resend the activity to the sender |
62 | const exceptions = [ byAccount ] | 63 | const exceptions = [ byAccount.Actor ] |
63 | await forwardActivity(activity, t, exceptions) | 64 | await forwardActivity(activity, t, exceptions) |
64 | } | 65 | } |
65 | }) | 66 | }) |
66 | } | 67 | } |
67 | 68 | ||
68 | function processUndoDislike (actor: string, activity: ActivityUndo) { | 69 | function processUndoDislike (actorUrl: string, activity: ActivityUndo) { |
69 | const options = { | 70 | const options = { |
70 | arguments: [ actor, activity ], | 71 | arguments: [ actorUrl, activity ], |
71 | errorMessage: 'Cannot undo dislike with many retries.' | 72 | errorMessage: 'Cannot undo dislike with many retries.' |
72 | } | 73 | } |
73 | 74 | ||
74 | return retryTransactionWrapper(undoDislike, options) | 75 | return retryTransactionWrapper(undoDislike, options) |
75 | } | 76 | } |
76 | 77 | ||
77 | function undoDislike (actor: string, activity: ActivityUndo) { | 78 | function undoDislike (actorUrl: string, activity: ActivityUndo) { |
78 | const dislike = activity.object.object as DislikeObject | 79 | const dislike = activity.object.object as DislikeObject |
79 | 80 | ||
80 | return sequelizeTypescript.transaction(async t => { | 81 | return sequelizeTypescript.transaction(async t => { |
81 | const byAccount = await AccountModel.loadByUrl(actor, t) | 82 | const byAccount = await AccountModel.loadByUrl(actorUrl, t) |
82 | if (!byAccount) throw new Error('Unknown account ' + actor) | 83 | if (!byAccount) throw new Error('Unknown account ' + actorUrl) |
83 | 84 | ||
84 | const video = await VideoModel.loadByUrlAndPopulateAccount(dislike.object, t) | 85 | const video = await VideoModel.loadByUrlAndPopulateAccount(dislike.object, t) |
85 | if (!video) throw new Error('Unknown video ' + dislike.actor) | 86 | if (!video) throw new Error('Unknown video ' + dislike.actor) |
@@ -92,30 +93,30 @@ function undoDislike (actor: string, activity: ActivityUndo) { | |||
92 | 93 | ||
93 | if (video.isOwned()) { | 94 | if (video.isOwned()) { |
94 | // Don't resend the activity to the sender | 95 | // Don't resend the activity to the sender |
95 | const exceptions = [ byAccount ] | 96 | const exceptions = [ byAccount.Actor ] |
96 | await forwardActivity(activity, t, exceptions) | 97 | await forwardActivity(activity, t, exceptions) |
97 | } | 98 | } |
98 | }) | 99 | }) |
99 | } | 100 | } |
100 | 101 | ||
101 | function processUndoFollow (actor: string, followActivity: ActivityFollow) { | 102 | function processUndoFollow (actorUrl: string, followActivity: ActivityFollow) { |
102 | const options = { | 103 | const options = { |
103 | arguments: [ actor, followActivity ], | 104 | arguments: [ actorUrl, followActivity ], |
104 | errorMessage: 'Cannot undo follow with many retries.' | 105 | errorMessage: 'Cannot undo follow with many retries.' |
105 | } | 106 | } |
106 | 107 | ||
107 | return retryTransactionWrapper(undoFollow, options) | 108 | return retryTransactionWrapper(undoFollow, options) |
108 | } | 109 | } |
109 | 110 | ||
110 | function undoFollow (actor: string, followActivity: ActivityFollow) { | 111 | function undoFollow (actorUrl: string, followActivity: ActivityFollow) { |
111 | return sequelizeTypescript.transaction(async t => { | 112 | return sequelizeTypescript.transaction(async t => { |
112 | const follower = await AccountModel.loadByUrl(actor, t) | 113 | const follower = await ActorModel.loadByUrl(actorUrl, t) |
113 | const following = await AccountModel.loadByUrl(followActivity.object, t) | 114 | const following = await ActorModel.loadByUrl(followActivity.object, t) |
114 | const accountFollow = await AccountFollowModel.loadByAccountAndTarget(follower.id, following.id, t) | 115 | const actorFollow = await ActorFollowModel.loadByActorAndTarget(follower.id, following.id, t) |
115 | 116 | ||
116 | if (!accountFollow) throw new Error(`'Unknown account follow ${follower.id} -> ${following.id}.`) | 117 | if (!actorFollow) throw new Error(`'Unknown actor follow ${follower.id} -> ${following.id}.`) |
117 | 118 | ||
118 | await accountFollow.destroy({ transaction: t }) | 119 | await actorFollow.destroy({ transaction: t }) |
119 | 120 | ||
120 | return undefined | 121 | return undefined |
121 | }) | 122 | }) |
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index 771021f0c..35912ee87 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -1,23 +1,19 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { VideoChannelObject, VideoTorrentObject } from '../../../../shared' | ||
3 | import { ActivityUpdate } from '../../../../shared/models/activitypub' | 2 | import { ActivityUpdate } from '../../../../shared/models/activitypub' |
4 | import { logger, resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers' | 3 | import { logger, resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers' |
5 | import { sequelizeTypescript } from '../../../initializers' | 4 | import { sequelizeTypescript } from '../../../initializers' |
6 | import { AccountModel } from '../../../models/account/account' | 5 | import { ActorModel } from '../../../models/activitypub/actor' |
7 | import { TagModel } from '../../../models/video/tag' | 6 | import { TagModel } from '../../../models/video/tag' |
8 | import { VideoModel } from '../../../models/video/video' | 7 | import { VideoModel } from '../../../models/video/video' |
9 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
10 | import { VideoFileModel } from '../../../models/video/video-file' | 8 | import { VideoFileModel } from '../../../models/video/video-file' |
11 | import { getOrCreateAccountAndServer } from '../account' | 9 | import { getOrCreateActorAndServerAndModel } from '../actor' |
12 | import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' | 10 | import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' |
13 | 11 | ||
14 | async function processUpdateActivity (activity: ActivityUpdate) { | 12 | async function processUpdateActivity (activity: ActivityUpdate) { |
15 | const account = await getOrCreateAccountAndServer(activity.actor) | 13 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
16 | 14 | ||
17 | if (activity.object.type === 'Video') { | 15 | if (activity.object.type === 'Video') { |
18 | return processUpdateVideo(account, activity.object) | 16 | return processUpdateVideo(actor, activity) |
19 | } else if (activity.object.type === 'VideoChannel') { | ||
20 | return processUpdateVideoChannel(account, activity.object) | ||
21 | } | 17 | } |
22 | 18 | ||
23 | return | 19 | return |
@@ -31,16 +27,18 @@ export { | |||
31 | 27 | ||
32 | // --------------------------------------------------------------------------- | 28 | // --------------------------------------------------------------------------- |
33 | 29 | ||
34 | function processUpdateVideo (account: AccountModel, video: VideoTorrentObject) { | 30 | function processUpdateVideo (actor: ActorModel, activity: ActivityUpdate) { |
35 | const options = { | 31 | const options = { |
36 | arguments: [ account, video ], | 32 | arguments: [ actor, activity ], |
37 | errorMessage: 'Cannot update the remote video with many retries' | 33 | errorMessage: 'Cannot update the remote video with many retries' |
38 | } | 34 | } |
39 | 35 | ||
40 | return retryTransactionWrapper(updateRemoteVideo, options) | 36 | return retryTransactionWrapper(updateRemoteVideo, options) |
41 | } | 37 | } |
42 | 38 | ||
43 | async function updateRemoteVideo (account: AccountModel, videoAttributesToUpdate: VideoTorrentObject) { | 39 | async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { |
40 | const videoAttributesToUpdate = activity.object | ||
41 | |||
44 | logger.debug('Updating remote video "%s".', videoAttributesToUpdate.uuid) | 42 | logger.debug('Updating remote video "%s".', videoAttributesToUpdate.uuid) |
45 | let videoInstance: VideoModel | 43 | let videoInstance: VideoModel |
46 | let videoFieldsSave: object | 44 | let videoFieldsSave: object |
@@ -54,23 +52,23 @@ async function updateRemoteVideo (account: AccountModel, videoAttributesToUpdate | |||
54 | const videoInstance = await VideoModel.loadByUrlAndPopulateAccount(videoAttributesToUpdate.id, t) | 52 | const videoInstance = await VideoModel.loadByUrlAndPopulateAccount(videoAttributesToUpdate.id, t) |
55 | if (!videoInstance) throw new Error('Video ' + videoAttributesToUpdate.id + ' not found.') | 53 | if (!videoInstance) throw new Error('Video ' + videoAttributesToUpdate.id + ' not found.') |
56 | 54 | ||
57 | if (videoInstance.VideoChannel.Account.id !== account.id) { | 55 | const videoChannel = videoInstance.VideoChannel |
58 | throw new Error('Account ' + account.url + ' does not own video channel ' + videoInstance.VideoChannel.url) | 56 | if (videoChannel.Account.Actor.id !== actor.id) { |
57 | throw new Error('Account ' + actor.url + ' does not own video channel ' + videoChannel.Actor.url) | ||
59 | } | 58 | } |
60 | 59 | ||
61 | const videoData = await videoActivityObjectToDBAttributes(videoInstance.VideoChannel, videoAttributesToUpdate) | 60 | const videoData = await videoActivityObjectToDBAttributes(videoChannel, videoAttributesToUpdate, activity.to, activity.cc) |
62 | videoInstance.set('name', videoData.name) | 61 | videoInstance.set('name', videoData.name) |
63 | videoInstance.set('category', videoData.category) | 62 | videoInstance.set('category', videoData.category) |
64 | videoInstance.set('licence', videoData.licence) | 63 | videoInstance.set('licence', videoData.licence) |
65 | videoInstance.set('language', videoData.language) | 64 | videoInstance.set('language', videoData.language) |
66 | videoInstance.set('nsfw', videoData.nsfw) | 65 | videoInstance.set('nsfw', videoData.nsfw) |
66 | videoInstance.set('privacy', videoData.privacy) | ||
67 | videoInstance.set('description', videoData.description) | 67 | videoInstance.set('description', videoData.description) |
68 | videoInstance.set('duration', videoData.duration) | 68 | videoInstance.set('duration', videoData.duration) |
69 | videoInstance.set('createdAt', videoData.createdAt) | 69 | videoInstance.set('createdAt', videoData.createdAt) |
70 | videoInstance.set('updatedAt', videoData.updatedAt) | 70 | videoInstance.set('updatedAt', videoData.updatedAt) |
71 | videoInstance.set('views', videoData.views) | 71 | videoInstance.set('views', videoData.views) |
72 | // videoInstance.set('likes', videoData.likes) | ||
73 | // videoInstance.set('dislikes', videoData.dislikes) | ||
74 | 72 | ||
75 | await videoInstance.save(sequelizeOptions) | 73 | await videoInstance.save(sequelizeOptions) |
76 | 74 | ||
@@ -101,36 +99,3 @@ async function updateRemoteVideo (account: AccountModel, videoAttributesToUpdate | |||
101 | throw err | 99 | throw err |
102 | } | 100 | } |
103 | } | 101 | } |
104 | |||
105 | async function processUpdateVideoChannel (account: AccountModel, videoChannel: VideoChannelObject) { | ||
106 | const options = { | ||
107 | arguments: [ account, videoChannel ], | ||
108 | errorMessage: 'Cannot update the remote video channel with many retries.' | ||
109 | } | ||
110 | |||
111 | await retryTransactionWrapper(updateRemoteVideoChannel, options) | ||
112 | } | ||
113 | |||
114 | async function updateRemoteVideoChannel (account: AccountModel, videoChannel: VideoChannelObject) { | ||
115 | logger.debug('Updating remote video channel "%s".', videoChannel.uuid) | ||
116 | |||
117 | await sequelizeTypescript.transaction(async t => { | ||
118 | const sequelizeOptions = { transaction: t } | ||
119 | |||
120 | const videoChannelInstance = await VideoChannelModel.loadByUrl(videoChannel.id) | ||
121 | if (!videoChannelInstance) throw new Error('Video ' + videoChannel.id + ' not found.') | ||
122 | |||
123 | if (videoChannelInstance.Account.id !== account.id) { | ||
124 | throw new Error('Account ' + account.id + ' does not own video channel ' + videoChannelInstance.url) | ||
125 | } | ||
126 | |||
127 | videoChannelInstance.set('name', videoChannel.name) | ||
128 | videoChannelInstance.set('description', videoChannel.content) | ||
129 | videoChannelInstance.set('createdAt', videoChannel.published) | ||
130 | videoChannelInstance.set('updatedAt', videoChannel.updated) | ||
131 | |||
132 | await videoChannelInstance.save(sequelizeOptions) | ||
133 | }) | ||
134 | |||
135 | logger.info('Remote video channel with uuid %s updated', videoChannel.uuid) | ||
136 | } | ||
diff --git a/server/lib/activitypub/process/process.ts b/server/lib/activitypub/process/process.ts index bfbf8053c..dfb60c1bf 100644 --- a/server/lib/activitypub/process/process.ts +++ b/server/lib/activitypub/process/process.ts | |||
@@ -1,8 +1,7 @@ | |||
1 | import { Activity, ActivityType } from '../../../../shared/models/activitypub' | 1 | import { Activity, ActivityType } from '../../../../shared/models/activitypub' |
2 | import { logger } from '../../../helpers' | 2 | import { logger } from '../../../helpers' |
3 | import { AccountModel } from '../../../models/account/account' | 3 | import { ActorModel } from '../../../models/activitypub/actor' |
4 | import { processAcceptActivity } from './process-accept' | 4 | import { processAcceptActivity } from './process-accept' |
5 | import { processAddActivity } from './process-add' | ||
6 | import { processAnnounceActivity } from './process-announce' | 5 | import { processAnnounceActivity } from './process-announce' |
7 | import { processCreateActivity } from './process-create' | 6 | import { processCreateActivity } from './process-create' |
8 | import { processDeleteActivity } from './process-delete' | 7 | import { processDeleteActivity } from './process-delete' |
@@ -11,9 +10,8 @@ import { processLikeActivity } from './process-like' | |||
11 | import { processUndoActivity } from './process-undo' | 10 | import { processUndoActivity } from './process-undo' |
12 | import { processUpdateActivity } from './process-update' | 11 | import { processUpdateActivity } from './process-update' |
13 | 12 | ||
14 | const processActivity: { [ P in ActivityType ]: (activity: Activity, inboxAccount?: AccountModel) => Promise<any> } = { | 13 | const processActivity: { [ P in ActivityType ]: (activity: Activity, inboxActor?: ActorModel) => Promise<any> } = { |
15 | Create: processCreateActivity, | 14 | Create: processCreateActivity, |
16 | Add: processAddActivity, | ||
17 | Update: processUpdateActivity, | 15 | Update: processUpdateActivity, |
18 | Delete: processDeleteActivity, | 16 | Delete: processDeleteActivity, |
19 | Follow: processFollowActivity, | 17 | Follow: processFollowActivity, |
@@ -23,11 +21,11 @@ const processActivity: { [ P in ActivityType ]: (activity: Activity, inboxAccoun | |||
23 | Like: processLikeActivity | 21 | Like: processLikeActivity |
24 | } | 22 | } |
25 | 23 | ||
26 | async function processActivities (activities: Activity[], signatureAccount?: AccountModel, inboxAccount?: AccountModel) { | 24 | async function processActivities (activities: Activity[], signatureActor?: ActorModel, inboxActor?: ActorModel) { |
27 | for (const activity of activities) { | 25 | for (const activity of activities) { |
28 | // When we fetch remote data, we don't have signature | 26 | // When we fetch remote data, we don't have signature |
29 | if (signatureAccount && activity.actor !== signatureAccount.url) { | 27 | if (signatureActor && activity.actor !== signatureActor.url) { |
30 | logger.warn('Signature mismatch between %s and %s.', activity.actor, signatureAccount.url) | 28 | logger.warn('Signature mismatch between %s and %s.', activity.actor, signatureActor.url) |
31 | continue | 29 | continue |
32 | } | 30 | } |
33 | 31 | ||
@@ -38,7 +36,7 @@ async function processActivities (activities: Activity[], signatureAccount?: Acc | |||
38 | } | 36 | } |
39 | 37 | ||
40 | try { | 38 | try { |
41 | await activityProcessor(activity, inboxAccount) | 39 | await activityProcessor(activity, inboxActor) |
42 | } catch (err) { | 40 | } catch (err) { |
43 | logger.warn('Cannot process activity %s.', activity.type, err) | 41 | logger.warn('Cannot process activity %s.', activity.type, err) |
44 | } | 42 | } |