diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index d6daed75..22ed3772 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -21,6 +21,10 @@ const BLOCK_ELEMENTS = [ "TFOOT", "TH", "THEAD", "TR", "UL" ] +function cleanAttribute (attribute) { + return attribute ? attribute.replace(/(\n+\s*)+/g, "\n") : "" +} + const turndownService = new TurndownService({ hr: "----", headingStyle: "atx", @@ -53,6 +57,27 @@ turndownService.addRule("blockquote", { } }) +turndownService.addRule("inlineLink", { + filter: function (node, options) { + return ( + options.linkStyle === "inlined" && + node.nodeName === "A" && + node.getAttribute("href") + ) + }, + + replacement: function (content, node) { + if (node.getAttribute("data-user-id")) return `<@${node.getAttribute("data-user-id")}>` + if (node.getAttribute("data-channel-id")) return `<#${node.getAttribute("data-channel-id")}>` + const href = node.getAttribute("href") + let title = cleanAttribute(node.getAttribute("title")) + if (title) title = ` "` + title + `"` + let brackets = ["", ""] + if (href.startsWith("https://matrix.to")) brackets = ["<", ">"] + return "[" + content + "](" + brackets[0] + href + title + brackets[1] + ")" + } +}) + turndownService.addRule("fencedCodeBlock", { filter: function (node, options) { return ( @@ -153,6 +178,21 @@ async function eventToMessage(event, guild, di) { replyLine += contentPreview + "\n" })() + // Handling mentions of Discord users + input = input.replace(/("https:\/\/matrix.to\/#\/(@[^"]+)")>/g, (whole, attributeValue, mxid) => { + if (!utils.eventSenderIsFromDiscord(mxid)) return whole + const userID = db.prepare("SELECT discord_id FROM sim WHERE mxid = ?").pluck().get(mxid) + if (!userID) return whole + return `${attributeValue} data-user-id="${userID}">` + }) + + // Handling mentions of Discord rooms + input = input.replace(/("https:\/\/matrix.to\/#\/(![^"]+)")>/g, (whole, attributeValue, roomID) => { + const channelID = db.prepare("SELECT channel_id FROM channel_room WHERE room_id = ?").pluck().get(roomID) + if (!channelID) return whole + return `${attributeValue} data-channel-id="${channelID}">` + }) + // Element adds a bunch of
before but doesn't render them. I can't figure out how this even works in the browser, so let's just delete those. input = input.replace(/(?:\n|
\s*)*<\/blockquote>/g, "") @@ -174,7 +214,7 @@ async function eventToMessage(event, guild, di) { } }) - // @ts-ignore + // @ts-ignore bad type from turndown content = turndownService.turndown(input) // It's optimised for commonmark, we need to replace the space-space-newline with just newline diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index b595be8c..61da83ce 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -506,3 +506,81 @@ test("event2message: with layered rich replies, the preview should only be the r }] ) }) + +test("event2message: mentioning discord users works", async t => { + t.deepEqual( + await eventToMessage({ + content: { + msgtype: "m.text", + body: "wrong body", + format: "org.matrix.custom.html", + formatted_body: `I'm just testing mentions` + }, + event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", + origin_server_ts: 1688301929913, + room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", + sender: "@cadence:cadence.moe", + type: "m.room.message", + unsigned: { + age: 405299 + } + }), + [{ + username: "cadence [they]", + content: "I'm just <@114147806469554185> testing mentions", + avatar_url: undefined + }] + ) +}) + +test("event2message: mentioning matrix users works", async t => { + t.deepEqual( + await eventToMessage({ + content: { + msgtype: "m.text", + body: "wrong body", + format: "org.matrix.custom.html", + formatted_body: `I'm just testing mentions` + }, + event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", + origin_server_ts: 1688301929913, + room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", + sender: "@cadence:cadence.moe", + type: "m.room.message", + unsigned: { + age: 405299 + } + }), + [{ + username: "cadence [they]", + content: "I'm just [▲]() testing mentions", + avatar_url: undefined + }] + ) +}) + +test("event2message: mentioning bridged rooms works", async t => { + t.deepEqual( + await eventToMessage({ + content: { + msgtype: "m.text", + body: "wrong body", + format: "org.matrix.custom.html", + formatted_body: `I'm just testing mentions` + }, + event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", + origin_server_ts: 1688301929913, + room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", + sender: "@cadence:cadence.moe", + type: "m.room.message", + unsigned: { + age: 405299 + } + }), + [{ + username: "cadence [they]", + content: "I'm just [▲]() testing mentions", + avatar_url: undefined + }] + ) +})