1 import * as express from 'express'
2 import * as Promise from 'bluebird'
4 import { database as db } from '../../../initializers/database'
7 retryTransactionWrapper
8 } from '../../../helpers'
11 REQUEST_VIDEO_EVENT_TYPES,
12 REQUEST_VIDEO_QADU_TYPES
13 } from '../../../initializers'
15 addEventsToRemoteVideo,
16 quickAndDirtyUpdatesVideoToFriends
21 } from '../../../middlewares'
22 import { UserVideoRateUpdate, VideoRateType } from '../../../../shared'
24 const rateVideoRouter = express.Router()
26 rateVideoRouter.put('/:id/rate',
32 // ---------------------------------------------------------------------------
38 // ---------------------------------------------------------------------------
40 function rateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
42 arguments: [ req, res ],
43 errorMessage: 'Cannot update the user video rate.'
46 retryTransactionWrapper(rateVideo, options)
47 .then(() => res.type('json').status(204).end())
48 .catch(err => next(err))
51 function rateVideo (req: express.Request, res: express.Response) {
52 const body: UserVideoRateUpdate = req.body
53 const rateType = body.rating
54 const videoInstance = res.locals.video
55 const userInstance = res.locals.oauth.token.User
57 return db.sequelize.transaction(t => {
58 return db.UserVideoRate.load(userInstance.id, videoInstance.id, t)
59 .then(previousRate => {
60 const options = { transaction: t }
62 let likesToIncrement = 0
63 let dislikesToIncrement = 0
65 if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++
66 else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
68 let promise: Promise<any>
70 // There was a previous rate, update it
72 // We will remove the previous rate, so we will need to update the video count attribute
73 if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
74 else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
76 if (rateType === 'none') { // Destroy previous rate
77 promise = previousRate.destroy()
78 } else { // Update previous rate
79 previousRate.type = rateType as VideoRateType
81 promise = previousRate.save()
83 } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate
85 userId: userInstance.id,
86 videoId: videoInstance.id,
90 promise = db.UserVideoRate.create(query, options)
92 promise = Promise.resolve()
95 return promise.then(() => ({ likesToIncrement, dislikesToIncrement }))
97 .then(({ likesToIncrement, dislikesToIncrement }) => {
98 const options = { transaction: t }
99 const incrementQuery = {
100 likes: likesToIncrement,
101 dislikes: dislikesToIncrement
104 // Even if we do not own the video we increment the attributes
105 // It is usefull for the user to have a feedback
106 return videoInstance.increment(incrementQuery, options).then(() => ({ likesToIncrement, dislikesToIncrement }))
108 .then(({ likesToIncrement, dislikesToIncrement }) => {
109 // No need for an event type, we own the video
110 if (videoInstance.isOwned()) return { likesToIncrement, dislikesToIncrement }
112 const eventsParams = []
114 if (likesToIncrement !== 0) {
116 videoId: videoInstance.id,
117 type: REQUEST_VIDEO_EVENT_TYPES.LIKES,
118 count: likesToIncrement
122 if (dislikesToIncrement !== 0) {
124 videoId: videoInstance.id,
125 type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
126 count: dislikesToIncrement
130 return addEventsToRemoteVideo(eventsParams, t).then(() => ({ likesToIncrement, dislikesToIncrement }))
132 .then(({ likesToIncrement, dislikesToIncrement }) => {
133 // We do not own the video, there is no need to send a quick and dirty update to friends
134 // Our rate was already sent by the addEvent function
135 if (videoInstance.isOwned() === false) return undefined
137 const qadusParams = []
139 if (likesToIncrement !== 0) {
141 videoId: videoInstance.id,
142 type: REQUEST_VIDEO_QADU_TYPES.LIKES
146 if (dislikesToIncrement !== 0) {
148 videoId: videoInstance.id,
149 type: REQUEST_VIDEO_QADU_TYPES.DISLIKES
153 return quickAndDirtyUpdatesVideoToFriends(qadusParams, t)
156 .then(() => logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username))
158 // This is just a debug because we will retry the insert
159 logger.debug('Cannot add the user video rate.', err)