diff options
Diffstat (limited to 'server/controllers/api/videos/rate.ts')
-rw-r--r-- | server/controllers/api/videos/rate.ts | 205 |
1 files changed, 93 insertions, 112 deletions
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts index 6ddc69817..354c3d8f9 100644 --- a/server/controllers/api/videos/rate.ts +++ b/server/controllers/api/videos/rate.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import * as Promise from 'bluebird' | ||
3 | 2 | ||
4 | import { database as db } from '../../../initializers/database' | 3 | import { database as db } from '../../../initializers/database' |
5 | import { | 4 | import { |
@@ -17,7 +16,8 @@ import { | |||
17 | } from '../../../lib' | 16 | } from '../../../lib' |
18 | import { | 17 | import { |
19 | authenticate, | 18 | authenticate, |
20 | videoRateValidator | 19 | videoRateValidator, |
20 | asyncMiddleware | ||
21 | } from '../../../middlewares' | 21 | } from '../../../middlewares' |
22 | import { UserVideoRateUpdate, VideoRateType } from '../../../../shared' | 22 | import { UserVideoRateUpdate, VideoRateType } from '../../../../shared' |
23 | 23 | ||
@@ -26,7 +26,7 @@ const rateVideoRouter = express.Router() | |||
26 | rateVideoRouter.put('/:id/rate', | 26 | rateVideoRouter.put('/:id/rate', |
27 | authenticate, | 27 | authenticate, |
28 | videoRateValidator, | 28 | videoRateValidator, |
29 | rateVideoRetryWrapper | 29 | asyncMiddleware(rateVideoRetryWrapper) |
30 | ) | 30 | ) |
31 | 31 | ||
32 | // --------------------------------------------------------------------------- | 32 | // --------------------------------------------------------------------------- |
@@ -37,126 +37,107 @@ export { | |||
37 | 37 | ||
38 | // --------------------------------------------------------------------------- | 38 | // --------------------------------------------------------------------------- |
39 | 39 | ||
40 | function rateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | 40 | async function rateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { |
41 | const options = { | 41 | const options = { |
42 | arguments: [ req, res ], | 42 | arguments: [ req, res ], |
43 | errorMessage: 'Cannot update the user video rate.' | 43 | errorMessage: 'Cannot update the user video rate.' |
44 | } | 44 | } |
45 | 45 | ||
46 | retryTransactionWrapper(rateVideo, options) | 46 | await retryTransactionWrapper(rateVideo, options) |
47 | .then(() => res.type('json').status(204).end()) | 47 | |
48 | .catch(err => next(err)) | 48 | return res.type('json').status(204).end() |
49 | } | 49 | } |
50 | 50 | ||
51 | function rateVideo (req: express.Request, res: express.Response) { | 51 | async function rateVideo (req: express.Request, res: express.Response) { |
52 | const body: UserVideoRateUpdate = req.body | 52 | const body: UserVideoRateUpdate = req.body |
53 | const rateType = body.rating | 53 | const rateType = body.rating |
54 | const videoInstance = res.locals.video | 54 | const videoInstance = res.locals.video |
55 | const userInstance = res.locals.oauth.token.User | 55 | const userInstance = res.locals.oauth.token.User |
56 | 56 | ||
57 | return db.sequelize.transaction(t => { | 57 | await db.sequelize.transaction(async t => { |
58 | return db.UserVideoRate.load(userInstance.id, videoInstance.id, t) | 58 | const sequelizeOptions = { transaction: t } |
59 | .then(previousRate => { | 59 | const previousRate = await db.UserVideoRate.load(userInstance.id, videoInstance.id, t) |
60 | const options = { transaction: t } | 60 | |
61 | 61 | let likesToIncrement = 0 | |
62 | let likesToIncrement = 0 | 62 | let dislikesToIncrement = 0 |
63 | let dislikesToIncrement = 0 | 63 | |
64 | 64 | if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ | |
65 | if (rateType === VIDEO_RATE_TYPES.LIKE) likesToIncrement++ | 65 | else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ |
66 | else if (rateType === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++ | 66 | |
67 | 67 | // There was a previous rate, update it | |
68 | let promise: Promise<any> | 68 | if (previousRate) { |
69 | 69 | // We will remove the previous rate, so we will need to update the video count attribute | |
70 | // There was a previous rate, update it | 70 | if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement-- |
71 | if (previousRate) { | 71 | else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- |
72 | // We will remove the previous rate, so we will need to update the video count attribute | 72 | |
73 | if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement-- | 73 | if (rateType === 'none') { // Destroy previous rate |
74 | else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- | 74 | await previousRate.destroy() |
75 | 75 | } else { // Update previous rate | |
76 | if (rateType === 'none') { // Destroy previous rate | 76 | previousRate.type = rateType as VideoRateType |
77 | promise = previousRate.destroy() | 77 | |
78 | } else { // Update previous rate | 78 | await previousRate.save() |
79 | previousRate.type = rateType as VideoRateType | 79 | } |
80 | 80 | } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate | |
81 | promise = previousRate.save() | 81 | const query = { |
82 | } | 82 | userId: userInstance.id, |
83 | } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate | 83 | videoId: videoInstance.id, |
84 | const query = { | 84 | type: rateType |
85 | userId: userInstance.id, | 85 | } |
86 | videoId: videoInstance.id, | 86 | |
87 | type: rateType | 87 | await db.UserVideoRate.create(query, sequelizeOptions) |
88 | } | 88 | } |
89 | 89 | ||
90 | promise = db.UserVideoRate.create(query, options) | 90 | const incrementQuery = { |
91 | } else { | 91 | likes: likesToIncrement, |
92 | promise = Promise.resolve() | 92 | dislikes: dislikesToIncrement |
93 | } | 93 | } |
94 | 94 | ||
95 | return promise.then(() => ({ likesToIncrement, dislikesToIncrement })) | 95 | // Even if we do not own the video we increment the attributes |
96 | }) | 96 | // It is useful for the user to have a feedback |
97 | .then(({ likesToIncrement, dislikesToIncrement }) => { | 97 | await videoInstance.increment(incrementQuery, sequelizeOptions) |
98 | const options = { transaction: t } | 98 | |
99 | const incrementQuery = { | 99 | // Send a event to original pod |
100 | likes: likesToIncrement, | 100 | if (videoInstance.isOwned() === false) { |
101 | dislikes: dislikesToIncrement | 101 | |
102 | } | 102 | const eventsParams = [] |
103 | 103 | ||
104 | // Even if we do not own the video we increment the attributes | 104 | if (likesToIncrement !== 0) { |
105 | // It is usefull for the user to have a feedback | 105 | eventsParams.push({ |
106 | return videoInstance.increment(incrementQuery, options).then(() => ({ likesToIncrement, dislikesToIncrement })) | 106 | videoId: videoInstance.id, |
107 | }) | 107 | type: REQUEST_VIDEO_EVENT_TYPES.LIKES, |
108 | .then(({ likesToIncrement, dislikesToIncrement }) => { | 108 | count: likesToIncrement |
109 | // No need for an event type, we own the video | 109 | }) |
110 | if (videoInstance.isOwned()) return { likesToIncrement, dislikesToIncrement } | 110 | } |
111 | 111 | ||
112 | const eventsParams = [] | 112 | if (dislikesToIncrement !== 0) { |
113 | 113 | eventsParams.push({ | |
114 | if (likesToIncrement !== 0) { | 114 | videoId: videoInstance.id, |
115 | eventsParams.push({ | 115 | type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES, |
116 | videoId: videoInstance.id, | 116 | count: dislikesToIncrement |
117 | type: REQUEST_VIDEO_EVENT_TYPES.LIKES, | 117 | }) |
118 | count: likesToIncrement | 118 | } |
119 | }) | 119 | |
120 | } | 120 | await addEventsToRemoteVideo(eventsParams, t) |
121 | 121 | } else { // We own the video, we need to send a quick and dirty update to friends to notify the counts changed | |
122 | if (dislikesToIncrement !== 0) { | 122 | const qadusParams = [] |
123 | eventsParams.push({ | 123 | |
124 | videoId: videoInstance.id, | 124 | if (likesToIncrement !== 0) { |
125 | type: REQUEST_VIDEO_EVENT_TYPES.DISLIKES, | 125 | qadusParams.push({ |
126 | count: dislikesToIncrement | 126 | videoId: videoInstance.id, |
127 | }) | 127 | type: REQUEST_VIDEO_QADU_TYPES.LIKES |
128 | } | 128 | }) |
129 | 129 | } | |
130 | return addEventsToRemoteVideo(eventsParams, t).then(() => ({ likesToIncrement, dislikesToIncrement })) | 130 | |
131 | }) | 131 | if (dislikesToIncrement !== 0) { |
132 | .then(({ likesToIncrement, dislikesToIncrement }) => { | 132 | qadusParams.push({ |
133 | // We do not own the video, there is no need to send a quick and dirty update to friends | 133 | videoId: videoInstance.id, |
134 | // Our rate was already sent by the addEvent function | 134 | type: REQUEST_VIDEO_QADU_TYPES.DISLIKES |
135 | if (videoInstance.isOwned() === false) return undefined | 135 | }) |
136 | 136 | } | |
137 | const qadusParams = [] | 137 | |
138 | 138 | await quickAndDirtyUpdatesVideoToFriends(qadusParams, t) | |
139 | if (likesToIncrement !== 0) { | 139 | } |
140 | qadusParams.push({ | ||
141 | videoId: videoInstance.id, | ||
142 | type: REQUEST_VIDEO_QADU_TYPES.LIKES | ||
143 | }) | ||
144 | } | ||
145 | |||
146 | if (dislikesToIncrement !== 0) { | ||
147 | qadusParams.push({ | ||
148 | videoId: videoInstance.id, | ||
149 | type: REQUEST_VIDEO_QADU_TYPES.DISLIKES | ||
150 | }) | ||
151 | } | ||
152 | |||
153 | return quickAndDirtyUpdatesVideoToFriends(qadusParams, t) | ||
154 | }) | ||
155 | }) | ||
156 | .then(() => logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username)) | ||
157 | .catch(err => { | ||
158 | // This is just a debug because we will retry the insert | ||
159 | logger.debug('Cannot add the user video rate.', err) | ||
160 | throw err | ||
161 | }) | 140 | }) |
141 | |||
142 | logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username) | ||
162 | } | 143 | } |