X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fcontrollers%2Fapi%2Fvideos%2Frate.ts;h=6b26a8eee68b662f7a21d331cbcd59e2a66343a9;hb=44e702ded455c118f9908b70d25e7c7e5512abe9;hp=1bc575675ae93bb2ff6e1056b97f5b069a062e58;hpb=4d4e5cd4dca78480ec7f40e747f424cd107376a4;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts index 1bc575675..6b26a8eee 100644 --- a/server/controllers/api/videos/rate.ts +++ b/server/controllers/api/videos/rate.ts @@ -1,34 +1,19 @@ -import * as express from 'express' -import { waterfall } from 'async' - -import { database as db } from '../../../initializers/database' -import { - logger, - retryTransactionWrapper, - startSerializableTransaction, - commitTransaction, - rollbackTransaction -} from '../../../helpers' -import { - VIDEO_RATE_TYPES, - REQUEST_VIDEO_EVENT_TYPES, - REQUEST_VIDEO_QADU_TYPES -} from '../../../initializers' -import { - addEventsToRemoteVideo, - quickAndDirtyUpdatesVideoToFriends -} from '../../../lib' -import { - authenticate, - videoRateValidator -} from '../../../middlewares' +import express from 'express' +import { HttpStatusCode, UserVideoRateUpdate } from '@shared/models' +import { logger } from '../../../helpers/logger' +import { VIDEO_RATE_TYPES } from '../../../initializers/constants' +import { sequelizeTypescript } from '../../../initializers/database' +import { getLocalRateUrl, sendVideoRateChange } from '../../../lib/activitypub/video-rates' +import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoUpdateRateValidator } from '../../../middlewares' +import { AccountModel } from '../../../models/account/account' +import { AccountVideoRateModel } from '../../../models/account/account-video-rate' const rateVideoRouter = express.Router() rateVideoRouter.put('/:id/rate', authenticate, - videoRateValidator, - rateVideoRetryWrapper + asyncMiddleware(videoUpdateRateValidator), + asyncRetryTransactionMiddleware(rateVideo) ) // --------------------------------------------------------------------------- @@ -39,143 +24,64 @@ export { // --------------------------------------------------------------------------- -function rateVideoRetryWrapper (req, res, next) { - const options = { - arguments: [ req, res ], - errorMessage: 'Cannot update the user video rate.' - } - - retryTransactionWrapper(rateVideo, options, function (err) { - if (err) return next(err) - - return res.type('json').status(204).end() - }) -} - -function rateVideo (req, res, finalCallback) { - const rateType = req.body.rating - const videoInstance = res.locals.video - const userInstance = res.locals.oauth.token.User +async function rateVideo (req: express.Request, res: express.Response) { + const body: UserVideoRateUpdate = req.body + const rateType = body.rating + const videoInstance = res.locals.videoAll + const userAccount = res.locals.oauth.token.User.Account - waterfall([ - startSerializableTransaction, + await sequelizeTypescript.transaction(async t => { + const sequelizeOptions = { transaction: t } - function findPreviousRate (t, callback) { - db.UserVideoRate.load(userInstance.id, videoInstance.id, t, function (err, previousRate) { - return callback(err, t, previousRate) - }) - }, + const accountInstance = await AccountModel.load(userAccount.id, t) + const previousRate = await AccountVideoRateModel.load(accountInstance.id, videoInstance.id, t) - function insertUserRateIntoDB (t, previousRate, callback) { - const options = { transaction: t } + // Same rate, nothing do to + if (rateType === 'none' && !previousRate || previousRate?.type === rateType) return - let likesToIncrement = 0 - let dislikesToIncrement = 0 + let likesToIncrement = 0 + let dislikesToIncrement = 0 - if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ - else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ + if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ + else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ - // There was a previous rate, update it - if (previousRate) { - // We will remove the previous rate, so we will need to remove it from the video attribute - if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement-- - else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- + // There was a previous rate, update it + if (previousRate) { + // We will remove the previous rate, so we will need to update the video count attribute + if (previousRate.type === 'like') likesToIncrement-- + else if (previousRate.type === 'dislike') dislikesToIncrement-- + if (rateType === 'none') { // Destroy previous rate + await previousRate.destroy(sequelizeOptions) + } else { // Update previous rate previousRate.type = rateType - - previousRate.save(options).asCallback(function (err) { - return callback(err, t, likesToIncrement, dislikesToIncrement) - }) - } else { // There was not a previous rate, insert a new one - const query = { - userId: userInstance.id, - videoId: videoInstance.id, - type: rateType - } - - db.UserVideoRate.create(query, options).asCallback(function (err) { - return callback(err, t, likesToIncrement, dislikesToIncrement) - }) - } - }, - - function updateVideoAttributeDB (t, likesToIncrement, dislikesToIncrement, callback) { - const options = { transaction: t } - const incrementQuery = { - likes: likesToIncrement, - dislikes: dislikesToIncrement - } - - // Even if we do not own the video we increment the attributes - // It is usefull for the user to have a feedback - videoInstance.increment(incrementQuery, options).asCallback(function (err) { - return callback(err, t, likesToIncrement, dislikesToIncrement) - }) - }, - - function sendEventsToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) { - // No need for an event type, we own the video - if (videoInstance.isOwned()) return callback(null, t, likesToIncrement, dislikesToIncrement) - - const eventsParams = [] - - if (likesToIncrement !== 0) { - eventsParams.push({ - videoId: videoInstance.id, - type: REQUEST_VIDEO_EVENT_TYPES.LIKES, - count: likesToIncrement - }) + previousRate.url = getLocalRateUrl(rateType, userAccount.Actor, videoInstance) + await previousRate.save(sequelizeOptions) } - - if (dislikesToIncrement !== 0) { - eventsParams.push({ - videoId: videoInstance.id, - type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES, - count: dislikesToIncrement - }) - } - - addEventsToRemoteVideo(eventsParams, t, function (err) { - return callback(err, t, likesToIncrement, dislikesToIncrement) - }) - }, - - function sendQaduToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) { - // We do not own the video, there is no need to send a quick and dirty update to friends - // Our rate was already sent by the addEvent function - if (videoInstance.isOwned() === false) return callback(null, t) - - const qadusParams = [] - - if (likesToIncrement !== 0) { - qadusParams.push({ - videoId: videoInstance.id, - type: REQUEST_VIDEO_QADU_TYPES.LIKES - }) + } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate + const query = { + accountId: accountInstance.id, + videoId: videoInstance.id, + type: rateType, + url: getLocalRateUrl(rateType, userAccount.Actor, videoInstance) } - if (dislikesToIncrement !== 0) { - qadusParams.push({ - videoId: videoInstance.id, - type: REQUEST_VIDEO_QADU_TYPES.DISLIKES - }) - } + await AccountVideoRateModel.create(query, sequelizeOptions) + } - quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) { - return callback(err, t) - }) - }, + const incrementQuery = { + likes: likesToIncrement, + dislikes: dislikesToIncrement + } - commitTransaction + await videoInstance.increment(incrementQuery, sequelizeOptions) - ], function (err, t) { - if (err) { - // This is just a debug because we will retry the insert - logger.debug('Cannot add the user video rate.', { error: err }) - return rollbackTransaction(err, t, finalCallback) - } + await sendVideoRateChange(accountInstance, videoInstance, likesToIncrement, dislikesToIncrement, t) - logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username) - return finalCallback(null) + logger.info('Account video rate for video %s of account %s updated.', videoInstance.name, accountInstance.name) }) + + return res.type('json') + .status(HttpStatusCode.NO_CONTENT_204) + .end() }