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