diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index 33d8696..6e9ce7b 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -669,7 +669,7 @@ async function messageToEvent(message, guild, options = {}, di) { const match = repliedToEventSenderMxid.match(/^@([^:]*)/) assert(match) repliedToDisplayName = referenced.author.username || match[1] || "a Matrix user" // grab the localpart as the display name, whatever - repliedToUserHtml = `${repliedToDisplayName}` + repliedToUserHtml = tag`${repliedToDisplayName}` } else { repliedToDisplayName = referenced.author.global_name || referenced.author.username || "a Discord user" repliedToUserHtml = repliedToDisplayName @@ -694,6 +694,12 @@ async function messageToEvent(message, guild, options = {}, di) { + html body = `${repliedToDisplayName}: ${repliedToBody}`.split("\n").map(line => "> " + line).join("\n") // scenario 1 part B for mentions + "\n\n" + body + } else if (referenced.type === DiscordTypes.MessageType.UserJoin) { + // Discord user join messages are bridged as joins, not text events. Generate substitute text for reply. + const joinerMxid = select("sim", "mxid", {user_id: referenced.author.id}).pluck().get() + const joinerHtml = joinerMxid ? tag`${repliedToDisplayName}` : tag`${repliedToDisplayName}` + html = `
${joinerHtml} joined the room` + html + body = `> ${repliedToDisplayName} joined the room\n\n` + body } else { // repliedToUnknownEvent const dateDisplay = dUtils.howOldUnbridgedMessage(referenced.timestamp, message.timestamp) html = `
In reply to ${dateDisplay} from ${repliedToDisplayName}:` diff --git a/src/d2m/converters/message-to-event.test.js b/src/d2m/converters/message-to-event.test.js index 97fc25d..b7f0867 100644 --- a/src/d2m/converters/message-to-event.test.js +++ b/src/d2m/converters/message-to-event.test.js @@ -4,6 +4,7 @@ const {MatrixServerError} = require("../../matrix/mreq") const data = require("../../../test/data") const {mockGetEffectivePower} = require("../../matrix/utils.test") const Ty = require("../../types") +const {db} = require("../../passthrough") /** * @param {string} roomID @@ -733,6 +734,31 @@ test("message2event: reply to a Discord message that wasn't bridged", async t => }]) }) +test("message2event: reply to a Discord member join (who didn't join on Matrix)", async t => { + const events = await messageToEvent(data.message.reply_to_member_join, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "> PEASANT!! joined the room\n\nwhen the broke friend who we pay to bring food shows up at the medieval lord party", + format: "org.matrix.custom.html", + formatted_body: "PEASANT!! joined the roomwhen the broke friend who we pay to bring food shows up at the medieval lord party", + "m.mentions": {} + }]) +}) + +test("message2event: reply to a Discord member join (who did join on Matrix)", async t => { + db.prepare("INSERT INTO sim (user_id, username, sim_name, mxid) VALUES ('1461677775554478161', 'peasant321_76775', 'peasant321_76775', '@_ooye_peasant321_76775:cadence.moe')").run() + const events = await messageToEvent(data.message.reply_to_member_join, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "> PEASANT!! joined the room\n\nwhen the broke friend who we pay to bring food shows up at the medieval lord party", + format: "org.matrix.custom.html", + formatted_body: `PEASANT!! joined the roomwhen the broke friend who we pay to bring food shows up at the medieval lord party`, + "m.mentions": {} + }]) +}) + test("message2event: simple written @mention for matrix user", async t => { const events = await messageToEvent(data.message.simple_written_at_mention_for_matrix, data.guild.general, {}, { api: { diff --git a/test/data.js b/test/data.js index cc054cf..f3092bc 100644 --- a/test/data.js +++ b/test/data.js @@ -2035,6 +2035,80 @@ module.exports = { tts: false } }, + reply_to_member_join: { + type: 19, + content: "when the broke friend who we pay to bring food shows up at the medieval lord party", + mentions: [], + mention_roles: [], + attachments: [], + embeds: [], + timestamp: "2026-03-30T12:11:04.443000+00:00", + edited_timestamp: null, + flags: 0, + components: [], + id: "1488148556962332692", + channel_id: "475599038536744962", + author: { + id: "576945009408999426", + username: "randomllama121", + avatar: "08510a70f957106dad1580323c40cd7a", + discriminator: "0", + public_flags: 128, + flags: 128, + banner: null, + accent_color: null, + global_name: "random :3", + avatar_decoration_data: null, + collectibles: null, + display_name_styles: null, + banner_color: null, + clan: null, + primary_guild: null + }, + pinned: false, + mention_everyone: false, + tts: false, + message_reference: { + type: 0, + channel_id: "475599038536744962", + message_id: "1488146734352826478", + guild_id: "475599038536744960" + }, + referenced_message: { + type: 7, + content: "", + mentions: [], + mention_roles: [], + attachments: [], + embeds: [], + timestamp: "2026-03-30T12:03:49.899000+00:00", + edited_timestamp: null, + flags: 0, + components: [], + id: "1488146734352826478", + channel_id: "475599038536744962", + author: { + id: "1461677775554478161", + username: "peasant321_76775", + avatar: null, + discriminator: "0", + public_flags: 0, + flags: 0, + banner: null, + accent_color: null, + global_name: "PEASANT!!", + avatar_decoration_data: null, + collectibles: null, + display_name_styles: null, + banner_color: null, + clan: null, + primary_guild: null + }, + pinned: false, + mention_everyone: false, + tts: false + } + }, attachment_no_content: { id: "1124628646670389348", type: 0,