forked from cadence/out-of-your-element
Emergency sync #11
4 changed files with 209 additions and 11 deletions
|
|
@ -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 + "<br>" + 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 = `<blockquote>${html}</blockquote>`
|
||||
|
||||
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: "🔀 <em>Forwarded message</em><br><blockquote><a href=\"https://fixupx.com/i/status/2032003668787020046\">https://fixupx.com/i/status/2032003668787020046</a></blockquote>",
|
||||
"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: "<blockquote><blockquote><p><strong><a href=\"https://x.com/AUTOMATON_ENG/status/2032003668787020046\">⏺️ AUTOMATON WEST (@AUTOMATON_ENG)</a></strong></p>"
|
||||
+ "<p>4chan owner Hiroyuki, Evangelion director Hideaki Anno and GACKT to participate in “humanity’s last non-AI made social network”"
|
||||
+ "<br>︀︀<br>︀︀<a href=\"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/\">automaton-media.com/en/news/4chan-owner-hiroyuki-evangelion-director-hideaki-anno-and-gackt-to-participate-in-humanitys-last-non-ai-made-social-network/</a>"
|
||||
+ "<br><br><strong><a href=\"https://x.com/intent/tweet?in_reply_to=2032003668787020046\">💬</a> 36 <a href=\"https://x.com/intent/retweet?tweet_id=2032003668787020046\">🔁</a> 212 <a href=\"https://x.com/intent/like?tweet_id=2032003668787020046\">❤</a> 3.0K 👁 131.7K </strong></p>"
|
||||
+ "<p>📸 https://pbs.twimg.com/media/HDMUyf6bQAM3yts.jpg?name=orig</p>— FixupX</blockquote>"
|
||||
+ "<p>📸 https://pbs.twimg.com/media/HDMUgxybQAE4FtJ.jpg?name=orig</p>"
|
||||
+ "<p>📸 https://pbs.twimg.com/media/HDMUrPobgAAeb90.jpg?name=orig</p>"
|
||||
+ "<p>📸 https://pbs.twimg.com/media/HDMUuy5bgAAInj5.jpg?name=orig</p></blockquote>",
|
||||
"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, [{
|
||||
|
|
|
|||
|
|
@ -1099,7 +1099,7 @@ test("message2event: multiple attachments are combined into the same event where
|
|||
formatted_body: "hey"
|
||||
+ `<br>📄 Uploaded file: <a href="https://bridge.example.org/download/discordcdn/123/456/789.mega">hey.jpg</a> (100 MB)`
|
||||
+ `<br><blockquote>📸 Uploaded SPOILER file: <a href="https://bridge.example.org/download/discordcdn/123/456/SPOILER_secret.jpg">https://bridge.example.org/download/discordcdn/123/456/SPOILER_secret.jpg</a> (38 KB)</blockquote>`
|
||||
+ `<br>📄 Uploaded file: <a href="https://bridge.example.org/download/discordcdn/123/456/789.mega">hey.jpg</a> (100 MB)`
|
||||
+ `📄 Uploaded file: <a href="https://bridge.example.org/download/discordcdn/123/456/789.mega">hey.jpg</a> (100 MB)`
|
||||
}, {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
|
|
|
|||
135
test/data.js
135
test/data.js
|
|
@ -5067,6 +5067,141 @@ module.exports = {
|
|||
pinned: false,
|
||||
mention_everyone: false,
|
||||
tts: false
|
||||
},
|
||||
four_images: {
|
||||
type: 0,
|
||||
content: "",
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
attachments: [],
|
||||
embeds: [],
|
||||
timestamp: "2026-03-12T18:00:50.737000+00:00",
|
||||
edited_timestamp: null,
|
||||
flags: 16384,
|
||||
components: [],
|
||||
id: "1481713598278533241",
|
||||
channel_id: "687028734322147344",
|
||||
author: {
|
||||
id: "112760500130975744",
|
||||
username: "minimus",
|
||||
avatar: "a_a354b9eaff512485b49c82b13691b941",
|
||||
discriminator: "0",
|
||||
public_flags: 512,
|
||||
flags: 512,
|
||||
banner: null,
|
||||
accent_color: null,
|
||||
global_name: "minimus",
|
||||
avatar_decoration_data: null,
|
||||
collectibles: null,
|
||||
display_name_styles: { font_id: 11, effect_id: 5, colors: [ 6106655 ] },
|
||||
banner_color: null,
|
||||
clan: null,
|
||||
primary_guild: null
|
||||
},
|
||||
pinned: false,
|
||||
mention_everyone: false,
|
||||
tts: false,
|
||||
message_reference: {
|
||||
type: 1,
|
||||
channel_id: "637339857118822430",
|
||||
message_id: "1481696763483258891",
|
||||
guild_id: "408573045540651009"
|
||||
},
|
||||
message_snapshots: [
|
||||
{
|
||||
message: {
|
||||
type: 0,
|
||||
content: "https://fixupx.com/i/status/2032003668787020046",
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
attachments: [],
|
||||
embeds: [
|
||||
{
|
||||
type: "rich",
|
||||
url: "https://fixupx.com/i/status/2032003668787020046",
|
||||
description: "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 **",
|
||||
color: 6513919,
|
||||
timestamp: "2026-03-12T08:00:02+00:00",
|
||||
author: {
|
||||
name: "AUTOMATON WEST (@AUTOMATON_ENG)",
|
||||
url: "https://x.com/AUTOMATON_ENG/status/2032003668787020046",
|
||||
icon_url: "https://pbs.twimg.com/profile_images/1353559126693961729/pz-WVnDc_200x200.jpg",
|
||||
proxy_icon_url: "https://images-ext-1.discordapp.net/external/1OzGhjvZTRstTxM38_7pqHXlmdbMddqh1F8R0-WrKqw/https/pbs.twimg.com/profile_images/1353559126693961729/pz-WVnDc_200x200.jpg"
|
||||
},
|
||||
image: {
|
||||
url: "https://pbs.twimg.com/media/HDMUyf6bQAM3yts.jpg?name=orig",
|
||||
proxy_url: "https://images-ext-1.discordapp.net/external/NkNgp2SyY1OCH9IdS8hqsUqbnbrp3A9oLNwYusVVCVQ/%3Fname%3Dorig/https/pbs.twimg.com/media/HDMUyf6bQAM3yts.jpg",
|
||||
width: 872,
|
||||
height: 886,
|
||||
content_type: "image/jpeg",
|
||||
placeholder: "6vcFFwL6R3lye2V3l1mIl5l3WPN5FZ8H",
|
||||
placeholder_version: 1,
|
||||
flags: 0
|
||||
},
|
||||
footer: {
|
||||
text: "FixupX",
|
||||
icon_url: "https://assets.fxembed.com/logos/fixupx64.png",
|
||||
proxy_icon_url: "https://images-ext-1.discordapp.net/external/LwQ70Uiqfu0OCN4ZbA4f482TGCgQa-xGsnUFYfhIgYA/https/assets.fxembed.com/logos/fixupx64.png"
|
||||
},
|
||||
content_scan_version: 4
|
||||
},
|
||||
{
|
||||
type: "rich",
|
||||
url: "https://fixupx.com/i/status/2032003668787020046",
|
||||
image: {
|
||||
url: "https://pbs.twimg.com/media/HDMUgxybQAE4FtJ.jpg?name=orig",
|
||||
proxy_url: "https://images-ext-1.discordapp.net/external/Rquh1ec-tG9hMqdHqIVSphO7zf5B5Fg_7yTWhCjlsek/%3Fname%3Dorig/https/pbs.twimg.com/media/HDMUgxybQAE4FtJ.jpg",
|
||||
width: 1114,
|
||||
height: 991,
|
||||
content_type: "image/jpeg",
|
||||
placeholder: "JQgKDoL3epZ8ZIdnlmmHZ4d4CIGmUEc=",
|
||||
placeholder_version: 1,
|
||||
flags: 0
|
||||
},
|
||||
content_scan_version: 4
|
||||
},
|
||||
{
|
||||
type: "rich",
|
||||
url: "https://fixupx.com/i/status/2032003668787020046",
|
||||
image: {
|
||||
url: "https://pbs.twimg.com/media/HDMUrPobgAAeb90.jpg?name=orig",
|
||||
proxy_url: "https://images-ext-1.discordapp.net/external/XrkhHNH3CvlZYvjkdykVnf-_xdz6HWX8uwesoAwwSfY/%3Fname%3Dorig/https/pbs.twimg.com/media/HDMUrPobgAAeb90.jpg",
|
||||
width: 944,
|
||||
height: 954,
|
||||
content_type: "image/jpeg",
|
||||
placeholder: "m/cJDwCbV0mfaoZzlihqeXdqCVN9A6oD",
|
||||
placeholder_version: 1,
|
||||
flags: 0
|
||||
},
|
||||
content_scan_version: 4
|
||||
},
|
||||
{
|
||||
type: "rich",
|
||||
url: "https://fixupx.com/i/status/2032003668787020046",
|
||||
image: {
|
||||
url: "https://pbs.twimg.com/media/HDMUuy5bgAAInj5.jpg?name=orig",
|
||||
proxy_url: "https://images-ext-1.discordapp.net/external/lO-5hBMU9bGH13Ax9xum2T2Mg0ATdv0b6BEx_VeVi80/%3Fname%3Dorig/https/pbs.twimg.com/media/HDMUuy5bgAAInj5.jpg",
|
||||
width: 1200,
|
||||
height: 630,
|
||||
content_type: "image/jpeg",
|
||||
placeholder: "tfcJDIK3mIl1eIiPdY23dX9b9w==",
|
||||
placeholder_version: 1,
|
||||
flags: 0
|
||||
},
|
||||
content_scan_version: 4
|
||||
}
|
||||
],
|
||||
timestamp: "2026-03-12T16:53:57.009000+00:00",
|
||||
edited_timestamp: null,
|
||||
flags: 0,
|
||||
components: []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
message_with_components: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue