diff options
Diffstat (limited to 'server/lib/activitypub/videos.ts')
-rw-r--r-- | server/lib/activitypub/videos.ts | 113 |
1 files changed, 57 insertions, 56 deletions
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 4cecf9345..998f90330 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -117,7 +117,7 @@ type SyncParam = { | |||
117 | shares: boolean | 117 | shares: boolean |
118 | comments: boolean | 118 | comments: boolean |
119 | thumbnail: boolean | 119 | thumbnail: boolean |
120 | refreshVideo: boolean | 120 | refreshVideo?: boolean |
121 | } | 121 | } |
122 | async function syncVideoExternalAttributes (video: VideoModel, fetchedVideo: VideoTorrentObject, syncParam: SyncParam) { | 122 | async function syncVideoExternalAttributes (video: VideoModel, fetchedVideo: VideoTorrentObject, syncParam: SyncParam) { |
123 | logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid) | 123 | logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid) |
@@ -158,13 +158,11 @@ async function syncVideoExternalAttributes (video: VideoModel, fetchedVideo: Vid | |||
158 | async function getOrCreateVideoAndAccountAndChannel (options: { | 158 | async function getOrCreateVideoAndAccountAndChannel (options: { |
159 | videoObject: VideoTorrentObject | string, | 159 | videoObject: VideoTorrentObject | string, |
160 | syncParam?: SyncParam, | 160 | syncParam?: SyncParam, |
161 | fetchType?: VideoFetchByUrlType, | 161 | fetchType?: VideoFetchByUrlType |
162 | refreshViews?: boolean | ||
163 | }) { | 162 | }) { |
164 | // Default params | 163 | // Default params |
165 | const syncParam = options.syncParam || { likes: true, dislikes: true, shares: true, comments: true, thumbnail: true, refreshVideo: false } | 164 | const syncParam = options.syncParam || { likes: true, dislikes: true, shares: true, comments: true, thumbnail: true, refreshVideo: false } |
166 | const fetchType = options.fetchType || 'all' | 165 | const fetchType = options.fetchType || 'all' |
167 | const refreshViews = options.refreshViews || false | ||
168 | 166 | ||
169 | // Get video url | 167 | // Get video url |
170 | const videoUrl = getAPUrl(options.videoObject) | 168 | const videoUrl = getAPUrl(options.videoObject) |
@@ -174,11 +172,11 @@ async function getOrCreateVideoAndAccountAndChannel (options: { | |||
174 | const refreshOptions = { | 172 | const refreshOptions = { |
175 | video: videoFromDatabase, | 173 | video: videoFromDatabase, |
176 | fetchedType: fetchType, | 174 | fetchedType: fetchType, |
177 | syncParam, | 175 | syncParam |
178 | refreshViews | ||
179 | } | 176 | } |
180 | const p = refreshVideoIfNeeded(refreshOptions) | 177 | |
181 | if (syncParam.refreshVideo === true) videoFromDatabase = await p | 178 | if (syncParam.refreshVideo === true) videoFromDatabase = await refreshVideoIfNeeded(refreshOptions) |
179 | else await JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', videoUrl: videoFromDatabase.url } }) | ||
182 | 180 | ||
183 | return { video: videoFromDatabase } | 181 | return { video: videoFromDatabase } |
184 | } | 182 | } |
@@ -199,7 +197,6 @@ async function updateVideoFromAP (options: { | |||
199 | videoObject: VideoTorrentObject, | 197 | videoObject: VideoTorrentObject, |
200 | account: AccountModel, | 198 | account: AccountModel, |
201 | channel: VideoChannelModel, | 199 | channel: VideoChannelModel, |
202 | updateViews: boolean, | ||
203 | overrideTo?: string[] | 200 | overrideTo?: string[] |
204 | }) { | 201 | }) { |
205 | logger.debug('Updating remote video "%s".', options.videoObject.uuid) | 202 | logger.debug('Updating remote video "%s".', options.videoObject.uuid) |
@@ -238,8 +235,8 @@ async function updateVideoFromAP (options: { | |||
238 | options.video.set('publishedAt', videoData.publishedAt) | 235 | options.video.set('publishedAt', videoData.publishedAt) |
239 | options.video.set('privacy', videoData.privacy) | 236 | options.video.set('privacy', videoData.privacy) |
240 | options.video.set('channelId', videoData.channelId) | 237 | options.video.set('channelId', videoData.channelId) |
238 | options.video.set('views', videoData.views) | ||
241 | 239 | ||
242 | if (options.updateViews === true) options.video.set('views', videoData.views) | ||
243 | await options.video.save(sequelizeOptions) | 240 | await options.video.save(sequelizeOptions) |
244 | 241 | ||
245 | { | 242 | { |
@@ -297,8 +294,58 @@ async function updateVideoFromAP (options: { | |||
297 | } | 294 | } |
298 | } | 295 | } |
299 | 296 | ||
297 | async function refreshVideoIfNeeded (options: { | ||
298 | video: VideoModel, | ||
299 | fetchedType: VideoFetchByUrlType, | ||
300 | syncParam: SyncParam | ||
301 | }): Promise<VideoModel> { | ||
302 | if (!options.video.isOutdated()) return options.video | ||
303 | |||
304 | // We need more attributes if the argument video was fetched with not enough joints | ||
305 | const video = options.fetchedType === 'all' ? options.video : await VideoModel.loadByUrlAndPopulateAccount(options.video.url) | ||
306 | |||
307 | try { | ||
308 | const { response, videoObject } = await fetchRemoteVideo(video.url) | ||
309 | if (response.statusCode === 404) { | ||
310 | logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url) | ||
311 | |||
312 | // Video does not exist anymore | ||
313 | await video.destroy() | ||
314 | return undefined | ||
315 | } | ||
316 | |||
317 | if (videoObject === undefined) { | ||
318 | logger.warn('Cannot refresh remote video %s: invalid body.', video.url) | ||
319 | |||
320 | await video.setAsRefreshed() | ||
321 | return video | ||
322 | } | ||
323 | |||
324 | const channelActor = await getOrCreateVideoChannelFromVideoObject(videoObject) | ||
325 | const account = await AccountModel.load(channelActor.VideoChannel.accountId) | ||
326 | |||
327 | const updateOptions = { | ||
328 | video, | ||
329 | videoObject, | ||
330 | account, | ||
331 | channel: channelActor.VideoChannel | ||
332 | } | ||
333 | await retryTransactionWrapper(updateVideoFromAP, updateOptions) | ||
334 | await syncVideoExternalAttributes(video, videoObject, options.syncParam) | ||
335 | |||
336 | return video | ||
337 | } catch (err) { | ||
338 | logger.warn('Cannot refresh video %s.', options.video.url, { err }) | ||
339 | |||
340 | // Don't refresh in loop | ||
341 | await video.setAsRefreshed() | ||
342 | return video | ||
343 | } | ||
344 | } | ||
345 | |||
300 | export { | 346 | export { |
301 | updateVideoFromAP, | 347 | updateVideoFromAP, |
348 | refreshVideoIfNeeded, | ||
302 | federateVideoIfNeeded, | 349 | federateVideoIfNeeded, |
303 | fetchRemoteVideo, | 350 | fetchRemoteVideo, |
304 | getOrCreateVideoAndAccountAndChannel, | 351 | getOrCreateVideoAndAccountAndChannel, |
@@ -362,52 +409,6 @@ async function createVideo (videoObject: VideoTorrentObject, channelActor: Actor | |||
362 | return videoCreated | 409 | return videoCreated |
363 | } | 410 | } |
364 | 411 | ||
365 | async function refreshVideoIfNeeded (options: { | ||
366 | video: VideoModel, | ||
367 | fetchedType: VideoFetchByUrlType, | ||
368 | syncParam: SyncParam, | ||
369 | refreshViews: boolean | ||
370 | }): Promise<VideoModel> { | ||
371 | if (!options.video.isOutdated()) return options.video | ||
372 | |||
373 | // We need more attributes if the argument video was fetched with not enough joints | ||
374 | const video = options.fetchedType === 'all' ? options.video : await VideoModel.loadByUrlAndPopulateAccount(options.video.url) | ||
375 | |||
376 | try { | ||
377 | const { response, videoObject } = await fetchRemoteVideo(video.url) | ||
378 | if (response.statusCode === 404) { | ||
379 | logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url) | ||
380 | |||
381 | // Video does not exist anymore | ||
382 | await video.destroy() | ||
383 | return undefined | ||
384 | } | ||
385 | |||
386 | if (videoObject === undefined) { | ||
387 | logger.warn('Cannot refresh remote video %s: invalid body.', video.url) | ||
388 | return video | ||
389 | } | ||
390 | |||
391 | const channelActor = await getOrCreateVideoChannelFromVideoObject(videoObject) | ||
392 | const account = await AccountModel.load(channelActor.VideoChannel.accountId) | ||
393 | |||
394 | const updateOptions = { | ||
395 | video, | ||
396 | videoObject, | ||
397 | account, | ||
398 | channel: channelActor.VideoChannel, | ||
399 | updateViews: options.refreshViews | ||
400 | } | ||
401 | await retryTransactionWrapper(updateVideoFromAP, updateOptions) | ||
402 | await syncVideoExternalAttributes(video, videoObject, options.syncParam) | ||
403 | |||
404 | return video | ||
405 | } catch (err) { | ||
406 | logger.warn('Cannot refresh video %s.', options.video.url, { err }) | ||
407 | return video | ||
408 | } | ||
409 | } | ||
410 | |||
411 | async function videoActivityObjectToDBAttributes ( | 412 | async function videoActivityObjectToDBAttributes ( |
412 | videoChannel: VideoChannelModel, | 413 | videoChannel: VideoChannelModel, |
413 | videoObject: VideoTorrentObject, | 414 | videoObject: VideoTorrentObject, |