+async function updateVideoFromAP (
+ video: VideoModel,
+ videoObject: VideoTorrentObject,
+ account: AccountModel,
+ channel: VideoChannelModel,
+ overrideTo?: string[]
+) {
+ logger.debug('Updating remote video "%s".', videoObject.uuid)
+ let videoFieldsSave: any
+
+ try {
+ const updatedVideo: VideoModel = await sequelizeTypescript.transaction(async t => {
+ const sequelizeOptions = {
+ transaction: t
+ }
+
+ videoFieldsSave = video.toJSON()
+
+ // Check actor has the right to update the video
+ const videoChannel = video.VideoChannel
+ if (videoChannel.Account.id !== account.id) {
+ throw new Error('Account ' + account.Actor.url + ' does not own video channel ' + videoChannel.Actor.url)
+ }
+
+ const to = overrideTo ? overrideTo : videoObject.to
+ const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, to)
+ video.set('name', videoData.name)
+ video.set('uuid', videoData.uuid)
+ video.set('url', videoData.url)
+ video.set('category', videoData.category)
+ video.set('licence', videoData.licence)
+ video.set('language', videoData.language)
+ video.set('description', videoData.description)
+ video.set('support', videoData.support)
+ video.set('nsfw', videoData.nsfw)
+ video.set('commentsEnabled', videoData.commentsEnabled)
+ video.set('waitTranscoding', videoData.waitTranscoding)
+ video.set('state', videoData.state)
+ video.set('duration', videoData.duration)
+ video.set('createdAt', videoData.createdAt)
+ video.set('publishedAt', videoData.publishedAt)
+ video.set('views', videoData.views)
+ video.set('privacy', videoData.privacy)
+ video.set('channelId', videoData.channelId)
+
+ await video.save(sequelizeOptions)
+
+ // Don't block on request
+ generateThumbnailFromUrl(video, videoObject.icon)
+ .catch(err => logger.warn('Cannot generate thumbnail of %s.', videoObject.id, { err }))
+
+ // Remove old video files
+ const videoFileDestroyTasks: Bluebird<void>[] = []
+ for (const videoFile of video.VideoFiles) {
+ videoFileDestroyTasks.push(videoFile.destroy(sequelizeOptions))
+ }
+ await Promise.all(videoFileDestroyTasks)
+
+ const videoFileAttributes = videoFileActivityUrlToDBAttributes(video, videoObject)
+ const tasks = videoFileAttributes.map(f => VideoFileModel.create(f, sequelizeOptions))
+ await Promise.all(tasks)
+
+ // Update Tags
+ const tags = videoObject.tag.map(tag => tag.name)
+ const tagInstances = await TagModel.findOrCreateTags(tags, t)
+ await video.$set('Tags', tagInstances, sequelizeOptions)
+
+ // Update captions
+ await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(video.id, t)
+
+ const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => {
+ return VideoCaptionModel.insertOrReplaceLanguage(video.id, c.identifier, t)
+ })
+ await Promise.all(videoCaptionsPromises)
+ })
+
+ logger.info('Remote video with uuid %s updated', videoObject.uuid)
+
+ return updatedVideo
+ } catch (err) {
+ if (video !== undefined && videoFieldsSave !== undefined) {
+ resetSequelizeInstance(video, videoFieldsSave)
+ }
+
+ // This is just a debug because we will retry the insert
+ logger.debug('Cannot update the remote video.', { err })
+ throw err
+ }