Add message formatters. Expose message formatters to plugins.

cshd
Dragory 2020-07-14 01:11:48 +03:00
parent 0c25afaec2
commit 8a975d7da4
No known key found for this signature in database
GPG Key ID: 5F387BA66DF8AAC1
3 changed files with 216 additions and 132 deletions

View File

@ -5,6 +5,7 @@ const knex = require('../knex');
const utils = require('../utils'); const utils = require('../utils');
const config = require('../config'); const config = require('../config');
const attachments = require('./attachments'); const attachments = require('./attachments');
const { formatters } = require('../formatters');
const ThreadMessage = require('./ThreadMessage'); const ThreadMessage = require('./ThreadMessage');
@ -28,133 +29,6 @@ class Thread {
utils.setDataModelProps(this, props); utils.setDataModelProps(this, props);
} }
/**
* @param {Eris.Member} moderator
* @param {string} text
* @param {boolean} isAnonymous
* @returns {string}
* @private
*/
_formatStaffReplyDM(moderator, text, isAnonymous) {
const mainRole = utils.getMainRole(moderator);
const modName = (config.useNicknames ? moderator.nick || moderator.user.username : moderator.user.username);
const modInfo = isAnonymous
? (mainRole ? mainRole.name : 'Moderator')
: (mainRole ? `(${mainRole.name}) ${modName}` : modName);
return `**${modInfo}:** ${text}`;
}
/**
* @param {Eris.Member} moderator
* @param {string} text
* @param {boolean} isAnonymous
* @param {number} messageNumber
* @param {number} timestamp
* @returns {string}
* @private
*/
_formatStaffReplyThreadMessage(moderator, text, isAnonymous, messageNumber, timestamp) {
const mainRole = utils.getMainRole(moderator);
const modName = (config.useNicknames ? moderator.nick || moderator.user.username : moderator.user.username);
const modInfo = isAnonymous
? `(Anonymous) (${modName}) ${mainRole ? mainRole.name : 'Moderator'}`
: (mainRole ? `(${mainRole.name}) ${modName}` : modName);
// TODO: Add \`[${messageNumber}]\` here once !edit and !delete exist
let result = `**${modInfo}:** ${text}`;
if (config.threadTimestamps) {
const formattedTimestamp = timestamp ? utils.getTimestamp(timestamp, 'x') : utils.getTimestamp();
result = `[${formattedTimestamp}] ${result}`;
}
return result;
}
/**
* @param {Eris.Member} moderator
* @param {string} text
* @param {boolean} isAnonymous
* @param {string[]} attachmentLinks
* @returns {string}
* @private
*/
_formatStaffReplyLogMessage(moderator, text, isAnonymous, attachmentLinks = []) {
const mainRole = utils.getMainRole(moderator);
const modName = moderator.user.username;
// Mirroring the DM formatting here...
const modInfo = isAnonymous
? (mainRole ? mainRole.name : 'Moderator')
: (mainRole ? `(${mainRole.name}) ${modName}` : modName);
let result = `**${modInfo}:** ${text}`;
if (attachmentLinks.length) {
result += '\n';
for (const link of attachmentLinks) {
result += `\n**Attachment:** ${link}`;
}
}
return result;
}
/**
* @param {Eris.User} user
* @param {string} body
* @param {Eris.EmbedBase[]} embeds
* @param {string[]} formattedAttachments
* @param {number} timestamp
* @return string
* @private
*/
_formatUserReplyThreadMessage(user, body, embeds, formattedAttachments = [], timestamp) {
const content = (body.trim() === '' && embeds.length)
? '<message contains embeds>'
: body;
let result = `**${user.username}#${user.discriminator}:** ${content}`;
if (formattedAttachments.length) {
for (const formatted of formattedAttachments) {
result += `\n\n${formatted}`;
}
}
if (config.threadTimestamps) {
const formattedTimestamp = timestamp ? utils.getTimestamp(timestamp, 'x') : utils.getTimestamp();
result = `[${formattedTimestamp}] ${result}`;
}
return result;
}
/**
* @param {Eris.User} user
* @param {string} body
* @param {Eris.EmbedBase[]} embeds
* @param {string[]} formattedAttachments
* @return string
* @private
*/
_formatUserReplyLogMessage(user, body, embeds, formattedAttachments = []) {
const content = (body.trim() === '' && embeds.length)
? '<message contains embeds>'
: body;
let result = content;
if (formattedAttachments.length) {
for (const formatted of formattedAttachments) {
result += `\n\n${formatted}`;
}
}
return result;
}
/** /**
* @param {string} text * @param {string} text
* @param {Eris.MessageFile|Eris.MessageFile[]} file * @param {Eris.MessageFile|Eris.MessageFile[]} file
@ -285,7 +159,7 @@ class Thread {
} }
// Send the reply DM // Send the reply DM
const dmContent = this._formatStaffReplyDM(moderator, text, isAnonymous); const dmContent = formatters.formatStaffReplyDM(moderator, text, { isAnonymous });
let dmMessage; let dmMessage;
try { try {
dmMessage = await this._sendDMToUser(dmContent, files); dmMessage = await this._sendDMToUser(dmContent, files);
@ -295,7 +169,7 @@ class Thread {
} }
// Save the log entry // Save the log entry
const logContent = this._formatStaffReplyLogMessage(moderator, text, isAnonymous, attachmentLinks); const logContent = formatters.formatStaffReplyLogMessage(moderator, text, { isAnonymous, attachmentLinks });
const threadMessage = await this._addThreadMessageToDB({ const threadMessage = await this._addThreadMessageToDB({
message_type: THREAD_MESSAGE_TYPE.TO_USER, message_type: THREAD_MESSAGE_TYPE.TO_USER,
user_id: moderator.id, user_id: moderator.id,
@ -306,7 +180,7 @@ class Thread {
}); });
// Show the reply in the inbox thread // Show the reply in the inbox thread
const inboxContent = this._formatStaffReplyThreadMessage(moderator, text, isAnonymous, threadMessage.message_number, null); const inboxContent = formatters.formatStaffReplyThreadMessage(moderator, text, threadMessage.message_number, { isAnonymous });
const inboxMessage = await this._postToThreadChannel(inboxContent, files); const inboxMessage = await this._postToThreadChannel(inboxContent, files);
await this._updateThreadMessage(threadMessage.id, { inbox_message_id: inboxMessage.id }); await this._updateThreadMessage(threadMessage.id, { inbox_message_id: inboxMessage.id });
@ -347,7 +221,7 @@ class Thread {
} }
// Save log entry // Save log entry
const logContent = this._formatUserReplyLogMessage(msg.author, msg.content, msg.embeds, logFormattedAttachments); const logContent = formatters.formatUserReplyLogMessage(msg.author, msg, { attachmentLinks: logFormattedAttachments });
const threadMessage = await this._addThreadMessageToDB({ const threadMessage = await this._addThreadMessageToDB({
message_type: THREAD_MESSAGE_TYPE.FROM_USER, message_type: THREAD_MESSAGE_TYPE.FROM_USER,
user_id: this.user_id, user_id: this.user_id,
@ -358,7 +232,7 @@ class Thread {
}); });
// Show user reply in the inbox thread // Show user reply in the inbox thread
const inboxContent = this._formatUserReplyThreadMessage(msg.author, msg.content, msg.embeds, threadFormattedAttachments, null); const inboxContent = formatters.formatUserReplyThreadMessage(msg.author, msg, { attachmentLinks: threadFormattedAttachments });
const inboxMessage = await this._postToThreadChannel(inboxContent, attachmentFiles); const inboxMessage = await this._postToThreadChannel(inboxContent, attachmentFiles);
if (inboxMessage) await this._updateThreadMessage(threadMessage.id, { inbox_message_id: inboxMessage.id }); if (inboxMessage) await this._updateThreadMessage(threadMessage.id, { inbox_message_id: inboxMessage.id });

208
src/formatters.js Normal file
View File

@ -0,0 +1,208 @@
const Eris = require('eris');
const utils = require('./utils');
const config = require('./config');
/**
* Function to format the DM that is sent to the user when a staff member replies to them via !reply
* @callback FormatStaffReplyDM
* @param {Eris.Member} moderator Staff member that is replying
* @param {string} text Reply text
* @param {{
* isAnonymous: boolean,
* }} opts={}
* @return {string} Message content to send as a DM
*/
/**
* Function to format a staff reply in a thread channel
* @callback FormatStaffReplyThreadMessage
* @param {Eris.Member} moderator
* @param {string} text
* @param {number} messageNumber
* @param {{
* isAnonymous: boolean,
* }} opts={}
* @return {string} Message content to post in the thread channel
*/
/**
* Function to format a staff reply in a log
* @callback FormatStaffReplyLogMessage
* @param {Eris.Member} moderator
* @param {string} text
* @param {{
* isAnonymous: boolean,
* attachmentLinks: string[],
* }} opts={}
* @returns {string} Text to show in the log
*/
/**
* Function to format a user reply in a thread channel
* @callback FormatUserReplyThreadMessage
* @param {Eris.User} user Use that sent the reply
* @param {Eris.Message} msg The message object that the user sent
* @param {{
* attachmentLinks: string[],
* }} opts
* @return {string} Message content to post in the thread channel
*/
/**
* @callback FormatUserReplyLogMessage
* @param {Eris.User} user
* @param {Eris.Message} msg
* @param {{
* attachmentLinks: string[],
* }} opts={}
* @return {string} Text to show in the log
*/
/**
* @typedef MessageFormatters
* @property {FormatStaffReplyDM} formatStaffReplyDM
* @property {FormatStaffReplyThreadMessage} formatStaffReplyThreadMessage
* @property {FormatStaffReplyLogMessage} formatStaffReplyLogMessage
* @property {FormatUserReplyThreadMessage} formatUserReplyThreadMessage
* @property {FormatUserReplyLogMessage} formatUserReplyLogMessage
*/
/**
* @type {MessageFormatters}
*/
const defaultFormatters = {
formatStaffReplyDM(moderator, text, opts = {}) {
const mainRole = utils.getMainRole(moderator);
const modName = (config.useNicknames ? moderator.nick || moderator.user.username : moderator.user.username);
const modInfo = opts.isAnonymous
? (mainRole ? mainRole.name : 'Moderator')
: (mainRole ? `(${mainRole.name}) ${modName}` : modName);
return `**${modInfo}:** ${text}`;
},
formatStaffReplyThreadMessage(moderator, text, messageNumber, opts = {}) {
const mainRole = utils.getMainRole(moderator);
const modName = (config.useNicknames ? moderator.nick || moderator.user.username : moderator.user.username);
const modInfo = opts.isAnonymous
? `(Anonymous) (${modName}) ${mainRole ? mainRole.name : 'Moderator'}`
: (mainRole ? `(${mainRole.name}) ${modName}` : modName);
// TODO: Add \`[${messageNumber}]\` here once !edit and !delete exist
let result = `**${modInfo}:** ${text}`;
if (config.threadTimestamps) {
const formattedTimestamp = utils.getTimestamp();
result = `[${formattedTimestamp}] ${result}`;
}
return result;
},
formatStaffReplyLogMessage(moderator, text, opts = {}) {
const mainRole = utils.getMainRole(moderator);
const modName = moderator.user.username;
// Mirroring the DM formatting here...
const modInfo = opts.isAnonymous
? (mainRole ? mainRole.name : 'Moderator')
: (mainRole ? `(${mainRole.name}) ${modName}` : modName);
let result = `**${modInfo}:** ${text}`;
if (opts.attachmentLinks && opts.attachmentLinks.length) {
result += '\n';
for (const link of opts.attachmentLinks) {
result += `\n**Attachment:** ${link}`;
}
}
return result;
},
formatUserReplyThreadMessage(user, msg, opts = {}) {
const content = (msg.content.trim() === '' && msg.embeds.length)
? '<message contains embeds>'
: msg.content;
let result = `**${user.username}#${user.discriminator}:** ${content}`;
if (opts.attachmentLinks && opts.attachmentLinks.length) {
for (const link of opts.attachmentLinks) {
result += `\n\n${link}`;
}
}
if (config.threadTimestamps) {
const formattedTimestamp = utils.getTimestamp(msg.timestamp, 'x');
result = `[${formattedTimestamp}] ${result}`;
}
return result;
},
formatUserReplyLogMessage(user, msg, opts = {}) {
const content = (msg.content.trim() === '' && msg.embeds.length)
? '<message contains embeds>'
: msg.content;
let result = content;
if (opts.attachmentLinks && opts.attachmentLinks.length) {
for (const link of opts.attachmentLinks) {
result += `\n\n${link}`;
}
}
return result;
},
};
/**
* @type {MessageFormatters}
*/
const formatters = { ...defaultFormatters };
module.exports = {
formatters,
/**
* @param {FormatStaffReplyDM} fn
* @return {void}
*/
setStaffReplyDMFormatter(fn) {
formatters.formatStaffReplyDM = fn;
},
/**
* @param {FormatStaffReplyThreadMessage} fn
* @return {void}
*/
setStaffReplyThreadMessageFormatter(fn) {
formatters.formatStaffReplyThreadMessage = fn;
},
/**
* @param {FormatStaffReplyLogMessage} fn
* @return {void}
*/
setStaffReplyLogMessageFormatter(fn) {
formatters.formatStaffReplyLogMessage = fn;
},
/**
* @param {FormatUserReplyThreadMessage} fn
* @return {void}
*/
setUserReplyThreadMessageFormatter(fn) {
formatters.formatUserReplyThreadMessage = fn;
},
/**
* @param {FormatUserReplyLogMessage} fn
* @return {void}
*/
setUserReplyLogMessageFormatter(fn) {
formatters.formatUserReplyLogMessage = fn;
},
};

View File

@ -1,5 +1,6 @@
const attachments = require('./data/attachments'); const attachments = require('./data/attachments');
const { beforeNewThread } = require('./hooks'); const { beforeNewThread } = require('./hooks');
const formats = require('./formatters');
module.exports = { module.exports = {
getPluginAPI({ bot, knex, config, commands }) { getPluginAPI({ bot, knex, config, commands }) {
@ -21,6 +22,7 @@ module.exports = {
hooks: { hooks: {
beforeNewThread, beforeNewThread,
}, },
formats,
}; };
}, },