Files
habitica/website/server/libs/slack.js
Alyssa Batula c350665076 Automatically mute users who attempt to post a slur, fixes #8062 (#8177)
* Initial psuedo-code for checking for slurs in messages

* Initial working prototype for blocking posting of slurs. Moved check from group.js to the chat api. Still needs: to permanently revoke chat privileges, to notify the moderators, a better method for checking for the blacklisted words, and a way to get the real list of words to check.

* Permanently revoke chat privileges when attempting to post a slur.

* Removed console logs

* Fixing rebase

* Do not moderate private groups

* Moved slur check to a generic check for banned words function

* Moved list of slurs to a separate file, fixed misplacement of return in ContainsBannedWords() function

* Slurs are blocked in both public and private groups

* Added code to send a slack message for slurs

* Fixed formatting issues

* Incorporated tectContainsBannedWords() function from PR 8197, added an argument to specify the list of banned words to check

* Added initial tests for blocking slurs and revoking chat priviliges

* Uncommented line to save revoked privileges

* Check that privileges are revoked in private groups

* Moved code to email/slack mods to chat api file

* Switched to BadRequest instead of NotFound error

* Restore chat privileges after test

* Using official placeholder slur

* Fixed line to export sendSubscriptionNotification function for slack

* Replaced muteUser function in user methods with a single line in the chat controller file

* Reset chatRevoked flag to false in a single line

* Switched method of setting chatRevoked flag so that it is updated locally and in the database

* First attempt at the muteUser function: revokes user's chat privileges and notifies moderators

* Manual merge for cherry-pick

* Initial working prototype for blocking posting of slurs. Moved check from group.js to the chat api. Still needs: to permanently revoke chat privileges, to notify the moderators, a better method for checking for the blacklisted words, and a way to get the real list of words to check.

* Permanently revoke chat privileges when attempting to post a slur.

* Removed console logs

* Created report to be sent to moderators via email

* Do not moderate private groups

* Moved slur check to a generic check for banned words function

* Moved list of slurs to a separate file, fixed misplacement of return in ContainsBannedWords() function

* Slurs are blocked in both public and private groups

* Added code to send a slack message for slurs

* Fixed formatting issues

* Incorporated tectContainsBannedWords() function from PR 8197, added an argument to specify the list of banned words to check

* Added initial tests for blocking slurs and revoking chat priviliges

* Uncommented line to save revoked privileges

* Check that privileges are revoked in private groups

* Moved code to email/slack mods to chat api file

* Switched to BadRequest instead of NotFound error

* Restore chat privileges after test

* Using official placeholder slur

* Fixed line to export sendSubscriptionNotification function for slack

* Replaced muteUser function in user methods with a single line in the chat controller file

* Reset chatRevoked flag to false in a single line

* Switched method of setting chatRevoked flag so that it is updated locally and in the database

* Removed some code that got re-added after rebase

* Tests for automatic slur muting pass but are incomplete (do not check that chatRevoked flag is true)

* Moved list of banned slurs to server side

* Added warning to bannedSlurs file

* Test chat privileges revoked when posting slur in public chat

* Fix issues left over after rebase (I hope)

* Added code to test for revoked chat privileges after posting a slur in a private group

* Moved banned slur message into locales message

* Added new code to check for banned slurs (parallels banned words code)

* Fixed AUTHOR_MOTAL_URL in sendTxn for slur blocking

* Added tests that email sent on attempted slur in chat post

* Created context for slur-related-tests, fixed sandboxing of email. Successfully tests that email.sendTxn is called, but the email content test fails

* commented out slack (for now) and cleaned up tests of sending email

* Successfully tests that slur-report-to-mods email is sent

* Slack message is sent, and testing works, but some user variables seem to only work when found in chat.js and passed to slack

* Made some fixes for lint, but not sure what to do about the camel case requirement fail, since that's how they're defined in other slack calls

* Slack tests pass, skipped camelcase check around those code blocks

* Fixed InternalServerError caused by slack messaging

* Updated chat privileges revoked error

* fix(locale): typo correction
2017-07-19 14:06:15 -07:00

142 lines
3.7 KiB
JavaScript

