Limit replies to fit within one message
This applies to both the DM to be sent to the user, and the message created in the thread channel. This is because edits (via !edit) could change the amount of messages a reply takes (based on message formatting), leading to either being unable to post the full edit if it goes over the message limits, or having to edit a previous message to be 'empty' if the result of the edit would take fewer messages to post than the original reply. This also fixes an issue where !edit/!delete would not apply to more than the first message created by a reply - whether in user DMs or in the thread channel.cshd
parent
42f6e79df8
commit
d5ea95d9e9
|
@ -223,8 +223,16 @@ class Thread {
|
|||
attachments: attachmentLinks,
|
||||
});
|
||||
|
||||
// Send the reply DM
|
||||
const dmContent = formatters.formatStaffReplyDM(threadMessage);
|
||||
const inboxContent = formatters.formatStaffReplyThreadMessage(threadMessage);
|
||||
|
||||
// Because moderator replies have to be editable, we enforce them to fit within 1 message
|
||||
if (! utils.messageContentIsWithinMaxLength(dmContent) || ! utils.messageContentIsWithinMaxLength(inboxContent)) {
|
||||
await this.postSystemMessage("Reply is too long! Make sure your reply is under 2000 characters total, moderator name in the reply included.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send the reply DM
|
||||
let dmMessage;
|
||||
try {
|
||||
dmMessage = await this._sendDMToUser(dmContent, files);
|
||||
|
@ -240,7 +248,6 @@ class Thread {
|
|||
});
|
||||
|
||||
// Show the reply in the inbox thread
|
||||
const inboxContent = formatters.formatStaffReplyThreadMessage(threadMessage);
|
||||
const inboxMessage = await this._postToThreadChannel(inboxContent, files);
|
||||
if (inboxMessage) {
|
||||
await this._updateThreadMessage(threadMessage.id, { inbox_message_id: inboxMessage.id });
|
||||
|
@ -719,6 +726,13 @@ class Thread {
|
|||
const formattedThreadMessage = formatters.formatStaffReplyThreadMessage(newThreadMessage);
|
||||
const formattedDM = formatters.formatStaffReplyDM(newThreadMessage);
|
||||
|
||||
// Same restriction as in replies. Because edits could theoretically change the number of messages a reply takes, we enforce replies
|
||||
// to fit within 1 message to avoid the headache and issues caused by that.
|
||||
if (! utils.messageContentIsWithinMaxLength(formattedDM) || ! utils.messageContentIsWithinMaxLength(formattedThreadMessage)) {
|
||||
await this.postSystemMessage("Edited reply is too long! Make sure the edit is under 2000 characters total, moderator name in the reply included.");
|
||||
return false;
|
||||
}
|
||||
|
||||
await bot.editMessage(threadMessage.dm_channel_id, threadMessage.dm_message_id, formattedDM);
|
||||
await bot.editMessage(this.channel_id, threadMessage.inbox_message_id, formattedThreadMessage);
|
||||
|
||||
|
|
52
src/utils.js
52
src/utils.js
|
@ -336,6 +336,56 @@ function readMultilineConfigValue(str) {
|
|||
|
||||
function noop() {}
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#create-message-params
|
||||
const MAX_MESSAGE_CONTENT_LENGTH = 2000;
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#embed-limits
|
||||
const MAX_EMBED_CONTENT_LENGTH = 6000;
|
||||
|
||||
/**
|
||||
* Checks if the given message content is within Discord's message length limits.
|
||||
*
|
||||
* Based on testing, Discord appears to enforce length limits (at least in the client)
|
||||
* the same way JavaScript does, using the UTF-16 byte count as the number of characters.
|
||||
*
|
||||
* @param {string|Eris.MessageContent} content
|
||||
*/
|
||||
function messageContentIsWithinMaxLength(content) {
|
||||
if (typeof content === "string") {
|
||||
content = { content };
|
||||
}
|
||||
|
||||
if (content.content && content.content.length > MAX_MESSAGE_CONTENT_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (content.embed) {
|
||||
let embedContentLength = 0;
|
||||
|
||||
if (content.embed.title) embedContentLength += content.embed.title.length;
|
||||
if (content.embed.description) embedContentLength += content.embed.description.length;
|
||||
if (content.embed.footer && content.embed.footer.text) {
|
||||
embedContentLength += content.embed.footer.text.length;
|
||||
}
|
||||
if (content.embed.author && content.embed.author.name) {
|
||||
embedContentLength += content.embed.author.name.length;
|
||||
}
|
||||
|
||||
if (content.embed.fields) {
|
||||
for (const field of content.embed.fields) {
|
||||
if (field.title) embedContentLength += field.name.length;
|
||||
if (field.description) embedContentLength += field.value.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (embedContentLength > MAX_EMBED_CONTENT_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
BotError,
|
||||
|
||||
|
@ -377,5 +427,7 @@ module.exports = {
|
|||
|
||||
readMultilineConfigValue,
|
||||
|
||||
messageContentIsWithinMaxLength,
|
||||
|
||||
noop,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue