diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-05-05 16:53:35 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-05-05 16:53:35 +0200 |
commit | d33242b047c68ae81c9657d05893d1838f1b1c89 (patch) | |
tree | 8c15535da8097b1ac3488d5b970e5aa69a035e4a /server/controllers | |
parent | 1f0215a908c3b447cef03c10d4b089c0788922bd (diff) | |
download | PeerTube-d33242b047c68ae81c9657d05893d1838f1b1c89.tar.gz PeerTube-d33242b047c68ae81c9657d05893d1838f1b1c89.tar.zst PeerTube-d33242b047c68ae81c9657d05893d1838f1b1c89.zip |
Server: split videos controller
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/api/videos/abuse.js | 112 | ||||
-rw-r--r-- | server/controllers/api/videos/blacklist.js | 43 | ||||
-rw-r--r-- | server/controllers/api/videos/index.js (renamed from server/controllers/api/videos.js) | 279 | ||||
-rw-r--r-- | server/controllers/api/videos/rate.js | 169 |
4 files changed, 339 insertions, 264 deletions
diff --git a/server/controllers/api/videos/abuse.js b/server/controllers/api/videos/abuse.js new file mode 100644 index 000000000..0fb44bb14 --- /dev/null +++ b/server/controllers/api/videos/abuse.js | |||
@@ -0,0 +1,112 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const express = require('express') | ||
4 | const waterfall = require('async/waterfall') | ||
5 | |||
6 | const db = require('../../../initializers/database') | ||
7 | const logger = require('../../../helpers/logger') | ||
8 | const friends = require('../../../lib/friends') | ||
9 | const middlewares = require('../../../middlewares') | ||
10 | const admin = middlewares.admin | ||
11 | const oAuth = middlewares.oauth | ||
12 | const pagination = middlewares.pagination | ||
13 | const validators = middlewares.validators | ||
14 | const validatorsPagination = validators.pagination | ||
15 | const validatorsSort = validators.sort | ||
16 | const validatorsVideos = validators.videos | ||
17 | const sort = middlewares.sort | ||
18 | const databaseUtils = require('../../../helpers/database-utils') | ||
19 | const utils = require('../../../helpers/utils') | ||
20 | |||
21 | const router = express.Router() | ||
22 | |||
23 | router.get('/abuse', | ||
24 | oAuth.authenticate, | ||
25 | admin.ensureIsAdmin, | ||
26 | validatorsPagination.pagination, | ||
27 | validatorsSort.videoAbusesSort, | ||
28 | sort.setVideoAbusesSort, | ||
29 | pagination.setPagination, | ||
30 | listVideoAbuses | ||
31 | ) | ||
32 | router.post('/:id/abuse', | ||
33 | oAuth.authenticate, | ||
34 | validatorsVideos.videoAbuseReport, | ||
35 | reportVideoAbuseRetryWrapper | ||
36 | ) | ||
37 | |||
38 | // --------------------------------------------------------------------------- | ||
39 | |||
40 | module.exports = router | ||
41 | |||
42 | // --------------------------------------------------------------------------- | ||
43 | |||
44 | function listVideoAbuses (req, res, next) { | ||
45 | db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) { | ||
46 | if (err) return next(err) | ||
47 | |||
48 | res.json(utils.getFormatedObjects(abusesList, abusesTotal)) | ||
49 | }) | ||
50 | } | ||
51 | |||
52 | function reportVideoAbuseRetryWrapper (req, res, next) { | ||
53 | const options = { | ||
54 | arguments: [ req, res ], | ||
55 | errorMessage: 'Cannot report abuse to the video with many retries.' | ||
56 | } | ||
57 | |||
58 | databaseUtils.retryTransactionWrapper(reportVideoAbuse, options, function (err) { | ||
59 | if (err) return next(err) | ||
60 | |||
61 | return res.type('json').status(204).end() | ||
62 | }) | ||
63 | } | ||
64 | |||
65 | function reportVideoAbuse (req, res, finalCallback) { | ||
66 | const videoInstance = res.locals.video | ||
67 | const reporterUsername = res.locals.oauth.token.User.username | ||
68 | |||
69 | const abuse = { | ||
70 | reporterUsername, | ||
71 | reason: req.body.reason, | ||
72 | videoId: videoInstance.id, | ||
73 | reporterPodId: null // This is our pod that reported this abuse | ||
74 | } | ||
75 | |||
76 | waterfall([ | ||
77 | |||
78 | databaseUtils.startSerializableTransaction, | ||
79 | |||
80 | function createAbuse (t, callback) { | ||
81 | db.VideoAbuse.create(abuse).asCallback(function (err, abuse) { | ||
82 | return callback(err, t, abuse) | ||
83 | }) | ||
84 | }, | ||
85 | |||
86 | function sendToFriendsIfNeeded (t, abuse, callback) { | ||
87 | // We send the information to the destination pod | ||
88 | if (videoInstance.isOwned() === false) { | ||
89 | const reportData = { | ||
90 | reporterUsername, | ||
91 | reportReason: abuse.reason, | ||
92 | videoRemoteId: videoInstance.remoteId | ||
93 | } | ||
94 | |||
95 | friends.reportAbuseVideoToFriend(reportData, videoInstance) | ||
96 | } | ||
97 | |||
98 | return callback(null, t) | ||
99 | }, | ||
100 | |||
101 | databaseUtils.commitTransaction | ||
102 | |||
103 | ], function andFinally (err, t) { | ||
104 | if (err) { | ||
105 | logger.debug('Cannot update the video.', { error: err }) | ||
106 | return databaseUtils.rollbackTransaction(err, t, finalCallback) | ||
107 | } | ||
108 | |||
109 | logger.info('Abuse report for video %s created.', videoInstance.name) | ||
110 | return finalCallback(null) | ||
111 | }) | ||
112 | } | ||
diff --git a/server/controllers/api/videos/blacklist.js b/server/controllers/api/videos/blacklist.js new file mode 100644 index 000000000..8c3e2a69d --- /dev/null +++ b/server/controllers/api/videos/blacklist.js | |||
@@ -0,0 +1,43 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const express = require('express') | ||
4 | |||
5 | const db = require('../../../initializers/database') | ||
6 | const logger = require('../../../helpers/logger') | ||
7 | const middlewares = require('../../../middlewares') | ||
8 | const admin = middlewares.admin | ||
9 | const oAuth = middlewares.oauth | ||
10 | const validators = middlewares.validators | ||
11 | const validatorsVideos = validators.videos | ||
12 | |||
13 | const router = express.Router() | ||
14 | |||
15 | router.post('/:id/blacklist', | ||
16 | oAuth.authenticate, | ||
17 | admin.ensureIsAdmin, | ||
18 | validatorsVideos.videosBlacklist, | ||
19 | addVideoToBlacklist | ||
20 | ) | ||
21 | |||
22 | // --------------------------------------------------------------------------- | ||
23 | |||
24 | module.exports = router | ||
25 | |||
26 | // --------------------------------------------------------------------------- | ||
27 | |||
28 | function addVideoToBlacklist (req, res, next) { | ||
29 | const videoInstance = res.locals.video | ||
30 | |||
31 | const toCreate = { | ||
32 | videoId: videoInstance.id | ||
33 | } | ||
34 | |||
35 | db.BlacklistedVideo.create(toCreate).asCallback(function (err) { | ||
36 | if (err) { | ||
37 | logger.error('Errors when blacklisting video ', { error: err }) | ||
38 | return next(err) | ||
39 | } | ||
40 | |||
41 | return res.type('json').status(204).end() | ||
42 | }) | ||
43 | } | ||
diff --git a/server/controllers/api/videos.js b/server/controllers/api/videos/index.js index aeefaa555..8de44d5ac 100644 --- a/server/controllers/api/videos.js +++ b/server/controllers/api/videos/index.js | |||
@@ -6,12 +6,11 @@ const multer = require('multer') | |||
6 | const path = require('path') | 6 | const path = require('path') |
7 | const waterfall = require('async/waterfall') | 7 | const waterfall = require('async/waterfall') |
8 | 8 | ||
9 | const constants = require('../../initializers/constants') | 9 | const constants = require('../../../initializers/constants') |
10 | const db = require('../../initializers/database') | 10 | const db = require('../../../initializers/database') |
11 | const logger = require('../../helpers/logger') | 11 | const logger = require('../../../helpers/logger') |
12 | const friends = require('../../lib/friends') | 12 | const friends = require('../../../lib/friends') |
13 | const middlewares = require('../../middlewares') | 13 | const middlewares = require('../../../middlewares') |
14 | const admin = middlewares.admin | ||
15 | const oAuth = middlewares.oauth | 14 | const oAuth = middlewares.oauth |
16 | const pagination = middlewares.pagination | 15 | const pagination = middlewares.pagination |
17 | const validators = middlewares.validators | 16 | const validators = middlewares.validators |
@@ -20,8 +19,12 @@ const validatorsSort = validators.sort | |||
20 | const validatorsVideos = validators.videos | 19 | const validatorsVideos = validators.videos |
21 | const search = middlewares.search | 20 | const search = middlewares.search |
22 | const sort = middlewares.sort | 21 | const sort = middlewares.sort |
23 | const databaseUtils = require('../../helpers/database-utils') | 22 | const databaseUtils = require('../../../helpers/database-utils') |
24 | const utils = require('../../helpers/utils') | 23 | const utils = require('../../../helpers/utils') |
24 | |||
25 | const abuseController = require('./abuse') | ||
26 | const blacklistController = require('./blacklist') | ||
27 | const rateController = require('./rate') | ||
25 | 28 | ||
26 | const router = express.Router() | 29 | const router = express.Router() |
27 | 30 | ||
@@ -45,31 +48,14 @@ const storage = multer.diskStorage({ | |||
45 | 48 | ||
46 | const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) | 49 | const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) |
47 | 50 | ||
51 | router.use('/', abuseController) | ||
52 | router.use('/', blacklistController) | ||
53 | router.use('/', rateController) | ||
54 | |||
48 | router.get('/categories', listVideoCategories) | 55 | router.get('/categories', listVideoCategories) |
49 | router.get('/licences', listVideoLicences) | 56 | router.get('/licences', listVideoLicences) |
50 | router.get('/languages', listVideoLanguages) | 57 | router.get('/languages', listVideoLanguages) |
51 | 58 | ||
52 | router.get('/abuse', | ||
53 | oAuth.authenticate, | ||
54 | admin.ensureIsAdmin, | ||
55 | validatorsPagination.pagination, | ||
56 | validatorsSort.videoAbusesSort, | ||
57 | sort.setVideoAbusesSort, | ||
58 | pagination.setPagination, | ||
59 | listVideoAbuses | ||
60 | ) | ||
61 | router.post('/:id/abuse', | ||
62 | oAuth.authenticate, | ||
63 | validatorsVideos.videoAbuseReport, | ||
64 | reportVideoAbuseRetryWrapper | ||
65 | ) | ||
66 | |||
67 | router.put('/:id/rate', | ||
68 | oAuth.authenticate, | ||
69 | validatorsVideos.videoRate, | ||
70 | rateVideoRetryWrapper | ||
71 | ) | ||
72 | |||
73 | router.get('/', | 59 | router.get('/', |
74 | validatorsPagination.pagination, | 60 | validatorsPagination.pagination, |
75 | validatorsSort.videosSort, | 61 | validatorsSort.videosSort, |
@@ -110,13 +96,6 @@ router.get('/search/:value', | |||
110 | searchVideos | 96 | searchVideos |
111 | ) | 97 | ) |
112 | 98 | ||
113 | router.post('/:id/blacklist', | ||
114 | oAuth.authenticate, | ||
115 | admin.ensureIsAdmin, | ||
116 | validatorsVideos.videosBlacklist, | ||
117 | addVideoToBlacklist | ||
118 | ) | ||
119 | |||
120 | // --------------------------------------------------------------------------- | 99 | // --------------------------------------------------------------------------- |
121 | 100 | ||
122 | module.exports = router | 101 | module.exports = router |
@@ -135,147 +114,6 @@ function listVideoLanguages (req, res, next) { | |||
135 | res.json(constants.VIDEO_LANGUAGES) | 114 | res.json(constants.VIDEO_LANGUAGES) |
136 | } | 115 | } |
137 | 116 | ||
138 | function rateVideoRetryWrapper (req, res, next) { | ||
139 | const options = { | ||
140 | arguments: [ req, res ], | ||
141 | errorMessage: 'Cannot update the user video rate.' | ||
142 | } | ||
143 | |||
144 | databaseUtils.retryTransactionWrapper(rateVideo, options, function (err) { | ||
145 | if (err) return next(err) | ||
146 | |||
147 | return res.type('json').status(204).end() | ||
148 | }) | ||
149 | } | ||
150 | |||
151 | function rateVideo (req, res, finalCallback) { | ||
152 | const rateType = req.body.rating | ||
153 | const videoInstance = res.locals.video | ||
154 | const userInstance = res.locals.oauth.token.User | ||
155 | |||
156 | waterfall([ | ||
157 | databaseUtils.startSerializableTransaction, | ||
158 | |||
159 | function findPreviousRate (t, callback) { | ||
160 | db.UserVideoRate.load(userInstance.id, videoInstance.id, t, function (err, previousRate) { | ||
161 | return callback(err, t, previousRate) | ||
162 | }) | ||
163 | }, | ||
164 | |||
165 | function insertUserRateIntoDB (t, previousRate, callback) { | ||
166 | const options = { transaction: t } | ||
167 | |||
168 | let likesToIncrement = 0 | ||
169 | let dislikesToIncrement = 0 | ||
170 | |||
171 | if (rateType === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement++ | ||
172 | else if (rateType === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ | ||
173 | |||
174 | // There was a previous rate, update it | ||
175 | if (previousRate) { | ||
176 | // We will remove the previous rate, so we will need to remove it from the video attribute | ||
177 | if (previousRate.type === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement-- | ||
178 | else if (previousRate.type === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- | ||
179 | |||
180 | previousRate.type = rateType | ||
181 | |||
182 | previousRate.save(options).asCallback(function (err) { | ||
183 | return callback(err, t, likesToIncrement, dislikesToIncrement) | ||
184 | }) | ||
185 | } else { // There was not a previous rate, insert a new one | ||
186 | const query = { | ||
187 | userId: userInstance.id, | ||
188 | videoId: videoInstance.id, | ||
189 | type: rateType | ||
190 | } | ||
191 | |||
192 | db.UserVideoRate.create(query, options).asCallback(function (err) { | ||
193 | return callback(err, t, likesToIncrement, dislikesToIncrement) | ||
194 | }) | ||
195 | } | ||
196 | }, | ||
197 | |||
198 | function updateVideoAttributeDB (t, likesToIncrement, dislikesToIncrement, callback) { | ||
199 | const options = { transaction: t } | ||
200 | const incrementQuery = { | ||
201 | likes: likesToIncrement, | ||
202 | dislikes: dislikesToIncrement | ||
203 | } | ||
204 | |||
205 | // Even if we do not own the video we increment the attributes | ||
206 | // It is usefull for the user to have a feedback | ||
207 | videoInstance.increment(incrementQuery, options).asCallback(function (err) { | ||
208 | return callback(err, t, likesToIncrement, dislikesToIncrement) | ||
209 | }) | ||
210 | }, | ||
211 | |||
212 | function sendEventsToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) { | ||
213 | // No need for an event type, we own the video | ||
214 | if (videoInstance.isOwned()) return callback(null, t, likesToIncrement, dislikesToIncrement) | ||
215 | |||
216 | const eventsParams = [] | ||
217 | |||
218 | if (likesToIncrement !== 0) { | ||
219 | eventsParams.push({ | ||
220 | videoId: videoInstance.id, | ||
221 | type: constants.REQUEST_VIDEO_EVENT_TYPES.LIKES, | ||
222 | count: likesToIncrement | ||
223 | }) | ||
224 | } | ||
225 | |||
226 | if (dislikesToIncrement !== 0) { | ||
227 | eventsParams.push({ | ||
228 | videoId: videoInstance.id, | ||
229 | type: constants.REQUEST_VIDEO_EVENT_TYPES.DISLIKES, | ||
230 | count: dislikesToIncrement | ||
231 | }) | ||
232 | } | ||
233 | |||
234 | friends.addEventsToRemoteVideo(eventsParams, t, function (err) { | ||
235 | return callback(err, t, likesToIncrement, dislikesToIncrement) | ||
236 | }) | ||
237 | }, | ||
238 | |||
239 | function sendQaduToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) { | ||
240 | // We do not own the video, there is no need to send a quick and dirty update to friends | ||
241 | // Our rate was already sent by the addEvent function | ||
242 | if (videoInstance.isOwned() === false) return callback(null, t) | ||
243 | |||
244 | const qadusParams = [] | ||
245 | |||
246 | if (likesToIncrement !== 0) { | ||
247 | qadusParams.push({ | ||
248 | videoId: videoInstance.id, | ||
249 | type: constants.REQUEST_VIDEO_QADU_TYPES.LIKES | ||
250 | }) | ||
251 | } | ||
252 | |||
253 | if (dislikesToIncrement !== 0) { | ||
254 | qadusParams.push({ | ||
255 | videoId: videoInstance.id, | ||
256 | type: constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES | ||
257 | }) | ||
258 | } | ||
259 | |||
260 | friends.quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) { | ||
261 | return callback(err, t) | ||
262 | }) | ||
263 | }, | ||
264 | |||
265 | databaseUtils.commitTransaction | ||
266 | |||
267 | ], function (err, t) { | ||
268 | if (err) { | ||
269 | // This is just a debug because we will retry the insert | ||
270 | logger.debug('Cannot add the user video rate.', { error: err }) | ||
271 | return databaseUtils.rollbackTransaction(err, t, finalCallback) | ||
272 | } | ||
273 | |||
274 | logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username) | ||
275 | return finalCallback(null) | ||
276 | }) | ||
277 | } | ||
278 | |||
279 | // Wrapper to video add that retry the function if there is a database error | 117 | // Wrapper to video add that retry the function if there is a database error |
280 | // We need this because we run the transaction in SERIALIZABLE isolation that can fail | 118 | // We need this because we run the transaction in SERIALIZABLE isolation that can fail |
281 | function addVideoRetryWrapper (req, res, next) { | 119 | function addVideoRetryWrapper (req, res, next) { |
@@ -564,90 +402,3 @@ function searchVideos (req, res, next) { | |||
564 | } | 402 | } |
565 | ) | 403 | ) |
566 | } | 404 | } |
567 | |||
568 | function listVideoAbuses (req, res, next) { | ||
569 | db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) { | ||
570 | if (err) return next(err) | ||
571 | |||
572 | res.json(utils.getFormatedObjects(abusesList, abusesTotal)) | ||
573 | }) | ||
574 | } | ||
575 | |||
576 | function reportVideoAbuseRetryWrapper (req, res, next) { | ||
577 | const options = { | ||
578 | arguments: [ req, res ], | ||
579 | errorMessage: 'Cannot report abuse to the video with many retries.' | ||
580 | } | ||
581 | |||
582 | databaseUtils.retryTransactionWrapper(reportVideoAbuse, options, function (err) { | ||
583 | if (err) return next(err) | ||
584 | |||
585 | return res.type('json').status(204).end() | ||
586 | }) | ||
587 | } | ||
588 | |||
589 | function reportVideoAbuse (req, res, finalCallback) { | ||
590 | const videoInstance = res.locals.video | ||
591 | const reporterUsername = res.locals.oauth.token.User.username | ||
592 | |||
593 | const abuse = { | ||
594 | reporterUsername, | ||
595 | reason: req.body.reason, | ||
596 | videoId: videoInstance.id, | ||
597 | reporterPodId: null // This is our pod that reported this abuse | ||
598 | } | ||
599 | |||
600 | waterfall([ | ||
601 | |||
602 | databaseUtils.startSerializableTransaction, | ||
603 | |||
604 | function createAbuse (t, callback) { | ||
605 | db.VideoAbuse.create(abuse).asCallback(function (err, abuse) { | ||
606 | return callback(err, t, abuse) | ||
607 | }) | ||
608 | }, | ||
609 | |||
610 | function sendToFriendsIfNeeded (t, abuse, callback) { | ||
611 | // We send the information to the destination pod | ||
612 | if (videoInstance.isOwned() === false) { | ||
613 | const reportData = { | ||
614 | reporterUsername, | ||
615 | reportReason: abuse.reason, | ||
616 | videoRemoteId: videoInstance.remoteId | ||
617 | } | ||
618 | |||
619 | friends.reportAbuseVideoToFriend(reportData, videoInstance) | ||
620 | } | ||
621 | |||
622 | return callback(null, t) | ||
623 | }, | ||
624 | |||
625 | databaseUtils.commitTransaction | ||
626 | |||
627 | ], function andFinally (err, t) { | ||
628 | if (err) { | ||
629 | logger.debug('Cannot update the video.', { error: err }) | ||
630 | return databaseUtils.rollbackTransaction(err, t, finalCallback) | ||
631 | } | ||
632 | |||
633 | logger.info('Abuse report for video %s created.', videoInstance.name) | ||
634 | return finalCallback(null) | ||
635 | }) | ||
636 | } | ||
637 | |||
638 | function addVideoToBlacklist (req, res, next) { | ||
639 | const videoInstance = res.locals.video | ||
640 | |||
641 | const toCreate = { | ||
642 | videoId: videoInstance.id | ||
643 | } | ||
644 | |||
645 | db.BlacklistedVideo.create(toCreate).asCallback(function (err) { | ||
646 | if (err) { | ||
647 | logger.error('Errors when blacklisting video ', { error: err }) | ||
648 | return next(err) | ||
649 | } | ||
650 | |||
651 | return res.type('json').status(204).end() | ||
652 | }) | ||
653 | } | ||
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 | } | ||