/* eslint-disable camelcase */
import { IncomingWebhook } from '@slack/client';
import logger from './logger';
import { TAVERN_ID } from '../models/group';
import nconf from 'nconf';
const SLACK_FLAGGING_URL = nconf.get('SLACK:FLAGGING_URL');
const SLACK_FLAGGING_FOOTER_LINK = nconf.get('SLACK:FLAGGING_FOOTER_LINK');
const SLACK_SUBSCRIPTIONS_URL = nconf.get('SLACK:SUBSCRIPTIONS_URL');
const BASE_URL = nconf.get('BASE_URL');
let flagSlack;
let subscriptionSlack;
try {
flagSlack = new IncomingWebhook(SLACK_FLAGGING_URL);
subscriptionSlack = new IncomingWebhook(SLACK_SUBSCRIPTIONS_URL);
} catch (err) {
logger.error(err);
}
function sendFlagNotification ({
authorEmail,
flagger,
group,
message,
}) {
if (!SLACK_FLAGGING_URL) {
return;
}
let titleLink;
let authorName;
let title = `Flag in ${group.name}`;
let text = `${flagger.profile.name} (${flagger.id}) flagged a message (language: ${flagger.preferences.language})`;
if (group.id === TAVERN_ID) {
titleLink = `${BASE_URL}/#/options/groups/tavern`;
} else if (group.privacy === 'public') {
titleLink = `${BASE_URL}/#/options/groups/guilds/${group.id}`;
} else {
title += ` - (${group.privacy} ${group.type})`;
}
if (!message.user && message.uuid === 'system') {
authorName = 'System Message';
} else {
authorName = `${message.user} - ${authorEmail} - ${message.uuid}`;
}
flagSlack.send({
text,
attachments: [{
fallback: 'Flag Message',
color: 'danger',
author_name: authorName,
title,
title_link: titleLink,
text: message.text,
footer: `<${SLACK_FLAGGING_FOOTER_LINK}?groupId=${group.id}&chatId=${message.id}|Flag this message>`,
mrkdwn_in: [
'text',
],
}],
});
}
function sendSubscriptionNotification ({
buyer,
recipient,
paymentMethod,
months,
groupId,
}) {
if (!SLACK_SUBSCRIPTIONS_URL) {
return;
}
let text;
let timestamp = new Date();
if (recipient.id) {
text = `${buyer.name} ${buyer.id} ${buyer.email} bought a ${months}-month gift subscription for ${recipient.name} ${recipient.id} ${recipient.email} using ${paymentMethod} on ${timestamp}`;
} else if (groupId) {
text = `${buyer.name} ${buyer.id} ${buyer.email} bought a 1-month recurring group-plan for ${groupId} using ${paymentMethod} on ${timestamp}`;
} else {
text = `${buyer.name} ${buyer.id} ${buyer.email} bought a ${months}-month recurring subscription using ${paymentMethod} on ${timestamp}`;
}
subscriptionSlack.send({
text,
});
}
module.exports = {
sendFlagNotification,
sendSubscriptionNotification,
};
function sendSlurNotification ({
authorEmail,
author,
group,
message,
}) {
if (!SLACK_FLAGGING_URL) {
return;
}
let titleLink;
let authorName;
let title = `Slur in ${group.name}`;
let text = `${author.profile.name} (${author._id}) tried to post a slur`;
if (group.id === TAVERN_ID) {
titleLink = `${BASE_URL}/#/options/groups/tavern`;
} else if (group.privacy === 'public') {
titleLink = `${BASE_URL}/#/options/groups/guilds/${group.id}`;
} else {
title += ` - (${group.privacy} ${group.type})`;
}
authorName = `${author.profile.name} - ${authorEmail} - ${author.id}`;
flagSlack.send({
text,
attachments: [{
fallback: 'Slur Message',
color: 'danger',
author_name: authorName,
title,
title_link: titleLink,
text: message,
// What to replace the footer with?
// footer: `<${SLACK_FLAGGING_FOOTER_LINK}?groupId=${group.id}&chatId=${message.id}|Flag this message>`,
mrkdwn_in: [
'text',
],
}],
});
}
module.exports = {
sendFlagNotification, sendSubscriptionNotification, sendSlurNotification,
};