Chat flag inbox (#9761)

* Refactored chat reporting

* Added inbox flag chat

* Added flag chat to inbox

* Added you have flagged message
This commit is contained in:
Keith Holliday
2018-01-08 13:13:25 -06:00
committed by GitHub
parent 7eac5cebf5
commit 98d4fb0f34
15 changed files with 494 additions and 218 deletions

View File

@@ -5,6 +5,7 @@ import {
import { find } from 'lodash'; import { find } from 'lodash';
describe('POST /chat/:chatId/flag', () => { describe('POST /chat/:chatId/flag', () => {
context('Flags a Group Chat', () => {
let user, admin, anotherUser, group; let user, admin, anotherUser, group;
const TEST_MESSAGE = 'Test Message'; const TEST_MESSAGE = 'Test Message';
@@ -145,4 +146,40 @@ describe('POST /chat/:chatId/flag', () => {
expect(auMessageToCheck).to.not.exist; expect(auMessageToCheck).to.not.exist;
}); });
});
context('Flags an inbox chat', () => {
let user;
beforeEach(async () => {
user = await generateUser();
});
it('Flags a chat', async () => {
const messageToSend = 'messageToSend';
const receiver = await generateUser();
await user.post('/members/send-private-message', {
message: messageToSend,
toUserId: receiver._id,
});
const updatedReceiver = await receiver.get('/user');
const sendersMessageInReceiversInbox = find(updatedReceiver.inbox.messages, (message) => {
return message.uuid === user._id && message.text === messageToSend;
});
const flagResult = await receiver.post(`/chat/${sendersMessageInReceiversInbox.id}/flag`);
expect(flagResult.flags[receiver._id]).to.equal(true);
expect(flagResult.flagCount).to.equal(1);
const updatedReceiverAfterFlag = await receiver.get('/user');
const receiversInboxAfterFlag = _.find(updatedReceiverAfterFlag.inbox.messages, (message) => {
return message.uuid === user._id && message.text === messageToSend;
});
expect(receiversInboxAfterFlag.flags[receiver._id]).to.equal(true);
expect(receiversInboxAfterFlag.flagCount).to.equal(1);
});
});
}); });

View File

