You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
3.5 KiB
124 lines
3.5 KiB
// content-vote.js
|
|
// Copyright (C) 2022 DTP Technologies, LLC
|
|
// License: Apache-2.0
|
|
|
|
'use strict';
|
|
|
|
const mongoose = require('mongoose');
|
|
const ContentVote = mongoose.model('ContentVote');
|
|
|
|
const ioEmitter = require('socket.io-emitter');
|
|
|
|
const { SiteService } = require('../../lib/site-lib');
|
|
|
|
class ContentVoteService extends SiteService {
|
|
|
|
constructor (dtp) {
|
|
super(dtp, module.exports);
|
|
}
|
|
|
|
async start ( ) {
|
|
await super.start();
|
|
this.emitter = ioEmitter(this.dtp.redis);
|
|
}
|
|
|
|
async recordVote (user, resourceType, resource, vote) {
|
|
const NOW = new Date();
|
|
const ResourceModel = mongoose.model(resourceType);
|
|
const updateOp = { $inc: { } };
|
|
let message;
|
|
|
|
const contentVote = await ContentVote.findOne({
|
|
user: user._id,
|
|
resource: resource._id,
|
|
});
|
|
|
|
this.log.debug('processing content vote', { resource: resource._id, user: user._id, vote, contentVote });
|
|
|
|
if (!contentVote) {
|
|
/*
|
|
* It's a new vote from a new user
|
|
*/
|
|
await ContentVote.create({
|
|
created: NOW,
|
|
resourceType,
|
|
resource: resource._id,
|
|
user: user._id,
|
|
vote
|
|
});
|
|
if (vote === 'up') {
|
|
updateOp.$inc['resourceStats.upvoteCount'] = 1;
|
|
message = 'Comment upvote recorded';
|
|
} else {
|
|
updateOp.$inc['resourceStats.downvoteCount'] = 1;
|
|
message = 'Comment downvote recorded';
|
|
}
|
|
} else {
|
|
/*
|
|
* If vote not changed, do no further work.
|
|
*/
|
|
if (contentVote.vote === vote) {
|
|
const updatedResource = await ResourceModel.findById(resource._id).select('resourceStats');
|
|
return { message: "Comment vote unchanged", resourceStats: updatedResource.resourceStats };
|
|
}
|
|
|
|
/*
|
|
* Update the user's existing vote
|
|
*/
|
|
await ContentVote.updateOne(
|
|
{ _id: contentVote._id },
|
|
{ $set: { vote } }
|
|
);
|
|
|
|
/*
|
|
* Adjust resource's stats based on the changed vote
|
|
*/
|
|
if (vote === 'up') {
|
|
updateOp.$inc['resourceStats.upvoteCount'] = 1;
|
|
updateOp.$inc['resourceStats.downvoteCount'] = -1;
|
|
message = 'Comment vote changed to upvote';
|
|
} else {
|
|
updateOp.$inc['resourceStats.upvoteCount'] = -1;
|
|
updateOp.$inc['resourceStats.downvoteCount'] = 1;
|
|
message = 'Comment vote changed to downvote';
|
|
}
|
|
}
|
|
|
|
this.log.info('updating resource stats', { resourceType, resource, updateOp });
|
|
await ResourceModel.updateOne({ _id: resource._id }, updateOp);
|
|
|
|
const updatedResource = await ResourceModel.findById(resource._id).select('resourceStats');
|
|
return { message, resourceStats: updatedResource.resourceStats };
|
|
}
|
|
|
|
async removeForResource (resource) {
|
|
this.log.info('removing all votes for resource', { resourceId: resource._id });
|
|
await ContentVote.deleteMany({ resource: resource._id });
|
|
}
|
|
|
|
async removeForUser (user) {
|
|
await ContentVote
|
|
.find({ user: user._id })
|
|
.cursor()
|
|
.eachAsync(async (vote) => {
|
|
const updateOp = { $inc: { } };
|
|
if (vote.vote === 'up') {
|
|
updateOp.$inc['resourceStats.upvoteCount'] = -1;
|
|
} else {
|
|
updateOp.$inc['resourceStats.downvoteCount'] = -1;
|
|
}
|
|
|
|
const resourceModel = mongoose.model(vote.resourceType);
|
|
await resourceModel.updateOne({ _id: vote.resource }, updateOp);
|
|
});
|
|
|
|
await ContentVote.deleteMany({ user: user._id });
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
slug: 'content-vote',
|
|
name: 'contentVote',
|
|
className: 'ContentVoteService',
|
|
create: (dtp) => { return new ContentVoteService(dtp); },
|
|
};
|