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