aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api/videos/rate.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api/videos/rate.js')
-rw-r--r--server/controllers/api/videos/rate.js169
1 files changed, 169 insertions, 0 deletions
diff --git a/server/controllers/api/videos/rate.js b/server/controllers/api/videos/rate.js
new file mode 100644
index 000000000..df8a69a1d
--- /dev/null
+++ b/server/controllers/api/videos/rate.js
@@ -0,0 +1,169 @@
1'use strict'
2
3const express = require('express')
4const waterfall = require('async/waterfall')
5
6const constants = require('../../../initializers/constants')
7const db = require('../../../initializers/database')
8const logger = require('../../../helpers/logger')
9const friends = require('../../../lib/friends')
10const middlewares = require('../../../middlewares')
11const oAuth = middlewares.oauth
12const validators = middlewares.validators
13const validatorsVideos = validators.videos
14const databaseUtils = require('../../../helpers/database-utils')
15
16const router = express.Router()
17
18router.put('/:id/rate',
19 oAuth.authenticate,
20 validatorsVideos.videoRate,
21 rateVideoRetryWrapper
22)
23
24// ---------------------------------------------------------------------------
25
26module.exports = router
27
28// ---------------------------------------------------------------------------
29
30function rateVideoRetryWrapper (req, res, next) {
31 const options = {
32 arguments: [ req, res ],
33 errorMessage: 'Cannot update the user video rate.'
34 }
35
36 databaseUtils.retryTransactionWrapper(rateVideo, options, function (err) {
37 if (err) return next(err)
38
39 return res.type('json').status(204).end()
40 })
41}
42
43function rateVideo (req, res, finalCallback) {
44 const rateType = req.body.rating
45 const videoInstance = res.locals.video
46 const userInstance = res.locals.oauth.token.User
47
48 waterfall([
49 databaseUtils.startSerializableTransaction,
50
51 function findPreviousRate (t, callback) {
52 db.UserVideoRate.load(userInstance.id, videoInstance.id, t, function (err, previousRate) {
53 return callback(err, t, previousRate)
54 })
55 },
56
57 function insertUserRateIntoDB (t, previousRate, callback) {
58 const options = { transaction: t }
59
60 let likesToIncrement = 0
61 let dislikesToIncrement = 0
62
63 if (rateType === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement++
64 else if (rateType === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
65
66 // There was a previous rate, update it
67 if (previousRate) {
68 // We will remove the previous rate, so we will need to remove it from the video attribute
69 if (previousRate.type === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement--
70 else if (previousRate.type === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
71
72 previousRate.type = rateType
73
74 previousRate.save(options).asCallback(function (err) {
75 return callback(err, t, likesToIncrement, dislikesToIncrement)
76 })
77 } else { // There was not a previous rate, insert a new one
78 const query = {
79 userId: userInstance.id,
80 videoId: videoInstance.id,
81 type: rateType
82 }
83
84 db.UserVideoRate.create(query, options).asCallback(function (err) {
85 return callback(err, t, likesToIncrement, dislikesToIncrement)
86 })
87 }
88 },
89
90 function updateVideoAttributeDB (t, likesToIncrement, dislikesToIncrement, callback) {
91 const options = { transaction: t }
92 const incrementQuery = {
93 likes: likesToIncrement,
94 dislikes: dislikesToIncrement
95 }
96
97 // Even if we do not own the video we increment the attributes
98 // It is usefull for the user to have a feedback
99 videoInstance.increment(incrementQuery, options).asCallback(function (err) {
100 return callback(err, t, likesToIncrement, dislikesToIncrement)
101 })
102 },
103
104 function sendEventsToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) {
105 // No need for an event type, we own the video
106 if (videoInstance.isOwned()) return callback(null, t, likesToIncrement, dislikesToIncrement)
107
108 const eventsParams = []
109
110 if (likesToIncrement !== 0) {
111 eventsParams.push({
112 videoId: videoInstance.id,
113 type: constants.REQUEST_VIDEO_EVENT_TYPES.LIKES,
114 count: likesToIncrement
115 })
116 }
117
118 if (dislikesToIncrement !== 0) {
119 eventsParams.push({
120 videoId: videoInstance.id,
121 type: constants.REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
122 count: dislikesToIncrement
123 })
124 }
125
126 friends.addEventsToRemoteVideo(eventsParams, t, function (err) {
127 return callback(err, t, likesToIncrement, dislikesToIncrement)
128 })
129 },
130
131 function sendQaduToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) {
132 // We do not own the video, there is no need to send a quick and dirty update to friends
133 // Our rate was already sent by the addEvent function
134 if (videoInstance.isOwned() === false) return callback(null, t)
135
136 const qadusParams = []
137
138 if (likesToIncrement !== 0) {
139 qadusParams.push({
140 videoId: videoInstance.id,
141 type: constants.REQUEST_VIDEO_QADU_TYPES.LIKES
142 })
143 }
144
145 if (dislikesToIncrement !== 0) {
146 qadusParams.push({
147 videoId: videoInstance.id,
148 type: constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES
149 })
150 }
151
152 friends.quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
153 return callback(err, t)
154 })
155 },
156
157 databaseUtils.commitTransaction
158
159 ], function (err, t) {
160 if (err) {
161 // This is just a debug because we will retry the insert
162 logger.debug('Cannot add the user video rate.', { error: err })
163 return databaseUtils.rollbackTransaction(err, t, finalCallback)
164 }
165
166 logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username)
167 return finalCallback(null)
168 })
169}