@@ -9,6 +9,7 @@ div
h2 {{$t('tipTitle', {tipNumber: currentTipNumber})}} h2 {{$t('tipTitle', {tipNumber: currentTipNumber})}}
p {{currentTip}} p {{currentTip}}
#app(:class='{"casting-spell": castingSpell}') #app(:class='{"casting-spell": castingSpell}')
report-flag-modal
amazon-payments-modal amazon-payments-modal
snackbars snackbars
router-view(v-if="!isUserLoggedIn || isStaticPage") router-view(v-if="!isUserLoggedIn || isStaticPage")
@@ -118,6 +119,7 @@ import SelectMembersModal from 'client/components/selectMembersModal.vue';
import notifications from 'client/mixins/notifications'; import notifications from 'client/mixins/notifications';
import { setup as setupPayments } from 'client/libs/payments'; import { setup as setupPayments } from 'client/libs/payments';
import amazonPaymentsModal from 'client/components/payments/amazonModal'; import amazonPaymentsModal from 'client/components/payments/amazonModal';
import reportFlagModal from 'client/components/chat/reportFlagModal';
export default { export default {
mixins: [notifications], mixins: [notifications],
@@ -131,6 +133,7 @@ export default {
BuyModal, BuyModal,
SelectMembersModal, SelectMembersModal,
amazonPaymentsModal, amazonPaymentsModal,
reportFlagModal,
}, },
data () { data () {
return { return {

View File

@@ -3,6 +3,7 @@ div
.mentioned-icon(v-if='isUserMentioned') .mentioned-icon(v-if='isUserMentioned')
.message-hidden(v-if='msg.flagCount === 1 && user.contributor.admin') Message flagged once, not hidden .message-hidden(v-if='msg.flagCount === 1 && user.contributor.admin') Message flagged once, not hidden
.message-hidden(v-if='msg.flagCount > 1 && user.contributor.admin') Message hidden .message-hidden(v-if='msg.flagCount > 1 && user.contributor.admin') Message hidden
.flag-message(v-if='msg.flags && msg.flags[user._id]') {{$t('youFlaggedThisMessage')}}
.card-body .card-body
h3.leader( h3.leader(
:class='userLevelStyle(msg)', :class='userLevelStyle(msg)',
@@ -23,7 +24,7 @@ div
.svg-icon(v-html="icons.copy") .svg-icon(v-html="icons.copy")
| {{$t('copyAsTodo')}} | {{$t('copyAsTodo')}}
// @TODO make copyAsTodo work in the inbox // @TODO make copyAsTodo work in the inbox
span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted && msg.uuid !== "system"', @click='report(msg)') span.action(v-if='user.flags.communityGuidelinesAccepted && msg.uuid !== "system"', @click='report(msg)')
.svg-icon(v-html="icons.report") .svg-icon(v-html="icons.report")
| {{$t('report')}} | {{$t('report')}}
// @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys // @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys
@@ -49,7 +50,7 @@ div
top: -.5em; top: -.5em;
} }
.message-hidden { .message-hidden, .flag-message {
margin-left: 1.5em; margin-left: 1.5em;
margin-top: 1em; margin-top: 1em;
color: red; color: red;

View File

@@ -3,7 +3,6 @@
.row .row
.col-12 .col-12
copy-as-todo-modal(:group-name='groupName', :group-id='groupId') copy-as-todo-modal(:group-name='groupName', :group-id='groupId')
report-flag-modal
div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)') div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)')
// @TODO: is there a different way to do these conditionals? This creates an infinite loop // @TODO: is there a different way to do these conditionals? This creates an infinite loop
//.hr(v-if='displayDivider(msg)') //.hr(v-if='displayDivider(msg)')
@@ -83,14 +82,12 @@ import findIndex from 'lodash/findIndex';
import Avatar from '../avatar'; import Avatar from '../avatar';
import copyAsTodoModal from './copyAsTodoModal'; import copyAsTodoModal from './copyAsTodoModal';
import reportFlagModal from './reportFlagModal';
import chatCard from './chatCard'; import chatCard from './chatCard';
export default { export default {
props: ['chat', 'groupId', 'groupName', 'inbox'], props: ['chat', 'groupId', 'groupName', 'inbox'],
components: { components: {
copyAsTodoModal, copyAsTodoModal,
reportFlagModal,
chatCard, chatCard,
Avatar, Avatar,
}, },

View File

@@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
b-modal#report-flag(:title='$t("abuseFlagModalHeading")', size='lg', :hide-footer='true') b-modal#report-flag(:title='$t("abuseFlagModalHeading")', size='lg', :hide-footer='true', v-if='user')
.modal-header .modal-header
h4(v-html="$t('abuseFlagModalHeading', reportData)") h4(v-html="$t('abuseFlagModalHeading', reportData)")
.modal-body .modal-body
@@ -49,7 +49,7 @@ export default {
}, },
created () { created () {
this.$root.$on('habitica::report-chat', data => { this.$root.$on('habitica::report-chat', data => {
if (!data.message || !data.groupId) return; if (!data.message) return;
this.abuseObject = data.message; this.abuseObject = data.message;
this.groupId = data.groupId; this.groupId = data.groupId;
this.$root.$emit('bv::show::modal', 'report-flag'); this.$root.$emit('bv::show::modal', 'report-flag');
@@ -64,10 +64,18 @@ export default {
}, },
async reportAbuse () { async reportAbuse () {
this.notify('Thank you for reporting this violation. The moderators have been notified.'); this.notify('Thank you for reporting this violation. The moderators have been notified.');
if (!this.groupId) {
await this.$store.dispatch('chat:flagInbox', {
chatId: this.abuseObject.id,
});
} else {
await this.$store.dispatch('chat:flag', { await this.$store.dispatch('chat:flag', {
groupId: this.groupId, groupId: this.groupId,
chatId: this.abuseObject.id, chatId: this.abuseObject.id,
}); });
}
this.close(); this.close();
}, },
async clearFlagCount () { async clearFlagCount () {

View File

@@ -239,6 +239,7 @@ export default {
user: message.user, user: message.user,
uuid: message.uuid, uuid: message.uuid,
id: message.id, id: message.id,
flags: message.flags,
}; };
if (message.sent) { if (message.sent) {

View File

@@ -74,6 +74,12 @@ export async function flag (store, payload) {
return response.data.data; return response.data.data;
} }
export async function flagInbox (store, payload) {
let url = `/api/v3/chat/${payload.chatId}/flag`;
let response = await axios.post(url);
return response.data.data;
}
export async function clearFlagCount (store, payload) { export async function clearFlagCount (store, payload) {
let url = `/api/v3/groups/${payload.groupId}/chat/${payload.chatId}/clearflags`; let url = `/api/v3/groups/${payload.groupId}/chat/${payload.chatId}/clearflags`;
let response = await axios.post(url); let response = await axios.post(url);

View File

@@ -66,5 +66,6 @@
"messageNotificationNotFound": "Notification not found.", "messageNotificationNotFound": "Notification not found.",
"notificationsRequired": "Notification ids are required.", "notificationsRequired": "Notification ids are required.",
"beginningOfConversation": "This is the beginning of your conversation with <%= userName %>. Remember to be kind, respectful, and follow the Community Guidelines!" "beginningOfConversation": "This is the beginning of your conversation with <%= userName %>. Remember to be kind, respectful, and follow the Community Guidelines!",
"youFlaggedThisMessage": "You have reported this message to moderators. They will contact you about the issue soon."
} }

View File

@@ -11,6 +11,8 @@ import { removeFromArray } from '../../libs/collectionManipulators';
import { getUserInfo, getGroupUrl, sendTxn } from '../../libs/email'; import { getUserInfo, getGroupUrl, sendTxn } from '../../libs/email';
import slack from '../../libs/slack'; import slack from '../../libs/slack';
import pusher from '../../libs/pusher'; import pusher from '../../libs/pusher';
import { getAuthorEmailFromMessage } from '../../libs/chat';
import { chatReporterFactory } from '../../libs/chatReporting/chatReporterFactory';
import nconf from 'nconf'; import nconf from 'nconf';
import Bluebird from 'bluebird'; import Bluebird from 'bluebird';
import bannedWords from '../../libs/bannedWords'; import bannedWords from '../../libs/bannedWords';
@@ -22,7 +24,6 @@ const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email)
return { email, canSend: true }; return { email, canSend: true };
}); });
const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL');
/** /**
* @apiDefine MessageNotFound * @apiDefine MessageNotFound
* @apiError (404) {NotFound} MessageNotFound The specified message could not be found. * @apiError (404) {NotFound} MessageNotFound The specified message could not be found.
@@ -40,22 +41,6 @@ const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL');
let api = {}; let api = {};
async function getAuthorEmailFromMessage (message) {
let authorId = message.uuid;
if (authorId === 'system') {
return 'system';
}
let author = await User.findOne({_id: authorId}, {auth: 1}).exec();
if (author) {
return getUserInfo(author, ['email']).email;
} else {
return 'Author Account Deleted';
}
}
function textContainsBannedSlur (message) { function textContainsBannedSlur (message) {
let bannedSlursMatched = getMatchesByWordArray(message, bannedSlurs); let bannedSlursMatched = getMatchesByWordArray(message, bannedSlurs);
return bannedSlursMatched.length > 0; return bannedSlursMatched.length > 0;
@@ -298,85 +283,51 @@ api.likeChat = {
* @apiError (404) {NotFound} AlreadyFlagged Chat messages cannot be flagged more than once by a user * @apiError (404) {NotFound} AlreadyFlagged Chat messages cannot be flagged more than once by a user
* @apiError (404) {NotFound} messageGroupChatFlagAlreadyReported The message has already been flagged * @apiError (404) {NotFound} messageGroupChatFlagAlreadyReported The message has already been flagged
*/ */
api.flagChat = { api.flagGroupChat = {
method: 'POST', method: 'POST',
url: '/groups/:groupId/chat/:chatId/flag', url: '/groups/:groupId/chat/:chatId/flag',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders()],
async handler (req, res) { async handler (req, res) {
let user = res.locals.user; const chatReporter = chatReporterFactory('Group', req, res);
let groupId = req.params.groupId; const message = await chatReporter.flag();
res.respond(200, message);
req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); },
req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); };
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
let group = await Group.getGroup({
user,
groupId,
optionalMembership: user.contributor.admin,
});
if (!group) throw new NotFound(res.t('groupNotFound'));
let message = _.find(group.chat, {id: req.params.chatId});
if (!message) throw new NotFound(res.t('messageGroupChatNotFound'));
if (message.uuid === 'system') throw new BadRequest(res.t('messageCannotFlagSystemMessages', {communityManagerEmail: COMMUNITY_MANAGER_EMAIL}));
let update = {$set: {}};
// Log user ids that have flagged the message
if (!message.flags) message.flags = {};
// TODO fix error type
if (message.flags[user._id] && !user.contributor.admin) throw new NotFound(res.t('messageGroupChatFlagAlreadyReported'));
message.flags[user._id] = true;
update.$set[`chat.$.flags.${user._id}`] = true;
// Log total number of flags (publicly viewable)
if (!message.flagCount) message.flagCount = 0;
if (user.contributor.admin) {
// Arbitrary amount, higher than 2
message.flagCount = 5;
} else {
message.flagCount++;
}
update.$set['chat.$.flagCount'] = message.flagCount;
await Group.update(
{_id: group._id, 'chat.id': message.id},
update
).exec();
let reporterEmailContent = getUserInfo(user, ['email']).email;
let authorEmail = await getAuthorEmailFromMessage(message);
let groupUrl = getGroupUrl(group);
sendTxn(FLAG_REPORT_EMAILS, 'flag-report-to-mods', [
{name: 'MESSAGE_TIME', content: (new Date(message.timestamp)).toString()},
{name: 'MESSAGE_TEXT', content: message.text},
{name: 'REPORTER_USERNAME', content: user.profile.name},
{name: 'REPORTER_UUID', content: user._id},
{name: 'REPORTER_EMAIL', content: reporterEmailContent},
{name: 'REPORTER_MODAL_URL', content: `/static/front/#?memberId=${user._id}`},
{name: 'AUTHOR_USERNAME', content: message.user},
{name: 'AUTHOR_UUID', content: message.uuid},
{name: 'AUTHOR_EMAIL', content: authorEmail},
{name: 'AUTHOR_MODAL_URL', content: `/static/front/#?memberId=${message.uuid}`},
{name: 'GROUP_NAME', content: group.name},
{name: 'GROUP_TYPE', content: group.type},
{name: 'GROUP_ID', content: group._id},
{name: 'GROUP_URL', content: groupUrl},
]);
slack.sendFlagNotification({
authorEmail,
flagger: user,
group,
message,
});
// @TODO:
/**
* @api {post} /api/v3/groups/:groupId/chat/:chatId/flag Flag a group chat message
* @apiDescription A message will be hidden from chat if two or more users flag a message. It will be hidden immediately if a moderator flags the message. An email is sent to the moderators about every flagged message.
* @apiName FlagChat
* @apiGroup Chat
*
* @apiParam (Path) {UUID} groupId The group id ('party' for the user party and 'habitrpg' for tavern are accepted)
* @apiParam (Path) {UUID} chatId The chat message id
*
* @apiSuccess {Object} data The flagged chat message
* @apiSuccess {UUID} data.id The id of the message
* @apiSuccess {String} data.text The text of the message
* @apiSuccess {Number} data.timestamp The timestamp of the message in milliseconds
* @apiSuccess {Object} data.likes The likes of the message
* @apiSuccess {Object} data.flags The flags of the message
* @apiSuccess {Number} data.flagCount The number of flags the message has
* @apiSuccess {UUID} data.uuid The user id of the author of the message
* @apiSuccess {String} data.user The username of the author of the message
*
* @apiUse GroupNotFound
* @apiUse MessageNotFound
* @apiUse GroupIdRequired
* @apiUse ChatIdRequired
* @apiError (404) {NotFound} AlreadyFlagged Chat messages cannot be flagged more than once by a user
* @apiError (404) {NotFound} messageGroupChatFlagAlreadyReported The message has already been flagged
*/
api.flagChat = {
method: 'POST',
url: '/chat/:chatId/flag',
middlewares: [authWithHeaders()],
async handler (req, res) {
const chatReporter = chatReporterFactory('Inbox', req, res);
const message = await chatReporter.flag();
res.respond(200, message); res.respond(200, message);
}, },
}; };

View File

@@ -0,0 +1,18 @@
import { model as User } from '../models/user';
import { getUserInfo } from './email';
export async function getAuthorEmailFromMessage (message) {
let authorId = message.uuid;
if (authorId === 'system') {
return 'system';
}
let author = await User.findOne({_id: authorId}, {auth: 1}).exec();
if (author) {
return getUserInfo(author, ['email']).email;
} else {
return 'Author Account Deleted';
}
}

View File

@@ -0,0 +1,36 @@
import {
} from '../errors';
import { getUserInfo } from '../email';
import { getAuthorEmailFromMessage } from '../chat';
export default class ChatReporter {
constructor (req, res) {
this.req = req;
this.res = res;
}
async validate () {}
async notify (group, message) {
const reporterEmailContent = getUserInfo(this.user, ['email']).email;
this.authorEmail = await getAuthorEmailFromMessage(message);
this.emailVariables = [
{name: 'MESSAGE_TIME', content: (new Date(message.timestamp)).toString()},
{name: 'MESSAGE_TEXT', content: message.text},
{name: 'REPORTER_USERNAME', content: this.user.profile.name},
{name: 'REPORTER_UUID', content: this.user._id},
{name: 'REPORTER_EMAIL', content: reporterEmailContent},
{name: 'REPORTER_MODAL_URL', content: `/static/front/#?memberId=${this.user._id}`},
{name: 'AUTHOR_USERNAME', content: message.user},
{name: 'AUTHOR_UUID', content: message.uuid},
{name: 'AUTHOR_EMAIL', content: this.authorEmail},
{name: 'AUTHOR_MODAL_URL', content: `/static/front/#?memberId=${message.uuid}`},
];
}
async flag () {
throw new Error('Flag must be implemented');
}
}

View File

@@ -0,0 +1,10 @@
import GroupChatReporter from './groupChatReporter';
import InboxChatReporter from './inboxChatReporter';
export function chatReporterFactory (type, req, res) {
if (type === 'Group') {
return new GroupChatReporter(req, res);
} else if (type === 'Inbox') {
return new InboxChatReporter(req, res);
}
}

View File

@@ -0,0 +1,97 @@
import find from 'lodash/find';
import nconf from 'nconf';
import ChatReporter from './chatReporter';
import {
BadRequest,
NotFound,
} from '../errors';
import { getGroupUrl, sendTxn } from '../email';
import slack from '../slack';
import { model as Group } from '../../models/group';
const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL');
const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => {
return { email, canSend: true };
});
export default class GroupChatReporter extends ChatReporter {
constructor (req, res) {
super(req, res);
this.user = res.locals.user;
this.groupId = req.params.groupId;
}
async validate () {
this.req.checkParams('groupId', this.res.t('groupIdRequired')).notEmpty();
this.req.checkParams('chatId', this.res.t('chatIdRequired')).notEmpty();
let validationErrors = this.req.validationErrors();
if (validationErrors) throw validationErrors;
let group = await Group.getGroup({
user: this.user,
groupId: this.groupId,
optionalMembership: this.user.contributor.admin,
});
if (!group) throw new NotFound(this.res.t('groupNotFound'));
let message = find(group.chat, {id: this.req.params.chatId});
if (!message) throw new NotFound(this.res.t('messageGroupChatNotFound'));
if (message.uuid === 'system') throw new BadRequest(this.res.t('messageCannotFlagSystemMessages', {communityManagerEmail: COMMUNITY_MANAGER_EMAIL}));
return {message, group};
}
async notify (group, message) {
await super.notify(group, message);
const groupUrl = getGroupUrl(group);
sendTxn(FLAG_REPORT_EMAILS, 'flag-report-to-mods', this.emailVariables.concat([
{name: 'GROUP_NAME', content: group.name},
{name: 'GROUP_TYPE', content: group.type},
{name: 'GROUP_ID', content: group._id},
{name: 'GROUP_URL', content: groupUrl},
]));
slack.sendFlagNotification({
authorEmail: this.authorEmail,
flagger: this.user,
group,
message,
});
}
async flagGroupMessage (group, message) {
let update = {$set: {}};
// Log user ids that have flagged the message
if (!message.flags) message.flags = {};
// TODO fix error type
if (message.flags[this.user._id] && !this.user.contributor.admin) throw new NotFound(this.res.t('messageGroupChatFlagAlreadyReported'));
message.flags[this.user._id] = true;
update.$set[`chat.$.flags.${this.user._id}`] = true;
// Log total number of flags (publicly viewable)
if (!message.flagCount) message.flagCount = 0;
if (this.user.contributor.admin) {
// Arbitrary amount, higher than 2
message.flagCount = 5;
} else {
message.flagCount++;
}
update.$set['chat.$.flagCount'] = message.flagCount;
await Group.update(
{_id: group._id, 'chat.id': message.id},
update
).exec();
}
async flag () {
let {message, group} = await this.validate();
await this.flagGroupMessage(group, message);
await this.notify(group, message);
return message;
}
}

View File

@@ -0,0 +1,74 @@
import find from 'lodash/find';
import nconf from 'nconf';
import ChatReporter from './chatReporter';
import {
NotFound,
} from '../errors';
import { sendTxn } from '../email';
import slack from '../slack';
const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => {
return { email, canSend: true };
});
export default class InboxChatReporter extends ChatReporter {
constructor (req, res) {
super(req, res);
this.user = res.locals.user;
}
async validate () {
this.req.checkParams('chatId', this.res.t('chatIdRequired')).notEmpty();
const validationErrors = this.req.validationErrors();
if (validationErrors) throw validationErrors;
const message = find(this.user.inbox.messages, {id: this.req.params.chatId});
if (!message) throw new NotFound(this.res.t('messageChatNotFound'));
return {message};
}
async notify (group, message) {
await super.notify(group, message);
sendTxn(FLAG_REPORT_EMAILS, 'flag-report-to-mods', this.emailVariables);
slack.sendInboxFlagNotification({
authorEmail: this.authorEmail,
flagger: this.user,
message,
});
}
async flagInboxMessage (message) {
let update = {$set: {}};
// Log user ids that have flagged the message
if (!message.flags) message.flags = {};
// TODO fix error type
if (message.flags[this.user._id] && !this.user.contributor.admin) throw new NotFound(this.res.t('messageGroupChatFlagAlreadyReported'));
message.flags[this.user._id] = true;
// update.$set[`inbox.messages.$.flags.${this.user._id}`] = true;
// Log total number of flags (publicly viewable)
if (!message.flagCount) message.flagCount = 0;
if (this.user.contributor.admin) {
// Arbitrary amount, higher than 2
message.flagCount = 5;
} else {
message.flagCount++;
}
update.$set['inbox.messages.$.flagCount'] = message.flagCount;
this.user.markModified('inbox.messages');
await this.user.save();
}
async flag () {
let {message} = await this.validate();
await this.flagInboxMessage(message);
await this.notify(null, message);
return message;
}
}

View File

@@ -64,6 +64,42 @@ function sendFlagNotification ({
}); });
} }
function sendInboxFlagNotification ({
authorEmail,
flagger,
message,
}) {
if (!SLACK_FLAGGING_URL) {
return;
}
let titleLink;
let authorName;
let title = `Flag in ${flagger.profile.name}'s Inbox'`;
let text = `${flagger.profile.name} (${flagger.id}) flagged a message (language: ${flagger.preferences.language})`;
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}?chatId=${message.id}|Flag this message>`,
mrkdwn_in: [
'text',
],
}],
});
}
function sendSubscriptionNotification ({ function sendSubscriptionNotification ({
buyer, buyer,
recipient, recipient,
@@ -137,5 +173,5 @@ function sendSlurNotification ({
} }
module.exports = { module.exports = {
sendFlagNotification, sendSubscriptionNotification, sendSlurNotification, sendFlagNotification, sendSubscriptionNotification, sendSlurNotification, sendInboxFlagNotification,
}; };