diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js index 26335189..3e121bd8 100644 --- a/d2m/converters/message-to-event.js +++ b/d2m/converters/message-to-event.js @@ -256,26 +256,35 @@ async function messageToEvent(message, guild, options = {}, di) { if (row) { repliedToEventRow = row } - } else if (dUtils.isWebhookMessage(message) && message.embeds[0]?.author?.name?.endsWith("↩️") && message.embeds[0].description?.startsWith("**[Reply to:]")) { - const match = message.embeds[0].description.match(/\/channels\/[0-9]*\/[0-9]*\/([0-9]{2,})/) - if (match) { - const row = from("event_message").join("message_channel", "message_id").join("channel_room", "channel_id").select("event_id", "room_id", "source").and("WHERE message_id = ? AND part = 0").get(match[1]) - if (row) { - /* - we generate a partial referenced_message based on what PK provided. we don't need everything, since this will only be used for further message-to-event converting. - the following properties are necessary: - - content: used for generating the reply fallback - - author: used for the top of the reply fallback (only used for discord authors. for matrix authors, repliedToEventSenderMxid is set.) - */ - message.referenced_message = { - content: message.embeds[0].description.replace(/^.*?\)\*\*\s*/, ""), - // @ts-ignore - author: { - username: message.embeds[0].author.name.replace(/\s*↩️\s*$/, "") + } else if (dUtils.isWebhookMessage(message) && message.embeds[0]?.author?.name?.endsWith("↩️")) { + // It could be a PluralKit emulated reply, let's see if it has a message link + const isEmulatedReplyToText = message.embeds[0].description?.startsWith("**[Reply to:]") + const isEmulatedReplyToAttachment = message.embeds[0].description?.startsWith("*[(click to see attachment") + if (isEmulatedReplyToText || isEmulatedReplyToAttachment) { + assert(message.embeds[0].description) + const match = message.embeds[0].description.match(/\/channels\/[0-9]*\/[0-9]*\/([0-9]{2,})/) + if (match) { + const row = from("event_message").join("message_channel", "message_id").join("channel_room", "channel_id").select("event_id", "room_id", "source").and("WHERE message_id = ? AND part = 0").get(match[1]) + if (row) { + /* + we generate a partial referenced_message based on what PK provided. we don't need everything, since this will only be used for further message-to-event converting. + the following properties are necessary: + - content: used for generating the reply fallback + - author: used for the top of the reply fallback (only used for discord authors. for matrix authors, repliedToEventSenderMxid is set.) + */ + const emulatedMessageContent = + ( isEmulatedReplyToAttachment ? "[Media]" + : message.embeds[0].description.replace(/^.*?\)\*\*\s*/, "")) + message.referenced_message = { + content: emulatedMessageContent, + // @ts-ignore + author: { + username: message.embeds[0].author.name.replace(/\s*↩️\s*$/, "") + } } + message.embeds.shift() + repliedToEventRow = row } - message.embeds.shift() - repliedToEventRow = row } } } @@ -407,7 +416,7 @@ async function messageToEvent(message, guild, options = {}, di) { if (repliedToEventRow?.source === 0 && repliedToEventSenderMxid) { const match = repliedToEventSenderMxid.match(/^@([^:]*)/) assert(match) - repliedToDisplayName = match[1] || "a Matrix user" // grab the localpart as the display name, whatever + repliedToDisplayName = message.referenced_message?.author.username || match[1] || "a Matrix user" // grab the localpart as the display name, whatever repliedToUserHtml = `${repliedToDisplayName}` } else { repliedToDisplayName = message.referenced_message?.author.global_name || message.referenced_message?.author.username || "a Discord user" diff --git a/d2m/converters/message-to-event.pk.test.js b/d2m/converters/message-to-event.pk.test.js index 4bf8eb2e..c4904694 100644 --- a/d2m/converters/message-to-event.pk.test.js +++ b/d2m/converters/message-to-event.pk.test.js @@ -50,9 +50,9 @@ test("message2event: pk reply to matrix is converted to native matrix reply", as ] }, msgtype: "m.text", - body: "> cadence: now for my next experiment:\n\nthis is a reply", + body: "> cadence [they]: now for my next experiment:\n\nthis is a reply", format: "org.matrix.custom.html", - formatted_body: '
In reply to cadence
' + formatted_body: '
In reply to cadence [they]
' + "now for my next experiment:
" + "this is a reply", "m.relates_to": { @@ -92,3 +92,43 @@ test("message2event: pk reply to discord is converted to native matrix reply", a } }]) }) + +test("message2event: pk reply to matrix attachment is converted to native matrix reply", async t => { + const events = await messageToEvent(data.pk_message.pk_reply_to_matrix_attachment, {}, {}, { + api: { + getEvent: mockGetEvent(t, "!TqlyQmifxGUggEmdBN:cadence.moe", "$OEEK-Wam2FTh6J-6kVnnJ6KnLA_lLRnLTHatKKL62-Y", { + sender: "@ampflower:matrix.org", + type: "m.room.message", + content: { + body: "catnod.gif", + filename: "catnod.gif", + info: { + h: 128, + mimetype: "image/gif", + size: 20816, + w: 128 + }, + msgtype: "m.image", + url: "mxc://matrix.org/jtzXIawXCkFIHSsMUNsKkUJX" + } + }) + } + }) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + "m.mentions": { + user_ids: ["@ampflower:matrix.org"] + }, + body: "> Ampflower 🌺: [Media]\n\nCat nod", + format: "org.matrix.custom.html", + formatted_body: '
In reply to Ampflower 🌺
' + + "[Media]
" + + "Cat nod", + "m.relates_to": { + "m.in_reply_to": { + event_id: "$OEEK-Wam2FTh6J-6kVnnJ6KnLA_lLRnLTHatKKL62-Y" + } + } + }]) +}) diff --git a/d2m/converters/message-to-event.test.js b/d2m/converters/message-to-event.test.js index 33eac94c..ce694fdc 100644 --- a/d2m/converters/message-to-event.test.js +++ b/d2m/converters/message-to-event.test.js @@ -553,9 +553,9 @@ test("message2event: simple reply in thread to a matrix user's reply", async t = user_ids: ["@cadence:cadence.moe"] }, msgtype: "m.text", - body: "> cadence: What about them?\n\nWell, they don't seem to...", + body: "> cadence [they]: What about them?\n\nWell, they don't seem to...", format: "org.matrix.custom.html", - formatted_body: "
In reply to cadence
What about them?
Well, they don't seem to...", + formatted_body: "
In reply to cadence [they]
What about them?
Well, they don't seem to...", }]) }) diff --git a/test/data.js b/test/data.js index c82ea5c3..8991e7bf 100644 --- a/test/data.js +++ b/test/data.js @@ -1883,6 +1883,46 @@ module.exports = { components: [], application_id: "466378653216014359", webhook_id: "1195662438662680720" + }, + pk_reply_to_matrix_attachment: { + id: "1207486739023798332", + type: 0, + content: "Cat nod", + channel_id: "1160894080998461480", + author: { + id: "1195662438662680720", + username: "Azalea &flwr; 🌺", + avatar: "48032c7bb5009701ef1aa9bd3446a67a", + discriminator: "0000", + public_flags: 0, + flags: 0, + bot: true, + global_name: null + }, + attachments: [], + embeds: [ + { + type: "rich", + description: "*[(click to see attachment)](https://discord.com/channels/1160893336324931584/1160894080998461480/1207486471489986620)*", + color: 14032878, + author: { + name: "Ampflower 🌺 ↩️", + icon_url: "https://cdn.discordapp.com/avatars/1162510387057545227/5d8c4e541a4d8255777fe64b4caef971.png", + proxy_icon_url: "https://images-ext-2.discordapp.net/external/RfjCRz6fSGzbIFtAqT0CGmQjJyuiD7d48mTU-CkqW5w/https/cdn.discordapp.com/avatars/1162510387057545227/5d8c4e541a4d8255777fe64b4caef971.png" + } + } + ], + mentions: [], + mention_roles: [], + pinned: false, + mention_everyone: false, + tts: false, + timestamp: "2024-02-15T00:41:12.602000+00:00", + edited_timestamp: null, + flags: 0, + components: [], + application_id: "466378653216014359", + webhook_id: "1195662438662680720" } }, message_with_embeds: { diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql index b41d609e..d9a8263a 100644 --- a/test/ooye-test-data.sql +++ b/test/ooye-test-data.sql @@ -50,7 +50,8 @@ INSERT INTO message_channel (message_id, channel_id) VALUES ('1162625810109317170', '497161350934560778'), ('1158842413025071135', '176333891320283136'), ('1197612733600895076', '112760669178241024'), -('1202543413652881428', '1160894080998461480'); +('1202543413652881428', '1160894080998461480'), +('1207486471489986620', '1160894080998461480'); INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, reaction_part, source) VALUES ('$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg', 'm.room.message', 'm.text', '1126786462646550579', 0, 0, 1), @@ -77,7 +78,8 @@ INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part ('$zJFjTvNn1w_YqpR4o4ISKUFisNRgZcu1KSMI_LADPVQ', 'm.room.message', 'm.notice', '1162625810109317170', 1, 0, 1), ('$dVCLyj6kxb3DaAWDtjcv2kdSny8JMMHdDhCMz8mDxVo', 'm.room.message', 'm.text', '1158842413025071135', 0, 0, 1), ('$7tJoMw1h44n2gxgLUE1T_YinGrLbK0x-TDY1z6M7GBw', 'm.room.message', 'm.text', '1197612733600895076', 0, 0, 1), -('$NB6nPgO2tfXyIwwDSF0Ga0BUrsgX1S-0Xl-jAvI8ucU', 'm.room.message', 'm.text', '1202543413652881428', 0, 0, 0); +('$NB6nPgO2tfXyIwwDSF0Ga0BUrsgX1S-0Xl-jAvI8ucU', 'm.room.message', 'm.text', '1202543413652881428', 0, 0, 0), +('$OEEK-Wam2FTh6J-6kVnnJ6KnLA_lLRnLTHatKKL62-Y', 'm.room.message', 'm.image', '1207486471489986620', 0, 0, 0); INSERT INTO file (discord_url, mxc_url) VALUES ('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'),