diff options
Diffstat (limited to 'server/lib/activitypub/process/process-update.ts')
-rw-r--r-- | server/lib/activitypub/process/process-update.ts | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts new file mode 100644 index 000000000..a3bfb1baf --- /dev/null +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -0,0 +1,135 @@ | |||
1 | import { VideoChannelObject, VideoTorrentObject } from '../../../../shared' | ||
2 | import { ActivityUpdate } from '../../../../shared/models/activitypub/activity' | ||
3 | import { getOrCreateAccount } from '../../../helpers/activitypub' | ||
4 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | ||
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) | ||
15 | |||
16 | if (activity.object.type === 'Video') { | ||
17 | return processUpdateVideo(account, activity.object) | ||
18 | } else if (activity.object.type === 'VideoChannel') { | ||
19 | return processUpdateVideoChannel(account, activity.object) | ||
20 | } | ||
21 | |||
22 | return undefined | ||
23 | } | ||
24 | |||
25 | // --------------------------------------------------------------------------- | ||
26 | |||
27 | export { | ||
28 | processUpdateActivity | ||
29 | } | ||
30 | |||
31 | // --------------------------------------------------------------------------- | ||
32 | |||
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 | } | ||
38 | |||
39 | return retryTransactionWrapper(updateRemoteVideo, options) | ||
40 | } | ||
41 | |||
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.loadByUrlAndPopulateAccount(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) | ||
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 | |||
74 | await videoInstance.save(sequelizeOptions) | ||
75 | |||
76 | // Remove old video files | ||
77 | const videoFileDestroyTasks: Bluebird<void>[] = [] | ||
78 | for (const videoFile of videoInstance.VideoFiles) { | ||
79 | videoFileDestroyTasks.push(videoFile.destroy(sequelizeOptions)) | ||
80 | } | ||
81 | await Promise.all(videoFileDestroyTasks) | ||
82 | |||
83 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoInstance, videoAttributesToUpdate) | ||
84 | const tasks: Bluebird<any>[] = videoFileAttributes.map(f => db.VideoFile.create(f)) | ||
85 | await Promise.all(tasks) | ||
86 | |||
87 | const tags = videoAttributesToUpdate.tag.map(t => t.name) | ||
88 | const tagInstances = await db.Tag.findOrCreateTags(tags, t) | ||
89 | await videoInstance.setTags(tagInstances, sequelizeOptions) | ||
90 | }) | ||
91 | |||
92 | logger.info('Remote video with uuid %s updated', videoAttributesToUpdate.uuid) | ||
93 | } catch (err) { | ||
94 | if (videoInstance !== undefined && videoFieldsSave !== undefined) { | ||
95 | resetSequelizeInstance(videoInstance, videoFieldsSave) | ||
96 | } | ||
97 | |||
98 | // This is just a debug because we will retry the insert | ||
99 | logger.debug('Cannot update the remote video.', err) | ||
100 | throw err | ||
101 | } | ||
102 | } | ||
103 | |||
104 | async function processUpdateVideoChannel (account: AccountInstance, videoChannel: VideoChannelObject) { | ||
105 | const options = { | ||
106 | arguments: [ account, videoChannel ], | ||
107 | errorMessage: 'Cannot update the remote video channel with many retries.' | ||
108 | } | ||
109 | |||
110 | await retryTransactionWrapper(updateRemoteVideoChannel, options) | ||
111 | } | ||
112 | |||
113 | async function updateRemoteVideoChannel (account: AccountInstance, videoChannel: VideoChannelObject) { | ||
114 | logger.debug('Updating remote video channel "%s".', videoChannel.uuid) | ||
115 | |||
116 | await db.sequelize.transaction(async t => { | ||
117 | const sequelizeOptions = { transaction: t } | ||
118 | |||
119 | const videoChannelInstance = await db.VideoChannel.loadByUrl(videoChannel.id) | ||
120 | if (!videoChannelInstance) throw new Error('Video ' + videoChannel.id + ' not found.') | ||
121 | |||
122 | if (videoChannelInstance.Account.id !== account.id) { | ||
123 | throw new Error('Account ' + account.id + ' does not own video channel ' + videoChannelInstance.url) | ||
124 | } | ||
125 | |||
126 | videoChannelInstance.set('name', videoChannel.name) | ||
127 | videoChannelInstance.set('description', videoChannel.content) | ||
128 | videoChannelInstance.set('createdAt', videoChannel.published) | ||
129 | videoChannelInstance.set('updatedAt', videoChannel.updated) | ||
130 | |||
131 | await videoChannelInstance.save(sequelizeOptions) | ||
132 | }) | ||
133 | |||
134 | logger.info('Remote video channel with uuid %s updated', videoChannel.uuid) | ||
135 | } | ||