From e2ab9fa9bf0c8ae9a3ac5dc88f423fded5bff09e Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Wed, 3 Jun 2026 00:02:48 +1200 Subject: [PATCH] Improve PK ping message --- src/d2m/converters/message-to-event.js | 22 ++- .../message-to-event.test.components.js | 22 +++ test/data.js | 183 ++++++++++++++++++ test/ooye-test-data.sql | 6 +- 4 files changed, 228 insertions(+), 5 deletions(-) diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index 7229d3d..83fab1b 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -265,8 +265,9 @@ function getFormattedInteraction(interaction, isThinkingInteraction) { * @param {any} newEvents merge into events * @param {any} events will be modified * @param {boolean} forceSameMsgtype whether m.text may only be combined with m.text, etc + * @param {boolean} [forceMerge] if true, must merge event, will error if it had to append */ -function mergeTextEvents(newEvents, events, forceSameMsgtype) { +function mergeTextEvents(newEvents, events, forceSameMsgtype, forceMerge = false) { let prev = events.at(-1) for (const ne of newEvents) { const isAllText = prev?.body && prev?.formatted_body && ["m.text", "m.notice"].includes(ne.msgtype) && ["m.text", "m.notice"].includes(prev?.msgtype) @@ -278,6 +279,8 @@ function mergeTextEvents(newEvents, events, forceSameMsgtype) { rep.addLine(ne.body, ne.formatted_body) prev.body = rep.body prev.formatted_body = rep.formattedBody + } else if (forceMerge) { + throw new Error("Unable to merge events") } else { events.push(ne) } @@ -967,7 +970,8 @@ async function messageToEvent(message, guild, options = {}, di) { // May only be a section accessory or in an action row (up to 5) if (component.style === DiscordTypes.ButtonStyle.Link) { assert(component.label) // required for Discord to validate link buttons - stack.msb.add(`[${component.label} ${component.url}] `, tag`${component.label} `) + const link = await transformContentMessageLinks(component.url) + stack.msb.add(`[${component.label} ${link}] `, tag`${component.label} `) } } @@ -980,7 +984,19 @@ async function messageToEvent(message, guild, options = {}, di) { const {body, formatted_body} = stack.msb.get() if (body.trim().length) { - await addTextEvent(body, formatted_body, "m.text") + // Create new message if Components V2 (cannot have regular content) + if ((message.flags ?? 0) & DiscordTypes.MessageFlags.IsComponentsV2) { + await addTextEvent(body, formatted_body, "m.text") + } + // Add to existing message if legacy components https://docs.discord.com/developers/components/reference#legacy-message-component-behavior + else { + mergeTextEvents([{ + msgtype: "m.text", + body, + format: "org.matrix.custom.html", + formatted_body + }], events, false, true) + } } } diff --git a/src/d2m/converters/message-to-event.test.components.js b/src/d2m/converters/message-to-event.test.components.js index 137b63b..1ef83c3 100644 --- a/src/d2m/converters/message-to-event.test.components.js +++ b/src/d2m/converters/message-to-event.test.components.js @@ -1,6 +1,7 @@ const {test} = require("supertape") const {messageToEvent} = require("./message-to-event") const data = require("../../../test/data") +const {mockGetEffectivePower} = require("../../matrix/utils.test") test("message2event components: pk question mark output", async t => { const events = await messageToEvent(data.message_with_components.pk_question_mark_response, data.guild.general, {}) @@ -77,3 +78,24 @@ test("message2event components: pk question mark output", async t => { msgtype: "m.text", }]) }) + +test("message2event components: pk ping message legacy components", async t => { + const events = await messageToEvent(data.message_with_components.pk_ping_components_v1, data.guild.general, {}, { + api: { + async getJoinedMembers() { + return {joined: {}} + }, + getEffectivePower: mockGetEffectivePower() + } + }) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "โญ cadence used `/๐Ÿ”” Ping author`" + + "\nPsst, **Red** (@cadence.worm:), you have been pinged by @cadence.worm:." + + "\n[Jump https://matrix.to/#/!TqlyQmifxGUggEmdBN:cadence.moe/$l9FMmsEbh9K0NUReeEpWOMZYGRlUOE8yLcm6P-TYHSM?via=cadence.moe] ", + format: "org.matrix.custom.html", + formatted_body: "
โญ cadence used /๐Ÿ”” Ping author
Psst, Red (@cadence.worm), you have been pinged by @cadence.worm.
Jump ", + "m.mentions": {} + }]) +}) diff --git a/test/data.js b/test/data.js index f3092bc..eab9a63 100644 --- a/test/data.js +++ b/test/data.js @@ -5473,6 +5473,189 @@ module.exports = { content: '-# Original Message ID: 1466556003645657118 ยท ' } ] + }, + pk_ping_components_v1: { + type: 23, + content: "Psst, **Red** (<@772659086046658620>), you have been pinged by <@772659086046658620>.", + mentions: [ + { + id: "772659086046658620", + username: "cadence.worm", + avatar: "466df0c98b1af1e1388f595b4c1ad1b9", + discriminator: "0", + public_flags: 0, + flags: 0, + banner: null, + accent_color: null, + global_name: "cadence", + avatar_decoration_data: null, + collectibles: null, + display_name_styles: null, + banner_color: null, + clan: { + identity_guild_id: "532245108070809601", + identity_enabled: true, + tag: "doll", + badge: "dba08126b4e810a0e096cc7cd5bc37f0" + }, + primary_guild: { + identity_guild_id: "532245108070809601", + identity_enabled: true, + tag: "doll", + badge: "dba08126b4e810a0e096cc7cd5bc37f0" + } + } + ], + mention_roles: [], + attachments: [], + embeds: [], + timestamp: "2026-03-25T07:07:02.626000+00:00", + edited_timestamp: null, + flags: 0, + components: [ + { + type: 1, + id: 1, + components: [ + { + type: 2, + id: 2, + style: 5, + label: "Jump", + url: "https://discord.com/channels/1160893336324931584/1160894080998461480/1440549403667468320" + } + ] + } + ], + id: "1486260105908457653", + channel_id: "1160894080998461480", + author: { + id: "466378653216014359", + username: "PluralKit", + avatar: "b78ef67a081737a830b60aa47d9ebcd9", + discriminator: "4020", + public_flags: 65536, + flags: 65536, + bot: true, + banner: null, + accent_color: null, + global_name: null, + 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, + application_id: "466378653216014359", + interaction: { + id: "1486260103928614932", + type: 2, + name: "๐Ÿ”” Ping author", + user: { + id: "772659086046658620", + username: "cadence.worm", + avatar: "466df0c98b1af1e1388f595b4c1ad1b9", + discriminator: "0", + public_flags: 0, + flags: 0, + banner: null, + accent_color: null, + global_name: "cadence", + avatar_decoration_data: null, + collectibles: null, + display_name_styles: null, + banner_color: null, + clan: { + identity_guild_id: "532245108070809601", + identity_enabled: true, + tag: "doll", + badge: "dba08126b4e810a0e096cc7cd5bc37f0" + }, + primary_guild: { + identity_guild_id: "532245108070809601", + identity_enabled: true, + tag: "doll", + badge: "dba08126b4e810a0e096cc7cd5bc37f0" + } + } + }, + webhook_id: "466378653216014359", + message_reference: { + type: 0, + channel_id: "1160894080998461480", + message_id: "1440549403667468320", + guild_id: "1160893336324931584" + }, + interaction_metadata: { + id: "1486260103928614932", + type: 2, + user: { + id: "772659086046658620", + username: "cadence.worm", + avatar: "466df0c98b1af1e1388f595b4c1ad1b9", + discriminator: "0", + public_flags: 0, + flags: 0, + banner: null, + accent_color: null, + global_name: "cadence", + avatar_decoration_data: null, + collectibles: null, + display_name_styles: null, + banner_color: null, + clan: { + identity_guild_id: "532245108070809601", + identity_enabled: true, + tag: "doll", + badge: "dba08126b4e810a0e096cc7cd5bc37f0" + }, + primary_guild: { + identity_guild_id: "532245108070809601", + identity_enabled: true, + tag: "doll", + badge: "dba08126b4e810a0e096cc7cd5bc37f0" + } + }, + authorizing_integration_owners: { "0": "1160893336324931584" }, + name: "๐Ÿ”” Ping author", + command_type: 3, + target_message_id: "1440549403667468320" + }, + referenced_message: { + type: 0, + content: "test", + mentions: [], + mention_roles: [], + attachments: [], + embeds: [], + timestamp: "2025-11-19T03:49:01.948000+00:00", + edited_timestamp: null, + flags: 0, + components: [], + id: "1440549403667468320", + channel_id: "1160894080998461480", + author: { + id: "1195662438662680720", + username: "special name", + avatar: "a82347890f2739e5880cd82b8c1a708e", + discriminator: "0000", + public_flags: 0, + flags: 0, + bot: true, + global_name: null, + clan: null, + primary_guild: null + }, + pinned: false, + mention_everyone: false, + tts: false, + application_id: "466378653216014359", + webhook_id: "1195662438662680720" + } } }, message_update: { diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql index 8dd71cd..1662320 100644 --- a/test/ooye-test-data.sql +++ b/test/ooye-test-data.sql @@ -95,7 +95,8 @@ WITH a (message_id, channel_id) AS (VALUES ('1381212840957972480', '112760669178241024'), ('1401760355339862066', '112760669178241024'), ('1439351590262800565', '1438284564815548418'), -('1404133238414376971', '112760669178241024')) +('1404133238414376971', '112760669178241024'), +('1440549403667468320', '1160894080998461480')) SELECT message_id, max(historical_room_index) as historical_room_index FROM a INNER JOIN historical_channel_room ON historical_channel_room.reference_channel_id = a.channel_id GROUP BY message_id; INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, reaction_part, source) VALUES @@ -143,7 +144,8 @@ INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part ('$7P2O_VTQNHvavX5zNJ35DV-dbJB1Ag80tGQP_JzGdhk', 'm.room.message', 'm.text', '1401760355339862066', 0, 0, 0), ('$ielAnR6geu0P1Tl5UXfrbxlIf-SV9jrNprxrGXP3v7M', 'm.room.message', 'm.image', '1439351590262800565', 0, 0, 0), ('$uUKLcTQvik5tgtTGDKuzn0Ci4zcCvSoUcYn2X7mXm9I', 'm.room.message', 'm.text', '1404133238414376971', 0, 1, 1), -('$LhmoWWvYyn5_AHkfb6FaXmLI6ZOC1kloql5P40YDmIk', 'm.room.message', 'm.notice', '1404133238414376971', 1, 0, 1); +('$LhmoWWvYyn5_AHkfb6FaXmLI6ZOC1kloql5P40YDmIk', 'm.room.message', 'm.notice', '1404133238414376971', 1, 0, 1), +('$l9FMmsEbh9K0NUReeEpWOMZYGRlUOE8yLcm6P-TYHSM', 'm.room.message', 'm.text', '1440549403667468320', 0, 0, 1); INSERT INTO file (discord_url, mxc_url) VALUES ('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'),