mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 19:42:24 +02:00
Add like/dislike system for videos
This commit is contained in:
parent
8f90644321
commit
d38b828106
31 changed files with 907 additions and 47 deletions
|
@ -60,6 +60,12 @@ router.post('/:id/abuse',
|
|||
reportVideoAbuseRetryWrapper
|
||||
)
|
||||
|
||||
router.put('/:id/rate',
|
||||
oAuth.authenticate,
|
||||
validatorsVideos.videoRate,
|
||||
rateVideoRetryWrapper
|
||||
)
|
||||
|
||||
router.get('/',
|
||||
validatorsPagination.pagination,
|
||||
validatorsSort.videosSort,
|
||||
|
@ -104,6 +110,147 @@ module.exports = router
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function rateVideoRetryWrapper (req, res, next) {
|
||||
const options = {
|
||||
arguments: [ req, res ],
|
||||
errorMessage: 'Cannot update the user video rate.'
|
||||
}
|
||||
|
||||
databaseUtils.retryTransactionWrapper(rateVideo, options, function (err) {
|
||||
if (err) return next(err)
|
||||
|
||||
return res.type('json').status(204).end()
|
||||
})
|
||||
}
|
||||
|
||||
function rateVideo (req, res, finalCallback) {
|
||||
const rateType = req.body.rating
|
||||
const videoInstance = res.locals.video
|
||||
const userInstance = res.locals.oauth.token.User
|
||||
|
||||
waterfall([
|
||||
databaseUtils.startSerializableTransaction,
|
||||
|
||||
function findPreviousRate (t, callback) {
|
||||
db.UserVideoRate.load(userInstance.id, videoInstance.id, t, function (err, previousRate) {
|
||||
return callback(err, t, previousRate)
|
||||
})
|
||||
},
|
||||
|
||||
function insertUserRateIntoDB (t, previousRate, callback) {
|
||||
const options = { transaction: t }
|
||||
|
||||
let likesToIncrement = 0
|
||||
let dislikesToIncrement = 0
|
||||
|
||||
if (rateType === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement++
|
||||
else if (rateType === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement++
|
||||
|
||||
// There was a previous rate, update it
|
||||
if (previousRate) {
|
||||
// We will remove the previous rate, so we will need to remove it from the video attribute
|
||||
if (previousRate.type === constants.VIDEO_RATE_TYPES.LIKE) likesToIncrement--
|
||||
else if (previousRate.type === constants.VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
|
||||
|
||||
previousRate.type = rateType
|
||||
|
||||
previousRate.save(options).asCallback(function (err) {
|
||||
return callback(err, t, likesToIncrement, dislikesToIncrement)
|
||||
})
|
||||
} else { // There was not a previous rate, insert a new one
|
||||
const query = {
|
||||
userId: userInstance.id,
|
||||
videoId: videoInstance.id,
|
||||
type: rateType
|
||||
}
|
||||
|
||||
db.UserVideoRate.create(query, options).asCallback(function (err) {
|
||||
return callback(err, t, likesToIncrement, dislikesToIncrement)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
function updateVideoAttributeDB (t, likesToIncrement, dislikesToIncrement, callback) {
|
||||
const options = { transaction: t }
|
||||
const incrementQuery = {
|
||||
likes: likesToIncrement,
|
||||
dislikes: dislikesToIncrement
|
||||
}
|
||||
|
||||
// Even if we do not own the video we increment the attributes
|
||||
// It is usefull for the user to have a feedback
|
||||
videoInstance.increment(incrementQuery, options).asCallback(function (err) {
|
||||
return callback(err, t, likesToIncrement, dislikesToIncrement)
|
||||
})
|
||||
},
|
||||
|
||||
function sendEventsToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) {
|
||||
// No need for an event type, we own the video
|
||||
if (videoInstance.isOwned()) return callback(null, t, likesToIncrement, dislikesToIncrement)
|
||||
|
||||
const eventsParams = []
|
||||
|
||||
if (likesToIncrement !== 0) {
|
||||
eventsParams.push({
|
||||
videoId: videoInstance.id,
|
||||
type: constants.REQUEST_VIDEO_EVENT_TYPES.LIKES,
|
||||
count: likesToIncrement
|
||||
})
|
||||
}
|
||||
|
||||
if (dislikesToIncrement !== 0) {
|
||||
eventsParams.push({
|
||||
videoId: videoInstance.id,
|
||||
type: constants.REQUEST_VIDEO_EVENT_TYPES.DISLIKES,
|
||||
count: dislikesToIncrement
|
||||
})
|
||||
}
|
||||
|
||||
friends.addEventsToRemoteVideo(eventsParams, t, function (err) {
|
||||
return callback(err, t, likesToIncrement, dislikesToIncrement)
|
||||
})
|
||||
},
|
||||
|
||||
function sendQaduToFriendsIfNeeded (t, likesToIncrement, dislikesToIncrement, callback) {
|
||||
// We do not own the video, there is no need to send a quick and dirty update to friends
|
||||
// Our rate was already sent by the addEvent function
|
||||
if (videoInstance.isOwned() === false) return callback(null, t)
|
||||
|
||||
const qadusParams = []
|
||||
|
||||
if (likesToIncrement !== 0) {
|
||||
qadusParams.push({
|
||||
videoId: videoInstance.id,
|
||||
type: constants.REQUEST_VIDEO_QADU_TYPES.LIKES
|
||||
})
|
||||
}
|
||||
|
||||
if (dislikesToIncrement !== 0) {
|
||||
qadusParams.push({
|
||||
videoId: videoInstance.id,
|
||||
type: constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES
|
||||
})
|
||||
}
|
||||
|
||||
friends.quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
|
||||
return callback(err, t)
|
||||
})
|
||||
},
|
||||
|
||||
databaseUtils.commitTransaction
|
||||
|
||||
], function (err, t) {
|
||||
if (err) {
|
||||
// This is just a debug because we will retry the insert
|
||||
logger.debug('Cannot add the user video rate.', { error: err })
|
||||
return databaseUtils.rollbackTransaction(err, t, finalCallback)
|
||||
}
|
||||
|
||||
logger.info('User video rate for video %s of user %s updated.', videoInstance.name, userInstance.username)
|
||||
return finalCallback(null)
|
||||
})
|
||||
}
|
||||
|
||||
// Wrapper to video add that retry the function if there is a database error
|
||||
// We need this because we run the transaction in SERIALIZABLE isolation that can fail
|
||||
function addVideoRetryWrapper (req, res, next) {
|
||||
|
@ -155,8 +302,7 @@ function addVideo (req, res, videoFile, finalCallback) {
|
|||
extname: path.extname(videoFile.filename),
|
||||
description: videoInfos.description,
|
||||
duration: videoFile.duration,
|
||||
authorId: author.id,
|
||||
views: videoInfos.views
|
||||
authorId: author.id
|
||||
}
|
||||
|
||||
const video = db.Video.build(videoData)
|
||||
|
@ -332,11 +478,19 @@ function getVideo (req, res, next) {
|
|||
|
||||
// FIXME: make a real view system
|
||||
// For example, only add a view when a user watch a video during 30s etc
|
||||
friends.quickAndDirtyUpdateVideoToFriends(videoInstance.id, constants.REQUEST_VIDEO_QADU_TYPES.VIEWS)
|
||||
const qaduParams = {
|
||||
videoId: videoInstance.id,
|
||||
type: constants.REQUEST_VIDEO_QADU_TYPES.VIEWS
|
||||
}
|
||||
friends.quickAndDirtyUpdateVideoToFriends(qaduParams)
|
||||
})
|
||||
} else {
|
||||
// Just send the event to our friends
|
||||
friends.addEventToRemoteVideo(videoInstance.id, constants.REQUEST_VIDEO_EVENT_TYPES.VIEWS)
|
||||
const eventParams = {
|
||||
videoId: videoInstance.id,
|
||||
type: constants.REQUEST_VIDEO_EVENT_TYPES.VIEWS
|
||||
}
|
||||
friends.addEventToRemoteVideo(eventParams)
|
||||
}
|
||||
|
||||
// Do not wait the view system
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue