diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index 75e04f9..5abfd49 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -158,6 +158,31 @@ async function getMemberFromCacheOrHomeserver(roomID, mxid, api) { }) } +/** + * Splits a display name into one chunk containing <=80 characters, and another chunk containing the rest of the characters. Splits on + * whitespace if possible. + * These chunks, respectively, go in the display name, and at the top of the message. + * If the second part isn't empty, it'll also contain boldening markdown and a line break at the end, so that regardless of its value it + * can be prepended to the message content as-is. + * @summary Splits too-long Matrix names into a display name chunk and a message content chunk. + * @param {string} displayName - The Matrix side display name to chop up. + * @returns {[string, string]} [shortened display name, display name runoff] + */ +function splitDisplayName(displayName) { + /** @type {string[]} */ + let displayNameChunks = chunk(displayName, 80) + + if (displayNameChunks.length === 1) { + return [displayName, ""] + } else { + const displayNamePreRunoff = displayNameChunks[0] + // displayNameRunoff is a slice of the original rather than a concatenation of the rest of the chunks in order to preserve whatever whitespace it was broken on. + const displayNameRunoff = `**${displayName.slice(displayNamePreRunoff.length + 1)}**\n` + + return [displayNamePreRunoff, displayNameRunoff] + } +} + /** * @param {Ty.Event.Outer_M_Room_Message | Ty.Event.Outer_M_Room_Message_File | Ty.Event.Outer_M_Sticker | Ty.Event.Outer_M_Room_Message_Encrypted_File} event * @param {import("discord-api-types/v10").APIGuild} guild @@ -179,6 +204,13 @@ async function eventToMessage(event, guild, di) { const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api) if (member.displayname) displayName = member.displayname if (member.avatar_url) avatarURL = utils.getPublicUrlForMxc(member.avatar_url) || undefined + // If the display name is too long to be put into the webhook (80 characters is the maximum), + // put the excess characters into displayNameRunoff, later to be put at the top of the message + let [displayNameShortened, displayNameRunoff] = splitDisplayName(displayName) + // If the message type is m.emote, the full name is already included at the start of the message, so remove any runoff + if (event.type === "m.room.message" && event.content.msgtype === "m.emote") { + displayNameRunoff = "" + } let content = event.content.body // ultimate fallback const attachments = [] @@ -364,13 +396,13 @@ async function eventToMessage(event, guild, di) { pendingFiles.push({name: filename, url}) } - content = replyLine + content + content = displayNameRunoff + replyLine + content // Split into 2000 character chunks const chunks = chunk(content, 2000) messages = messages.concat(chunks.map(content => ({ content, - username: displayName, + username: displayNameShortened, avatar_url: avatarURL }))) @@ -379,7 +411,7 @@ async function eventToMessage(event, guild, di) { // There needs to be a message to add attachments to. if (!messages.length) messages.push({ content, - username: displayName, + username: displayNameShortened, avatar_url: avatarURL }) messages[0].attachments = attachments diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index e7d2314..3619e8b 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -1436,8 +1436,8 @@ test("event2message: overly long usernames are shifted into the message content" messagesToDelete: [], messagesToEdit: [], messagesToSend: [{ - username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS IMPORTAN", - content: "**T and I DON'T MATTER**: testing the member state cache", + username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS", + content: "**IMPORTANT and I DON'T MATTER**\ntesting the member state cache", avatar_url: undefined }] } @@ -1468,7 +1468,7 @@ test("event2message: overly long usernames are not treated specially when the ms messagesToDelete: [], messagesToEdit: [], messagesToSend: [{ - username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS IMPORTAN", + username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS", content: "\\* I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS IMPORTANT and I DON'T MATTER looks at the start of the message", avatar_url: undefined }]