diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js
index 05a376a..adc56e6 100644
--- a/src/d2m/converters/message-to-event.js
+++ b/src/d2m/converters/message-to-event.js
@@ -261,6 +261,29 @@ 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
+ */
+function mergeTextEvents(newEvents, events, forceSameMsgtype) {
+ 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)
+ const typesPermitted = !forceSameMsgtype || ne?.msgtype === prev?.msgtype
+ if (isAllText && typesPermitted) {
+ const rep = new mxUtils.MatrixStringBuilder()
+ rep.body = prev.body
+ rep.formattedBody = prev.formatted_body
+ rep.addLine(ne.body, ne.formatted_body)
+ prev.body = rep.body
+ prev.formatted_body = rep.formattedBody
+ } else {
+ events.push(ne)
+ }
+ }
+}
+
/**
* @param {DiscordTypes.APIMessage} message
* @param {DiscordTypes.APIGuild} guild
@@ -835,15 +858,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// Try to merge attachment events with the previous event
// This means that if the attachments ended up as a text link, and especially if there were many of them, the events will be joined together.
- let prev = events.at(-1)
- for (const atch of attachmentEvents) {
- if (atch.msgtype === "m.text" && prev?.body && prev?.formatted_body && ["m.text", "m.notice"].includes(prev?.msgtype)) {
- prev.body = prev.body + "\n" + atch.body
- prev.formatted_body = prev.formatted_body + "
" + atch.formatted_body
- } else {
- events.push(atch)
- }
- }
+ mergeTextEvents(attachmentEvents, events, false)
}
// Then components
@@ -981,6 +996,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// Start building up a replica ("rep") of the embed in Discord-markdown format, which we will convert into both plaintext and formatted body at once
const rep = new mxUtils.MatrixStringBuilder()
+ let isAdditionalImage = false
if (isKlipyGIF) {
assert(embed.video?.url)
@@ -1047,7 +1063,11 @@ async function messageToEvent(message, guild, options = {}, di) {
let chosenImage = embed.image?.url
// the thumbnail seems to be used for "article" type but displayed big at the bottom by discord
if (embed.type === "article" && embed.thumbnail?.url && !chosenImage) chosenImage = embed.thumbnail.url
- if (chosenImage) rep.addParagraph(`📸 ${dUtils.getPublicUrlForCdn(chosenImage)}`)
+
+ if (chosenImage) {
+ isAdditionalImage = !rep.body && !!events.length
+ rep.addParagraph(`📸 ${dUtils.getPublicUrlForCdn(chosenImage)}`)
+ }
if (embed.video?.url) rep.addParagraph(`🎞️ ${dUtils.getPublicUrlForCdn(embed.video.url)}`)
@@ -1056,6 +1076,11 @@ async function messageToEvent(message, guild, options = {}, di) {
body = body.split("\n").map(l => "| " + l).join("\n")
html = `
${html}` + if (isAdditionalImage) { + mergeTextEvents([{...rep.get(), body, html, msgtype: "m.notice"}], events, true) + continue + } + // Send as m.notice to apply the usual automated/subtle appearance, showing this wasn't actually typed by the person await addTextEvent(body, html, "m.notice") } diff --git a/src/d2m/converters/message-to-event.test.embeds.js b/src/d2m/converters/message-to-event.test.embeds.js index 259aa66..73244d3 100644 --- a/src/d2m/converters/message-to-event.test.embeds.js +++ b/src/d2m/converters/message-to-event.test.embeds.js @@ -204,6 +204,44 @@ test("message2event embeds: author url without name", async t => { }]) }) +test("message2event embeds: 4 images", async t => { + const events = await messageToEvent(data.message_with_embeds.four_images, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "[🔀 Forwarded message]\n» https://fixupx.com/i/status/2032003668787020046", + format: "org.matrix.custom.html", + formatted_body: "🔀 Forwarded message
https://fixupx.com/i/status/2032003668787020046", + "m.mentions": {} + }, { + $type: "m.room.message", + msgtype: "m.notice", + body: "» | ## ⏺️ AUTOMATON WEST (@AUTOMATON_ENG) https://x.com/AUTOMATON_ENG/status/2032003668787020046" + + "\n» | " + + "\n» | 4chan owner Hiroyuki, Evangelion director Hideaki Anno and GACKT to participate in “humanity’s last non\\-AI made social network”" + + "\n» | ︀︀" + + "\n» | ︀︀[automaton-media.com/en/news/4chan-owner-hiroyuki-evangelion-director-hideaki-anno-and-gackt-to-participate-in-humanitys-last-non-ai-made-social-network/](https://automaton-media.com/en/news/4chan-owner-hiroyuki-evangelion-director-hideaki-anno-and-gackt-to-participate-in-humanitys-last-non-ai-made-social-network/)" + + "\n» | " + + "\n» | **[💬](https://x.com/intent/tweet?in_reply_to=2032003668787020046) 36 [🔁](https://x.com/intent/retweet?tweet_id=2032003668787020046) 212 [❤](https://x.com/intent/like?tweet_id=2032003668787020046) 3\\.0K 👁 131\\.7K **" + + "\n» | " + + "\n» | 📸 https://pbs.twimg.com/media/HDMUyf6bQAM3yts.jpg?name=orig" + + "\n» | — FixupX" + + "\n» | 📸 https://pbs.twimg.com/media/HDMUgxybQAE4FtJ.jpg?name=orig" + + "\n» | 📸 https://pbs.twimg.com/media/HDMUrPobgAAeb90.jpg?name=orig" + + "\n» | 📸 https://pbs.twimg.com/media/HDMUuy5bgAAInj5.jpg?name=orig", + format: "org.matrix.custom.html", + formatted_body: "
", + "m.mentions": {} + }]) +}) + test("message2event embeds: vx image", async t => { const events = await messageToEvent(data.message_with_embeds.vx_image, data.guild.general) t.deepEqual(events, [{ diff --git a/src/d2m/converters/message-to-event.test.js b/src/d2m/converters/message-to-event.test.js index 4728c2b..e805365 100644 --- a/src/d2m/converters/message-to-event.test.js +++ b/src/d2m/converters/message-to-event.test.js @@ -1099,7 +1099,7 @@ test("message2event: multiple attachments are combined into the same event where formatted_body: "hey" + `" + + "⏺️ AUTOMATON WEST (@AUTOMATON_ENG)
" + + "4chan owner Hiroyuki, Evangelion director Hideaki Anno and GACKT to participate in “humanity’s last non-AI made social network”" + + "
" + + "
︀︀
︀︀automaton-media.com/en/news/4chan-owner-hiroyuki-evangelion-director-hideaki-anno-and-gackt-to-participate-in-humanitys-last-non-ai-made-social-network/" + + "
💬 36 🔁 212 ❤ 3.0K 👁 131.7K📸 https://pbs.twimg.com/media/HDMUyf6bQAM3yts.jpg?name=orig
— FixupX📸 https://pbs.twimg.com/media/HDMUgxybQAE4FtJ.jpg?name=orig
" + + "📸 https://pbs.twimg.com/media/HDMUrPobgAAeb90.jpg?name=orig
" + + "📸 https://pbs.twimg.com/media/HDMUuy5bgAAInj5.jpg?name=orig
📸 Uploaded SPOILER file: https://bridge.example.org/download/discordcdn/123/456/SPOILER_secret.jpg (38 KB)` - + `