+ await db.sequelize.transaction(async t => {
+ const videoAuthor = await db.Author.loadAuthorByPodAndUUID(authorAttributesToRemove.uuid, fromPod.id, t)
+ await videoAuthor.destroy({ transaction: t })
+ })
+
+ logger.info('Remote video author with uuid %s removed.', authorAttributesToRemove.uuid)
+}
+
+async function addRemoteVideoChannelRetryWrapper (videoChannelToCreateData: RemoteVideoChannelCreateData, fromPod: PodInstance) {
+ const options = {
+ arguments: [ videoChannelToCreateData, fromPod ],
+ errorMessage: 'Cannot insert the remote video channel with many retries.'
+ }
+
+ await retryTransactionWrapper(addRemoteVideoChannel, options)
+}
+
+async function addRemoteVideoChannel (videoChannelToCreateData: RemoteVideoChannelCreateData, fromPod: PodInstance) {
+ logger.debug('Adding remote video channel "%s".', videoChannelToCreateData.uuid)
+
+ await db.sequelize.transaction(async t => {
+ const videoChannelInDatabase = await db.VideoChannel.loadByUUID(videoChannelToCreateData.uuid)
+ if (videoChannelInDatabase) {
+ throw new Error('Video channel with UUID ' + videoChannelToCreateData.uuid + ' already exists.')
+ }
+
+ const authorUUID = videoChannelToCreateData.ownerUUID
+ const podId = fromPod.id
+
+ const author = await db.Author.loadAuthorByPodAndUUID(authorUUID, podId, t)
+ if (!author) throw new Error('Unknown author UUID' + authorUUID + '.')
+
+ const videoChannelData = {
+ name: videoChannelToCreateData.name,
+ description: videoChannelToCreateData.description,
+ uuid: videoChannelToCreateData.uuid,
+ createdAt: videoChannelToCreateData.createdAt,
+ updatedAt: videoChannelToCreateData.updatedAt,
+ remote: true,
+ authorId: author.id
+ }
+
+ const videoChannel = db.VideoChannel.build(videoChannelData)
+ await videoChannel.save({ transaction: t })
+ })
+
+ logger.info('Remote video channel with uuid %s inserted.', videoChannelToCreateData.uuid)
+}
+
+async function updateRemoteVideoChannelRetryWrapper (videoChannelAttributesToUpdate: RemoteVideoChannelUpdateData, fromPod: PodInstance) {
+ const options = {
+ arguments: [ videoChannelAttributesToUpdate, fromPod ],
+ errorMessage: 'Cannot update the remote video channel with many retries.'
+ }
+
+ await retryTransactionWrapper(updateRemoteVideoChannel, options)
+}
+
+async function updateRemoteVideoChannel (videoChannelAttributesToUpdate: RemoteVideoChannelUpdateData, fromPod: PodInstance) {
+ logger.debug('Updating remote video channel "%s".', videoChannelAttributesToUpdate.uuid)
+
+ await db.sequelize.transaction(async t => {
+ const sequelizeOptions = { transaction: t }
+
+ const videoChannelInstance = await fetchVideoChannelByHostAndUUID(fromPod.host, videoChannelAttributesToUpdate.uuid, t)
+ videoChannelInstance.set('name', videoChannelAttributesToUpdate.name)
+ videoChannelInstance.set('description', videoChannelAttributesToUpdate.description)
+ videoChannelInstance.set('createdAt', videoChannelAttributesToUpdate.createdAt)
+ videoChannelInstance.set('updatedAt', videoChannelAttributesToUpdate.updatedAt)
+
+ await videoChannelInstance.save(sequelizeOptions)
+ })
+
+ logger.info('Remote video channel with uuid %s updated', videoChannelAttributesToUpdate.uuid)
+}
+
+async function removeRemoteVideoChannelRetryWrapper (videoChannelAttributesToRemove: RemoteVideoChannelRemoveData, fromPod: PodInstance) {
+ const options = {
+ arguments: [ videoChannelAttributesToRemove, fromPod ],
+ errorMessage: 'Cannot remove the remote video channel with many retries.'
+ }
+
+ await retryTransactionWrapper(removeRemoteVideoChannel, options)
+}
+
+async function removeRemoteVideoChannel (videoChannelAttributesToRemove: RemoteVideoChannelRemoveData, fromPod: PodInstance) {
+ logger.debug('Removing remote video channel "%s".', videoChannelAttributesToRemove.uuid)
+
+ await db.sequelize.transaction(async t => {
+ const videoChannel = await fetchVideoChannelByHostAndUUID(fromPod.host, videoChannelAttributesToRemove.uuid, t)
+ await videoChannel.destroy({ transaction: t })
+ })
+
+ logger.info('Remote video channel with uuid %s removed.', videoChannelAttributesToRemove.uuid)
+}
+
+async function reportAbuseRemoteVideoRetryWrapper (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
+ const options = {
+ arguments: [ reportData, fromPod ],
+ errorMessage: 'Cannot create remote abuse video with many retries.'
+ }
+
+ await retryTransactionWrapper(reportAbuseRemoteVideo, options)
+}
+
+async function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
+ logger.debug('Reporting remote abuse for video %s.', reportData.videoUUID)
+
+ await db.sequelize.transaction(async t => {
+ const videoInstance = await fetchLocalVideoByUUID(reportData.videoUUID, t)
+ const videoAbuseData = {
+ reporterUsername: reportData.reporterUsername,
+ reason: reportData.reportReason,
+ reporterPodId: fromPod.id,
+ videoId: videoInstance.id
+ }
+
+ await db.VideoAbuse.create(videoAbuseData)
+
+ })
+
+ logger.info('Remote abuse for video uuid %s created', reportData.videoUUID)
+}
+
+async function fetchLocalVideoByUUID (id: string, t: Sequelize.Transaction) {
+ try {
+ const video = await db.Video.loadLocalVideoByUUID(id, t)
+
+ if (!video) throw new Error('Video ' + id + ' not found')
+
+ return video
+ } catch (err) {
+ logger.error('Cannot load owned video from id.', { error: err.stack, id })
+ throw err
+ }
+}
+
+async function fetchVideoByHostAndUUID (podHost: string, uuid: string, t: Sequelize.Transaction) {
+ try {
+ const video = await db.Video.loadByHostAndUUID(podHost, uuid, t)
+ if (!video) throw new Error('Video not found')
+
+ return video
+ } catch (err) {
+ logger.error('Cannot load video from host and uuid.', { error: err.stack, podHost, uuid })
+ throw err
+ }