diff options
Diffstat (limited to 'server/lib/activitypub/process-update.ts')
-rw-r--r-- | server/lib/activitypub/process-update.ts | 127 |
1 files changed, 117 insertions, 10 deletions
diff --git a/server/lib/activitypub/process-update.ts b/server/lib/activitypub/process-update.ts index 187c7be7c..cd8a4b8e2 100644 --- a/server/lib/activitypub/process-update.ts +++ b/server/lib/activitypub/process-update.ts | |||
@@ -1,15 +1,25 @@ | |||
1 | import { | 1 | import { VideoChannelObject, VideoTorrentObject } from '../../../shared' |
2 | ActivityCreate, | 2 | import { ActivityUpdate } from '../../../shared/models/activitypub/activity' |
3 | VideoTorrentObject, | 3 | import { getOrCreateAccount } from '../../helpers/activitypub' |
4 | VideoChannelObject | 4 | import { retryTransactionWrapper } from '../../helpers/database-utils' |
5 | } from '../../../shared' | 5 | import { logger } from '../../helpers/logger' |
6 | import { resetSequelizeInstance } from '../../helpers/utils' | ||
7 | import { database as db } from '../../initializers' | ||
8 | import { AccountInstance } from '../../models/account/account-interface' | ||
9 | import { VideoInstance } from '../../models/video/video-interface' | ||
10 | import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' | ||
11 | import Bluebird = require('bluebird') | ||
12 | |||
13 | async function processUpdateActivity (activity: ActivityUpdate) { | ||
14 | const account = await getOrCreateAccount(activity.actor) | ||
6 | 15 | ||
7 | function processUpdateActivity (activity: ActivityCreate) { | ||
8 | if (activity.object.type === 'Video') { | 16 | if (activity.object.type === 'Video') { |
9 | return processUpdateVideo(activity.object) | 17 | return processUpdateVideo(account, activity.object) |
10 | } else if (activity.object.type === 'VideoChannel') { | 18 | } else if (activity.object.type === 'VideoChannel') { |
11 | return processUpdateVideoChannel(activity.object) | 19 | return processUpdateVideoChannel(account, activity.object) |
12 | } | 20 | } |
21 | |||
22 | return undefined | ||
13 | } | 23 | } |
14 | 24 | ||
15 | // --------------------------------------------------------------------------- | 25 | // --------------------------------------------------------------------------- |
@@ -20,10 +30,107 @@ export { | |||
20 | 30 | ||
21 | // --------------------------------------------------------------------------- | 31 | // --------------------------------------------------------------------------- |
22 | 32 | ||
23 | function processUpdateVideo (video: VideoTorrentObject) { | 33 | function processUpdateVideo (account: AccountInstance, video: VideoTorrentObject) { |
34 | const options = { | ||
35 | arguments: [ account, video ], | ||
36 | errorMessage: 'Cannot update the remote video with many retries' | ||
37 | } | ||
24 | 38 | ||
39 | return retryTransactionWrapper(updateRemoteVideo, options) | ||
25 | } | 40 | } |
26 | 41 | ||
27 | function processUpdateVideoChannel (videoChannel: VideoChannelObject) { | 42 | async function updateRemoteVideo (account: AccountInstance, videoAttributesToUpdate: VideoTorrentObject) { |
43 | logger.debug('Updating remote video "%s".', videoAttributesToUpdate.uuid) | ||
44 | let videoInstance: VideoInstance | ||
45 | let videoFieldsSave: object | ||
46 | |||
47 | try { | ||
48 | await db.sequelize.transaction(async t => { | ||
49 | const sequelizeOptions = { | ||
50 | transaction: t | ||
51 | } | ||
52 | |||
53 | const videoInstance = await db.Video.loadByUrl(videoAttributesToUpdate.id, t) | ||
54 | if (!videoInstance) throw new Error('Video ' + videoAttributesToUpdate.id + ' not found.') | ||
55 | |||
56 | if (videoInstance.VideoChannel.Account.id !== account.id) { | ||
57 | throw new Error('Account ' + account.url + ' does not own video channel ' + videoInstance.VideoChannel.url) | ||
58 | } | ||
59 | |||
60 | const videoData = await videoActivityObjectToDBAttributes(videoInstance.VideoChannel, videoAttributesToUpdate, t) | ||
61 | videoInstance.set('name', videoData.name) | ||
62 | videoInstance.set('category', videoData.category) | ||
63 | videoInstance.set('licence', videoData.licence) | ||
64 | videoInstance.set('language', videoData.language) | ||
65 | videoInstance.set('nsfw', videoData.nsfw) | ||
66 | videoInstance.set('description', videoData.description) | ||
67 | videoInstance.set('duration', videoData.duration) | ||
68 | videoInstance.set('createdAt', videoData.createdAt) | ||
69 | videoInstance.set('updatedAt', videoData.updatedAt) | ||
70 | videoInstance.set('views', videoData.views) | ||
71 | // videoInstance.set('likes', videoData.likes) | ||
72 | // videoInstance.set('dislikes', videoData.dislikes) | ||
73 | // videoInstance.set('privacy', videoData.privacy) | ||
74 | |||
75 | await videoInstance.save(sequelizeOptions) | ||
76 | |||
77 | // Remove old video files | ||
78 | const videoFileDestroyTasks: Bluebird<void>[] = [] | ||
79 | for (const videoFile of videoInstance.VideoFiles) { | ||
80 | videoFileDestroyTasks.push(videoFile.destroy(sequelizeOptions)) | ||
81 | } | ||
82 | await Promise.all(videoFileDestroyTasks) | ||
83 | |||
84 | const videoFileAttributes = await videoFileActivityUrlToDBAttributes(videoInstance, videoAttributesToUpdate) | ||
85 | const tasks: Bluebird<any>[] = videoFileAttributes.map(f => db.VideoFile.create(f)) | ||
86 | await Promise.all(tasks) | ||
87 | |||
88 | const tags = videoAttributesToUpdate.tag.map(t => t.name) | ||
89 | const tagInstances = await db.Tag.findOrCreateTags(tags, t) | ||
90 | await videoInstance.setTags(tagInstances, sequelizeOptions) | ||
91 | }) | ||
92 | |||
93 | logger.info('Remote video with uuid %s updated', videoAttributesToUpdate.uuid) | ||
94 | } catch (err) { | ||
95 | if (videoInstance !== undefined && videoFieldsSave !== undefined) { | ||
96 | resetSequelizeInstance(videoInstance, videoFieldsSave) | ||
97 | } | ||
98 | |||
99 | // This is just a debug because we will retry the insert | ||
100 | logger.debug('Cannot update the remote video.', err) | ||
101 | throw err | ||
102 | } | ||
103 | } | ||
104 | |||
105 | async function processUpdateVideoChannel (account: AccountInstance, 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: AccountInstance, videoChannel: VideoChannelObject) { | ||
115 | logger.debug('Updating remote video channel "%s".', videoChannel.uuid) | ||
116 | |||
117 | await db.sequelize.transaction(async t => { | ||
118 | const sequelizeOptions = { transaction: t } | ||
119 | |||
120 | const videoChannelInstance = await db.VideoChannel.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 | }) | ||
28 | 134 | ||
135 | logger.info('Remote video channel with uuid %s updated', videoChannel.uuid) | ||
29 | } | 136 | } |