diff options
Diffstat (limited to 'server/controllers/api/videos/rate.js')
-rw-r--r-- | server/controllers/api/videos/rate.js | 169 |
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 | |||
3 | const express = require('express') | ||
4 | const waterfall = require('async/waterfall') | ||
5 | |||
6 | const constants = require('../../../initializers/constants') | ||
7 | const db = require('../../../initializers/database') | ||
8 | const logger = require('../../../helpers/logger') | ||
9 | const friends = require('../../../lib/friends') | ||
10 | const middlewares = require('../../../middlewares') | ||
11 | const oAuth = middlewares.oauth | ||
12 | const validators = middlewares.validators | ||
13 | const validatorsVideos = validators.videos | ||
14 | const databaseUtils = require('../../../helpers/database-utils') | ||
15 | |||
16 | const router = express.Router() | ||
17 | |||
18 | router.put('/:id/rate', | ||
19 | oAuth.authenticate, | ||
20 | validatorsVideos.videoRate, | ||
21 | rateVideoRetryWrapper | ||
22 | ) | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
25 | |||
26 | module.exports = router | ||
27 | |||
28 | // --------------------------------------------------------------------------- | ||
29 | |||
30 | function 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 | |||
43 | function 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 | } | ||