Merge branch 'instream-ban' of github.com:coralproject/talk into instream-ban

This commit is contained in:
Belen Curcio
2017-09-18 10:05:12 -03:00
28 changed files with 437 additions and 200 deletions
@@ -0,0 +1,81 @@
const _ = require('lodash');
const DataLoader = require('dataloader');
const CommentModel = require('../../models/comment');
console.warn('Enabling the talk-plugin-deep-reply-count plugin introduces a signifigant performance impact on larger sites, use with care.');
// genDeepCommentCount will return the deep comment count for a given parent id.
const genDeepCommentCount = async (context, parent_ids) => {
// Get all the replies to the parent comments.
const replies = await CommentModel
.find({
parent_id: {
$in: _.uniq(parent_ids),
},
}, {
id: 1,
reply_count: 1,
parent_id: 1,
});
// Get all the replies that have comments on them.
const commentedOnReplies = replies.filter(({reply_count}) => {
return reply_count && reply_count > 0;
});
let deepReplyCount = [];
// And if there were any..
if (commentedOnReplies.length > 0) {
// Load the reply count for each of them.
deepReplyCount = await context.loaders.Comments.getDeepCount.loadMany(_.uniq(commentedOnReplies.map(({id}) => {
return id;
})));
}
// Get all the direct replies to the parent comments.
const allDirectReplies = _.groupBy(replies, 'parent_id');
// Collect all the ancestor replies.
const allAncestorReplies = _.groupBy(_.zip(commentedOnReplies, deepReplyCount), ([{parent_id}]) => {
return parent_id;
});
// Return the replies in an array matching that of the input parent_ids array.
return parent_ids.map((parent_id) => {
// Get the direct replies to this comment.
const directReplies = parent_id in allDirectReplies ? allDirectReplies[parent_id] : [];
const ancestorReplies = parent_id in allAncestorReplies ? allAncestorReplies[parent_id] : [];
// Reduce this array.
return ancestorReplies.reduce((acc, [, count]) => {
return acc + count;
}, directReplies.length);
});
};
module.exports = {
typeDefs: `
type Comment {
# deepReplyCount is the count of all decendant replies.
deepReplyCount: Int
}
`,
loaders: (context) => ({
Comments: {
getDeepCount: new DataLoader((parent_ids) => genDeepCommentCount(context, parent_ids)),
}
}),
resolvers: {
Comment: {
deepReplyCount({id}, args, {loaders: {Comments}}) {
return Comments.getDeepCount.load(id);
}
}
}
};
@@ -1,6 +1,5 @@
const {getScores, isToxic} = require('./perspective');
const {ErrToxic} = require('./errors');
const ActionsService = require('../../../services/actions');
// We don't add the hooks during _test_ as the perspective API is not available.
if (process.env.NODE_ENV === 'test') {
@@ -12,55 +11,36 @@ module.exports = {
createComment: {
async pre(_, {input}, _context, _info) {
let scores;
// Try getting scores.
let scores;
try {
scores = await getScores(input.body);
}
catch(err) {
} catch(err) {
// Warn and let mutation pass.
console.trace(err);
return;
}
const commentIsToxic = isToxic(scores);
if (input.checkToxicity && commentIsToxic) {
throw ErrToxic;
}
// attach scores to metadata.
// Attach scores to metadata.
input.metadata = Object.assign({}, input.metadata, {
perspective: scores,
});
if (commentIsToxic) {
if (isToxic(scores)) {
if (input.checkToxicity) {
throw ErrToxic;
}
// TODO: this should have a different status than Premod.
input.status = 'PREMOD';
}
},
async post(_, _input, _context, _info, result) {
const metadata = result.comment.metadata;
if (metadata.perspective && isToxic(metadata.perspective)) {
// TODO: this is kind of fragile, we should refactor this to resolve
// all these const's that we're using like 'COMMENTS', 'FLAG' to be
// defined in a checkable schema.
// Add a flag to the comment.
await ActionsService.create({
item_id: result.comment.id,
item_type: 'COMMENTS',
input.status = 'SYSTEM_WITHHELD';
input.actions = input.actions && input.actions.length >= 0 ? input.actions : [];
input.actions.push({
action_type: 'FLAG',
user_id: null,
group_id: 'Comment contains toxic language',
metadata: {}
});
}
return result;
},
},
},