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