diff --git a/src/data/Thread.js b/src/data/Thread.js index f4357eb..0304dcc 100644 --- a/src/data/Thread.js +++ b/src/data/Thread.js @@ -286,18 +286,22 @@ class Thread { /** * @param {Eris.MessageContent} content * @param {Eris.MessageFile} file + * @param {object} opts + * @param {boolean} opts.saveToLog + * @param {string} opts.logBody * @returns {Promise} */ - async postSystemMessage(content, file = null) { + async postSystemMessage(content, file = null, opts = {}) { const msg = await this._postToThreadChannel(content, file); - if (msg) { + if (msg && opts.saveToLog !== false) { + const finalLogBody = opts.logBody || msg.content || ''; await this._addThreadMessageToDB({ message_type: THREAD_MESSAGE_TYPE.SYSTEM, user_id: null, user_name: '', - body: typeof content === 'string' ? content : content.content, + body: finalLogBody, is_anonymous: 0, - dm_message_id: msg.id + inbox_message_id: msg.id, }); } } @@ -305,18 +309,24 @@ class Thread { /** * @param {Eris.MessageContent} content * @param {Eris.MessageFile} file + * @param {object} opts + * @param {boolean} opts.saveToLog + * @param {string} opts.logBody * @returns {Promise} */ - async sendSystemMessageToUser(content, file = null) { + async sendSystemMessageToUser(content, file = null, opts = {}) { const msg = await this._sendDMToUser(content, file); - await this._addThreadMessageToDB({ - message_type: THREAD_MESSAGE_TYPE.SYSTEM_TO_USER, - user_id: null, - user_name: '', - body: typeof content === 'string' ? content : content.content, - is_anonymous: 0, - dm_message_id: msg.id - }); + if (opts.saveToLog !== false) { + const finalLogBody = opts.logBody || msg.content || ''; + await this._addThreadMessageToDB({ + message_type: THREAD_MESSAGE_TYPE.SYSTEM_TO_USER, + user_id: null, + user_name: '', + body: finalLogBody, + is_anonymous: 0, + dm_message_id: msg.id, + }); + } } /** @@ -529,6 +539,56 @@ class Thread { }); } + /** + * @param {Eris.Member} moderator + * @param {ThreadMessage} threadMessage + * @param {string} newText + * @param {object} opts + * @param {boolean} opts.quiet Whether to suppress edit notifications in the thread channel + * @returns {Promise} + */ + async editStaffReply(moderator, threadMessage, newText, opts = {}) { + const formattedThreadMessage = formatters.formatStaffReplyThreadMessage( + moderator, + newText, + threadMessage.message_number, + { isAnonymous: threadMessage.is_anonymous } + ); + + const formattedDM = formatters.formatStaffReplyDM( + moderator, + newText, + { isAnonymous: threadMessage.is_anonymous } + ); + + await bot.editMessage(threadMessage.dm_channel_id, threadMessage.dm_message_id, formattedDM); + await bot.editMessage(this.channel_id, threadMessage.inbox_message_id, formattedThreadMessage); + + if (! opts.quiet) { + const threadNotification = formatters.formatStaffReplyEditNotificationThreadMessage(moderator, threadMessage, newText); + const logNotification = formatters.formatStaffReplyEditNotificationLogMessage(moderator, threadMessage, newText); + await this.postSystemMessage(threadNotification, null, { logBody: logNotification }); + } + } + + /** + * @param {Eris.Member} moderator + * @param {ThreadMessage} threadMessage + * @param {object} opts + * @param {boolean} opts.quiet Whether to suppress edit notifications in the thread channel + * @returns {Promise} + */ + async deleteStaffReply(moderator, threadMessage, opts = {}) { + await bot.deleteMessage(threadMessage.dm_channel_id, threadMessage.dm_message_id); + await bot.deleteMessage(this.channel_id, threadMessage.inbox_message_id); + + if (! opts.quiet) { + const threadNotification = formatters.formatStaffReplyDeletionNotificationThreadMessage(moderator, threadMessage); + const logNotification = formatters.formatStaffReplyDeletionNotificationLogMessage(moderator, threadMessage); + await this.postSystemMessage(threadNotification, null, { logBody: logNotification }); + } + } + /** * @returns {Promise} */ diff --git a/src/formatters.js b/src/formatters.js index 04ed053..c3af718 100644 --- a/src/formatters.js +++ b/src/formatters.js @@ -1,6 +1,7 @@ const Eris = require('eris'); const utils = require('./utils'); const config = require('./cfg'); +const ThreadMessage = require('./data/ThreadMessage'); /** * Function to format the DM that is sent to the user when a staff member replies to them via !reply @@ -49,6 +50,7 @@ const config = require('./cfg'); */ /** + * Function to format a user reply in a log * @callback FormatUserReplyLogMessage * @param {Eris.User} user * @param {Eris.Message} msg @@ -58,6 +60,40 @@ const config = require('./cfg'); * @return {string} Text to show in the log */ +/** + * Function to format the inbox channel notification for a staff reply edit + * @callback FormatStaffReplyEditNotificationThreadMessage + * @param {Eris.Member} moderator + * @param {ThreadMessage} threadMessage + * @param {string} newText + * @return {Eris.MessageContent} Message content to post in the thread channel + */ + +/** + * Function to format the log notification for a staff reply edit + * @callback FormatStaffReplyEditNotificationLogMessage + * @param {Eris.Member} moderator + * @param {ThreadMessage} threadMessage + * @param {string} newText + * @return {string} Text to show in the log + */ + +/** + * Function to format the inbox channel notification for a staff reply deletion + * @callback FormatStaffReplyDeletionNotificationThreadMessage + * @param {Eris.Member} moderator + * @param {ThreadMessage} threadMessage + * @return {Eris.MessageContent} Message content to post in the thread channel + */ + +/** + * Function to format the log notification for a staff reply deletion + * @callback FormatStaffReplyDeletionNotificationLogMessage + * @param {Eris.Member} moderator + * @param {ThreadMessage} threadMessage + * @return {string} Text to show in the log + */ + /** * @typedef MessageFormatters * @property {FormatStaffReplyDM} formatStaffReplyDM @@ -65,6 +101,10 @@ const config = require('./cfg'); * @property {FormatStaffReplyLogMessage} formatStaffReplyLogMessage * @property {FormatUserReplyThreadMessage} formatUserReplyThreadMessage * @property {FormatUserReplyLogMessage} formatUserReplyLogMessage + * @property {FormatStaffReplyEditNotificationThreadMessage} formatStaffReplyEditNotificationThreadMessage + * @property {FormatStaffReplyEditNotificationLogMessage} formatStaffReplyEditNotificationLogMessage + * @property {FormatStaffReplyDeletionNotificationThreadMessage} formatStaffReplyDeletionNotificationThreadMessage + * @property {FormatStaffReplyDeletionNotificationLogMessage} formatStaffReplyDeletionNotificationLogMessage */ /** @@ -156,6 +196,32 @@ const defaultFormatters = { return result; }, + + formatStaffReplyEditNotificationThreadMessage(moderator, threadMessage, newText) { + let content = `**${moderator.user.username}#${moderator.user.discriminator} (\`${moderator.id}\`) edited reply \`[${threadMessage.message_number}]\`:**`; + content += `\n\`B:\` ${threadMessage.body}`; + content += `\n\`A:\` ${newText}`; + return utils.disableLinkPreviews(content); + }, + + formatStaffReplyEditNotificationLogMessage(moderator, threadMessage, newText) { + let content = `${moderator.user.username}#${moderator.user.discriminator} (${moderator.id}) edited reply [${threadMessage.message_number}]:`; + content += `\nB: ${threadMessage.body}`; + content += `\nA: ${newText}`; + return content; + }, + + formatStaffReplyDeletionNotificationThreadMessage(moderator, threadMessage) { + let content = `**${moderator.user.username}#${moderator.user.discriminator} (\`${moderator.id}\`) deleted reply \`[${threadMessage.message_number}]\`:**`; + content += `\n\`B:\` ${threadMessage.body}`; + return utils.disableLinkPreviews(content); + }, + + formatStaffReplyDeletionNotificationLogMessage(moderator, threadMessage) { + let content = `${moderator.user.username}#${moderator.user.discriminator} (${moderator.id}) deleted reply [${threadMessage.message_number}]:`; + content += `\nB: ${threadMessage.body}`; + return content; + }, }; /** @@ -205,4 +271,36 @@ module.exports = { setUserReplyLogMessageFormatter(fn) { formatters.formatUserReplyLogMessage = fn; }, + + /** + * @param {FormatStaffReplyEditNotificationThreadMessage} fn + * @return {void} + */ + setStaffReplyEditNotificationThreadMessageFormatter(fn) { + formatters.formatStaffReplyEditNotificationThreadMessage = fn; + }, + + /** + * @param {FormatStaffReplyEditNotificationLogMessage} fn + * @return {void} + */ + setStaffReplyEditNotificationLogMessageFormatter(fn) { + formatters.formatStaffReplyEditNotificationLogMessage = fn; + }, + + /** + * @param {FormatStaffReplyDeletionNotificationThreadMessage} fn + * @return {void} + */ + setStaffReplyDeletionNotificationThreadMessageFormatter(fn) { + formatters.formatStaffReplyDeletionNotificationThreadMessage = fn; + }, + + /** + * @param {FormatStaffReplyDeletionNotificationLogMessage} fn + * @return {void} + */ + setStaffReplyDeletionNotificationLogMessageFormatter(fn) { + formatters.formatStaffReplyDeletionNotificationLogMessage = fn; + }, };