From 1e8066ca0ab9908eb5c5d1509375684e4d276729 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 6 Mar 2024 09:34:46 +1300
Subject: [PATCH 001/346] Embed URL should only appear when embed has title
---
.../message-to-event.embeds.test.js | 52 +++-
d2m/converters/message-to-event.js | 4 +-
test/data.js | 240 ++++++++++++++++++
3 files changed, 290 insertions(+), 6 deletions(-)
diff --git a/d2m/converters/message-to-event.embeds.test.js b/d2m/converters/message-to-event.embeds.test.js
index dfc5679..0ac5018 100644
--- a/d2m/converters/message-to-event.embeds.test.js
+++ b/d2m/converters/message-to-event.embeds.test.js
@@ -27,7 +27,6 @@ test("message2event embeds: reply with just an embed", async t => {
msgtype: "m.notice",
"m.mentions": {},
body: "| ## ⏺️ dynastic (@dynastic) https://twitter.com/i/user/719631291747078145"
- + "\n| \n| ## https://twitter.com/i/status/1707484191963648161"
+ "\n| \n| does anyone know where to find that one video of the really mysterious yam-like object being held up to a bunch of random objects, like clocks, and they have unexplained impossible reactions to it?"
+ "\n| \n| ### Retweets"
+ "\n| 119"
@@ -35,8 +34,7 @@ test("message2event embeds: reply with just an embed", async t => {
+ "\n| 5581"
+ "\n| — Twitter",
format: "org.matrix.custom.html",
- formatted_body: '⏺️ dynastic (@dynastic)
'
- + 'https://twitter.com/i/status/1707484191963648161'
+ formatted_body: '
⏺️ dynastic (@dynastic)'
+ '
does anyone know where to find that one video of the really mysterious yam-like object being held up to a bunch of random objects, like clocks, and they have unexplained impossible reactions to it?'
+ '
Retweets
119
Likes
5581
— Twitter
'
}])
@@ -141,3 +139,51 @@ test("message2event embeds: crazy html is all escaped", async t => {
"m.mentions": {}
}])
})
+
+test("message2event embeds: title without url", async t => {
+ const events = await messageToEvent(data.message_with_embeds.title_without_url, data.guild.general)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| ## Hi, I'm Amanda!\n| \n| I condone pirating music!",
+ format: "org.matrix.custom.html",
+ formatted_body: `Hi, I'm Amanda!
I condone pirating music!
`,
+ "m.mentions": {}
+ }])
+})
+
+test("message2event embeds: url without title", async t => {
+ const events = await messageToEvent(data.message_with_embeds.url_without_title, data.guild.general)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| I condone pirating music!",
+ format: "org.matrix.custom.html",
+ formatted_body: `I condone pirating music!
`,
+ "m.mentions": {}
+ }])
+})
+
+test("message2event embeds: author without url", async t => {
+ const events = await messageToEvent(data.message_with_embeds.author_without_url, data.guild.general)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| ## Amanda\n| \n| I condone pirating music!",
+ format: "org.matrix.custom.html",
+ formatted_body: `Amanda
I condone pirating music!
`,
+ "m.mentions": {}
+ }])
+})
+
+test("message2event embeds: author url without name", async t => {
+ const events = await messageToEvent(data.message_with_embeds.author_url_without_name, data.guild.general)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| I condone pirating music!",
+ format: "org.matrix.custom.html",
+ formatted_body: `I condone pirating music!
`,
+ "m.mentions": {}
+ }])
+})
diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js
index 89edacc..69a4808 100644
--- a/d2m/converters/message-to-event.js
+++ b/d2m/converters/message-to-event.js
@@ -517,7 +517,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// Author and URL into a paragraph
let authorNameText = embed.author?.name || ""
if (authorNameText && embed.author?.icon_url) authorNameText = `⏺️ ${authorNameText}` // using the emoji instead of an image
- if (authorNameText || embed.author?.url) {
+ if (authorNameText) {
if (embed.author?.url) {
const authorURL = await transformContentMessageLinks(embed.author.url)
rep.addParagraph(`## ${authorNameText} ${authorURL}`, tag`${authorNameText}`)
@@ -534,8 +534,6 @@ async function messageToEvent(message, guild, options = {}, di) {
} else {
rep.addParagraph(`## ${body}`, `${html}`)
}
- } else if (embed.url) {
- rep.addParagraph(`## ${embed.url}`, tag`${embed.url}`)
}
if (embed.description) {
diff --git a/test/data.js b/test/data.js
index 2d0f795..49b84e6 100644
--- a/test/data.js
+++ b/test/data.js
@@ -2282,6 +2282,246 @@ module.exports = {
edited_timestamp: null,
flags: 0,
components: []
+ },
+ title_without_url: {
+ guild_id: "497159726455455754",
+ mentions: [],
+ id: "1141934888862351440",
+ type: 20,
+ content: "",
+ channel_id: "497161350934560778",
+ author: {
+ id: "1109360903096369153",
+ username: "Amanda 🎵",
+ avatar: "d56cd1b26e043ae512edae2214962faa",
+ discriminator: "2192",
+ public_flags: 524288,
+ flags: 524288,
+ bot: true,
+ banner: null,
+ accent_color: null,
+ global_name: null,
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "rich",
+ color: 3092790,
+ title: "Hi, I'm Amanda!",
+ description: "I condone pirating music!"
+ }
+ ],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2023-08-18T03:21:33.629000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: [],
+ application_id: "1109360903096369153",
+ interaction: {
+ id: "1141934887608254475",
+ type: 2,
+ name: "stats",
+ user: {
+ id: "320067006521147393",
+ username: "papiophidian",
+ avatar: "47a19b0445069b826e136da4df4259bb",
+ discriminator: "0",
+ public_flags: 4194880,
+ flags: 4194880,
+ banner: null,
+ accent_color: null,
+ global_name: "PapiOphidian",
+ avatar_decoration_data: null,
+ banner_color: null
+ }
+ },
+ webhook_id: "1109360903096369153"
+ },
+ url_without_title: {
+ guild_id: "497159726455455754",
+ mentions: [],
+ id: "1141934888862351440",
+ type: 20,
+ content: "",
+ channel_id: "497161350934560778",
+ author: {
+ id: "1109360903096369153",
+ username: "Amanda 🎵",
+ avatar: "d56cd1b26e043ae512edae2214962faa",
+ discriminator: "2192",
+ public_flags: 524288,
+ flags: 524288,
+ bot: true,
+ banner: null,
+ accent_color: null,
+ global_name: null,
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "rich",
+ color: 3092790,
+ url: "https://amanda.moe",
+ description: "I condone pirating music!"
+ }
+ ],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2023-08-18T03:21:33.629000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: [],
+ application_id: "1109360903096369153",
+ interaction: {
+ id: "1141934887608254475",
+ type: 2,
+ name: "stats",
+ user: {
+ id: "320067006521147393",
+ username: "papiophidian",
+ avatar: "47a19b0445069b826e136da4df4259bb",
+ discriminator: "0",
+ public_flags: 4194880,
+ flags: 4194880,
+ banner: null,
+ accent_color: null,
+ global_name: "PapiOphidian",
+ avatar_decoration_data: null,
+ banner_color: null
+ }
+ },
+ webhook_id: "1109360903096369153"
+ },
+ author_without_url: {
+ guild_id: "497159726455455754",
+ mentions: [],
+ id: "1141934888862351440",
+ type: 20,
+ content: "",
+ channel_id: "497161350934560778",
+ author: {
+ id: "1109360903096369153",
+ username: "Amanda 🎵",
+ avatar: "d56cd1b26e043ae512edae2214962faa",
+ discriminator: "2192",
+ public_flags: 524288,
+ flags: 524288,
+ bot: true,
+ banner: null,
+ accent_color: null,
+ global_name: null,
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "rich",
+ color: 3092790,
+ author: {
+ name: "Amanda"
+ },
+ description: "I condone pirating music!"
+ }
+ ],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2023-08-18T03:21:33.629000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: [],
+ application_id: "1109360903096369153",
+ interaction: {
+ id: "1141934887608254475",
+ type: 2,
+ name: "stats",
+ user: {
+ id: "320067006521147393",
+ username: "papiophidian",
+ avatar: "47a19b0445069b826e136da4df4259bb",
+ discriminator: "0",
+ public_flags: 4194880,
+ flags: 4194880,
+ banner: null,
+ accent_color: null,
+ global_name: "PapiOphidian",
+ avatar_decoration_data: null,
+ banner_color: null
+ }
+ },
+ webhook_id: "1109360903096369153"
+ },
+ author_url_without_name: {
+ guild_id: "497159726455455754",
+ mentions: [],
+ id: "1141934888862351440",
+ type: 20,
+ content: "",
+ channel_id: "497161350934560778",
+ author: {
+ id: "1109360903096369153",
+ username: "Amanda 🎵",
+ avatar: "d56cd1b26e043ae512edae2214962faa",
+ discriminator: "2192",
+ public_flags: 524288,
+ flags: 524288,
+ bot: true,
+ banner: null,
+ accent_color: null,
+ global_name: null,
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "rich",
+ color: 3092790,
+ author: {
+ url: "https://amanda.moe"
+ },
+ description: "I condone pirating music!"
+ }
+ ],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2023-08-18T03:21:33.629000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: [],
+ application_id: "1109360903096369153",
+ interaction: {
+ id: "1141934887608254475",
+ type: 2,
+ name: "stats",
+ user: {
+ id: "320067006521147393",
+ username: "papiophidian",
+ avatar: "47a19b0445069b826e136da4df4259bb",
+ discriminator: "0",
+ public_flags: 4194880,
+ flags: 4194880,
+ banner: null,
+ accent_color: null,
+ global_name: "PapiOphidian",
+ avatar_decoration_data: null,
+ banner_color: null
+ }
+ },
+ webhook_id: "1109360903096369153"
}
},
message_update: {
From e2d0ea41d54395e6d0049a9860e7e8675531fdad Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 6 Mar 2024 11:38:46 +1300
Subject: [PATCH 002/346] Improve video embed formatting
---
.../message-to-event.embeds.test.js | 95 ++++++++++
d2m/converters/message-to-event.js | 19 +-
test/data.js | 179 ++++++++++++++++++
3 files changed, 291 insertions(+), 2 deletions(-)
diff --git a/d2m/converters/message-to-event.embeds.test.js b/d2m/converters/message-to-event.embeds.test.js
index 0ac5018..fc02a3f 100644
--- a/d2m/converters/message-to-event.embeds.test.js
+++ b/d2m/converters/message-to-event.embeds.test.js
@@ -187,3 +187,98 @@ test("message2event embeds: author url without name", async t => {
"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, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "https://vxtwitter.com/TomorrowCorp/status/1760330671074287875 we got a release date!!!",
+ format: "org.matrix.custom.html",
+ formatted_body: 'https://vxtwitter.com/TomorrowCorp/status/1760330671074287875 we got a release date!!!',
+ "m.mentions": {}
+ }, {
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| via vxTwitter / fixvx https://github.com/dylanpdx/BetterTwitFix"
+ + "\n| "
+ + "\n| ## Twitter https://twitter.com/tomorrowcorp/status/1760330671074287875"
+ + "\n| "
+ + "\n| ## Tomorrow Corporation (@TomorrowCorp) https://vxtwitter.com/TomorrowCorp/status/1760330671074287875"
+ + "\n| "
+ + "\n| Mark your calendar with a wet black stain! World of Goo 2 releases on May 23, 2024 on Nintendo Switch, Epic Games Store (Win/Mac), and http://WorldOfGoo2.com (Win/Mac/Linux)."
+ + "\n| "
+ + "\n| https://tomorrowcorporation.com/posts/world-of-goo-2-now-with-100-more-release-dates-and-platforms"
+ + "\n| "
+ + "\n| 💖 123 🔁 36"
+ + "\n| "
+ + "\n| 📸 https://pbs.twimg.com/media/GG3zUMGbIAAxs3h.jpg",
+ format: "org.matrix.custom.html",
+ formatted_body: `vxTwitter / fixvx`
+ + `
Twitter`
+ + `
Tomorrow Corporation (@TomorrowCorp)`
+ + `
Mark your calendar with a wet black stain! World of Goo 2 releases on May 23, 2024 on Nintendo Switch, Epic Games Store (Win/Mac), and http://WorldOfGoo2.com (Win/Mac/Linux).`
+ + `
https://tomorrowcorporation.com/posts/world-of-goo-2-now-with-100-more-release-dates-and-platforms`
+ + `
💖 123 🔁 36`
+ + `
📸 https://pbs.twimg.com/media/GG3zUMGbIAAxs3h.jpg
`,
+ "m.mentions": {}
+ }])
+})
+
+test("message2event embeds: vx video", async t => {
+ const events = await messageToEvent(data.message_with_embeds.vx_video, data.guild.general)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "https://vxtwitter.com/McDonalds/status/1759971752254341417",
+ format: "org.matrix.custom.html",
+ formatted_body: 'https://vxtwitter.com/McDonalds/status/1759971752254341417',
+ "m.mentions": {}
+ }, {
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| via vxTwitter / fixvx https://github.com/dylanpdx/BetterTwitFix"
+ + "\n| \n| ## McDonald’s🤝@studiopierrot"
+ + "\n| \n| 💖 89 🔁 21 https://twitter.com/McDonalds/status/1759971752254341417"
+ + "\n| \n| ## McDonald's (@McDonalds) https://vxtwitter.com/McDonalds/status/1759971752254341417"
+ + "\n| \n| 🎞️ https://video.twimg.com/ext_tw_video/1759967449548541952/pu/vid/avc1/1280x720/XN1LFIJqAFBdtaoh.mp4?tag=12",
+ format: "org.matrix.custom.html",
+ formatted_body: `vxTwitter / fixvx`
+ + `
McDonald’s🤝@studiopierrot\n\n💖 89 🔁 21`
+ + `
McDonald's (@McDonalds)`
+ + `
🎞️ https://video.twimg.com/ext_tw_video/1759967449548541952/pu/vid/avc1/1280x720/XN1LFIJqAFBdtaoh.mp4?tag=12
`,
+ "m.mentions": {}
+ }])
+})
+
+test("message2event embeds: youtube video", async t => {
+ const events = await messageToEvent(data.message_with_embeds.youtube_video, data.guild.general)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "https://youtu.be/kDMHHw8JqLE?si=NaqNjVTtXugHeG_E\n\n\nJutomi I'm gonna make these sounds in your walls tonight",
+ format: "org.matrix.custom.html",
+ formatted_body: `https://youtu.be/kDMHHw8JqLE?si=NaqNjVTtXugHeG_E
Jutomi I'm gonna make these sounds in your walls tonight`,
+ "m.mentions": {}
+ }, {
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| via YouTube https://www.youtube.com"
+ + "\n| \n| ## Happy O Funny https://www.youtube.com/channel/UCEpQ9aEb1NafpvWp5Aoizrg"
+ + "\n| \n| ## Shoebill stork clattering sounds like machine guun~!! (Japan Matsue... https://www.youtube.com/watch?v=kDMHHw8JqLE"
+ + "\n| \n| twitter"
+ + "\n| https://twitter.com/matsuevogelpark"
+ + "\n| \n| The shoebill (Balaeniceps rex) also known as whalehead, whale-headed stork, or shoe-billed stork, is a very large stork-like bird. It derives its name from its enormous shoe-shaped bill"
+ + "\n| some people also called them the living dinosaur~~"
+ + "\n| \n| #shoebill #livingdinosaur #happyofunny #weirdcreature #weirdsoun..."
+ + "\n| \n| 🎞️ https://www.youtube.com/embed/kDMHHw8JqLE",
+ format: "org.matrix.custom.html",
+ formatted_body: `YouTube
`
+ + `Happy O Funny`
+ + `
Shoebill stork clattering sounds like machine guun~!! (Japan Matsue...`
+ + `
twitter
https://twitter.com/matsuevogelpark
The shoebill (Balaeniceps rex) also known as whalehead, whale-headed stork, or shoe-billed stork, is a very large stork-like bird. It derives its name from its enormous shoe-shaped bill
some people also called them the living dinosaur~~
#shoebill #livingdinosaur #happyofunny #weirdcreature #weirdsoun...`
+ + `
🎞️ https://www.youtube.com/embed/kDMHHw8JqLE`
+ + `
`,
+ "m.mentions": {}
+ }])
+})
diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js
index 69a4808..054b12c 100644
--- a/d2m/converters/message-to-event.js
+++ b/d2m/converters/message-to-event.js
@@ -514,6 +514,15 @@ 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()
+ // Provider
+ if (embed.provider?.name) {
+ if (embed.provider.url) {
+ rep.addParagraph(`via ${embed.provider.name} ${embed.provider.url}`, tag`${embed.provider.name}`)
+ } else {
+ rep.addParagraph(`via ${embed.provider.name}`, tag`${embed.provider.name}`)
+ }
+ }
+
// Author and URL into a paragraph
let authorNameText = embed.author?.name || ""
if (authorNameText && embed.author?.icon_url) authorNameText = `⏺️ ${authorNameText}` // using the emoji instead of an image
@@ -536,7 +545,9 @@ async function messageToEvent(message, guild, options = {}, di) {
}
}
- if (embed.description) {
+ let embedTypeShouldShowDescription = embed.type !== "video" // Discord doesn't display descriptions for videos
+ if (embed.provider?.name === "YouTube") embedTypeShouldShowDescription = true // But I personally like showing the descriptions for YouTube videos specifically
+ if (embed.description && embedTypeShouldShowDescription) {
const {body, html} = await transformContent(embed.description)
rep.addParagraph(body, html)
}
@@ -550,7 +561,11 @@ async function messageToEvent(message, guild, options = {}, di) {
rep.addParagraph(fieldRep.get().body, fieldRep.get().formatted_body)
}
- if (embed.image?.url) rep.addParagraph(`📸 ${embed.image.url}`)
+ 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(`📸 ${chosenImage}`)
+
if (embed.video?.url) rep.addParagraph(`🎞️ ${embed.video.url}`)
if (embed.footer?.text) rep.addLine(`— ${embed.footer.text}`, tag`— ${embed.footer.text}`)
diff --git a/test/data.js b/test/data.js
index 49b84e6..b4f95b3 100644
--- a/test/data.js
+++ b/test/data.js
@@ -2123,6 +2123,185 @@ module.exports = {
attachments: [],
guild_id: "1150201337112449045"
},
+ vx_image: {
+ id: "1209926442981269544",
+ type: 0,
+ content: "https://vxtwitter.com/TomorrowCorp/status/1760330671074287875 we got a release date!!!",
+ channel_id: "288058913985789953",
+ author: {
+ id: "113340068197859328",
+ username: "kumaccino",
+ avatar: "b48302623a12bc7c59a71328f72ccb39",
+ discriminator: "0",
+ public_flags: 128,
+ premium_type: 0,
+ flags: 128,
+ banner: null,
+ accent_color: null,
+ global_name: "kumaccino",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "article",
+ url: "https://vxtwitter.com/TomorrowCorp/status/1760330671074287875",
+ title: "Tomorrow Corporation (@TomorrowCorp)",
+ description: "Mark your calendar with a wet black stain! World of Goo 2 releases on May 23, 2024 on Nintendo Switch, Epic Games Store (Win/Mac), and http://WorldOfGoo2.com (Win/Mac/Linux).\n" +
+ "\n" +
+ "https://tomorrowcorporation.com/posts/world-of-goo-2-now-with-100-more-release-dates-and-platforms\n" +
+ "\n" +
+ "💖 123 🔁 36",
+ color: 8388564,
+ author: {
+ name: "Twitter",
+ url: "https://twitter.com/tomorrowcorp/status/1760330671074287875"
+ },
+ provider: {
+ name: "vxTwitter / fixvx",
+ url: "https://github.com/dylanpdx/BetterTwitFix"
+ },
+ thumbnail: {
+ url: "https://pbs.twimg.com/media/GG3zUMGbIAAxs3h.jpg",
+ proxy_url: "https://images-ext-2.discordapp.net/external/eqA-NKoXzJ0Y_l-MlwN6shFDJibC0TbPxMNWSU5IpKY/https/pbs.twimg.com/media/GG3zUMGbIAAxs3h.jpg",
+ width: 1200,
+ height: 1200,
+ placeholder: "5SgKDwTIlqiPjIhzlspniIiNaN8It3AD",
+ placeholder_version: 1
+ }
+ }
+ ],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-02-21T18:15:43.353000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
+ vx_video: {
+ id: "1209804622206599190",
+ type: 0,
+ content: "https://vxtwitter.com/McDonalds/status/1759971752254341417",
+ channel_id: "112760669178241024",
+ author: {
+ id: "113340068197859328",
+ username: "kumaccino",
+ avatar: "b48302623a12bc7c59a71328f72ccb39",
+ discriminator: "0",
+ public_flags: 128,
+ premium_type: 0,
+ flags: 128,
+ banner: null,
+ accent_color: null,
+ global_name: "kumaccino",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "video",
+ url: "https://vxtwitter.com/McDonalds/status/1759971752254341417",
+ title: "McDonald's (@McDonalds)",
+ description: "McDonald’s🤝@studiopierrot\n\n💖 89 🔁 21",
+ color: 8388564,
+ author: {
+ name: "McDonald’s🤝@studiopierrot\n\n💖 89 🔁 21",
+ url: "https://twitter.com/McDonalds/status/1759971752254341417"
+ },
+ provider: {
+ name: "vxTwitter / fixvx",
+ url: "https://github.com/dylanpdx/BetterTwitFix"
+ },
+ video: {
+ url: "https://video.twimg.com/ext_tw_video/1759967449548541952/pu/vid/avc1/1280x720/XN1LFIJqAFBdtaoh.mp4?tag=12",
+ proxy_url: "https://images-ext-1.discordapp.net/external/TInoGDskHFBRSQR0ErWEmvmzi75EO28aSyiEXs3SB8E/%3Ftag%3D12/https/video.twimg.com/ext_tw_video/1759967449548541952/pu/vid/avc1/1280x720/XN1LFIJqAFBdtaoh.mp4",
+ width: 1280,
+ height: 720,
+ placeholder: "AggGBIAIp4iGeYdxjHgAAAAAAA==",
+ placeholder_version: 1
+ }
+ }
+ ],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-02-21T10:11:39.017000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
+ youtube_video: {
+ id: "1214383754479534100",
+ type: 0,
+ content: "https://youtu.be/kDMHHw8JqLE?si=NaqNjVTtXugHeG_E\n\n\nJutomi I'm gonna make these sounds in your walls tonight",
+ channel_id: "112760669178241024",
+ author: {
+ id: "1060361805152669766",
+ username: "occimyy",
+ avatar: "3bf268de3eab1c5441da9585534d8aa5",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "Occimyy",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "video",
+ url: "https://www.youtube.com/watch?v=kDMHHw8JqLE",
+ title: "Shoebill stork clattering sounds like machine guun~!! (Japan Matsue...",
+ description: "twitter\n" +
+ "https://twitter.com/matsuevogelpark\n" +
+ "\n" +
+ "The shoebill (Balaeniceps rex) also known as whalehead, whale-headed stork, or shoe-billed stork, is a very large stork-like bird. It derives its name from its enormous shoe-shaped bill\n" +
+ "some people also called them the living dinosaur~~\n" +
+ "\n" +
+ "#shoebill #livingdinosaur #happyofunny #weirdcreature #weirdsoun...",
+ color: 16711680,
+ author: {
+ name: "Happy O Funny",
+ url: "https://www.youtube.com/channel/UCEpQ9aEb1NafpvWp5Aoizrg"
+ },
+ provider: { name: "YouTube", url: "https://www.youtube.com" },
+ thumbnail: {
+ url: "https://i.ytimg.com/vi/kDMHHw8JqLE/maxresdefault.jpg",
+ proxy_url: "https://images-ext-1.discordapp.net/external/eEPOxZQXfTHqvPQJBWqsgG3wxTQN20b8LXqw3jSqyRM/https/i.ytimg.com/vi/kDMHHw8JqLE/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ placeholder: "WAgSDIIIdIprl4h4h4dNoEoEaQ==",
+ placeholder_version: 1
+ },
+ video: {
+ url: "https://www.youtube.com/embed/kDMHHw8JqLE",
+ width: 1280,
+ height: 720,
+ placeholder: "WAgSDIIIdIprl4h4h4dNoEoEaQ==",
+ placeholder_version: 1
+ }
+ }
+ ],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-03-05T01:27:29.227000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
image_embed_and_attachment: {
id: "1157854642810654821",
type: 0,
From 2fb68900c72c15bdfabf92c93f6d6ca1adda30c2 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 6 Mar 2024 11:56:21 +1300
Subject: [PATCH 003/346] d->m: Support permissioned @everyone -> @room
This only works if #9 is fixed in the future.
---
d2m/converters/message-to-event.js | 4 +-
d2m/converters/message-to-event.test.js | 60 +++++++++
test/data.js | 157 ++++++++++++++++++++++++
3 files changed, 220 insertions(+), 1 deletion(-)
diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js
index 054b12c..3ede0a4 100644
--- a/d2m/converters/message-to-event.js
+++ b/d2m/converters/message-to-event.js
@@ -249,6 +249,8 @@ async function messageToEvent(message, guild, options = {}, di) {
let repliedToEventRow = null
let repliedToEventSenderMxid = null
+ if (message.mention_everyone) mentions.room = true
+
function addMention(mxid) {
if (!mentions.user_ids) mentions.user_ids = []
if (!mentions.user_ids.includes(mxid)) mentions.user_ids.push(mxid)
@@ -480,7 +482,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// Mentions scenario 3: scan the message content for written @mentions of matrix users. Allows for up to one space between @ and mention.
const matches = [...message.content.matchAll(/@ ?([a-z0-9._]+)\b/gi)]
- if (matches.length && matches.some(m => m[1].match(/[a-z]/i))) {
+ if (matches.length && matches.some(m => m[1].match(/[a-z]/i) && m[1] !== "everyone" && m[1] !== "here")) {
const writtenMentionsText = matches.map(m => m[1].toLowerCase())
const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
assert(roomID)
diff --git a/d2m/converters/message-to-event.test.js b/d2m/converters/message-to-event.test.js
index ce694fd..edcb44c 100644
--- a/d2m/converters/message-to-event.test.js
+++ b/d2m/converters/message-to-event.test.js
@@ -789,3 +789,63 @@ test("message2event: crossposted announcements say where they are crossposted fr
formatted_body: "🔀 Chewey Bot Official Server #announcements
All text based commands are now inactive on Chewey Bot
To continue using commands you'll need to use them as slash commands"
}])
})
+
+test("message2event: @everyone", async t => {
+ const events = await messageToEvent(data.message_mention_everyone.at_everyone)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "@room",
+ "m.mentions": {
+ room: true
+ }
+ }])
+})
+
+test("message2event: @here", async t => {
+ const events = await messageToEvent(data.message_mention_everyone.at_here)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "@room",
+ "m.mentions": {
+ room: true
+ }
+ }])
+})
+
+test("message2event: @everyone without permission", async t => {
+ const events = await messageToEvent(data.message_mention_everyone.at_everyone_without_permission)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "@everyone <-- this is testing that it DOESN'T mention. if this mentions everyone then my apologies.",
+ format: "org.matrix.custom.html",
+ formatted_body: "@everyone <-- this is testing that it DOESN'T mention. if this mentions everyone then my apologies.",
+ "m.mentions": {}
+ }])
+})
+
+test("message2event: @here without permission", async t => {
+ const events = await messageToEvent(data.message_mention_everyone.at_here_without_permission)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "@here <-- this is testing that it DOESN'T mention. if this mentions people then my apologies.",
+ format: "org.matrix.custom.html",
+ formatted_body: "@here <-- this is testing that it DOESN'T mention. if this mentions people then my apologies.",
+ "m.mentions": {}
+ }])
+})
+
+test("message2event: @everyone within a link", async t => {
+ const events = await messageToEvent(data.message_mention_everyone.at_everyone_within_link)
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "https://github.com/@everyone",
+ format: "org.matrix.custom.html",
+ formatted_body: `https://github.com/@everyone`,
+ "m.mentions": {}
+ }])
+})
diff --git a/test/data.js b/test/data.js
index b4f95b3..61ee5d0 100644
--- a/test/data.js
+++ b/test/data.js
@@ -1925,6 +1925,163 @@ module.exports = {
webhook_id: "1195662438662680720"
}
},
+ message_mention_everyone: {
+ at_everyone: {
+ id: "1214510099058655252",
+ type: 0,
+ content: "@everyone",
+ channel_id: "1100319550446252084",
+ author: {
+ id: "772659086046658620",
+ username: "cadence.worm",
+ avatar: "4b5c4b28051144e4c111f0113a0f1cf1",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "cadence",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: true,
+ tts: false,
+ timestamp: "2024-03-05T09:49:32.122000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
+ at_here: {
+ id: "1214510192230797332",
+ type: 0,
+ content: "@here",
+ channel_id: "1100319550446252084",
+ author: {
+ id: "772659086046658620",
+ username: "cadence.worm",
+ avatar: "4b5c4b28051144e4c111f0113a0f1cf1",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "cadence",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: true,
+ tts: false,
+ timestamp: "2024-03-05T09:49:54.336000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
+ at_everyone_without_permission: {
+ id: "1214510346623258654",
+ type: 0,
+ content: "@everyone <-- this is testing that it DOESN'T mention. if this mentions everyone then my apologies.",
+ channel_id: "112760669178241024",
+ author: {
+ id: "772659086046658620",
+ username: "cadence.worm",
+ avatar: "4b5c4b28051144e4c111f0113a0f1cf1",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "cadence",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-03-05T09:50:31.146000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
+ at_here_without_permission: {
+ id: "1214510346623258654",
+ type: 0,
+ content: "@here <-- this is testing that it DOESN'T mention. if this mentions people then my apologies.",
+ channel_id: "112760669178241024",
+ author: {
+ id: "772659086046658620",
+ username: "cadence.worm",
+ avatar: "4b5c4b28051144e4c111f0113a0f1cf1",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "cadence",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-03-05T09:50:31.146000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ },
+ at_everyone_within_link: {
+ id: "1214510225885888563",
+ type: 0,
+ content: "https://github.com/@everyone",
+ channel_id: "1100319550446252084",
+ author: {
+ id: "772659086046658620",
+ username: "cadence.worm",
+ avatar: "4b5c4b28051144e4c111f0113a0f1cf1",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "cadence",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-03-05T09:50:02.360000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
+ }
+ },
message_with_embeds: {
nothing_but_a_field: {
guild_id: "497159726455455754",
From bf3d219716b46daf51dc4907270b8bbbb7d1ef62 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 6 Mar 2024 17:37:16 +1300
Subject: [PATCH 004/346] Add helper for permission calculations
---
d2m/converters/remove-reaction.js | 2 +-
d2m/event-dispatcher.js | 6 ++--
discord/discord-command-handler.js | 2 +-
discord/utils.js | 46 ++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/d2m/converters/remove-reaction.js b/d2m/converters/remove-reaction.js
index a6c8ace..caa96d1 100644
--- a/d2m/converters/remove-reaction.js
+++ b/d2m/converters/remove-reaction.js
@@ -12,7 +12,7 @@ const utils = sync.require("../../m2d/converters/utils")
* @typedef ReactionRemoveRequest
* @prop {string} eventID
* @prop {string | null} mxid
- * @prop {BigInt} [hash]
+ * @prop {bigint} [hash]
*/
/**
diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js
index e769053..3db1d45 100644
--- a/d2m/event-dispatcher.js
+++ b/d2m/event-dispatcher.js
@@ -115,8 +115,7 @@ module.exports = {
if (!member) return
if (!("permission_overwrites" in channel)) continue
const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites)
- const wants = BigInt(1 << 10) | BigInt(1 << 16) // VIEW_CHANNEL + READ_MESSAGE_HISTORY
- if ((permissions & wants) !== wants) continue // We don't have permission to look back in this channel
+ if (!dUtils.hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])) continue // We don't have permission to look back in this channel
/** More recent messages come first. */
// console.log(`[check missed messages] in ${channel.id} (${guild.name} / ${channel.name}) because its last message ${channel.last_message_id} is not in the database`)
@@ -164,8 +163,7 @@ module.exports = {
// Permissions check
const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites)
- const wants = BigInt(1 << 10) | BigInt(1 << 16) // VIEW_CHANNEL + READ_MESSAGE_HISTORY
- if ((permissions & wants) !== wants) continue // We don't have permission to look up the pins in this channel
+ if (!dUtils.hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])) continue // We don't have permission to look up the pins in this channel
const row = select("channel_room", ["room_id", "last_bridged_pin_timestamp"], {channel_id: channel.id}).get()
if (!row) continue // Only care about already bridged channels
diff --git a/discord/discord-command-handler.js b/discord/discord-command-handler.js
index aad06e1..f69346f 100644
--- a/discord/discord-command-handler.js
+++ b/discord/discord-command-handler.js
@@ -137,7 +137,7 @@ const commands = [{
// Check CREATE_INSTANT_INVITE permission
assert(message.member)
const guildPermissions = utils.getPermissions(message.member.roles, guild.roles)
- if (!(guildPermissions & BigInt(1))) {
+ if (!(guildPermissions & DiscordTypes.PermissionFlagsBits.CreateInstantInvite)) {
return discord.snow.channel.createMessage(channel.id, {
...ctx,
content: "You don't have permission to invite people to this Discord server."
diff --git a/discord/utils.js b/discord/utils.js
index 6788bcf..ff1f215 100644
--- a/discord/utils.js
+++ b/discord/utils.js
@@ -1,6 +1,7 @@
// @ts-check
const DiscordTypes = require("discord-api-types/v10")
+const assert = require("assert").strict
const EPOCH = 1420070400000
@@ -49,6 +50,48 @@ function getPermissions(userRoles, guildRoles, userID, channelOverwrites) {
return allowed
}
+/**
+ * Note: You can only provide one permission bit to permissionToCheckFor. To check multiple permissions, call `hasAllPermissions` or `hasSomePermissions`.
+ * It is designed like this to avoid developer error with bit manipulations.
+ *
+ * @param {bigint} resolvedPermissions
+ * @param {bigint} permissionToCheckFor
+ * @returns {boolean} whether the user has the requested permission
+ * @example
+ * const permissions = getPermissions(userRoles, guildRoles, userID, channelOverwrites)
+ * hasPermission(permissions, DiscordTypes.PermissionFlagsBits.ViewChannel)
+ */
+function hasPermission(resolvedPermissions, permissionToCheckFor) {
+ // Make sure permissionToCheckFor has exactly one permission in it
+ assert.equal(permissionToCheckFor.toString(2).match(/1/g), 1)
+ // Do the actual calculation
+ return (resolvedPermissions & permissionToCheckFor) === permissionToCheckFor
+}
+
+/**
+ * @param {bigint} resolvedPermissions
+ * @param {(keyof DiscordTypes.PermissionFlagsBits)[]} permissionsToCheckFor
+ * @returns {boolean} whether the user has any of the requested permissions
+ * @example
+ * const permissions = getPermissions(userRoles, guildRoles, userID, channelOverwrites)
+ * hasSomePermissions(permissions, ["ViewChannel", "ReadMessageHistory"])
+ */
+function hasSomePermissions(resolvedPermissions, permissionsToCheckFor) {
+ return permissionsToCheckFor.some(x => hasPermission(resolvedPermissions, DiscordTypes.PermissionFlagsBits[x]))
+}
+
+/**
+ * @param {bigint} resolvedPermissions
+ * @param {(keyof DiscordTypes.PermissionFlagsBits)[]} permissionsToCheckFor
+ * @returns {boolean} whether the user has all of the requested permissions
+ * @example
+ * const permissions = getPermissions(userRoles, guildRoles, userID, channelOverwrites)
+ * hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])
+ */
+function hasAllPermissions(resolvedPermissions, permissionsToCheckFor) {
+ return permissionsToCheckFor.every(x => hasPermission(resolvedPermissions, DiscordTypes.PermissionFlagsBits[x]))
+}
+
/**
* Command interaction responses have a webhook_id for some reason, but still have real author info of a real bot user in the server.
* @param {DiscordTypes.APIMessage} message
@@ -69,6 +112,9 @@ function timestampToSnowflakeInexact(timestamp) {
}
module.exports.getPermissions = getPermissions
+module.exports.hasPermission = hasPermission
+module.exports.hasSomePermissions = hasSomePermissions
+module.exports.hasAllPermissions = hasAllPermissions
module.exports.isWebhookMessage = isWebhookMessage
module.exports.snowflakeToTimestampExact = snowflakeToTimestampExact
module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact
From 043f178d1e424b0d61c6f912d8712fc3ac137687 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 6 Mar 2024 17:40:06 +1300
Subject: [PATCH 005/346] Map Discord member permissions to sim user PLs
Including PL 20 for members who can mention everyone.
---
d2m/actions/create-room.js | 3 ++
d2m/actions/register-pk-user.js | 2 +-
d2m/actions/register-user.js | 90 ++++++++++++++++++++++++++-------
3 files changed, 76 insertions(+), 19 deletions(-)
diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js
index 6994b57..0dea283 100644
--- a/d2m/actions/create-room.js
+++ b/d2m/actions/create-room.js
@@ -135,6 +135,9 @@ async function channelToKState(channel, guild) {
events: {
"m.room.avatar": 0
},
+ notifications: {
+ room: 20 // TODO: Matrix users should have the same abilities as unprivileged Discord members. So make this automatically configured based on the guild or channel's default mention everyone permissions. That way if unprivileged Discord members can mention everyone, Matrix users can too.
+ },
users: reg.ooye.invite.reduce((a, c) => (a[c] = 100, a), {})
},
"chat.schildi.hide_ui/read_receipts": {
diff --git a/d2m/actions/register-pk-user.js b/d2m/actions/register-pk-user.js
index ca47b7c..1e223c6 100644
--- a/d2m/actions/register-pk-user.js
+++ b/d2m/actions/register-pk-user.js
@@ -131,7 +131,7 @@ async function syncUser(author, pkMessage, roomID) {
db.prepare("INSERT OR IGNORE INTO sim_proxy (user_id, proxy_owner_id, displayname) VALUES (?, ?, ?)").run(pkMessage.member.uuid, pkMessage.sender, author.username)
// Sync the member state
const content = await memberToStateContent(pkMessage, author)
- const currentHash = registerUser._hashProfileContent(content)
+ const currentHash = registerUser._hashProfileContent(content, 0)
const existingHash = select("sim_member", "hashed_profile_content", {room_id: roomID, mxid}).safeIntegers().pluck().get()
// only do the actual sync if the hash has changed since we last looked
if (existingHash !== currentHash) {
diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js
index 8244fe2..7e1d9f9 100644
--- a/d2m/actions/register-user.js
+++ b/d2m/actions/register-user.js
@@ -2,6 +2,8 @@
const assert = require("assert")
const reg = require("../../matrix/read-registration")
+const DiscordTypes = require("discord-api-types/v10")
+const mixin = require("mixin-deep")
const passthrough = require("../../passthrough")
const {discord, sync, db, select} = passthrough
@@ -9,6 +11,8 @@ const {discord, sync, db, select} = passthrough
const api = sync.require("../../matrix/api")
/** @type {import("../../matrix/file")} */
const file = sync.require("../../matrix/file")
+/** @type {import("../../discord/utils")} */
+const utils = sync.require("../../discord/utils")
/** @type {import("../converters/user-to-mxid")} */
const userToMxid = sync.require("../converters/user-to-mxid")
/** @type {import("xxhash-wasm").XXHashAPI} */ // @ts-ignore
@@ -18,7 +22,7 @@ require("xxhash-wasm")().then(h => hasher = h)
/**
* A sim is an account that is being simulated by the bridge to copy events from the other side.
- * @param {import("discord-api-types/v10").APIUser} user
+ * @param {DiscordTypes.APIUser} user
* @returns mxid
*/
async function createSim(user) {
@@ -46,7 +50,7 @@ async function createSim(user) {
/**
* Ensure a sim is registered for the user.
* If there is already a sim, use that one. If there isn't one yet, register a new sim.
- * @param {import("discord-api-types/v10").APIUser} user
+ * @param {DiscordTypes.APIUser} user
* @returns {Promise} mxid
*/
async function ensureSim(user) {
@@ -62,7 +66,7 @@ async function ensureSim(user) {
/**
* Ensure a sim is registered for the user and is joined to the room.
- * @param {import("discord-api-types/v10").APIUser} user
+ * @param {DiscordTypes.APIUser} user
* @param {string} roomID
* @returns {Promise} mxid
*/
@@ -92,8 +96,8 @@ async function ensureSimJoined(user, roomID) {
}
/**
- * @param {import("discord-api-types/v10").APIUser} user
- * @param {Omit} member
+ * @param {DiscordTypes.APIUser} user
+ * @param {Omit} member
*/
async function memberToStateContent(user, member, guildID) {
let displayname = user.username
@@ -123,8 +127,46 @@ async function memberToStateContent(user, member, guildID) {
return content
}
-function _hashProfileContent(content) {
- const unsignedHash = hasher.h64(`${content.displayname}\u0000${content.avatar_url}`)
+/**
+ * https://gitdab.com/cadence/out-of-your-element/issues/9
+ * @param {DiscordTypes.APIUser} user
+ * @param {Omit} member
+ * @param {DiscordTypes.APIGuild} guild
+ * @param {DiscordTypes.APIGuildChannel} channel
+ * @returns {number} 0 to 100
+ */
+function memberToPowerLevel(user, member, guild, channel) {
+ const permissions = utils.getPermissions(member.roles, guild.roles, user.id, channel.permission_overwrites)
+ /*
+ * PL 100 = Administrator = People who can brick the room. RATIONALE:
+ * - Administrator.
+ * - Manage Webhooks: People who remove the webhook can break the room.
+ * - Manage Guild: People who can manage guild can add bots.
+ * - Manage Channels: People who can manage the channel can delete it.
+ * (Setting sim users to PL 100 is safe because even though we can't demote the sims we can use code to make the sims demote themselves.)
+ */
+ if (guild.owner_id === user.id || utils.hasSomePermissions(permissions, ["Administrator", "ManageWebhooks", "ManageGuild", "ManageChannels"])) return 100
+ /*
+ * PL 50 = Moderator = People who can manage people and messages in many ways. RATIONALE:
+ * - Manage Messages: Can moderate by pinning or deleting the conversation.
+ * - Manage Nicknames: Can moderate by removing inappropriate nicknames.
+ * - Manage Threads: Can moderate by deleting conversations.
+ * - Kick Members & Ban Members: Can moderate by removing disruptive people.
+ * - Mute Members & Deafen Members: Can moderate by silencing disruptive people in ways they can't undo.
+ * - Moderate Members.
+ */
+ if (utils.hasSomePermissions(permissions, ["ManageMessages", "ManageNicknames", "ManageThreads", "KickMembers", "BanMembers", "MuteMembers", "DeafenMembers", "ModerateMembers"])) return 50
+ /* PL 20 = Mention Everyone for technical reasons. */
+ if (utils.hasSomePermissions(permissions, ["MentionEveryone"])) return 20
+ return 0
+}
+
+/**
+ * @param {any} content
+ * @param {number} powerLevel
+ */
+function _hashProfileContent(content, powerLevel) {
+ const unsignedHash = hasher.h64(`${content.displayname}\u0000${content.avatar_url}\u0000${powerLevel}`)
const signedHash = unsignedHash - 0x8000000000000000n // shifting down to signed 64-bit range
return signedHash
}
@@ -133,20 +175,30 @@ function _hashProfileContent(content) {
* Sync profile data for a sim user. This function follows the following process:
* 1. Join the sim to the room if needed
* 2. Make an object of what the new room member state content would be, including uploading the profile picture if it hasn't been done before
- * 3. Compare against the previously known state content, which is helpfully stored in the database
- * 4. If the state content has changed, send it to Matrix and update it in the database for next time
- * @param {import("discord-api-types/v10").APIUser} user
- * @param {Omit} member
+ * 3. Calculate the power level the user should get based on their Discord permissions
+ * 4. Compare against the previously known state content, which is helpfully stored in the database
+ * 5. If the state content or power level have changed, send them to Matrix and update them in the database for next time
+ * @param {DiscordTypes.APIUser} user
+ * @param {Omit} member
+ * @param {DiscordTypes.APIGuild} guild
+ * @param {DiscordTypes.APIGuildChannel} channel
* @returns {Promise} mxid of the updated sim
*/
-async function syncUser(user, member, guildID, roomID) {
+async function syncUser(user, member, guild, channel, roomID) {
const mxid = await ensureSimJoined(user, roomID)
- const content = await memberToStateContent(user, member, guildID)
- const currentHash = _hashProfileContent(content)
+ const content = await memberToStateContent(user, member, guild.id)
+ const powerLevel = memberToPowerLevel(user, member, guild, channel)
+ const currentHash = _hashProfileContent(content, powerLevel)
const existingHash = select("sim_member", "hashed_profile_content", {room_id: roomID, mxid}).safeIntegers().pluck().get()
// only do the actual sync if the hash has changed since we last looked
if (existingHash !== currentHash) {
+ // Update room member state
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
+ // Update power levels
+ const powerLevelsStateContent = await api.getStateEvent(roomID, "m.room.power_levels", "")
+ mixin(powerLevelsStateContent, {users: {[mxid]: powerLevel}})
+ api.sendState(roomID, "m.room.power_levels", "", powerLevelsStateContent)
+ // Update cached hash
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
}
return mxid
@@ -158,23 +210,25 @@ async function syncAllUsersInRoom(roomID) {
const channelID = select("channel_room", "channel_id", {room_id: roomID}).pluck().get()
assert.ok(typeof channelID === "string")
- /** @ts-ignore @type {import("discord-api-types/v10").APIGuildChannel} */
+ /** @ts-ignore @type {DiscordTypes.APIGuildChannel} */
const channel = discord.channels.get(channelID)
const guildID = channel.guild_id
assert.ok(typeof guildID === "string")
+ /** @ts-ignore @type {DiscordTypes.APIGuild} */
+ const guild = discord.guilds.get(guildID)
for (const mxid of mxids) {
const userID = select("sim", "user_id", {mxid}).pluck().get()
assert.ok(typeof userID === "string")
- /** @ts-ignore @type {Required} */
+ /** @ts-ignore @type {Required} */
const member = await discord.snow.guild.getGuildMember(guildID, userID)
- /** @ts-ignore @type {Required} user */
+ /** @ts-ignore @type {Required} user */
const user = member.user
assert.ok(user)
console.log(`[user sync] to matrix: ${user.username} in ${channel.name}`)
- await syncUser(user, member, guildID, roomID)
+ await syncUser(user, member, guild, channel, roomID)
}
}
From 0f1cf7a20c9b22ef5801146e852f8e3b3483701f Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 7 Mar 2024 09:13:25 +1300
Subject: [PATCH 006/346] Fix calls to syncUser/registerUser
---
d2m/actions/register-user.js | 12 ++++++++----
d2m/actions/send-message.js | 12 +++++++-----
d2m/event-dispatcher.js | 2 +-
discord/utils.js | 2 +-
4 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js
index 7e1d9f9..68b1a88 100644
--- a/d2m/actions/register-user.js
+++ b/d2m/actions/register-user.js
@@ -1,6 +1,6 @@
// @ts-check
-const assert = require("assert")
+const assert = require("assert").strict
const reg = require("../../matrix/read-registration")
const DiscordTypes = require("discord-api-types/v10")
const mixin = require("mixin-deep")
@@ -180,11 +180,12 @@ function _hashProfileContent(content, powerLevel) {
* 5. If the state content or power level have changed, send them to Matrix and update them in the database for next time
* @param {DiscordTypes.APIUser} user
* @param {Omit} member
- * @param {DiscordTypes.APIGuild} guild
* @param {DiscordTypes.APIGuildChannel} channel
+ * @param {DiscordTypes.APIGuild} guild
+ * @param {string} roomID
* @returns {Promise} mxid of the updated sim
*/
-async function syncUser(user, member, guild, channel, roomID) {
+async function syncUser(user, member, channel, guild, roomID) {
const mxid = await ensureSimJoined(user, roomID)
const content = await memberToStateContent(user, member, guild.id)
const powerLevel = memberToPowerLevel(user, member, guild, channel)
@@ -204,6 +205,9 @@ async function syncUser(user, member, guild, channel, roomID) {
return mxid
}
+/**
+ * @param {string} roomID
+ */
async function syncAllUsersInRoom(roomID) {
const mxids = select("sim_member", "mxid", {room_id: roomID}).pluck().all()
@@ -228,7 +232,7 @@ async function syncAllUsersInRoom(roomID) {
assert.ok(user)
console.log(`[user sync] to matrix: ${user.username} in ${channel.name}`)
- await syncUser(user, member, guild, channel, roomID)
+ await syncUser(user, member, channel, guild, roomID)
}
}
diff --git a/d2m/actions/send-message.js b/d2m/actions/send-message.js
index 8c26f07..a1290e0 100644
--- a/d2m/actions/send-message.js
+++ b/d2m/actions/send-message.js
@@ -1,6 +1,7 @@
// @ts-check
-const assert = require("assert")
+const assert = require("assert").strict
+const DiscordTypes = require("discord-api-types/v10")
const passthrough = require("../../passthrough")
const { discord, sync, db } = passthrough
@@ -18,17 +19,18 @@ const createRoom = sync.require("../actions/create-room")
const dUtils = sync.require("../../discord/utils")
/**
- * @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message
- * @param {import("discord-api-types/v10").APIGuild} guild
+ * @param {DiscordTypes.GatewayMessageCreateDispatchData} message
+ * @param {DiscordTypes.APIGuildChannel} channel
+ * @param {DiscordTypes.APIGuild} guild
* @param {{speedbump_id: string, speedbump_webhook_id: string} | null} row data about the webhook which is proxying messages in this channel
*/
-async function sendMessage(message, guild, row) {
+async function sendMessage(message, channel, guild, row) {
const roomID = await createRoom.ensureRoom(message.channel_id)
let senderMxid = null
if (!dUtils.isWebhookMessage(message)) {
if (message.member) { // available on a gateway message create event
- senderMxid = await registerUser.syncUser(message.author, message.member, message.guild_id, roomID)
+ senderMxid = await registerUser.syncUser(message.author, message.member, channel, guild, roomID)
} else { // well, good enough...
senderMxid = await registerUser.ensureSimJoined(message.author, roomID)
}
diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js
index 3db1d45..2c4dcd5 100644
--- a/d2m/event-dispatcher.js
+++ b/d2m/event-dispatcher.js
@@ -248,7 +248,7 @@ module.exports = {
if (affected) return
// @ts-ignore
- await sendMessage.sendMessage(message, guild, row),
+ await sendMessage.sendMessage(message, channel, guild, row),
await discordCommandHandler.execute(message, channel, guild)
},
diff --git a/discord/utils.js b/discord/utils.js
index ff1f215..6b6b602 100644
--- a/discord/utils.js
+++ b/discord/utils.js
@@ -63,7 +63,7 @@ function getPermissions(userRoles, guildRoles, userID, channelOverwrites) {
*/
function hasPermission(resolvedPermissions, permissionToCheckFor) {
// Make sure permissionToCheckFor has exactly one permission in it
- assert.equal(permissionToCheckFor.toString(2).match(/1/g), 1)
+ assert.equal(permissionToCheckFor.toString(2).match(/1/g)?.length, 1)
// Do the actual calculation
return (resolvedPermissions & permissionToCheckFor) === permissionToCheckFor
}
From 12d85c982e20adba182f73b7576a02d62b0b9ca4 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 7 Mar 2024 10:17:39 +1300
Subject: [PATCH 007/346] Allow Matrixers to @room if Discorders can too
---
d2m/actions/create-room.js | 7 ++++++-
d2m/actions/create-room.test.js | 11 +++++++++++
discord/utils.js | 2 +-
test/data.js | 22 +++++++++++++++++-----
4 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js
index 0dea283..a8d2846 100644
--- a/d2m/actions/create-room.js
+++ b/d2m/actions/create-room.js
@@ -12,6 +12,8 @@ const file = sync.require("../../matrix/file")
const api = sync.require("../../matrix/api")
/** @type {import("../../matrix/kstate")} */
const ks = sync.require("../../matrix/kstate")
+/** @type {import("../../discord/utils")} */
+const utils = sync.require("../../discord/utils")
/** @type {import("./create-space")}) */
const createSpace = sync.require("./create-space") // watch out for the require loop
@@ -119,6 +121,9 @@ async function channelToKState(channel, guild) {
join_rules = {join_rule: PRIVACY_ENUMS.ROOM_JOIN_RULES[privacyLevel]}
}
+ const everyonePermissions = utils.getPermissions([], guild.roles, undefined, channel.permission_overwrites)
+ const everyoneCanMentionEveryone = utils.hasAllPermissions(everyonePermissions, ["MentionEveryone"])
+
const channelKState = {
"m.room.name/": {name: convertedName},
"m.room.topic/": {topic: convertedTopic},
@@ -136,7 +141,7 @@ async function channelToKState(channel, guild) {
"m.room.avatar": 0
},
notifications: {
- room: 20 // TODO: Matrix users should have the same abilities as unprivileged Discord members. So make this automatically configured based on the guild or channel's default mention everyone permissions. That way if unprivileged Discord members can mention everyone, Matrix users can too.
+ room: everyoneCanMentionEveryone ? 0 : 20
},
users: reg.ooye.invite.reduce((a, c) => (a[c] = 100, a), {})
},
diff --git a/d2m/actions/create-room.test.js b/d2m/actions/create-room.test.js
index 93f9203..be0febb 100644
--- a/d2m/actions/create-room.test.js
+++ b/d2m/actions/create-room.test.js
@@ -1,5 +1,6 @@
// @ts-check
+const mixin = require("mixin-deep")
const {channelToKState, _convertNameAndTopic} = require("./create-room")
const {kstateStripConditionals} = require("../../matrix/kstate")
const {test} = require("supertape")
@@ -39,6 +40,16 @@ test("channel2room: invite-only privacy room", async t => {
)
})
+test("channel2room: room where limited people can mention everyone", async t => {
+ const limitedGuild = mixin({}, testData.guild.general)
+ limitedGuild.roles[0].permissions = (BigInt(limitedGuild.roles[0].permissions) - 131072n).toString()
+ const limitedRoom = mixin({}, testData.room.general, {"m.room.power_levels/": {notifications: {room: 20}}})
+ t.deepEqual(
+ kstateStripConditionals(await channelToKState(testData.channel.general, limitedGuild).then(x => x.channelKState)),
+ limitedRoom
+ )
+})
+
test("convertNameAndTopic: custom name and topic", t => {
t.deepEqual(
_convertNameAndTopic({id: "123", name: "the-twilight-zone", topic: "Spooky stuff here. :ghost:", type: 0}, {id: "456"}, "hauntings"),
diff --git a/discord/utils.js b/discord/utils.js
index 6b6b602..2726a1a 100644
--- a/discord/utils.js
+++ b/discord/utils.js
@@ -26,7 +26,7 @@ function getPermissions(userRoles, guildRoles, userID, channelOverwrites) {
}
if (channelOverwrites) {
- /** @type {((overwrite: Required["permission_overwrites"][0]) => any)[]} */
+ /** @type {((overwrite: Required) => any)[]} */
const actions = [
// Channel @everyone deny
overwrite => overwrite.id === everyoneID && (allowed &= ~BigInt(overwrite.deny)),
diff --git a/test/data.js b/test/data.js
index 61ee5d0..c165322 100644
--- a/test/data.js
+++ b/test/data.js
@@ -47,6 +47,9 @@ module.exports = {
},
users: {
"@test_auto_invite:example.org": 100
+ },
+ notifications: {
+ room: 0
}
},
"chat.schildi.hide_ui/read_receipts": {hidden: true},
@@ -98,7 +101,6 @@ module.exports = {
icon: "a_f83622e09ead74f0c5c527fe241f8f8c",
emojis: [
{
- version: 0,
roles: [],
require_colons: true,
name: "hippo",
@@ -108,7 +110,6 @@ module.exports = {
animated: false
},
{
- version: 0,
roles: [],
require_colons: true,
name: "hipposcope",
@@ -121,7 +122,20 @@ module.exports = {
premium_subscription_count: 14,
roles: [
{
- version: 1696964862461,
+ unicode_emoji: null,
+ tags: {},
+ position: 0,
+ permissions: '559623605575360',
+ name: '@everyone',
+ mentionable: false,
+ managed: false,
+ id: '112760669178241024',
+ icon: null,
+ hoist: false,
+ flags: 0,
+ color: 0
+ },
+ {
unicode_emoji: null,
tags: {},
position: 22,
@@ -135,7 +149,6 @@ module.exports = {
flags: 0,
color: 0
}, {
- version: 1696964862776,
unicode_emoji: null,
tags: {},
position: 131,
@@ -149,7 +162,6 @@ module.exports = {
flags: 0,
color: 11076095
}, {
- version: 1696964862698,
unicode_emoji: '🍂',
tags: {},
position: 102,
From a190e690b1b30e9be12f27ab1b1a6a0c52e9df22 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 7 Mar 2024 10:22:49 +1300
Subject: [PATCH 008/346] Add tests for somePermissions/allPermissions check
---
discord/utils.test.js | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/discord/utils.test.js b/discord/utils.test.js
index 1f3783f..815c0a1 100644
--- a/discord/utils.test.js
+++ b/discord/utils.test.js
@@ -1,3 +1,4 @@
+const DiscordTypes = require("discord-api-types/v10")
const {test} = require("supertape")
const data = require("../test/data")
const utils = require("./utils")
@@ -82,3 +83,27 @@ test("getPermissions: channel overwrite to allow role works", t => {
const want = BigInt(1 << 10 | 1 << 16)
t.equal((permissions & want), want)
})
+
+test("hasSomePermissions: detects the permission", t => {
+ const userPermissions = DiscordTypes.PermissionFlagsBits.MentionEveryone | DiscordTypes.PermissionFlagsBits.BanMembers
+ const canRemoveMembers = utils.hasSomePermissions(userPermissions, ["KickMembers", "BanMembers"])
+ t.equal(canRemoveMembers, true)
+})
+
+test("hasSomePermissions: doesn't detect not the permission", t => {
+ const userPermissions = DiscordTypes.PermissionFlagsBits.MentionEveryone | DiscordTypes.PermissionFlagsBits.SendMessages
+ const canRemoveMembers = utils.hasSomePermissions(userPermissions, ["KickMembers", "BanMembers"])
+ t.equal(canRemoveMembers, false)
+})
+
+test("hasAllPermissions: detects the permissions", t => {
+ const userPermissions = DiscordTypes.PermissionFlagsBits.KickMembers | DiscordTypes.PermissionFlagsBits.BanMembers | DiscordTypes.PermissionFlagsBits.MentionEveryone
+ const canRemoveMembers = utils.hasAllPermissions(userPermissions, ["KickMembers", "BanMembers"])
+ t.equal(canRemoveMembers, true)
+})
+
+test("hasAllPermissions: doesn't detect not the permissions", t => {
+ const userPermissions = DiscordTypes.PermissionFlagsBits.MentionEveryone | DiscordTypes.PermissionFlagsBits.SendMessages | DiscordTypes.PermissionFlagsBits.KickMembers
+ const canRemoveMembers = utils.hasAllPermissions(userPermissions, ["KickMembers", "BanMembers"])
+ t.equal(canRemoveMembers, false)
+})
From e03155817750553719bc05ad6967190b39879f29 Mon Sep 17 00:00:00 2001
From: RNLFoof
Date: Wed, 6 Mar 2024 17:08:43 -0500
Subject: [PATCH 009/346] Added a comment explaining sims to db\orm-defs.d.ts
---
db/orm-defs.d.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/db/orm-defs.d.ts b/db/orm-defs.d.ts
index 622e1a0..3e68639 100644
--- a/db/orm-defs.d.ts
+++ b/db/orm-defs.d.ts
@@ -50,6 +50,7 @@ export type Models = {
channel_id: string
}
+ // A sim is an account that is being simulated by the bridge to copy events from the other side. See d2m\actions\register-user.js for relevant behavior and comments.
sim: {
user_id: string
sim_name: string
From cc9e1de49ee1c5689cd1e32507c71fba2762293e Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 7 Mar 2024 12:19:07 +1300
Subject: [PATCH 010/346] Remove deep-equal dependency
---
d2m/actions/create-space.js | 4 +-
db/orm-defs.d.ts | 2 +-
db/orm.test.js | 2 +-
matrix/kstate.js | 6 +-
package-lock.json | 283 ++++++++++++++++++++++--------------
package.json | 1 -
readme.md | 1 -
7 files changed, 179 insertions(+), 120 deletions(-)
diff --git a/d2m/actions/create-space.js b/d2m/actions/create-space.js
index 7d50199..a7390ed 100644
--- a/d2m/actions/create-space.js
+++ b/d2m/actions/create-space.js
@@ -1,8 +1,8 @@
// @ts-check
const assert = require("assert").strict
+const {isDeepStrictEqual} = require("util")
const DiscordTypes = require("discord-api-types/v10")
-const deepEqual = require("deep-equal")
const reg = require("../../matrix/read-registration")
const passthrough = require("../../passthrough")
@@ -226,7 +226,7 @@ async function syncSpaceExpressions(data, checkBeforeSync) {
// State event not found. This space doesn't have any existing emojis. We create a dummy empty event for comparison's sake.
existing = fn([])
}
- if (deepEqual(existing, content, {strict: true})) return
+ if (isDeepStrictEqual(existing, content)) return
}
api.sendState(spaceID, "im.ponies.room_emotes", eventKey, content)
}
diff --git a/db/orm-defs.d.ts b/db/orm-defs.d.ts
index 622e1a0..0223058 100644
--- a/db/orm-defs.d.ts
+++ b/db/orm-defs.d.ts
@@ -100,7 +100,7 @@ export type Prepared = {
safeIntegers: () => Prepared<{[K in keyof Row]: Row[K] extends number ? BigInt : Row[K]}>
raw: () => Prepared
all: (..._: any[]) => Row[]
- get: (..._: any[]) => Row | null
+ get: (..._: any[]) => Row | null | undefined
}
export type AllKeys = U extends any ? keyof U : never
diff --git a/db/orm.test.js b/db/orm.test.js
index 066eabb..3d4e8ef 100644
--- a/db/orm.test.js
+++ b/db/orm.test.js
@@ -51,5 +51,5 @@ test("orm: from: join direction works", t => {
const hasNoOwner = from("sim").join("sim_proxy", "user_id", "left").select("user_id", "proxy_owner_id").where({sim_name: "crunch_god"}).get()
t.deepEqual(hasNoOwner, {user_id: "820865262526005258", proxy_owner_id: null})
const hasNoOwnerInner = from("sim").join("sim_proxy", "user_id", "inner").select("user_id", "proxy_owner_id").where({sim_name: "crunch_god"}).get()
- t.deepEqual(hasNoOwnerInner, null)
+ t.deepEqual(hasNoOwnerInner, undefined)
})
diff --git a/matrix/kstate.js b/matrix/kstate.js
index 6358974..3c4189d 100644
--- a/matrix/kstate.js
+++ b/matrix/kstate.js
@@ -2,7 +2,7 @@
const assert = require("assert").strict
const mixin = require("mixin-deep")
-const deepEqual = require("deep-equal")
+const {isDeepStrictEqual} = require("util")
/** Mutates the input. */
function kstateStripConditionals(kstate) {
@@ -51,14 +51,14 @@ function diffKState(actual, target) {
// Special handling for power levels, we want to deep merge the actual and target into the final state.
if (!(key in actual)) throw new Error(`want to apply a power levels diff, but original power level data is missing\nstarted with: ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
const temp = mixin({}, actual[key], target[key])
- if (!deepEqual(actual[key], temp, {strict: true})) {
+ if (!isDeepStrictEqual(actual[key], temp)) {
// they differ. use the newly prepared object as the diff.
diff[key] = temp
}
} else if (key in actual) {
// diff
- if (!deepEqual(actual[key], target[key], {strict: true})) {
+ if (!isDeepStrictEqual(actual[key], target[key])) {
// they differ. use the target as the diff.
diff[key] = target[key]
}
diff --git a/package-lock.json b/package-lock.json
index 880c150..2e45796 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,7 +13,6 @@
"better-sqlite3": "^9.0.0",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
- "deep-equal": "^2.2.3",
"discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
@@ -549,12 +548,16 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -581,9 +584,13 @@
"dev": true
},
"node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
"engines": {
"node": ">= 0.4"
},
@@ -797,13 +804,18 @@
}
},
"node_modules/call-bind": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
- "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
"function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.1",
- "set-function-length": "^1.1.1"
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1084,6 +1096,7 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
"integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
+ "dev": true,
"dependencies": {
"array-buffer-byte-length": "^1.0.0",
"call-bind": "^1.0.5",
@@ -1120,23 +1133,28 @@
}
},
"node_modules/define-data-property": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
- "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dependencies": {
- "get-intrinsic": "^1.2.1",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-properties": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
- "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
"dependencies": {
+ "define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
},
@@ -1252,10 +1270,30 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-get-iterator": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
"integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+ "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.3",
@@ -1469,6 +1507,7 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
"dependencies": {
"is-callable": "^1.1.3"
}
@@ -1548,6 +1587,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1562,15 +1602,19 @@
}
},
"node_modules/get-intrinsic": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
- "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dependencies": {
+ "es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1667,21 +1711,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
"node_modules/has-bigints": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1696,11 +1730,11 @@
}
},
"node_modules/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dependencies": {
- "get-intrinsic": "^1.1.1"
+ "es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1729,11 +1763,12 @@
}
},
"node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
"dependencies": {
- "has-symbols": "^1.0.2"
+ "has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -1846,12 +1881,13 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"node_modules/internal-slot": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
- "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
+ "dev": true,
"dependencies": {
- "get-intrinsic": "^1.2.0",
- "has": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.0",
"side-channel": "^1.0.4"
},
"engines": {
@@ -1870,6 +1906,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -1882,13 +1919,16 @@
}
},
"node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
+ "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1903,6 +1943,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
"dependencies": {
"has-bigints": "^1.0.1"
},
@@ -1914,6 +1955,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -1929,6 +1971,7 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -1952,6 +1995,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@@ -1975,6 +2019,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
"integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+ "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1983,6 +2028,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@@ -1997,6 +2043,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -2012,16 +2059,21 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
"integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
+ "dev": true,
"dependencies": {
- "call-bind": "^1.0.2"
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -2031,6 +2083,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@@ -2045,6 +2098,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@@ -2055,28 +2109,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-typed-array": {
- "version": "1.1.10",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
- "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
"integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -2085,6 +2122,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
"integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
@@ -2096,7 +2134,8 @@
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
},
"node_modules/isexe": {
"version": "2.0.0",
@@ -2449,12 +2488,13 @@
}
},
"node_modules/object-is": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
- "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
+ "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+ "dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
@@ -2467,17 +2507,19 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
"has-symbols": "^1.0.3",
"object-keys": "^1.1.1"
},
@@ -2636,6 +2678,15 @@
"node": ">=14.19.0"
}
},
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@@ -2840,13 +2891,15 @@
}
},
"node_modules/regexp.prototype.flags": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
- "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
+ "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
+ "dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "set-function-name": "^2.0.0"
+ "call-bind": "^1.0.6",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.1"
},
"engines": {
"node": ">= 0.4"
@@ -3027,27 +3080,31 @@
}
},
"node_modules/set-function-length": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
- "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
+ "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
"dependencies": {
- "define-data-property": "^1.1.1",
- "get-intrinsic": "^1.2.1",
+ "define-data-property": "^1.1.2",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.3",
"gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
+ "has-property-descriptors": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/set-function-name": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
- "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
"dependencies": {
- "define-data-property": "^1.0.1",
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.0"
+ "has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -3254,6 +3311,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
"integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+ "dev": true,
"dependencies": {
"internal-slot": "^1.0.4"
},
@@ -3820,6 +3878,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
"dependencies": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
@@ -3835,6 +3894,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
"integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "dev": true,
"dependencies": {
"is-map": "^2.0.1",
"is-set": "^2.0.1",
@@ -3846,15 +3906,16 @@
}
},
"node_modules/which-typed-array": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
- "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz",
+ "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==",
+ "dev": true,
"dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.4",
+ "available-typed-arrays": "^1.0.6",
+ "call-bind": "^1.0.5",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
+ "has-tostringtag": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
diff --git a/package.json b/package.json
index 3a9a12c..bff4724 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,6 @@
"better-sqlite3": "^9.0.0",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
- "deep-equal": "^2.2.3",
"discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
diff --git a/readme.md b/readme.md
index 49c2e66..b64f780 100644
--- a/readme.md
+++ b/readme.md
@@ -167,7 +167,6 @@ To get into the rooms on your Matrix account, either add yourself to `invite` in
* (1) chunk-text: It does what I want.
* (0) cloudstorm: Discord gateway library with bring-your-own-caching that I trust.
* (8) snowtransfer: Discord API library with bring-your-own-caching that I trust.
-* (0) deep-equal: It's already pulled in by supertape.
* (1) discord-markdown: This is my fork!
* (0) get-stream: Only needed if content_length_workaround is true.
* (0) giframe: This is my fork!
From 25cd8cb289f8238c622bb5d4364e6d26098bec72 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 7 Mar 2024 13:07:10 +1300
Subject: [PATCH 011/346] Use allowed_mentions instead of disableEveryone
---
m2d/converters/event-to-message.js | 11 +-
m2d/converters/event-to-message.test.js | 405 +++++++++++++++++++-----
2 files changed, 330 insertions(+), 86 deletions(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index d589277..8da3004 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -425,9 +425,6 @@ const attachmentEmojis = new Map([
* @param {{api: import("../../matrix/api"), snow: import("snowtransfer").SnowTransfer, fetch: import("node-fetch")["default"], mxcDownloader: (mxc: string) => Promise}} di simple-as-nails dependency injection for the matrix API
*/
async function eventToMessage(event, guild, di) {
- /** @type {(DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {files?: {name: string, file: Buffer | Readable}[]})[]} */
- let messages = []
-
let displayName = event.sender
let avatarURL = undefined
/** @type {string[]} */
@@ -786,11 +783,15 @@ async function eventToMessage(event, guild, di) {
// Split into 2000 character chunks
const chunks = chunk(content, 2000)
- messages = messages.concat(chunks.map(content => ({
+ /** @type {(DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {files?: {name: string, file: Buffer | Readable}[]})[]} */
+ const messages = chunks.map(content => ({
content,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ },
username: displayNameShortened,
avatar_url: avatarURL
- })))
+ }))
if (attachments.length) {
// If content is empty (should be the case when uploading a file) then chunk-text will create 0 messages.
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 7471f6a..3366d18 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -90,7 +90,10 @@ test("event2message: body is used when there is no formatted_body", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "testing plaintext",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -125,7 +128,10 @@ test("event2message: any markdown in body is escaped, except strikethrough", asy
messagesToSend: [{
username: "cadence [they]",
content: "testing \\*\\*special\\*\\* ~~things~~ which \\_should\\_ \\*not\\* \\`trigger\\` @any , except strikethrough",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -157,7 +163,10 @@ test("event2message: links in formatted body are not broken", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "<@111604486476181504> I wonder what the midjourney text description of this photo is https://upload.wikimedia.org/wikipedia/commons/f/f3/After_gay_pride%2C_rainbow_flags_flying_along_Beach_Street_%2814853144744%29.jpg",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -187,7 +196,10 @@ test("event2message: links in plaintext body are not broken", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "I wonder what the midjourney text description of this photo is https://upload.wikimedia.org/wikipedia/commons/f/f3/After_gay_pride%2C_rainbow_flags_flying_along_Beach_Street_%2814853144744%29.jpg",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -214,7 +226,10 @@ test("event2message: links in formatted body where the text & href are the same,
messagesToSend: [{
username: "cadence [they]",
content: "https://privatebin.net/?9111cb16f28da21b#62CKkEr6WvXZ1gQv2M6agazsA7tGYX8ZP8drETYujYZr",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -245,7 +260,10 @@ test("event2message: basic html is converted to markdown", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "this **is** a _**test** __of___ ~~_formatting_~~",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -276,7 +294,10 @@ test("event2message: spoilers work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "this **is** a ||_test_|| of ||spoilers||",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -307,7 +328,10 @@ test("event2message: spoiler reasons work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "\\(cw crossword spoilers you'll never believe. don't tell anybody\\) ||zoe kills a 5 letter noun at the end||",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -338,7 +362,10 @@ test("event2message: markdown syntax is escaped", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "this \\*\\*is\\*\\* an **_extreme_** \\\\\\*test\\\\\\* of",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -369,7 +396,10 @@ test("event2message: html lines are bridged correctly", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "paragraph one\nline _two_\nline three\n\nparagraph two\nline _two_\nline three\n\nparagraph three\n\nparagraph four\nline two\nline three\nline four\n\nparagraph five",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -400,7 +430,10 @@ test("event2message: html lines are bridged correctly", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\n line five",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -432,7 +465,10 @@ test("event2message: whitespace is collapsed", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\nline five",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -465,7 +501,10 @@ test("event2message: lists are bridged correctly", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -494,11 +533,17 @@ test("event2message: long messages are split", async t => {
messagesToSend: [{
username: "cadence [they]",
content: (("a".repeat(130) + " ").repeat(15)).slice(0, -1),
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}, {
username: "cadence [they]",
content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1),
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -529,7 +574,10 @@ test("event2message: code blocks work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -556,7 +604,10 @@ test("event2message: code block contents are formatted correctly and not escaped
messagesToSend: [{
username: "cadence [they]",
content: "```\ninput = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n_input_ = input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n```\n\n`input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,`",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -585,7 +636,10 @@ test("event2message: code blocks are uploaded as attachments instead if they con
content: "So if you run code like this `[inline_code.java]` it should print a markdown formatted code block",
attachments: [{id: "0", filename: "inline_code.java"}],
pendingFiles: [{name: "inline_code.java", buffer: Buffer.from('System.out.println("```");')}],
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -625,7 +679,10 @@ test("event2message: characters are encoded properly in code blocks", async t =>
+ '\n .map(|c| c.get(1).unwrap().as_str())'
+ '\n .collect::();'
)}],
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -656,7 +713,10 @@ test("event2message: quotes have an appropriate amount of whitespace", async t =
messagesToSend: [{
username: "cadence [they]",
content: "> Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands\n🤨",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -694,7 +754,10 @@ test("event2message: lists have appropriate line breaks", async t => {
messagesToSend: [{
username: "Milan",
content: `i am not certain what you mean by "already exists with as discord". my goals are\n\n* bridgeing specific channels with existing matrix rooms\n * optionally maybe entire "servers"\n* offering the bridge as a public service`,
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -732,7 +795,10 @@ test("event2message: ordered list start attribute works", async t => {
messagesToSend: [{
username: "Milan",
content: `i am not certain what you mean by "already exists with as discord". my goals are\n\n1. bridgeing specific channels with existing matrix rooms\n 2. optionally maybe entire "servers"\n2. offering the bridge as a public service`,
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -761,7 +827,10 @@ test("event2message: m.emote plaintext works", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "\\* cadence \\[they\\] tests an m.emote message",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -792,7 +861,10 @@ test("event2message: m.emote markdown syntax is escaped", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "\\* cadence \\[they\\] shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -842,7 +914,10 @@ test("event2message: rich reply to a sim user", async t => {
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ "\n> Slow news day."
+ "\nTesting this reply, ignore",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -911,7 +986,10 @@ test("event2message: rich reply to a rich reply to a multi-line message should c
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ "\n> I just checked in a fix that will probably work..."
+ "\nwill try later (tomorrow if I don't forgor)",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -988,7 +1066,10 @@ test("event2message: rich reply to an already-edited message will quote the new
content: "> <:L1:1144820033948762203><:L2:1144820084079087647><@111604486476181504>:"
+ "\n> this is the new content. heya!"
+ "\nhiiiii....",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1038,7 +1119,10 @@ test("event2message: rich reply to a missing event will quote from formatted_bod
username: "cadence [they]",
content: "> But who sees the seashells she sells sitting..."
+ "\nWhat a tongue-bender...",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1084,7 +1168,10 @@ test("event2message: rich reply to a missing event without formatted_body will u
messagesToSend: [{
username: "cadence [they]",
content: "Testing this reply, ignore",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1132,7 +1219,10 @@ test("event2message: rich reply to a missing event and no reply fallback will no
messagesToSend: [{
username: "cadence [they]",
content: "Testing this reply, ignore.",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1181,7 +1271,10 @@ test("event2message: should avoid using blockquote contents as reply preview in
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ "\n> that can't be true! there's no way :o"
+ "\nI agree!",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1267,7 +1360,10 @@ test("event2message: should include a reply preview when message ends with a blo
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**_ooye_cookie**:"
+ "\n> https://tootsuite.net/Warp-Gate2.gif tanget: @..."
+ "\naichmophobia",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1348,7 +1444,10 @@ test("event2message: should include a reply preview when replying to a descripti
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/497161350934560778/1162625810109317170 <@1109360903096369153>:"
+ "\n> It looks like this queue has ended."
+ `\nso you're saying on matrix side I would have to edit ^this^ to add "Timed out" before the blockquote?`,
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1398,7 +1497,10 @@ test("event2message: entities are not escaped in main message or reply preview",
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ "\n> Testing? \"':.`[]&things"
+ "\n_Testing?_ \"':.\\`\\[\\]&things",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1445,7 +1547,10 @@ test("event2message: reply preview converts emoji formatting when replying to a
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ "\n> <:hippo:230201364309868544>"
+ "\nreply",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1492,7 +1597,10 @@ test("event2message: reply preview can guess custom emoji based on the name if i
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ "\n> <:hippo:230201364309868544>"
+ "\nreply",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1539,7 +1647,10 @@ test("event2message: reply preview uses emoji title text when replying to an unk
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ "\n> :svkftngur_gkdne:"
+ "\nreply",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1586,7 +1697,10 @@ test("event2message: reply preview ignores garbage image", async t => {
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ "\n> I am having a nice day"
+ "\nreply",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1632,7 +1746,10 @@ test("event2message: reply to empty message doesn't show an extra line or anythi
username: "cadence [they]",
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**"
+ "\nreply",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1712,7 +1829,10 @@ test("event2message: editing a rich reply to a sim user", async t => {
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ "\n> Slow news day."
+ "\nEditing this reply, which is also a test",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}
}],
messagesToSend: []
@@ -1765,7 +1885,10 @@ test("event2message: editing a plaintext body message", async t => {
message: {
username: "cadence [they]",
content: "well, I guess it's no longer brand new... it's existed for mere seconds...",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}
}],
messagesToSend: []
@@ -1817,13 +1940,19 @@ test("event2message: editing a plaintext message to be longer", async t => {
message: {
content: "aaaaaaaaa ".repeat(198) + "well, I guess it's",
username: "cadence [they]",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}
}],
messagesToSend: [{
content: "no longer brand new... it's existed for mere seconds..." + ("aaaaaaaaa ".repeat(20)).slice(0, -1),
username: "cadence [they]",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -1873,7 +2002,10 @@ test("event2message: editing a plaintext message to be shorter", async t => {
message: {
username: "cadence [they]",
content: "well, I guess it's no longer brand new... it's existed for mere seconds...",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}
}],
messagesToSend: []
@@ -1931,7 +2063,10 @@ test("event2message: editing a formatted body message", async t => {
message: {
username: "cadence [they]",
content: "**well, I guess it's no longer brand new... it's existed for mere seconds...**",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}
}],
messagesToSend: []
@@ -1985,7 +2120,10 @@ test("event2message: rich reply to a matrix user's long message with formatting"
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence [they]**:"
+ "\n> i should have a little happy test list bold em..."
+ "\n**no you can't!!!**",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2044,7 +2182,10 @@ test("event2message: rich reply to an image", async t => {
username: "cadence [they]",
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504> 🖼️"
+ "\nCaught in 8K UHD VR QLED Epic Edition",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2097,7 +2238,10 @@ test("event2message: rich reply to a spoiler should ensure the spoiler is hidden
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ "\n> [spoiler] cw crossword spoilers you'll never..."
+ "\nomg NO WAY!!",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2149,7 +2293,10 @@ test("event2message: with layered rich replies, the preview should only be the r
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence [they]**:"
+ "\n> two"
+ "\nthree",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2203,7 +2350,10 @@ test("event2message: if event is a reply and starts with a quote, they should be
+ "\n> i have a feeling that clients are meant to strip..."
+ "\n"
+ "\n> To strip the fallback on the `body`, the client should iterate over each line of the string, removing any lines that start with the fallback prefix (\"> “, including the space, without quotes) and stopping when a line is encountered without the prefix. This prefix is known as the “fallback prefix sequence”.",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/syndicated.gay/ZkBUPXCiXTjdJvONpLJmcbKP"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/syndicated.gay/ZkBUPXCiXTjdJvONpLJmcbKP",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2258,7 +2408,10 @@ test("event2message: rich reply to a deleted event", async t => {
username: "Ampflower 🌺",
content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**Ampflower 🌺** (in reply to a deleted message)"
+ "\nHuh it did the same thing here too",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/PRfhXYBTOalvgQYtmCLeUXko"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/PRfhXYBTOalvgQYtmCLeUXko",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2287,7 +2440,10 @@ test("event2message: raw mentioning discord users in plaintext body works", asyn
messagesToSend: [{
username: "cadence [they]",
content: "<@114147806469554185> what do you think?",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2318,7 +2474,10 @@ test("event2message: raw mentioning discord users in formatted body works", asyn
messagesToSend: [{
username: "cadence [they]",
content: "<@114147806469554185> what do you think?",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2349,7 +2508,10 @@ test("event2message: mentioning discord users works", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "I'm just <@114147806469554185> testing mentions",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2380,7 +2542,10 @@ test("event2message: mentioning discord users works when URL encoded", async t =
messagesToSend: [{
username: "cadence [they]",
content: "<@771520384671416320> a sample message",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2411,7 +2576,10 @@ test("event2message: mentioning PK discord users works", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "I'm just **@Azalea &flwr; 🌺** (<@196188877885538304>) testing mentions",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2442,7 +2610,10 @@ test("event2message: mentioning matrix users works", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "I'm just [@▲]() testing mentions",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2469,7 +2640,10 @@ test("event2message: mentioning matrix users works even when Element disambiguat
messagesToSend: [{
username: "cadence [they]",
content: "[@unascribed]() if you want to run some experimental software, `11864f80cf` branch of OOYE has _vastly_ improved handling of PluralKit users. feel free to try it out, if you find bugs I'd appreciate you letting me know (just tag me at the place in chat where something went wrong)",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2500,7 +2674,10 @@ test("event2message: mentioning bridged rooms works", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "I'm just <#1100319550446252084> testing channel mentions",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2529,7 +2706,10 @@ test("event2message: mentioning bridged rooms works (plaintext body)", async t =
messagesToSend: [{
username: "cadence [they]",
content: "I'm just <#1100319550446252084> testing channel mentions",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2558,7 +2738,10 @@ test("event2message: mentioning known bridged events works (plaintext body)", as
messagesToSend: [{
username: "cadence [they]",
content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020, take a look!",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2589,7 +2772,10 @@ test("event2message: mentioning known bridged events works (partially formatted
messagesToSend: [{
username: "cadence [they]",
content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2620,7 +2806,10 @@ test("event2message: mentioning known bridged events works (formatted body)", as
messagesToSend: [{
username: "cadence [they]",
content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2663,7 +2852,10 @@ test("event2message: mentioning unknown bridged events can approximate with time
messagesToSend: [{
username: "cadence [they]",
content: "it was uploaded years ago in https://discord.com/channels/497159726455455754/497161350934560778/753895613661184000",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2705,7 +2897,10 @@ test("event2message: mentioning events falls back to original link when server d
messagesToSend: [{
username: "cadence [they]",
content: "it was uploaded years ago in [amanda-spam]()",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2746,7 +2941,10 @@ test("event2message: mentioning events falls back to original link when the chan
messagesToSend: [{
username: "cadence [they]",
content: "it was uploaded years ago in [ex-room-doesnt-exist-any-more]()",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2773,7 +2971,10 @@ test("event2message: link to event in an unknown room (href link)", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "ah yeah, here's where the bug was reported: ",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2800,7 +3001,10 @@ test("event2message: link to event in an unknown room (bare link)", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "PK API failure, tho idk how you'd handle that ",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2825,7 +3029,10 @@ test("event2message: link to event in an unknown room (plaintext)", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "ah yeah, here's where the bug was reported: ",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2856,7 +3063,10 @@ test("event2message: colon after mentions is stripped", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "<@114147806469554185> hey, I'm just [@▲]() testing mentions",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2898,7 +3108,10 @@ test("event2message: caches the member if the member is not known", async t => {
messagesToSend: [{
username: "should_be_newly_cached",
content: "testing the member state cache",
- avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/this_is_the_avatar"
+ avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/this_is_the_avatar",
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2943,7 +3156,10 @@ test("event2message: skips caching the member if the member does not exist, some
messagesToSend: [{
username: "not_real",
content: "should honestly never happen",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -2987,7 +3203,10 @@ test("event2message: overly long usernames are shifted into the message content"
messagesToSend: [{
username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS",
content: "**IMPORTANT and I DON'T MATTER**\ntesting the member state cache",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -3020,7 +3239,10 @@ test("event2message: overly long usernames are not treated specially when the ms
messagesToSend: [{
username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS",
content: "\\* I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS IMPORTANT and I DON'T MATTER looks at the start of the message",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -3319,7 +3541,10 @@ test("event2message: static emojis work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "<:hippo:230201364309868544>",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -3346,7 +3571,10 @@ test("event2message: animated emojis work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -3373,7 +3601,10 @@ test("event2message: unknown emojis in the middle are linked", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "a [:ms_robot_grin:](https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/RLMgJGfgTPjIQtvvWZsYjhjy) b",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}]
}
)
@@ -3419,7 +3650,10 @@ test("event2message: guessed @mentions in plaintext may join members to mention"
messagesToSend: [{
username: "cadence [they]",
content: "hey <@321876634777218072>, what food would you like to order?",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}],
ensureJoined: [subtext.user]
}
@@ -3469,7 +3703,10 @@ test("event2message: guessed @mentions in formatted body may join members to men
messagesToSend: [{
username: "cadence [they]",
content: "**_HEY <@321876634777218072>, WHAT FOOD WOULD YOU LIKE TO ORDER??_**",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}],
ensureJoined: [subtext.user]
}
@@ -3509,7 +3746,10 @@ test("event2message: guessed @mentions feature will not activate on links or cod
messagesToSend: [{
username: "cadence [they]",
content: "in link [view timeline](https://example.com/social/@subtext) in autolink https://example.com/social/@subtext in pre-code```\n@subtext\n```",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}],
ensureJoined: []
}
@@ -3536,7 +3776,10 @@ test("event2message: guessed @mentions work with other matrix bridge old users",
messagesToSend: [{
username: "cadence [they]",
content: "<@114147806469554185> <@176943908762006200> back me up on this sentiment, if not necessarily the phrasing",
- avatar_url: undefined
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
}],
ensureJoined: [] // we already think it worked on Matrix side due to the pill, so no need for the OOYE sim user to join the room to indicate success.
}
From f5ffc09fab8f589234d30d70cf204393fc59d692 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 7 Mar 2024 16:23:23 +1300
Subject: [PATCH 012/346] Convert @room to @everyone using permissions
---
m2d/actions/channel-webhook.js | 2 +-
m2d/converters/event-to-message.js | 45 +++++--
m2d/converters/event-to-message.test.js | 168 ++++++++++++++++++++++++
3 files changed, 201 insertions(+), 14 deletions(-)
diff --git a/m2d/actions/channel-webhook.js b/m2d/actions/channel-webhook.js
index 52b4095..d52f174 100644
--- a/m2d/actions/channel-webhook.js
+++ b/m2d/actions/channel-webhook.js
@@ -57,7 +57,7 @@ async function withWebhook(channelID, callback) {
*/
async function sendMessageWithWebhook(channelID, data, threadID) {
const result = await withWebhook(channelID, async webhook => {
- return discord.snow.webhook.executeWebhook(webhook.id, webhook.token, data, {wait: true, thread_id: threadID, disableEveryone: true})
+ return discord.snow.webhook.executeWebhook(webhook.id, webhook.token, data, {wait: true, thread_id: threadID})
})
return result
}
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index 8da3004..87fadc8 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -384,19 +384,35 @@ async function handleRoomOrMessageLinks(input, di) {
/**
* @param {string} content
+ * @param {string} senderMxid
+ * @param {string} roomID
* @param {DiscordTypes.APIGuild} guild
* @param {{api: import("../../matrix/api"), snow: import("snowtransfer").SnowTransfer, fetch: import("node-fetch")["default"]}} di
*/
-async function checkWrittenMentions(content, guild, di) {
+async function checkWrittenMentions(content, senderMxid, roomID, guild, di) {
let writtenMentionMatch = content.match(/(?:^|[^"[<>/A-Za-z0-9])@([A-Za-z][A-Za-z0-9._\[\]\(\)-]+):?/d) // /d flag for indices requires node.js 16+
if (writtenMentionMatch) {
- const results = await di.snow.guild.searchGuildMembers(guild.id, {query: writtenMentionMatch[1]})
- if (results[0]) {
- assert(results[0].user)
- return {
- // @ts-ignore - typescript doesn't know about indices yet
- content: content.slice(0, writtenMentionMatch.indices[1][0]-1) + `<@${results[0].user.id}>` + content.slice(writtenMentionMatch.indices[1][1]),
- ensureJoined: results[0].user
+ if (writtenMentionMatch[1] === "room") { // convert @room to @everyone
+ const powerLevels = await di.api.getStateEvent(roomID, "m.room.power_levels", "")
+ const userPower = powerLevels.users?.[senderMxid] || 0
+ if (userPower >= powerLevels.notifications?.room) {
+ return {
+ // @ts-ignore - typescript doesn't know about indices yet
+ content: content.slice(0, writtenMentionMatch.indices[1][0]-1) + `@everyone` + content.slice(writtenMentionMatch.indices[1][1]),
+ ensureJoined: [],
+ allowedMentionsParse: ["everyone"]
+ }
+ }
+ } else {
+ const results = await di.snow.guild.searchGuildMembers(guild.id, {query: writtenMentionMatch[1]})
+ if (results[0]) {
+ assert(results[0].user)
+ return {
+ // @ts-ignore - typescript doesn't know about indices yet
+ content: content.slice(0, writtenMentionMatch.indices[1][0]-1) + `<@${results[0].user.id}>` + content.slice(writtenMentionMatch.indices[1][1]),
+ ensureJoined: [results[0].user],
+ allowedMentionsParse: []
+ }
}
}
}
@@ -427,6 +443,7 @@ const attachmentEmojis = new Map([
async function eventToMessage(event, guild, di) {
let displayName = event.sender
let avatarURL = undefined
+ const allowedMentionsParse = ["users", "roles"]
/** @type {string[]} */
let messageIDsToEdit = []
let replyLine = ""
@@ -656,10 +673,11 @@ async function eventToMessage(event, guild, di) {
for (; node; node = node.nextSibling) {
// Check written mentions
if (node.nodeType === 3 && node.nodeValue.includes("@") && !nodeIsChildOf(node, ["A", "CODE", "PRE"])) {
- const result = await checkWrittenMentions(node.nodeValue, guild, di)
+ const result = await checkWrittenMentions(node.nodeValue, event.sender, event.room_id, guild, di)
if (result) {
node.nodeValue = result.content
- ensureJoined.push(result.ensureJoined)
+ ensureJoined.push(...result.ensureJoined)
+ allowedMentionsParse.push(...result.allowedMentionsParse)
}
}
// Check for incompatible backticks in code blocks
@@ -727,10 +745,11 @@ async function eventToMessage(event, guild, di) {
content = await handleRoomOrMessageLinks(content, di) // Replace matrix.to links with discord.com equivalents where possible
content = content.replace(/\bhttps?:\/\/matrix\.to\/[^ )]*/, "<$&>") // Put < > around any surviving matrix.to links to hide the URL previews
- const result = await checkWrittenMentions(content, guild, di)
+ const result = await checkWrittenMentions(content, event.sender, event.room_id, guild, di)
if (result) {
content = result.content
- ensureJoined.push(result.ensureJoined)
+ ensureJoined.push(...result.ensureJoined)
+ allowedMentionsParse.push(...result.allowedMentionsParse)
}
// Markdown needs to be escaped, though take care not to escape the middle of links
@@ -787,7 +806,7 @@ async function eventToMessage(event, guild, di) {
const messages = chunks.map(content => ({
content,
allowed_mentions: {
- parse: ["users", "roles"]
+ parse: allowedMentionsParse
},
username: displayNameShortened,
avatar_url: avatarURL
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 3366d18..90da51c 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -3786,6 +3786,174 @@ test("event2message: guessed @mentions work with other matrix bridge old users",
)
})
+test("event2message: @room converts to @everyone and is allowed when the room doesn't restrict who can use it (plaintext body)", async t => {
+ let called = 0
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "@room dinner's ready",
+ },
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
+ event_id: "$SiXetU9h9Dg-M9Frcw_C6ahnoXZ3QPZe3MVJR5tcB9A"
+ }, data.guild.general, {
+ api: {
+ getStateEvent(roomID, type, key) {
+ called++
+ t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
+ t.equal(type, "m.room.power_levels")
+ t.equal(key, "")
+ return {
+ users: {},
+ notifications: {
+ room: 0
+ }
+ }
+ }
+ }
+ }),
+ {
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "@everyone dinner's ready",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles", "everyone"]
+ }
+ }],
+ ensureJoined: []
+ }
+ )
+})
+
+test("event2message: @room converts to @everyone but is not allowed when the room restricts who can use it", async t => {
+ let called = 0
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "wrong body",
+ format: "org.matrix.custom.html",
+ formatted_body: "@room dinner's ready"
+ },
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
+ event_id: "$SiXetU9h9Dg-M9Frcw_C6ahnoXZ3QPZe3MVJR5tcB9A"
+ }, data.guild.general, {
+ api: {
+ getStateEvent(roomID, type, key) {
+ called++
+ t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
+ t.equal(type, "m.room.power_levels")
+ t.equal(key, "")
+ return {
+ users: {},
+ notifications: {
+ room: 20
+ }
+ }
+ }
+ }
+ }),
+ {
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "@room dinner's ready",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }],
+ ensureJoined: []
+ }
+ )
+})
+
+test("event2message: @room converts to @everyone and is allowed if the user has sufficient power to use it", async t => {
+ let called = 0
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "wrong body",
+ format: "org.matrix.custom.html",
+ formatted_body: "@room dinner's ready"
+ },
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
+ event_id: "$SiXetU9h9Dg-M9Frcw_C6ahnoXZ3QPZe3MVJR5tcB9A"
+ }, data.guild.general, {
+ api: {
+ getStateEvent(roomID, type, key) {
+ called++
+ t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
+ t.equal(type, "m.room.power_levels")
+ t.equal(key, "")
+ return {
+ users: {
+ "@cadence:cadence.moe": 20
+ },
+ notifications: {
+ room: 20
+ }
+ }
+ }
+ }
+ }),
+ {
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "@everyone dinner's ready",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles", "everyone"]
+ }
+ }],
+ ensureJoined: []
+ }
+ )
+})
+
+test("event2message: @room in the middle of a link is not converted", async t => {
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "wrong body",
+ format: "org.matrix.custom.html",
+ formatted_body: `https://github.com/@room/repositories https://github.com/@room/repositories`
+ },
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
+ event_id: "$SiXetU9h9Dg-M9Frcw_C6ahnoXZ3QPZe3MVJR5tcB9A"
+ }),
+ {
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "https://github.com/@room/repositories https://github.com/@room/repositories",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }],
+ ensureJoined: []
+ }
+ )
+})
+
slow()("event2message: unknown emoji at the end is reuploaded as a sprite sheet", async t => {
const messages = await eventToMessage({
type: "m.room.message",
From 08c01e866419a48096f8ccfe41b00bc92fd06fe2 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Fri, 8 Mar 2024 12:56:51 +1300
Subject: [PATCH 013/346] Update dependencies
---
package-lock.json | 527 +---------------------------------------------
package.json | 4 +-
2 files changed, 9 insertions(+), 522 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 2e45796..49c9dc3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,7 @@
"discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
- "giframe": "github:cloudrac3r/giframe#v0.4.1",
+ "giframe": "github:cloudrac3r/giframe#v0.4.2",
"heatsync": "^2.4.1",
"html-template-tag": "github:cloudrac3r/html-template-tag#v5.0",
"js-yaml": "^4.1.0",
@@ -40,7 +40,7 @@
"colorette": "^1.4.0",
"cross-env": "^7.0.3",
"discord-api-types": "^0.37.60",
- "supertape": "^10.3.0",
+ "supertape": "^10.4.0",
"tap-dot": "github:cloudrac3r/tap-dot#9dd7750ececeae3a96afba91905be812b6b2cc2d"
}
},
@@ -547,22 +547,6 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
- "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.5",
- "is-array-buffer": "^3.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -583,21 +567,6 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true
},
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
- "dev": true,
- "dependencies": {
- "possible-typed-array-names": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/b4a": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
@@ -1092,38 +1061,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/deep-equal": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
- "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "call-bind": "^1.0.5",
- "es-get-iterator": "^1.1.3",
- "get-intrinsic": "^1.2.2",
- "is-arguments": "^1.1.1",
- "is-array-buffer": "^3.0.2",
- "is-date-object": "^1.0.5",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "isarray": "^2.0.5",
- "object-is": "^1.1.5",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.1",
- "side-channel": "^1.0.4",
- "which-boxed-primitive": "^1.0.2",
- "which-collection": "^1.0.1",
- "which-typed-array": "^1.1.13"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -1148,23 +1085,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -1289,26 +1209,6 @@
"node": ">= 0.4"
}
},
- "node_modules/es-get-iterator": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
- "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "has-symbols": "^1.0.3",
- "is-arguments": "^1.1.1",
- "is-map": "^2.0.2",
- "is-set": "^2.0.2",
- "is-string": "^1.0.7",
- "isarray": "^2.0.5",
- "stop-iteration-iterator": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -1503,15 +1403,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.3"
- }
- },
"node_modules/foreground-child": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
@@ -1583,15 +1474,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -1641,8 +1523,8 @@
}
},
"node_modules/giframe": {
- "version": "0.3.0",
- "resolved": "git+ssh://git@github.com/cloudrac3r/giframe.git#1630f4d3b2bf5acd197409c85edd11e0da72d0a1",
+ "version": "0.4.2",
+ "resolved": "git+ssh://git@github.com/cloudrac3r/giframe.git#39b9d9af4184ea9df72c0ccd4db96da51bd1082c",
"license": "MIT"
},
"node_modules/github-from-package": {
@@ -1711,15 +1593,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -1762,21 +1635,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
@@ -1880,20 +1738,6 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
- "node_modules/internal-slot": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
- "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
- "dev": true,
- "dependencies": {
- "es-errors": "^1.3.0",
- "hasown": "^2.0.0",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -1902,83 +1746,11 @@
"node": ">= 0.10"
}
},
- "node_modules/is-arguments": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
- "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
- "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
- "node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dev": true,
- "dependencies": {
- "has-bigints": "^1.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-core-module": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
@@ -1991,21 +1763,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -2015,128 +1772,6 @@
"node": ">=8"
}
},
- "node_modules/is-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
- "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-set": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
- "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
- "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakmap": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
- "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakset": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
- "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
- },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -2487,49 +2122,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/object-is": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
- "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
- "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.5",
- "define-properties": "^1.2.1",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -2678,15 +2270,6 @@
"node": ">=14.19.0"
}
},
- "node_modules/possible-typed-array-names": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
- "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@@ -2890,24 +2473,6 @@
"node": ">= 6"
}
},
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
- "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.6",
- "define-properties": "^1.2.1",
- "es-errors": "^1.3.0",
- "set-function-name": "^2.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -3095,21 +2660,6 @@
"node": ">= 0.4"
}
},
- "node_modules/set-function-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
- "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -3307,18 +2857,6 @@
"node": ">= 0.8"
}
},
- "node_modules/stop-iteration-iterator": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
- "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
- "dev": true,
- "dependencies": {
- "internal-slot": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/stream-head": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/stream-head/-/stream-head-2.0.2.tgz",
@@ -3493,9 +3031,9 @@
}
},
"node_modules/supertape": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/supertape/-/supertape-10.3.0.tgz",
- "integrity": "sha512-z/HQbwB1+UMpmCQZXxxSU2zhzc+0yQq1Q9naCpyVDcRr2/cO/Bo3YhbSXJpEPVbvGy3BADl+vt5cfbXRJYFO0g==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/supertape/-/supertape-10.4.0.tgz",
+ "integrity": "sha512-mQbcPU3jyDQsbncbS2flHELhZ7qEIF9q4Swnn/0782aN+rMQBzcJR3yapVn+9k3pUoUi64IcTaGxs24WSLDCvQ==",
"dev": true,
"dependencies": {
"@cloudcmd/stub": "^4.0.0",
@@ -3510,7 +3048,6 @@
"@supertape/formatter-time": "^1.0.0",
"@supertape/operator-stub": "^3.0.0",
"cli-progress": "^3.8.2",
- "deep-equal": "^2.0.3",
"fullstore": "^3.0.0",
"glob": "^10.3.10",
"jest-diff": "^29.0.1",
@@ -3874,56 +3411,6 @@
"node": ">= 8"
}
},
- "node_modules/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
- "dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-collection": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
- "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
- "dev": true,
- "dependencies": {
- "is-map": "^2.0.1",
- "is-set": "^2.0.1",
- "is-weakmap": "^2.0.1",
- "is-weakset": "^2.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz",
- "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.6",
- "call-bind": "^1.0.5",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
diff --git a/package.json b/package.json
index bff4724..be55cf4 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
- "giframe": "github:cloudrac3r/giframe#v0.4.1",
+ "giframe": "github:cloudrac3r/giframe#v0.4.2",
"heatsync": "^2.4.1",
"html-template-tag": "github:cloudrac3r/html-template-tag#v5.0",
"js-yaml": "^4.1.0",
@@ -46,7 +46,7 @@
"colorette": "^1.4.0",
"cross-env": "^7.0.3",
"discord-api-types": "^0.37.60",
- "supertape": "^10.3.0",
+ "supertape": "^10.4.0",
"tap-dot": "github:cloudrac3r/tap-dot#9dd7750ececeae3a96afba91905be812b6b2cc2d"
},
"scripts": {
From 955310b759dbcd8b423d4d9290d74ba8e6917f56 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Fri, 15 Mar 2024 15:52:20 +1300
Subject: [PATCH 014/346] Set sim power a little bit better
I should probably change this to use kstate.
---
d2m/actions/register-user.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js
index 68b1a88..6b688d4 100644
--- a/d2m/actions/register-user.js
+++ b/d2m/actions/register-user.js
@@ -198,7 +198,8 @@ async function syncUser(user, member, channel, guild, roomID) {
// Update power levels
const powerLevelsStateContent = await api.getStateEvent(roomID, "m.room.power_levels", "")
mixin(powerLevelsStateContent, {users: {[mxid]: powerLevel}})
- api.sendState(roomID, "m.room.power_levels", "", powerLevelsStateContent)
+ if (powerLevel === 0) delete powerLevelsStateContent.users[mxid] // keep the event compact
+ await api.sendState(roomID, "m.room.power_levels", "", powerLevelsStateContent)
// Update cached hash
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
}
From d01c888d02180a30ee8313122ac2f5744dd356ad Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Fri, 15 Mar 2024 15:54:13 +1300
Subject: [PATCH 015/346] Support embed generate MESSAGE_UPDATE events
---
d2m/converters/edit-to-changes.js | 73 +++++++++++++++-----------
d2m/converters/edit-to-changes.test.js | 25 +++++++++
d2m/converters/message-to-event.js | 39 +++++++-------
test/data.js | 25 +++++++++
test/ooye-test-data.sql | 6 ++-
5 files changed, 117 insertions(+), 51 deletions(-)
diff --git a/d2m/converters/edit-to-changes.js b/d2m/converters/edit-to-changes.js
index 08f787c..ef170ca 100644
--- a/d2m/converters/edit-to-changes.js
+++ b/d2m/converters/edit-to-changes.js
@@ -3,13 +3,22 @@
const assert = require("assert").strict
const passthrough = require("../../passthrough")
-const {discord, sync, db, select, from} = passthrough
+const {sync, select, from} = passthrough
/** @type {import("./message-to-event")} */
const messageToEvent = sync.require("../converters/message-to-event")
-/** @type {import("../actions/register-user")} */
-const registerUser = sync.require("../actions/register-user")
-/** @type {import("../actions/create-room")} */
-const createRoom = sync.require("../actions/create-room")
+
+function eventCanBeEdited(ev) {
+ // Discord does not allow files, images, attachments, or videos to be edited.
+ if (ev.old.event_type === "m.room.message" && ev.old.event_subtype !== "m.text" && ev.old.event_subtype !== "m.emote" && ev.old.event_subtype !== "m.notice") {
+ return false
+ }
+ // Discord does not allow stickers to be edited.
+ if (ev.old.event_type === "m.sticker") {
+ return false
+ }
+ // Anything else is fair game.
+ return true
+}
/**
* @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message
@@ -19,12 +28,16 @@ const createRoom = sync.require("../actions/create-room")
* @param {import("../../matrix/api")} api simple-as-nails dependency injection for the matrix API
*/
async function editToChanges(message, guild, api) {
+ // If it is a user edit, allow deleting old messages (e.g. they might have removed text from an image). If it is the system adding a generated embed to a message, don't delete old messages since the system only sends partial data.
+
+ const isGeneratedEmbed = !("content" in message)
+
// Figure out what events we will be replacing
const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
assert(roomID)
/** @type {string?} Null if we don't have a sender in the room, which will happen if it's a webhook's message. The bridge bot will do the edit instead. */
- const senderMxid = from("sim").join("sim_member", "mxid").where({user_id: message.author.id, room_id: roomID}).pluck("mxid").get() || null
+ const senderMxid = message.author && from("sim").join("sim_member", "mxid").where({user_id: message.author.id, room_id: roomID}).pluck("mxid").get() || null
const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part", "reaction_part"], {message_id: message.id}).all()
@@ -48,7 +61,8 @@ async function editToChanges(message, guild, api) {
let eventsToRedact = []
/** 3. Events that are present in the new version only, and should be sent as new, with references back to the context */
let eventsToSend = []
- // 4. Events that are matched and have definitely not changed, so they don't need to be edited or replaced at all. This is represented as nothing.
+ /** 4. Events that are matched and have definitely not changed, so they don't need to be edited or replaced at all. */
+ let unchangedEvents = []
function shift() {
newFallbackContent.shift()
@@ -81,22 +95,35 @@ async function editToChanges(message, guild, api) {
shift()
}
// Anything remaining in oldEventRows is present in the old version only and should be redacted.
- eventsToRedact = oldEventRows
+ eventsToRedact = oldEventRows.map(e => ({old: e}))
+
+ // If this is a generated embed update, only allow the embeds to be updated, since the system only sends data about events. Ignore changes to other things.
+ if (isGeneratedEmbed) {
+ unchangedEvents.push(...eventsToRedact.filter(e => e.old.event_subtype !== "m.notice")) // Move them from eventsToRedact to unchangedEvents.
+ eventsToRedact = eventsToRedact.filter(e => e.old.event_subtype === "m.notice")
+ }
+
+ // Now, everything in eventsToSend and eventsToRedact is a real change, but everything in eventsToReplace might not have actually changed!
+ // (Example: a MESSAGE_UPDATE for a text+image message - Discord does not allow the image to be changed, but the text might have been.)
+ // So we'll remove entries from eventsToReplace that *definitely* cannot have changed. (This is category 4 mentioned above.) Everything remaining *may* have changed.
+ unchangedEvents.push(...eventsToReplace.filter(ev => !eventCanBeEdited(ev))) // Move them from eventsToRedact to unchangedEvents.
+ eventsToReplace = eventsToReplace.filter(eventCanBeEdited)
// We want to maintain exactly one part = 0 and one reaction_part = 0 database row at all times.
/** @type {({column: string, eventID: string} | {column: string, nextEvent: true})[]} */
const promotions = []
for (const column of ["part", "reaction_part"]) {
+ const candidatesForParts = unchangedEvents.concat(eventsToReplace)
// If no events with part = 0 exist (or will exist), we need to do some management.
- if (!eventsToReplace.some(e => e.old[column] === 0)) {
- if (eventsToReplace.length) {
+ if (!candidatesForParts.some(e => e.old[column] === 0)) {
+ if (candidatesForParts.length) {
// We can choose an existing event to promote. Bigger order is better.
- const order = e => 2*+(e.event_type === "m.room.message") + 1*+(e.event_subtype === "m.text")
- eventsToReplace.sort((a, b) => order(b) - order(a))
+ const order = e => 2*+(e.event_type === "m.room.message") + 1*+(e.old.event_subtype === "m.text")
+ candidatesForParts.sort((a, b) => order(b) - order(a))
if (column === "part") {
- promotions.push({column, eventID: eventsToReplace[0].old.event_id}) // part should be the first one
+ promotions.push({column, eventID: candidatesForParts[0].old.event_id}) // part should be the first one
} else {
- promotions.push({column, eventID: eventsToReplace[eventsToReplace.length - 1].old.event_id}) // reaction_part should be the last one
+ promotions.push({column, eventID: candidatesForParts[candidatesForParts.length - 1].old.event_id}) // reaction_part should be the last one
}
} else {
// No existing events to promote, but new events are being sent. Whatever gets sent will be the next part = 0.
@@ -105,24 +132,8 @@ async function editToChanges(message, guild, api) {
}
}
- // Now, everything in eventsToSend and eventsToRedact is a real change, but everything in eventsToReplace might not have actually changed!
- // (Example: a MESSAGE_UPDATE for a text+image message - Discord does not allow the image to be changed, but the text might have been.)
- // So we'll remove entries from eventsToReplace that *definitely* cannot have changed. (This is category 4 mentioned above.) Everything remaining *may* have changed.
- eventsToReplace = eventsToReplace.filter(ev => {
- // Discord does not allow files, images, attachments, or videos to be edited.
- if (ev.old.event_type === "m.room.message" && ev.old.event_subtype !== "m.text" && ev.old.event_subtype !== "m.emote" && ev.old.event_subtype !== "m.notice") {
- return false
- }
- // Discord does not allow stickers to be edited.
- if (ev.old.event_type === "m.sticker") {
- return false
- }
- // Anything else is fair game.
- return true
- })
-
// Removing unnecessary properties before returning
- eventsToRedact = eventsToRedact.map(e => e.event_id)
+ eventsToRedact = eventsToRedact.map(e => e.old.event_id)
eventsToReplace = eventsToReplace.map(e => ({oldID: e.old.event_id, newContent: makeReplacementEventContent(e.old.event_id, e.newFallbackContent, e.newInnerContent)}))
return {roomID, eventsToReplace, eventsToRedact, eventsToSend, senderMxid, promotions}
diff --git a/d2m/converters/edit-to-changes.test.js b/d2m/converters/edit-to-changes.test.js
index 04f5568..1004c34 100644
--- a/d2m/converters/edit-to-changes.test.js
+++ b/d2m/converters/edit-to-changes.test.js
@@ -235,3 +235,28 @@ test("edit2changes: promotes the text event when multiple rows have part = 1 (sh
}
])
})
+
+test("edit2changes: generated embed", async t => {
+ const {eventsToRedact, eventsToReplace, eventsToSend, promotions} = await editToChanges(data.message_update.embed_generated_social_media_image, data.guild.general, {})
+ t.deepEqual(eventsToRedact, [])
+ t.deepEqual(eventsToReplace, [])
+ t.deepEqual(eventsToSend, [{
+ $type: "m.room.message",
+ msgtype: "m.notice",
+ body: "| via hthrflwrs on cohost"
+ + "\n| \n| ## This post nerdsniped me, so here's some RULES FOR REAL-LIFE BALATRO https://cohost.org/jkap/post/4794219-empty"
+ + "\n| \n| 1v1 physical card game. Each player gets one standard deck of cards with a different backing to differentiate. Every turn proceeds as follows:"
+ + "\n| \n| * Both players draw eight cards"
+ + "\n| * Both players may choose up to eight cards to discard, then draw that number of cards to put back in their hand"
+ + "\n| * Both players present their best five-or-less-card pok...",
+ format: "org.matrix.custom.html",
+ formatted_body: `hthrflwrs on cohost`
+ + `
This post nerdsniped me, so here's some RULES FOR REAL-LIFE BALATRO`
+ + `
1v1 physical card game. Each player gets one standard deck of cards with a different backing to differentiate. Every turn proceeds as follows:`
+ + `
- Both players draw eight cards`
+ + `
- Both players may choose up to eight cards to discard, then draw that number of cards to put back in their hand`
+ + `
- Both players present their best five-or-less-card pok...
`,
+ "m.mentions": {}
+ }])
+ t.deepEqual(promotions, []) // TODO: it would be ideal to promote this to reaction_part = 0. this is OK to do because the main message won't have had any reactions yet.
+})
diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js
index 3ede0a4..518d041 100644
--- a/d2m/converters/message-to-event.js
+++ b/d2m/converters/message-to-event.js
@@ -480,32 +480,35 @@ async function messageToEvent(message, guild, options = {}, di) {
message.content = "changed the channel name to **" + message.content + "**"
}
- // Mentions scenario 3: scan the message content for written @mentions of matrix users. Allows for up to one space between @ and mention.
- const matches = [...message.content.matchAll(/@ ?([a-z0-9._]+)\b/gi)]
- if (matches.length && matches.some(m => m[1].match(/[a-z]/i) && m[1] !== "everyone" && m[1] !== "here")) {
- const writtenMentionsText = matches.map(m => m[1].toLowerCase())
- const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
- assert(roomID)
- const {joined} = await di.api.getJoinedMembers(roomID)
- for (const [mxid, member] of Object.entries(joined)) {
- if (!userRegex.some(rx => mxid.match(rx))) {
- const localpart = mxid.match(/@([^:]*)/)
- assert(localpart)
- const displayName = member.display_name || localpart[1]
- if (writtenMentionsText.includes(localpart[1].toLowerCase()) || writtenMentionsText.includes(displayName.toLowerCase())) addMention(mxid)
+
+ if (message.content) {
+ // Mentions scenario 3: scan the message content for written @mentions of matrix users. Allows for up to one space between @ and mention.
+ const matches = [...message.content.matchAll(/@ ?([a-z0-9._]+)\b/gi)]
+ if (matches.length && matches.some(m => m[1].match(/[a-z]/i) && m[1] !== "everyone" && m[1] !== "here")) {
+ const writtenMentionsText = matches.map(m => m[1].toLowerCase())
+ const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
+ assert(roomID)
+ const {joined} = await di.api.getJoinedMembers(roomID)
+ for (const [mxid, member] of Object.entries(joined)) {
+ if (!userRegex.some(rx => mxid.match(rx))) {
+ const localpart = mxid.match(/@([^:]*)/)
+ assert(localpart)
+ const displayName = member.display_name || localpart[1]
+ if (writtenMentionsText.includes(localpart[1].toLowerCase()) || writtenMentionsText.includes(displayName.toLowerCase())) addMention(mxid)
+ }
}
}
- }
- // Text content appears first
- if (message.content) {
+ // Text content appears first
const {body, html} = await transformContent(message.content)
await addTextEvent(body, html, msgtype, {scanMentions: true})
}
// Then attachments
- const attachmentEvents = await Promise.all(message.attachments.map(attachmentToEvent.bind(null, mentions)))
- events.push(...attachmentEvents)
+ if (message.attachments) {
+ const attachmentEvents = await Promise.all(message.attachments.map(attachmentToEvent.bind(null, mentions)))
+ events.push(...attachmentEvents)
+ }
// Then embeds
for (const embed of message.embeds || []) {
diff --git a/test/data.js b/test/data.js
index c165322..17b92cf 100644
--- a/test/data.js
+++ b/test/data.js
@@ -3469,6 +3469,31 @@ module.exports = {
}
],
guild_id: "112760669178241024"
+ },
+ embed_generated_social_media_image: {
+ channel_id: "112760669178241024",
+ embeds: [
+ {
+ color: 8594767,
+ description: "1v1 physical card game. Each player gets one standard deck of cards with a different backing to differentiate. Every turn proceeds as follows:\n\n * Both players draw eight cards\n * Both players may choose up to eight cards to discard, then draw that number of cards to put back in their hand\n * Both players present their best five-or-less-card pok...",
+ provider: {
+ name: "hthrflwrs on cohost"
+ },
+ thumbnail: {
+ height: 1587,
+ placeholder: "GpoKP5BJZphshnhwmmmYlmh3l7+m+mwJ",
+ placeholder_version: 1,
+ proxy_url: "https://images-ext-2.discordapp.net/external/9vTXIzlXU4wyUZvWfmlmQkck8nGLUL-A090W4lWsZ48/https/staging.cohostcdn.org/avatar/292-6b64b03c-4ada-42f6-8452-109275bfe68d-profile.png",
+ url: "https://staging.cohostcdn.org/avatar/292-6b64b03c-4ada-42f6-8452-109275bfe68d-profile.png",
+ width: 1644
+ },
+ title: "This post nerdsniped me, so here's some RULES FOR REAL-LIFE BALATRO",
+ type: "link",
+ url: "https://cohost.org/jkap/post/4794219-empty"
+ }
+ ],
+ guild_id: "112760669178241024",
+ id: "1210387798297682020"
}
},
special_message: {
diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql
index 573d7a4..35368f4 100644
--- a/test/ooye-test-data.sql
+++ b/test/ooye-test-data.sql
@@ -53,7 +53,8 @@ INSERT INTO message_channel (message_id, channel_id) VALUES
('1158842413025071135', '176333891320283136'),
('1197612733600895076', '112760669178241024'),
('1202543413652881428', '1160894080998461480'),
-('1207486471489986620', '1160894080998461480');
+('1207486471489986620', '1160894080998461480'),
+('1210387798297682020', '112760669178241024');
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),
@@ -87,7 +88,8 @@ INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part
('$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),
-('$OEEK-Wam2FTh6J-6kVnnJ6KnLA_lLRnLTHatKKL62-Y', 'm.room.message', 'm.image', '1207486471489986620', 0, 0, 0);
+('$OEEK-Wam2FTh6J-6kVnnJ6KnLA_lLRnLTHatKKL62-Y', 'm.room.message', 'm.image', '1207486471489986620', 0, 0, 0),
+('$mPSzglkCu-6cZHbYro0RW2u5mHvbH9aXDjO5FCzosc0', 'm.room.message', 'm.text', '1210387798297682020', 0, 0, 1);
INSERT INTO file (discord_url, mxc_url) VALUES
('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'),
From 23d85547f34b7998a4eddeebb3051aff7de1125c Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sun, 17 Mar 2024 01:07:50 +1300
Subject: [PATCH 016/346] Send generated embeds as original user
---
d2m/converters/edit-to-changes.js | 15 ++++++++++++++-
d2m/converters/edit-to-changes.test.js | 12 +++++++++++-
d2m/event-dispatcher.js | 3 ++-
scripts/capture-message-update-events.js | 2 +-
4 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/d2m/converters/edit-to-changes.js b/d2m/converters/edit-to-changes.js
index ef170ca..dd8e39f 100644
--- a/d2m/converters/edit-to-changes.js
+++ b/d2m/converters/edit-to-changes.js
@@ -6,6 +6,8 @@ const passthrough = require("../../passthrough")
const {sync, select, from} = passthrough
/** @type {import("./message-to-event")} */
const messageToEvent = sync.require("../converters/message-to-event")
+/** @type {import("../../m2d/converters/utils")} */
+const utils = sync.require("../../m2d/converters/utils")
function eventCanBeEdited(ev) {
// Discord does not allow files, images, attachments, or videos to be edited.
@@ -37,7 +39,18 @@ async function editToChanges(message, guild, api) {
const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
assert(roomID)
/** @type {string?} Null if we don't have a sender in the room, which will happen if it's a webhook's message. The bridge bot will do the edit instead. */
- const senderMxid = message.author && from("sim").join("sim_member", "mxid").where({user_id: message.author.id, room_id: roomID}).pluck("mxid").get() || null
+ let senderMxid = null
+ if (message.author) {
+ senderMxid = from("sim").join("sim_member", "mxid").where({user_id: message.author.id, room_id: roomID}).pluck("mxid").get() || null
+ } else {
+ // Should be a system generated embed. We want the embed to be sent by the same user who sent the message, so that the messages get grouped in most clients.
+ const eventID = select("event_message", "event_id", {message_id: message.id}).pluck().get()
+ assert(eventID) // this should have been checked earlier in a calling function
+ const event = await api.getEvent(roomID, eventID)
+ if (utils.eventSenderIsFromDiscord(event.sender)) {
+ senderMxid = event.sender
+ }
+ }
const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part", "reaction_part"], {message_id: message.id}).all()
diff --git a/d2m/converters/edit-to-changes.test.js b/d2m/converters/edit-to-changes.test.js
index 1004c34..b00a2c4 100644
--- a/d2m/converters/edit-to-changes.test.js
+++ b/d2m/converters/edit-to-changes.test.js
@@ -237,7 +237,15 @@ test("edit2changes: promotes the text event when multiple rows have part = 1 (sh
})
test("edit2changes: generated embed", async t => {
- const {eventsToRedact, eventsToReplace, eventsToSend, promotions} = await editToChanges(data.message_update.embed_generated_social_media_image, data.guild.general, {})
+ let called = 0
+ const {senderMxid, eventsToRedact, eventsToReplace, eventsToSend, promotions} = await editToChanges(data.message_update.embed_generated_social_media_image, data.guild.general, {
+ async getEvent(roomID, eventID) {
+ called++
+ t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
+ t.equal(eventID, "$mPSzglkCu-6cZHbYro0RW2u5mHvbH9aXDjO5FCzosc0")
+ return {sender: "@_ooye_cadence:cadence.moe"}
+ }
+ })
t.deepEqual(eventsToRedact, [])
t.deepEqual(eventsToReplace, [])
t.deepEqual(eventsToSend, [{
@@ -259,4 +267,6 @@ test("edit2changes: generated embed", async t => {
"m.mentions": {}
}])
t.deepEqual(promotions, []) // TODO: it would be ideal to promote this to reaction_part = 0. this is OK to do because the main message won't have had any reactions yet.
+ t.equal(senderMxid, "@_ooye_cadence:cadence.moe")
+ t.equal(called, 1)
})
diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js
index 2c4dcd5..54d858a 100644
--- a/d2m/event-dispatcher.js
+++ b/d2m/event-dispatcher.js
@@ -268,7 +268,8 @@ module.exports = {
// Based on looking at data they've sent me over the gateway, this is the best way to check for meaningful changes.
// If the message content is a string then it includes all interesting fields and is meaningful.
- if (typeof data.content === "string") {
+ // Otherwise, if there are embeds, then the system generated URL preview embeds.
+ if (typeof data.content === "string" || "embeds" in data) {
/** @type {DiscordTypes.GatewayMessageCreateDispatchData} */
// @ts-ignore
const message = data
diff --git a/scripts/capture-message-update-events.js b/scripts/capture-message-update-events.js
index f345d3f..671b062 100644
--- a/scripts/capture-message-update-events.js
+++ b/scripts/capture-message-update-events.js
@@ -37,7 +37,7 @@ passthrough.discord = discord
})()
const events = new sqlite("scripts/events.db")
-const sql = "INSERT INTO \"update\" (json, " + interestingFields.join(", ") + ") VALUES (" + "?".repeat(interestingFields.length + 1).split("").join(", ") + ")"
+const sql = "INSERT INTO update_event (json, " + interestingFields.join(", ") + ") VALUES (" + "?".repeat(interestingFields.length + 1).split("").join(", ") + ")"
console.log(sql)
const prepared = events.prepare(sql)
From c615ea1e6162a1f193f29e52d277d5a01f9fecdd Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 19 Mar 2024 15:06:31 +1300
Subject: [PATCH 017/346] Reflect immediately generated link embeds
---
m2d/actions/send-event.js | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/m2d/actions/send-event.js b/m2d/actions/send-event.js
index 6c0448f..d35c558 100644
--- a/m2d/actions/send-event.js
+++ b/m2d/actions/send-event.js
@@ -17,6 +17,8 @@ const eventToMessage = sync.require("../converters/event-to-message")
const api = sync.require("../../matrix/api")
/** @type {import("../../d2m/actions/register-user")} */
const registerUser = sync.require("../../d2m/actions/register-user")
+/** @type {import("../../d2m/actions/edit-message")} */
+const editMessage = sync.require("../../d2m/actions/edit-message")
/** @type {import("../actions/emoji-sheet")} */
const emojiSheet = sync.require("../actions/emoji-sheet")
@@ -111,6 +113,22 @@ async function sendEvent(event) {
eventPart = 1
messageResponses.push(messageResponse)
+
+ /*
+ If the Discord system has a cached link preview embed for one of the links just sent,
+ it will be instantly added as part of `embeds` and there won't be a MESSAGE_UPDATE.
+ To reflect the generated embed back to Matrix, we pretend the message was updated right away.
+ */
+ const sentEmbedsCount = message.embeds?.length || 0
+ if (messageResponse.embeds.length > sentEmbedsCount) {
+ // @ts-ignore this is a valid message edit payload
+ editMessage.editMessage({ // not awaiting because requests to Matrix shouldn't block requests to Discord
+ id: messageResponse.channel_id,
+ channel_id: messageResponse.channel_id,
+ guild_id: guild.id,
+ embeds: messageResponse.embeds
+ }, guild, null)
+ }
}
for (const user of ensureJoined) {
From bce3d0f2c9b622a9aa9d564ee69a5c833e70d51d Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 19 Mar 2024 21:58:48 +1300
Subject: [PATCH 018/346] Fix reflecting generated embeds
---
m2d/actions/send-event.js | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/m2d/actions/send-event.js b/m2d/actions/send-event.js
index d35c558..4422ad3 100644
--- a/m2d/actions/send-event.js
+++ b/m2d/actions/send-event.js
@@ -90,6 +90,7 @@ async function sendEvent(event) {
}))
let eventPart = 0 // 0 is primary, 1 is supporting
+ const pendingEdits = []
/** @type {DiscordTypes.APIMessage[]} */
const messageResponses = []
@@ -121,13 +122,16 @@ async function sendEvent(event) {
*/
const sentEmbedsCount = message.embeds?.length || 0
if (messageResponse.embeds.length > sentEmbedsCount) {
- // @ts-ignore this is a valid message edit payload
- editMessage.editMessage({ // not awaiting because requests to Matrix shouldn't block requests to Discord
- id: messageResponse.channel_id,
- channel_id: messageResponse.channel_id,
- guild_id: guild.id,
- embeds: messageResponse.embeds
- }, guild, null)
+ // not awaiting here because requests to Matrix shouldn't block requests to Discord
+ pendingEdits.push(() =>
+ // @ts-ignore this is a valid message edit payload
+ editMessage.editMessage({
+ id: messageResponse.id,
+ channel_id: messageResponse.channel_id,
+ guild_id: guild.id,
+ embeds: messageResponse.embeds
+ }, guild, null)
+ )
}
}
@@ -135,6 +139,8 @@ async function sendEvent(event) {
registerUser.ensureSimJoined(user, event.room_id)
}
+ await Promise.all(pendingEdits.map(f => f())) // `await` will propagate any errors during editing
+
return messageResponses
}
From 0deb4155115e22646718b1cee69b866800bfdffe Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 19 Mar 2024 22:15:44 +1300
Subject: [PATCH 019/346] Don't update profile data of the bridge bot
---
d2m/actions/send-message.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/d2m/actions/send-message.js b/d2m/actions/send-message.js
index a1290e0..346ac0d 100644
--- a/d2m/actions/send-message.js
+++ b/d2m/actions/send-message.js
@@ -29,7 +29,9 @@ async function sendMessage(message, channel, guild, row) {
let senderMxid = null
if (!dUtils.isWebhookMessage(message)) {
- if (message.member) { // available on a gateway message create event
+ if (message.author.id === discord.application.id) {
+ // no need to sync the bot's own user
+ } else if (message.member) { // available on a gateway message create event
senderMxid = await registerUser.syncUser(message.author, message.member, channel, guild, roomID)
} else { // well, good enough...
senderMxid = await registerUser.ensureSimJoined(message.author, roomID)
From 566b2a9d9e3ddfec02725c7713c74829a5827ecf Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sat, 23 Mar 2024 18:39:37 +1300
Subject: [PATCH 020/346] Move bridge bot to its real ID in the database
---
.../0011-move-bridge-bot-to-real-id.up.js | 16 ++++++++++++++++
scripts/seed.js | 12 +++++++-----
2 files changed, 23 insertions(+), 5 deletions(-)
create mode 100644 db/migrations/0011-move-bridge-bot-to-real-id.up.js
diff --git a/db/migrations/0011-move-bridge-bot-to-real-id.up.js b/db/migrations/0011-move-bridge-bot-to-real-id.up.js
new file mode 100644
index 0000000..1808fcd
--- /dev/null
+++ b/db/migrations/0011-move-bridge-bot-to-real-id.up.js
@@ -0,0 +1,16 @@
+/*
+ a. If the bridge bot sim already has the correct ID:
+ - No rows updated.
+
+ b. If the bridge bot sim has the wrong ID but there's no duplicate:
+ - One row updated.
+
+ c. If the bridge bot sim has the wrong ID and there's a duplicate:
+ - One row updated (replaces an existing row).
+*/
+
+module.exports = async function(db) {
+ const config = require("../../config")
+ const id = Buffer.from(config.discordToken.split(".")[0], "base64").toString()
+ db.prepare("UPDATE OR REPLACE sim SET user_id = ? WHERE user_id = '0'").run(id)
+}
diff --git a/scripts/seed.js b/scripts/seed.js
index 1a21490..2ab3e02 100644
--- a/scripts/seed.js
+++ b/scripts/seed.js
@@ -53,17 +53,19 @@ async function uploadAutoEmoji(guild, name, filename) {
const mxid = `@${reg.sender_localpart}:${reg.ooye.server_name}`
// ensure registration is correctly set...
- assert(reg.sender_localpart.startsWith(reg.ooye.namespace_prefix)) // appservice's localpart must be in the namespace it controls
- assert(utils.eventSenderIsFromDiscord(mxid)) // appservice's mxid must be in the namespace it controls
- assert(reg.ooye.server_origin.match(/^https?:\/\//)) // must start with http or https
- assert.notEqual(reg.ooye.server_origin.slice(-1), "/") // must not end in slash
+ assert(reg.sender_localpart.startsWith(reg.ooye.namespace_prefix), "appservice's localpart must be in the namespace it controls")
+ assert(utils.eventSenderIsFromDiscord(mxid), "appservice's mxid must be in the namespace it controls")
+ assert(reg.ooye.server_origin.match(/^https?:\/\//), "server origin must start with http or https")
+ assert.notEqual(reg.ooye.server_origin.slice(-1), "/", "server origin must not end in slash")
+ const botID = Buffer.from(config.discordToken.split(".")[0], "base64").toString()
+ assert(botID.match(/^[0-9]{10,}$/), "discord token must follow the correct format")
console.log("✅ Configuration looks good...")
// database ddl...
await migrate.migrate(db)
// add initial rows to database, like adding the bot to sim...
- db.prepare("INSERT OR IGNORE INTO sim (user_id, sim_name, localpart, mxid) VALUES (?, ?, ?, ?)").run("0", reg.sender_localpart.slice(reg.ooye.namespace_prefix.length), reg.sender_localpart, mxid)
+ db.prepare("INSERT OR IGNORE INTO sim (user_id, sim_name, localpart, mxid) VALUES (?, ?, ?, ?)").run(botID, reg.sender_localpart.slice(reg.ooye.namespace_prefix.length), reg.sender_localpart, mxid)
console.log("✅ Database is ready...")
From 7a00b95883a58bbe90f36748a28f9f4039a25fd1 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sat, 23 Mar 2024 21:26:42 +1300
Subject: [PATCH 021/346] Put < > around ALL the matrix.to links
---
m2d/converters/event-to-message.js | 2 +-
m2d/converters/event-to-message.test.js | 34 +++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index 87fadc8..f9403f9 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -724,7 +724,7 @@ async function eventToMessage(event, guild, di) {
content = turndownService.turndown(root)
// Put < > around any surviving matrix.to links to hide the URL previews
- content = content.replace(/\bhttps?:\/\/matrix\.to\/[^ )]*/, "<$&>")
+ content = content.replace(/\bhttps?:\/\/matrix\.to\/[^ )]*/g, "<$&>")
// It's designed for commonmark, we need to replace the space-space-newline with just newline
content = content.replace(/ \n/g, "\n")
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 90da51c..9035ddb 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -2619,6 +2619,40 @@ test("event2message: mentioning matrix users works", async t => {
)
})
+test("event2message: multiple mentions are both escaped", async t => {
+ t.deepEqual(
+ await eventToMessage({
+ content: {
+ msgtype: "m.text",
+ body: "wrong body",
+ format: "org.matrix.custom.html",
+ formatted_body: `@cadence:cadence.moe can you kick my old account over there @amyiscoolz:matrix.atiusamy.com`
+ },
+ event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU",
+ origin_server_ts: 1688301929913,
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
+ sender: "@cadence:cadence.moe",
+ type: "m.room.message",
+ unsigned: {
+ age: 405299
+ }
+ }),
+ {
+ ensureJoined: [],
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "[@cadence:cadence.moe]() can you kick my old account over there [@amyiscoolz:matrix.atiusamy.com]()",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }]
+ }
+ )
+})
+
test("event2message: mentioning matrix users works even when Element disambiguates the user", async t => {
t.deepEqual(
await eventToMessage({
From ff7af39802e34ac3972396cda67d0442dabf00c3 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Mon, 25 Mar 2024 18:05:19 +1300
Subject: [PATCH 022/346] Exclude generated embeds for discord.com
---
.../message-to-event.embeds.test.js | 34 ++++++++++++++++
d2m/converters/message-to-event.js | 4 ++
test/data.js | 40 +++++++++++++++++++
3 files changed, 78 insertions(+)
diff --git a/d2m/converters/message-to-event.embeds.test.js b/d2m/converters/message-to-event.embeds.test.js
index fc02a3f..61a0822 100644
--- a/d2m/converters/message-to-event.embeds.test.js
+++ b/d2m/converters/message-to-event.embeds.test.js
@@ -282,3 +282,37 @@ test("message2event embeds: youtube video", async t => {
"m.mentions": {}
}])
})
+
+test("message2event embeds: if discord creates an embed preview for a discord channel link, don't copy that embed", async t => {
+ const events = await messageToEvent(data.message_with_embeds.discord_server_included_punctuation_bad_discord, data.guild.general, {}, {
+ api: {
+ async getStateEvent(roomID, type, key) {
+ t.equal(roomID, "!TqlyQmifxGUggEmdBN:cadence.moe")
+ t.equal(type, "m.room.power_levels")
+ t.equal(key, "")
+ return {
+ users: {
+ "@_ooye_bot:cadence.moe": 100
+ }
+ }
+ },
+ async getJoinedMembers(roomID) {
+ t.equal(roomID, "!TqlyQmifxGUggEmdBN:cadence.moe")
+ return {
+ joined: {
+ "@_ooye_bot:cadence.moe": {display_name: null, avatar_url: null},
+ "@user:matrix.org": {display_name: null, avatar_url: null}
+ }
+ }
+ }
+ }
+ })
+ t.deepEqual(events, [{
+ $type: "m.room.message",
+ msgtype: "m.text",
+ body: "(test https://matrix.to/#/!TqlyQmifxGUggEmdBN:cadence.moe/$NB6nPgO2tfXyIwwDSF0Ga0BUrsgX1S-0Xl-jAvI8ucU?via=cadence.moe&via=matrix.org)",
+ format: "org.matrix.custom.html",
+ formatted_body: `(test https://matrix.to/#/!TqlyQmifxGUggEmdBN:cadence.moe/$NB6nPgO2tfXyIwwDSF0Ga0BUrsgX1S-0Xl-jAvI8ucU?via=cadence.moe&via=matrix.org)`,
+ "m.mentions": {}
+ }])
+})
diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js
index 518d041..45e43dd 100644
--- a/d2m/converters/message-to-event.js
+++ b/d2m/converters/message-to-event.js
@@ -516,6 +516,10 @@ async function messageToEvent(message, guild, options = {}, di) {
continue // Matrix's own URL previews are fine for images.
}
+ if (embed.url?.startsWith("https://discord.com/")) {
+ continue // If discord creates an embed preview for a discord channel link, don't copy that embed
+ }
+
// 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()
diff --git a/test/data.js b/test/data.js
index 17b92cf..77b2ada 100644
--- a/test/data.js
+++ b/test/data.js
@@ -2870,6 +2870,46 @@ module.exports = {
}
},
webhook_id: "1109360903096369153"
+ },
+ discord_server_included_punctuation_bad_discord: {
+ id: "1221672425792606349",
+ type: 0,
+ content: "(test https://discord.com/channels/1160894080998461480/1160894080998461480/1202543413652881428)",
+ channel_id: "1160894080998461480",
+ author: {
+ id: "772659086046658620",
+ username: "cadence.worm",
+ avatar: "4b5c4b28051144e4c111f0113a0f1cf1",
+ discriminator: "0",
+ public_flags: 0,
+ premium_type: 0,
+ flags: 0,
+ banner: null,
+ accent_color: null,
+ global_name: "cadence",
+ avatar_decoration_data: null,
+ banner_color: null
+ },
+ attachments: [],
+ embeds: [
+ {
+ type: "article",
+ url: "https://discord.com/channels/1160894080998461480/1160894080998461480/1202543413652881428)",
+ title: "Discord - A New Way to Chat with Friends & Communities",
+ description: "Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.",
+ provider: { name: "Discord" },
+ content_scan_version: 0
+ }
+ ],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "2024-03-25T04:10:03.885000+00:00",
+ edited_timestamp: null,
+ flags: 0,
+ components: []
}
},
message_update: {
From 642be26313bd69fbb563a3fbe2dabb4679e62f79 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 26 Mar 2024 01:10:29 +1300
Subject: [PATCH 023/346] Enumerate child rooms with hierarchy endpoint
---
d2m/actions/create-space.js | 14 +++++++++++---
matrix/api.js | 14 ++++++++++++++
types.d.ts | 17 +++++++++++++++++
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/d2m/actions/create-space.js b/d2m/actions/create-space.js
index a7390ed..3bad2a1 100644
--- a/d2m/actions/create-space.js
+++ b/d2m/actions/create-space.js
@@ -3,6 +3,7 @@
const assert = require("assert").strict
const {isDeepStrictEqual} = require("util")
const DiscordTypes = require("discord-api-types/v10")
+const Ty = require("../../types")
const reg = require("../../matrix/read-registration")
const passthrough = require("../../passthrough")
@@ -181,9 +182,16 @@ async function syncSpaceFully(guildID) {
const spaceDiff = ks.diffKState(spaceKState, guildKState)
await createRoom.applyKStateDiffToRoom(spaceID, spaceDiff)
- const childRooms = ks.kstateToState(spaceKState).filter(({type, content}) => {
- return type === "m.space.child" && "via" in content
- }).map(({state_key}) => state_key)
+ /** @type {string[]} room IDs */
+ let childRooms = []
+ /** @type {string | undefined} */
+ let nextBatch = undefined
+ do {
+ /** @type {Ty.HierarchyPagination} */
+ const res = await api.getHierarchy(spaceID, {from: nextBatch})
+ childRooms.push(...res.rooms.map(room => room.room_id))
+ nextBatch = res.next_batch
+ } while (nextBatch)
for (const roomID of childRooms) {
const channelID = select("channel_room", "channel_id", {room_id: roomID}).pluck().get()
diff --git a/matrix/api.js b/matrix/api.js
index baa5d96..82b1c10 100644
--- a/matrix/api.js
+++ b/matrix/api.js
@@ -121,6 +121,19 @@ function getJoinedMembers(roomID) {
return mreq.mreq("GET", `/client/v3/rooms/${roomID}/joined_members`)
}
+/**
+ * @param {string} roomID
+ * @param {{from?: string, limit?: any}} pagination
+ * @returns {Promise>}
+ */
+function getHierarchy(roomID, pagination) {
+ let path = `/client/v1/rooms/${roomID}/hierarchy`
+ if (!pagination.from) delete pagination.from
+ if (!pagination.limit) pagination.limit = 50
+ path += `?${new URLSearchParams(pagination)}`
+ return mreq.mreq("GET", path)
+}
+
/**
* @param {string} roomID
* @param {string} eventID
@@ -239,6 +252,7 @@ module.exports.getEventForTimestamp = getEventForTimestamp
module.exports.getAllState = getAllState
module.exports.getStateEvent = getStateEvent
module.exports.getJoinedMembers = getJoinedMembers
+module.exports.getHierarchy = getHierarchy
module.exports.getRelations = getRelations
module.exports.sendState = sendState
module.exports.sendEvent = sendEvent
diff --git a/types.d.ts b/types.d.ts
index 2788f60..68430d9 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -257,6 +257,18 @@ export namespace R {
export type EventRedacted = {
event_id: string
}
+
+ export type Hierarchy = {
+ avatar_url?: string
+ canonical_alias?: string
+ children_state: {}
+ guest_can_join: boolean
+ join_rule?: string
+ name?: string
+ num_joined_members: number
+ room_id: string
+ room_type?: string
+ }
}
export type Pagination = {
@@ -264,3 +276,8 @@ export type Pagination = {
next_batch?: string
prev_match?: string
}
+
+export type HierarchyPagination = {
+ rooms: T[]
+ next_batch?: string
+}
From 5f0e765934bbd1dd3e5765e19d9624f0356ae9e6 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 26 Mar 2024 01:11:13 +1300
Subject: [PATCH 024/346] Bridge forums as spaces
---
d2m/actions/create-room.js | 40 +++++++++++++++++++++++++++++---------
1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js
index a8d2846..4559ffa 100644
--- a/d2m/actions/create-room.js
+++ b/d2m/actions/create-room.js
@@ -59,13 +59,16 @@ function applyKStateDiffToRoom(roomID, kstate) {
}
/**
- * @param {{id: string, name: string, topic?: string?, type: number}} channel
+ * @param {{id: string, name: string, topic?: string?, type: number, parent_id?: string?}} channel
* @param {{id: string}} guild
* @param {string | null | undefined} customName
*/
function convertNameAndTopic(channel, guild, customName) {
+ // @ts-ignore
+ const parentChannel = discord.channels.get(channel.parent_id)
let channelPrefix =
- ( channel.type === DiscordTypes.ChannelType.PublicThread ? "[⛓️] "
+ ( parentChannel?.type === DiscordTypes.ChannelType.GuildForum ? ""
+ : channel.type === DiscordTypes.ChannelType.PublicThread ? "[⛓️] "
: channel.type === DiscordTypes.ChannelType.PrivateThread ? "[🔒⛓️] "
: channel.type === DiscordTypes.ChannelType.GuildVoice ? "[🔊] "
: "")
@@ -88,9 +91,24 @@ function convertNameAndTopic(channel, guild, customName) {
* @param {DiscordTypes.APIGuild} guild
*/
async function channelToKState(channel, guild) {
- const spaceID = await createSpace.ensureSpace(guild)
- assert(typeof spaceID === "string")
- const privacyLevel = select("guild_space", "privacy_level", {space_id: spaceID}).pluck().get()
+ // @ts-ignore
+ const parentChannel = discord.channels.get(channel.parent_id)
+ /** Used for membership/permission checks. */
+ let guildSpaceID
+ /** Used as the literal parent on Matrix, for categorisation. Will be the same as `guildSpaceID` unless it's a forum channel's thread, in which case a different space is used to group those threads. */
+ let parentSpaceID
+ let privacyLevel
+ if (parentChannel?.type === DiscordTypes.ChannelType.GuildForum) { // it's a forum channel's thread, so use a different space to group those threads
+ guildSpaceID = await createSpace.ensureSpace(guild)
+ parentSpaceID = await ensureRoom(channel.parent_id)
+ privacyLevel = select("guild_space", "privacy_level", {space_id: guildSpaceID}).pluck().get()
+ } else { // otherwise use the guild's space like usual
+ parentSpaceID = await createSpace.ensureSpace(guild)
+ guildSpaceID = parentSpaceID
+ privacyLevel = select("guild_space", "privacy_level", {space_id: parentSpaceID}).pluck().get()
+ }
+ assert(typeof parentSpaceID === "string")
+ assert(typeof guildSpaceID === "string")
assert(typeof privacyLevel === "number")
const row = select("channel_room", ["nick", "custom_avatar"], {channel_id: channel.id}).get()
@@ -114,7 +132,7 @@ async function channelToKState(channel, guild) {
join_rule: "restricted",
allow: [{
type: "m.room_membership",
- room_id: spaceID
+ room_id: guildSpaceID
}]
}
if (PRIVACY_ENUMS.ROOM_JOIN_RULES[privacyLevel] !== "restricted") {
@@ -130,7 +148,7 @@ async function channelToKState(channel, guild) {
"m.room.avatar/": avatarEventContent,
"m.room.guest_access/": {guest_access: PRIVACY_ENUMS.GUEST_ACCESS[privacyLevel]},
"m.room.history_visibility/": {history_visibility},
- [`m.space.parent/${spaceID}`]: {
+ [`m.space.parent/${parentSpaceID}`]: {
via: [reg.ooye.server_name],
canonical: true
},
@@ -167,7 +185,7 @@ async function channelToKState(channel, guild) {
}
}
- return {spaceID, privacyLevel, channelKState}
+ return {spaceID: parentSpaceID, privacyLevel, channelKState}
}
/**
@@ -183,6 +201,9 @@ async function createRoom(channel, guild, spaceID, kstate, privacyLevel) {
let threadParent = null
if (channel.type === DiscordTypes.ChannelType.PublicThread) threadParent = channel.parent_id
+ let spaceCreationContent = {}
+ if (channel.type === DiscordTypes.ChannelType.GuildForum) spaceCreationContent = {creation_content: {type: "m.space"}}
+
// Name and topic can be done earlier in room creation rather than in initial_state
// https://spec.matrix.org/latest/client-server-api/#creation
const name = kstate["m.room.name/"].name
@@ -199,7 +220,8 @@ async function createRoom(channel, guild, spaceID, kstate, privacyLevel) {
preset: PRIVACY_ENUMS.PRESET[privacyLevel], // This is closest to what we want, but properties from kstate override it anyway
visibility: PRIVACY_ENUMS.VISIBILITY[privacyLevel],
invite: [],
- initial_state: ks.kstateToState(kstate)
+ initial_state: ks.kstateToState(kstate),
+ ...spaceCreationContent
})
db.prepare("INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent) VALUES (?, ?, ?, NULL, ?)").run(channel.id, roomID, channel.name, threadParent)
From b6b65992f70622bda27de7d1984f3d0ee0a5f8c5 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 14 May 2024 23:07:54 +1200
Subject: [PATCH 025/346] Forward redaction errors to error handler
---
m2d/actions/redact.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/m2d/actions/redact.js b/m2d/actions/redact.js
index 26a7142..7569df4 100644
--- a/m2d/actions/redact.js
+++ b/m2d/actions/redact.js
@@ -16,7 +16,7 @@ async function deleteMessage(event) {
db.prepare("DELETE FROM event_message WHERE event_id = ?").run(event.event_id)
for (const row of rows) {
db.prepare("DELETE FROM message_channel WHERE message_id = ?").run(row.message_id)
- discord.snow.channel.deleteMessage(row.channel_id, row.message_id, event.content.reason)
+ await discord.snow.channel.deleteMessage(row.channel_id, row.message_id, event.content.reason)
}
}
From 1f5865b0d8a14ba56b07cc1d4f94c5e57ed058c4 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 14 May 2024 23:09:51 +1200
Subject: [PATCH 026/346] Avoid sending ephemeral messages from Discord
---
d2m/event-dispatcher.js | 4 ++++
discord/utils.js | 9 +++++++++
2 files changed, 13 insertions(+)
diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js
index 54d858a..ec04750 100644
--- a/d2m/event-dispatcher.js
+++ b/d2m/event-dispatcher.js
@@ -244,6 +244,8 @@ module.exports = {
if (row) return // The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
}
+ if (dUtils.isEphemeralMessage(message)) return // Ephemeral messages are for the eyes of the receiver only!
+
const {affected, row} = await speedbump.maybeDoSpeedbump(message.channel_id, message.id)
if (affected) return
@@ -262,6 +264,8 @@ module.exports = {
if (row) return // The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
}
+ if (dUtils.isEphemeralMessage(data)) return // Ephemeral messages are for the eyes of the receiver only!
+
// Edits need to go through the speedbump as well. If the message is delayed but the edit isn't, we don't have anything to edit from.
const {affected, row} = await speedbump.maybeDoSpeedbump(data.channel_id, data.id)
if (affected) return
diff --git a/discord/utils.js b/discord/utils.js
index 2726a1a..c7045ec 100644
--- a/discord/utils.js
+++ b/discord/utils.js
@@ -101,6 +101,14 @@ function isWebhookMessage(message) {
return message.webhook_id && !isInteractionResponse
}
+/**
+ * Ephemeral messages can be generated if a slash command is attached to the same bot that OOYE is running on
+ * @param {DiscordTypes.APIMessage} message
+ */
+function isEphemeralMessage(message) {
+ return message.flags & (1 << 6);
+}
+
/** @param {string} snowflake */
function snowflakeToTimestampExact(snowflake) {
return Number(BigInt(snowflake) >> 22n) + EPOCH
@@ -116,5 +124,6 @@ module.exports.hasPermission = hasPermission
module.exports.hasSomePermissions = hasSomePermissions
module.exports.hasAllPermissions = hasAllPermissions
module.exports.isWebhookMessage = isWebhookMessage
+module.exports.isEphemeralMessage = isEphemeralMessage
module.exports.snowflakeToTimestampExact = snowflakeToTimestampExact
module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact
From 07a133eba96871cb93acdb3f133859190e751ec0 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sat, 25 May 2024 22:46:28 +1200
Subject: [PATCH 027/346] Fix "...\nhttps://..." corrupting the link
---
m2d/converters/event-to-message.js | 11 +++++-----
m2d/converters/event-to-message.test.js | 28 +++++++++++++++++++++++++
2 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index f9403f9..c22e1a8 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -54,16 +54,17 @@ const turndownService = new TurndownService({
*/
// @ts-ignore bad type from turndown
turndownService.escape = function (string) {
- const escapedWords = string.split(" ").map(word => {
- if (word.match(/^https?:\/\//)) {
- return word
+ return string.replace(/\s+|\S+/g, part => { // match chunks of spaces or non-spaces
+ if (part.match(/\s/)) return part // don't process spaces
+
+ if (part.match(/^https?:\/\//)) {
+ return part
} else {
return markdownEscapes.reduce(function (accumulator, escape) {
return accumulator.replace(escape[0], escape[1])
- }, word)
+ }, part)
}
})
- return escapedWords.join(" ")
}
turndownService.remove("mx-reply")
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 9035ddb..db44393 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -205,6 +205,34 @@ test("event2message: links in plaintext body are not broken", async t => {
)
})
+test("event2message: links in plaintext body are not broken when preceded by a newline", async t => {
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "java redstoners will be like \"I hate bedrock edition redstone!!\" meanwhile java edition:\nhttps://youtu.be/g_ORb7bN3CM"
+ },
+ event_id: "$b1c5gJZfh1gq3zz6UkhI1whJ61JVvgvvzbdSPEYnTbY",
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe"
+ }),
+ {
+ ensureJoined: [],
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "java redstoners will be like \"I hate bedrock edition redstone!!\" meanwhile java edition:\nhttps://youtu.be/g_ORb7bN3CM",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }]
+ }
+ )
+})
+
test("event2message: links in formatted body where the text & href are the same, just post the link once", async t => {
t.deepEqual(
await eventToMessage({
From 24a3b9b0f49d5f252ee81104fb884512ebaca42e Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 6 Jun 2024 12:12:48 +1200
Subject: [PATCH 028/346] Refactor kstate resource uploading
---
d2m/actions/create-room.js | 6 +--
d2m/actions/create-space.js | 18 +++----
d2m/actions/create-space.test.js | 39 ++++++++++++++++
m2d/converters/event-to-message.test.js | 62 ++++++++++++++++++++++++-
matrix/kstate.js | 34 +++++++++++++-
matrix/kstate.test.js | 51 ++++++++++++++++++--
test/test.js | 4 ++
7 files changed, 196 insertions(+), 18 deletions(-)
create mode 100644 d2m/actions/create-space.test.js
diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js
index 4559ffa..051e889 100644
--- a/d2m/actions/create-room.js
+++ b/d2m/actions/create-room.js
@@ -51,8 +51,8 @@ async function roomToKState(roomID) {
* @param {string} roomID
* @param {any} kstate
*/
-function applyKStateDiffToRoom(roomID, kstate) {
- const events = ks.kstateToState(kstate)
+async function applyKStateDiffToRoom(roomID, kstate) {
+ const events = await ks.kstateToState(kstate)
return Promise.all(events.map(({type, state_key, content}) =>
api.sendState(roomID, type, state_key, content)
))
@@ -220,7 +220,7 @@ async function createRoom(channel, guild, spaceID, kstate, privacyLevel) {
preset: PRIVACY_ENUMS.PRESET[privacyLevel], // This is closest to what we want, but properties from kstate override it anyway
visibility: PRIVACY_ENUMS.VISIBILITY[privacyLevel],
invite: [],
- initial_state: ks.kstateToState(kstate),
+ initial_state: await ks.kstateToState(kstate),
...spaceCreationContent
})
diff --git a/d2m/actions/create-space.js b/d2m/actions/create-space.js
index 3bad2a1..dbefd6d 100644
--- a/d2m/actions/create-space.js
+++ b/d2m/actions/create-space.js
@@ -45,7 +45,7 @@ async function createSpace(guild, kstate) {
creation_content: {
type: "m.space"
},
- initial_state: ks.kstateToState(kstate)
+ initial_state: await ks.kstateToState(kstate)
})
})
db.prepare("INSERT INTO guild_space (guild_id, space_id) VALUES (?, ?)").run(guild.id, roomID)
@@ -57,15 +57,14 @@ async function createSpace(guild, kstate) {
* @param {number} privacyLevel
*/
async function guildToKState(guild, privacyLevel) {
- const avatarEventContent = {}
- if (guild.icon) {
- avatarEventContent.discord_path = file.guildIcon(guild)
- avatarEventContent.url = await file.uploadDiscordFileToMxc(avatarEventContent.discord_path) // TODO: somehow represent future values in kstate (callbacks?), while still allowing for diffing, so test cases don't need to touch the media API
- }
-
+ assert.equal(typeof privacyLevel, "number")
const guildKState = {
"m.room.name/": {name: guild.name},
- "m.room.avatar/": avatarEventContent,
+ "m.room.avatar/": {
+ $if: guild.icon,
+ discord_path: file.guildIcon(guild),
+ url: {$url: file.guildIcon(guild)}
+ },
"m.room.guest_access/": {guest_access: createRoom.PRIVACY_ENUMS.GUEST_ACCESS[privacyLevel]},
"m.room.history_visibility/": {history_visibility: createRoom.PRIVACY_ENUMS.SPACE_HISTORY_VISIBILITY[privacyLevel]},
"m.room.join_rules/": {join_rule: createRoom.PRIVACY_ENUMS.SPACE_JOIN_RULES[privacyLevel]},
@@ -123,7 +122,8 @@ async function _syncSpace(guild, shouldActuallySync) {
// don't try to update rooms with custom avatars though
const roomsWithCustomAvatars = select("channel_room", "room_id", {}, "WHERE custom_avatar IS NOT NULL").pluck().all()
- const childRooms = ks.kstateToState(spaceKState).filter(({type, state_key, content}) => {
+ const state = await ks.kstateToState(spaceKState)
+ const childRooms = state.filter(({type, state_key, content}) => {
return type === "m.space.child" && "via" in content && !roomsWithCustomAvatars.includes(state_key)
}).map(({state_key}) => state_key)
diff --git a/d2m/actions/create-space.test.js b/d2m/actions/create-space.test.js
new file mode 100644
index 0000000..368bb32
--- /dev/null
+++ b/d2m/actions/create-space.test.js
@@ -0,0 +1,39 @@
+// @ts-check
+
+const mixin = require("mixin-deep")
+const {guildToKState, ensureSpace} = require("./create-space")
+const {kstateStripConditionals, kstateUploadMxc} = require("../../matrix/kstate")
+const {test} = require("supertape")
+const testData = require("../../test/data")
+
+const passthrough = require("../../passthrough")
+const {db} = passthrough
+
+test("guild2space: can generate kstate for a guild, passing privacy level 0", async t => {
+ t.deepEqual(
+ await kstateUploadMxc(kstateStripConditionals(await guildToKState(testData.guild.general, 0))),
+ {
+ "m.room.avatar/": {
+ discord_path: "/icons/112760669178241024/a_f83622e09ead74f0c5c527fe241f8f8c.png?size=1024",
+ url: "mxc://cadence.moe/zKXGZhmImMHuGQZWJEFKJbsF"
+ },
+ "m.room.guest_access/": {
+ guest_access: "can_join"
+ },
+ "m.room.history_visibility/": {
+ history_visibility: "invited"
+ },
+ "m.room.join_rules/": {
+ join_rule: "invite"
+ },
+ "m.room.name/": {
+ name: "Psychonauts 3"
+ },
+ "m.room.power_levels/": {
+ users: {
+ "@test_auto_invite:example.org": 100
+ },
+ },
+ }
+ )
+})
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index db44393..6d750a5 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -584,7 +584,7 @@ test("event2message: code blocks work", async t => {
msgtype: "m.text",
body: "wrong body",
format: "org.matrix.custom.html",
- formatted_body: "preceding
\ncode block\n
\nfollowing code
is inline
\n"
+ formatted_body: "preceding
\ncode block\n
\nfollowing code
is inline
"
},
event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU",
origin_server_ts: 1688301929913,
@@ -641,6 +641,66 @@ test("event2message: code block contents are formatted correctly and not escaped
)
})
+test("event2message: code blocks use double backtick as delimiter when necessary", async t => {
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "wrong body",
+ format: "org.matrix.custom.html",
+ formatted_body: "backtick in ` the middle
, backtick at the edge`
"
+ },
+ event_id: "$pGkWQuGVmrPNByrFELxhzI6MCBgJecr5I2J3z88Gc2s",
+ room_id: "!BpMdOUkWWhFxmTrENV:cadence.moe"
+ }),
+ {
+ ensureJoined: [],
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "``backtick in ` the middle``, `` backtick at the edge` ``",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }]
+ }
+ )
+})
+
+test("event2message: inline code is converted to code block if it contains both delimiters", async t => {
+ t.deepEqual(
+ await eventToMessage({
+ type: "m.room.message",
+ sender: "@cadence:cadence.moe",
+ content: {
+ msgtype: "m.text",
+ body: "wrong body",
+ format: "org.matrix.custom.html",
+ formatted_body: "` one two ``
"
+ },
+ event_id: "$pGkWQuGVmrPNByrFELxhzI6MCBgJecr5I2J3z88Gc2s",
+ room_id: "!BpMdOUkWWhFxmTrENV:cadence.moe"
+ }),
+ {
+ ensureJoined: [],
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "``` ` one two `` ```",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }]
+ }
+ )
+})
+
test("event2message: code blocks are uploaded as attachments instead if they contain incompatible backticks", async t => {
t.deepEqual(
await eventToMessage({
diff --git a/matrix/kstate.js b/matrix/kstate.js
index 3c4189d..eca9522 100644
--- a/matrix/kstate.js
+++ b/matrix/kstate.js
@@ -4,7 +4,12 @@ const assert = require("assert").strict
const mixin = require("mixin-deep")
const {isDeepStrictEqual} = require("util")
-/** Mutates the input. */
+const passthrough = require("../passthrough")
+const {sync} = passthrough
+/** @type {import("./file")} */
+const file = sync.require("./file")
+
+/** Mutates the input. Not recursive - can only include or exclude entire state events. */
function kstateStripConditionals(kstate) {
for (const [k, content] of Object.entries(kstate)) {
// conditional for whether a key is even part of the kstate (doing this declaratively on json is hard, so represent it as a property instead.)
@@ -16,9 +21,33 @@ function kstateStripConditionals(kstate) {
return kstate
}
-function kstateToState(kstate) {
+/** Mutates the input. Works recursively through object tree. */
+async function kstateUploadMxc(obj) {
+ const promises = []
+ function inner(obj) {
+ for (const [k, v] of Object.entries(obj)) {
+ if (v == null || typeof v !== "object") continue
+
+ if (v.$url) {
+ promises.push(
+ file.uploadDiscordFileToMxc(v.$url)
+ .then(mxc => obj[k] = mxc)
+ )
+ }
+
+ inner(v)
+ }
+ }
+ inner(obj)
+ await Promise.all(promises)
+ return obj
+}
+
+/** Automatically strips conditionals and uploads URLs to mxc. */
+async function kstateToState(kstate) {
const events = []
kstateStripConditionals(kstate)
+ await kstateUploadMxc(kstate)
for (const [k, content] of Object.entries(kstate)) {
const slashIndex = k.indexOf("/")
assert(slashIndex > 0)
@@ -74,6 +103,7 @@ function diffKState(actual, target) {
}
module.exports.kstateStripConditionals = kstateStripConditionals
+module.exports.kstateUploadMxc = kstateUploadMxc
module.exports.kstateToState = kstateToState
module.exports.stateToKState = stateToKState
module.exports.diffKState = diffKState
diff --git a/matrix/kstate.test.js b/matrix/kstate.test.js
index 239de75..0538450 100644
--- a/matrix/kstate.test.js
+++ b/matrix/kstate.test.js
@@ -1,5 +1,5 @@
const assert = require("assert")
-const {kstateToState, stateToKState, diffKState, kstateStripConditionals} = require("./kstate")
+const {kstateToState, stateToKState, diffKState, kstateStripConditionals, kstateUploadMxc} = require("./kstate")
const {test} = require("supertape")
test("kstate strip: strips false conditions", t => {
@@ -21,8 +21,53 @@ test("kstate strip: keeps true conditions while removing $if", t => {
})
})
-test("kstate2state: general", t => {
- t.deepEqual(kstateToState({
+test("kstateUploadMxc: sets the mxc", async t => {
+ const input = {
+ "m.room.avatar/": {
+ url: {$url: "https://cdn.discordapp.com/guilds/112760669178241024/users/134826546694193153/avatars/38dd359aa12bcd52dd3164126c587f8c.png?size=1024"},
+ test1: {
+ test2: {
+ test3: {$url: "https://cdn.discordapp.com/attachments/176333891320283136/1157854643037163610/Screenshot_20231001_034036.jpg"}
+ }
+ }
+ }
+ }
+ await kstateUploadMxc(input)
+ t.deepEqual(input, {
+ "m.room.avatar/": {
+ url: "mxc://cadence.moe/rfemHmAtcprjLEiPiEuzPhpl",
+ test1: {
+ test2: {
+ test3: "mxc://cadence.moe/zAXdQriaJuLZohDDmacwWWDR"
+ }
+ }
+ }
+ })
+})
+
+test("kstateUploadMxc and strip: work together", async t => {
+ const input = {
+ "m.room.avatar/yes": {
+ $if: true,
+ url: {$url: "https://cdn.discordapp.com/guilds/112760669178241024/users/134826546694193153/avatars/38dd359aa12bcd52dd3164126c587f8c.png?size=1024"}
+ },
+ "m.room.avatar/no": {
+ $if: false,
+ url: {$url: "https://cdn.discordapp.com/avatars/320067006521147393/5fc4ad85c1ea876709e9a7d3374a78a1.png?size=1024"}
+ },
+ }
+ kstateStripConditionals(input)
+ await kstateUploadMxc(input)
+ t.deepEqual(input, {
+ "m.room.avatar/yes": {
+ url: "mxc://cadence.moe/rfemHmAtcprjLEiPiEuzPhpl"
+ }
+ })
+})
+
+
+test("kstate2state: general", async t => {
+ t.deepEqual(await kstateToState({
"m.room.name/": {name: "test name"},
"m.room.member/@cadence:cadence.moe": {membership: "join"},
"uk.half-shot.bridge/org.matrix.appservice-irc://irc/epicord.net/#general": {creator: "@cadence:cadence.moe"}
diff --git a/test/test.js b/test/test.js
index 58459f6..396dea9 100644
--- a/test/test.js
+++ b/test/test.js
@@ -21,6 +21,9 @@ const reg = require("../matrix/read-registration")
reg.ooye.server_origin = "https://matrix.cadence.moe" // so that tests will pass even when hard-coded
reg.ooye.server_name = "cadence.moe"
reg.ooye.invite = ["@test_auto_invite:example.org"]
+reg.id = "baby" // don't actually take authenticated actions on the server
+reg.as_token = "baby"
+reg.hs_token = "baby"
const sync = new HeatSync({watchFS: false})
@@ -117,6 +120,7 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not
require("../matrix/read-registration.test")
require("../matrix/txnid.test")
require("../d2m/actions/create-room.test")
+ require("../d2m/actions/create-space.test")
require("../d2m/actions/register-user.test")
require("../d2m/converters/edit-to-changes.test")
require("../d2m/converters/emoji-to-key.test")
From c9aa5b4c64ac9f47dc75059950aee67e8244b575 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 11 Jun 2024 10:21:09 +1200
Subject: [PATCH 029/346] Update heatsync
This fixes an issue where matrix spaces would be initially created
without a default privacy level.
---
package-lock.json | 88 +++++++++++------------------------------------
package.json | 2 +-
2 files changed, 21 insertions(+), 69 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 49c9dc3..5132540 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"entities": "^4.5.0",
"get-stream": "^6.0.1",
"giframe": "github:cloudrac3r/giframe#v0.4.2",
- "heatsync": "^2.4.1",
+ "heatsync": "^2.5.3",
"html-template-tag": "github:cloudrac3r/html-template-tag#v5.0",
"js-yaml": "^4.1.0",
"matrix-appservice": "^2.0.0",
@@ -155,14 +155,6 @@
"node": ">=8"
}
},
- "node_modules/@fastify/busboy": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
- "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -573,9 +565,9 @@
"integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw=="
},
"node_modules/backtracker": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/backtracker/-/backtracker-3.3.2.tgz",
- "integrity": "sha512-bXosLBp95xGE1kcWRnbG+e+Sw1xCKTT1GMdvaqEk9cGfBQoFPEvdI78fepKIJWFejV4NCl7OLUt8SNvYom/D/w=="
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/backtracker/-/backtracker-4.0.0.tgz",
+ "integrity": "sha512-XG2ldN+WDRq9niJMnoZDjLLUnhDOQGhFZc6qZQotN59xj8oOa4KXSCu6YyZQawPqi6gG3HilGFt91zT6Hbdh1w=="
},
"node_modules/balanced-match": {
"version": "1.0.2",
@@ -984,9 +976,9 @@
"dev": true
},
"node_modules/cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"engines": {
"node": ">= 0.6"
}
@@ -1258,16 +1250,16 @@
}
},
"node_modules/express": {
- "version": "4.18.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
- "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
+ "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.1",
+ "body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.5.0",
+ "cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@@ -1298,43 +1290,6 @@
"node": ">= 0.10.0"
}
},
- "node_modules/express/node_modules/body-parser": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
- "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
- "dependencies": {
- "bytes": "3.1.2",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.11.0",
- "raw-body": "2.5.1",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/express/node_modules/raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
- "dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
@@ -1647,11 +1602,11 @@
}
},
"node_modules/heatsync": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.4.2.tgz",
- "integrity": "sha512-s+YzwGpCjsJLRCuz6Ur8JFKz7vXEMFAPLqDbaEvMR5Um/IPPJpmupBH7LKeiyfGkIScFz9iyBPa1TifcoU4D7A==",
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.5.3.tgz",
+ "integrity": "sha512-NvR6wZZquJqDO/Tl1JGMGdNph0TTfhgWdj3sMWOkdQa9rs4fspHV+kGiZEgZQ0j8AQiYUEPQgRI7vdNZCKH+uw==",
"dependencies": {
- "backtracker": "3.3.2"
+ "backtracker": "^4.0.0"
}
},
"node_modules/html-es6cape": {
@@ -3329,14 +3284,11 @@
}
},
"node_modules/undici": {
- "version": "6.6.2",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.6.2.tgz",
- "integrity": "sha512-vSqvUE5skSxQJ5sztTZ/CdeJb1Wq0Hf44hlYMciqHghvz+K88U0l7D6u1VsndoFgskDcnU+nG3gYmMzJVzd9Qg==",
- "dependencies": {
- "@fastify/busboy": "^2.0.0"
- },
+ "version": "6.18.2",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.2.tgz",
+ "integrity": "sha512-o/MQLTwRm9IVhOqhZ0NQ9oXax1ygPjw6Vs+Vq/4QRjbOAC3B1GCHy7TYxxbExKlb7bzDRzt9vBWU6BDz0RFfYg==",
"engines": {
- "node": ">=18.0"
+ "node": ">=18.17"
}
},
"node_modules/unpipe": {
diff --git a/package.json b/package.json
index be55cf4..5d6192c 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"entities": "^4.5.0",
"get-stream": "^6.0.1",
"giframe": "github:cloudrac3r/giframe#v0.4.2",
- "heatsync": "^2.4.1",
+ "heatsync": "^2.5.3",
"html-template-tag": "github:cloudrac3r/html-template-tag#v5.0",
"js-yaml": "^4.1.0",
"matrix-appservice": "^2.0.0",
From 49598c7af7ac491daf8e8b63ccfac8eec35c8566 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 20 Jun 2024 13:50:38 +1200
Subject: [PATCH 030/346] Fix bulk message deletes
I have finally e2e tested this function
---
d2m/actions/delete-message.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/d2m/actions/delete-message.js b/d2m/actions/delete-message.js
index 440e123..bc8adfb 100644
--- a/d2m/actions/delete-message.js
+++ b/d2m/actions/delete-message.js
@@ -33,9 +33,9 @@ async function deleteMessageBulk(data) {
if (!roomID) return
const sids = JSON.stringify(data.ids)
- const eventsToRedact = from("event_message").pluck("event_id").and("WHERE message_id IN (SELECT value FROM json_each(?)").all(sids)
- db.prepare("DELETE FROM message_channel WHERE message_id IN (SELECT value FROM json_each(?)").run(sids)
- db.prepare("DELETE FROM event_message WHERE message_id IN (SELECT value FROM json_each(?)").run(sids)
+ const eventsToRedact = from("event_message").pluck("event_id").and("WHERE message_id IN (SELECT value FROM json_each(?))").all(sids)
+ db.prepare("DELETE FROM message_channel WHERE message_id IN (SELECT value FROM json_each(?))").run(sids)
+ db.prepare("DELETE FROM event_message WHERE message_id IN (SELECT value FROM json_each(?))").run(sids)
for (const eventID of eventsToRedact) {
// Awaiting will make it go slower, but since this could be a long-running operation either way, we want to leave rate limit capacity for other operations
await api.redactEvent(roomID, eventID)
From 8c506ed27009e9c8e15186a9c1af0bae49acdefc Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Mon, 15 Jul 2024 15:27:21 +1200
Subject: [PATCH 031/346] Drop admin permissions correctly
---
d2m/actions/register-user.js | 4 +++-
discord/utils.js | 4 ++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js
index 6b688d4..2ea0afc 100644
--- a/d2m/actions/register-user.js
+++ b/d2m/actions/register-user.js
@@ -197,9 +197,11 @@ async function syncUser(user, member, channel, guild, roomID) {
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
// Update power levels
const powerLevelsStateContent = await api.getStateEvent(roomID, "m.room.power_levels", "")
+ const oldPowerLevel = powerLevelsStateContent.users?.[mxid] || 0
mixin(powerLevelsStateContent, {users: {[mxid]: powerLevel}})
if (powerLevel === 0) delete powerLevelsStateContent.users[mxid] // keep the event compact
- await api.sendState(roomID, "m.room.power_levels", "", powerLevelsStateContent)
+ const sendPowerLevelAs = powerLevel < oldPowerLevel ? mxid : undefined // bridge bot won't not have permission to demote equal power users, so do this action as themselves
+ await api.sendState(roomID, "m.room.power_levels", "", powerLevelsStateContent, sendPowerLevelAs)
// Update cached hash
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
}
diff --git a/discord/utils.js b/discord/utils.js
index c7045ec..6e95d17 100644
--- a/discord/utils.js
+++ b/discord/utils.js
@@ -103,10 +103,10 @@ function isWebhookMessage(message) {
/**
* Ephemeral messages can be generated if a slash command is attached to the same bot that OOYE is running on
- * @param {DiscordTypes.APIMessage} message
+ * @param {Pick} message
*/
function isEphemeralMessage(message) {
- return message.flags & (1 << 6);
+ return message.flags && (message.flags & (1 << 6));
}
/** @param {string} snowflake */
From 9e51482b60ce988e9c96e475be28b2dcdcd9d851 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 16 Jul 2024 16:51:00 +1200
Subject: [PATCH 032/346] Recover from webhooks being deleted
---
m2d/actions/channel-webhook.js | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/m2d/actions/channel-webhook.js b/m2d/actions/channel-webhook.js
index d52f174..13c3ab1 100644
--- a/m2d/actions/channel-webhook.js
+++ b/m2d/actions/channel-webhook.js
@@ -44,8 +44,13 @@ async function ensureWebhook(channelID, forceCreate = false) {
*/
async function withWebhook(channelID, callback) {
const webhook = await ensureWebhook(channelID, false)
- return callback(webhook).catch(e => {
- // TODO: check if the error was webhook-related and if webhook.created === false, then: const webhook = ensureWebhook(channelID, true); return callback(webhook)
+ return callback(webhook).catch(async e => {
+ if (e.message === `{"message": "Unknown Webhook", "code": 10015}`) { // pathetic error handling from SnowTransfer
+ // Our webhook is gone. Maybe somebody deleted it, or removed and re-added OOYE from the guild.
+ const newWebhook = await ensureWebhook(channelID, true)
+ return callback(newWebhook) // not caught; if the error happens again just throw it instead of looping
+ }
+
throw e
})
}
From 149cee845a3f93ff7c9f92c16c97a12ed1f66f3a Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 16 Jul 2024 22:01:20 +1200
Subject: [PATCH 033/346] Retry PK API if it doesn't return a message
---
d2m/actions/register-pk-user.js | 15 +++++++++++++--
d2m/actions/send-message.js | 11 ++---------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/d2m/actions/register-pk-user.js b/d2m/actions/register-pk-user.js
index 1e223c6..2ead4ff 100644
--- a/d2m/actions/register-pk-user.js
+++ b/d2m/actions/register-pk-user.js
@@ -142,8 +142,19 @@ async function syncUser(author, pkMessage, roomID) {
}
/** @returns {Promise} */
-function fetchMessage(messageID) {
- return fetch(`https://api.pluralkit.me/v2/messages/${messageID}`).then(res => res.json())
+async function fetchMessage(messageID) {
+ // Their backend is weird. Sometimes it says "message not found" (code 20006) on the first try, so we make multiple attempts.
+ let attempts = 0
+ do {
+ var res = await fetch(`https://api.pluralkit.me/v2/messages/${messageID}`)
+ if (res.ok) return res.json()
+
+ // I think the backend needs some time to update.
+ await new Promise(resolve => setTimeout(resolve, 2000))
+ } while (++attempts < 3)
+
+ const errorMessage = await res.json()
+ throw new Error(`PK API returned an error after ${attempts} tries: ${JSON.stringify(errorMessage)}`)
}
module.exports._memberToStateContent = memberToStateContent
diff --git a/d2m/actions/send-message.js b/d2m/actions/send-message.js
index 346ac0d..6d100d4 100644
--- a/d2m/actions/send-message.js
+++ b/d2m/actions/send-message.js
@@ -39,15 +39,8 @@ async function sendMessage(message, channel, guild, row) {
} else if (row && row.speedbump_webhook_id === message.webhook_id) {
// Handle the PluralKit public instance
if (row.speedbump_id === "466378653216014359") {
- const root = await registerPkUser.fetchMessage(message.id)
- // Member is null if member was deleted. We just got this message, so member surely exists.
- if (!root.member) {
- const e = new Error("PK API did not return a member")
- message["__pk_response__"] = root
- console.error(root)
- throw e
- }
- senderMxid = await registerPkUser.syncUser(message.author, root, roomID)
+ const pkMessage = await registerPkUser.fetchMessage(message.id)
+ senderMxid = await registerPkUser.syncUser(message.author, pkMessage, roomID)
}
}
From a2f0bb79db93d89ecef07427f84cac40c2594e96 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 16 Jul 2024 23:48:03 +1200
Subject: [PATCH 034/346] Retrigger events that arrive too early
---
d2m/actions/retrigger.js | 61 +++++++++++++++++++++++++++++++
d2m/converters/edit-to-changes.js | 10 ++---
d2m/event-dispatcher.js | 36 +++++++++++-------
3 files changed, 88 insertions(+), 19 deletions(-)
create mode 100644 d2m/actions/retrigger.js
diff --git a/d2m/actions/retrigger.js b/d2m/actions/retrigger.js
new file mode 100644
index 0000000..2475daf
--- /dev/null
+++ b/d2m/actions/retrigger.js
@@ -0,0 +1,61 @@
+// @ts-check
+
+const {EventEmitter} = require("events")
+const passthrough = require("../../passthrough")
+const {select} = passthrough
+
+const DEBUG_RETRIGGER = false
+
+function debugRetrigger(message) {
+ if (DEBUG_RETRIGGER) {
+ console.log(message)
+ }
+}
+
+const emitter = new EventEmitter()
+
+/**
+ * Due to Eventual Consistency(TM) an update/delete may arrive before the original message arrives
+ * (or before the it has finished being bridged to an event).
+ * In this case, wait until the original message has finished bridging, then retrigger the passed function.
+ * @template {(...args: any) => Promise} T
+ * @param {string} messageID
+ * @param {T} fn
+ * @param {Parameters} rest
+ * @returns {boolean} false if the event was found and the function will be ignored, true if the event was not found and the function will be retriggered
+ */
+function eventNotFoundThenRetrigger(messageID, fn, ...rest) {
+ const eventID = select("event_message", "event_id", {message_id: messageID}).pluck().get()
+ if (eventID) {
+ debugRetrigger(`[retrigger] OK mid <-> eid = ${messageID} <-> ${eventID}`)
+ return false // event was found so don't retrigger
+ }
+
+ debugRetrigger(`[retrigger] WAIT mid <-> eid = ${messageID} <-> ${eventID}`)
+ emitter.addListener(messageID, () => {
+ debugRetrigger(`[retrigger] TRIGGER mid = ${messageID}`)
+ fn(...rest)
+ })
+ // if the event never arrives, don't trigger the callback, just clean up
+ setTimeout(() => {
+ if (emitter.listeners(messageID).length) {
+ debugRetrigger(`[retrigger] EXPIRE mid = ${messageID}`)
+ }
+ emitter.removeAllListeners(messageID)
+ }, 60 * 1000) // 1 minute
+ return true // event was not found, then retrigger
+}
+
+/**
+ * Triggers any pending operations that were waiting on the corresponding event ID.
+ * @param {string} messageID
+ */
+function messageFinishedBridging(messageID) {
+ if (emitter.listeners(messageID).length) {
+ debugRetrigger(`[retrigger] EMIT mid = ${messageID}`)
+ }
+ emitter.emit(messageID)
+}
+
+module.exports.eventNotFoundThenRetrigger = eventNotFoundThenRetrigger
+module.exports.messageFinishedBridging = messageFinishedBridging
diff --git a/d2m/converters/edit-to-changes.js b/d2m/converters/edit-to-changes.js
index dd8e39f..c80bb49 100644
--- a/d2m/converters/edit-to-changes.js
+++ b/d2m/converters/edit-to-changes.js
@@ -30,7 +30,8 @@ function eventCanBeEdited(ev) {
* @param {import("../../matrix/api")} api simple-as-nails dependency injection for the matrix API
*/
async function editToChanges(message, guild, api) {
- // If it is a user edit, allow deleting old messages (e.g. they might have removed text from an image). If it is the system adding a generated embed to a message, don't delete old messages since the system only sends partial data.
+ // If it is a user edit, allow deleting old messages (e.g. they might have removed text from an image).
+ // If it is the system adding a generated embed to a message, don't delete old messages since the system only sends partial data.
const isGeneratedEmbed = !("content" in message)
@@ -38,22 +39,21 @@ async function editToChanges(message, guild, api) {
const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
assert(roomID)
+ const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part", "reaction_part"], {message_id: message.id}).all()
+
/** @type {string?} Null if we don't have a sender in the room, which will happen if it's a webhook's message. The bridge bot will do the edit instead. */
let senderMxid = null
if (message.author) {
senderMxid = from("sim").join("sim_member", "mxid").where({user_id: message.author.id, room_id: roomID}).pluck("mxid").get() || null
} else {
// Should be a system generated embed. We want the embed to be sent by the same user who sent the message, so that the messages get grouped in most clients.
- const eventID = select("event_message", "event_id", {message_id: message.id}).pluck().get()
- assert(eventID) // this should have been checked earlier in a calling function
+ const eventID = oldEventRows[0].event_id // a calling function should have already checked that there is at least one message to edit
const event = await api.getEvent(roomID, eventID)
if (utils.eventSenderIsFromDiscord(event.sender)) {
senderMxid = event.sender
}
}
- const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part", "reaction_part"], {message_id: message.id}).all()
-
// Figure out what we will be replacing them with
const newFallbackContent = await messageToEvent.messageToEvent(message, guild, {includeEditFallbackStar: true}, {api})
diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js
index ec04750..7f27b77 100644
--- a/d2m/event-dispatcher.js
+++ b/d2m/event-dispatcher.js
@@ -33,6 +33,8 @@ const discordCommandHandler = sync.require("../discord/discord-command-handler")
const mxUtils = require("../m2d/converters/utils")
/** @type {import("./actions/speedbump")} */
const speedbump = sync.require("./actions/speedbump")
+/** @type {import("./actions/retrigger")} */
+const retrigger = sync.require("./actions/retrigger")
/** @type {any} */ // @ts-ignore bad types from semaphore
const Semaphore = require("@chriscdn/promise-semaphore")
@@ -252,6 +254,8 @@ module.exports = {
// @ts-ignore
await sendMessage.sendMessage(message, channel, guild, row),
await discordCommandHandler.execute(message, channel, guild)
+
+ retrigger.messageFinishedBridging(message.id)
},
/**
@@ -259,6 +263,14 @@ module.exports = {
* @param {DiscordTypes.GatewayMessageUpdateDispatchData} data
*/
async onMessageUpdate(client, data) {
+ // Based on looking at data they've sent me over the gateway, this is the best way to check for meaningful changes.
+ // If the message content is a string then it includes all interesting fields and is meaningful.
+ // Otherwise, if there are embeds, then the system generated URL preview embeds.
+ if (!(typeof data.content === "string" || "embeds" in data)) return
+
+ // Deal with Eventual Consistency(TM)
+ if (retrigger.eventNotFoundThenRetrigger(data.id, module.exports.onMessageUpdate, client, data)) return
+
if (data.webhook_id) {
const row = select("webhook", "webhook_id", {webhook_id: data.webhook_id}).pluck().get()
if (row) return // The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
@@ -270,21 +282,16 @@ module.exports = {
const {affected, row} = await speedbump.maybeDoSpeedbump(data.channel_id, data.id)
if (affected) return
- // Based on looking at data they've sent me over the gateway, this is the best way to check for meaningful changes.
- // If the message content is a string then it includes all interesting fields and is meaningful.
- // Otherwise, if there are embeds, then the system generated URL preview embeds.
- if (typeof data.content === "string" || "embeds" in data) {
- /** @type {DiscordTypes.GatewayMessageCreateDispatchData} */
- // @ts-ignore
- const message = data
+ /** @type {DiscordTypes.GatewayMessageCreateDispatchData} */
+ // @ts-ignore
+ const message = data
- const channel = client.channels.get(message.channel_id)
- if (!channel || !("guild_id" in channel) || !channel.guild_id) return // Nothing we can do in direct messages.
- const guild = client.guilds.get(channel.guild_id)
- assert(guild)
- // @ts-ignore
- await editMessage.editMessage(message, guild, row)
- }
+ const channel = client.channels.get(message.channel_id)
+ if (!channel || !("guild_id" in channel) || !channel.guild_id) return // Nothing we can do in direct messages.
+ const guild = client.guilds.get(channel.guild_id)
+ assert(guild)
+ // @ts-ignore
+ await editMessage.editMessage(message, guild, row)
},
/**
@@ -311,6 +318,7 @@ module.exports = {
*/
async onMessageDelete(client, data) {
speedbump.onMessageDelete(data.id)
+ if (retrigger.eventNotFoundThenRetrigger(data.id, module.exports.onMessageDelete, client, data)) return
await deleteMessage.deleteMessage(data)
},
From 5a65e6f6da9b81f7031f26089f8010b46ed85b36 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 17 Jul 2024 12:08:04 +1200
Subject: [PATCH 035/346] Only retrigger once, just in case
---
d2m/actions/retrigger.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/d2m/actions/retrigger.js b/d2m/actions/retrigger.js
index 2475daf..030ffbf 100644
--- a/d2m/actions/retrigger.js
+++ b/d2m/actions/retrigger.js
@@ -18,7 +18,7 @@ const emitter = new EventEmitter()
* Due to Eventual Consistency(TM) an update/delete may arrive before the original message arrives
* (or before the it has finished being bridged to an event).
* In this case, wait until the original message has finished bridging, then retrigger the passed function.
- * @template {(...args: any) => Promise} T
+ * @template {(...args: any[]) => Promise} T
* @param {string} messageID
* @param {T} fn
* @param {Parameters} rest
@@ -32,7 +32,7 @@ function eventNotFoundThenRetrigger(messageID, fn, ...rest) {
}
debugRetrigger(`[retrigger] WAIT mid <-> eid = ${messageID} <-> ${eventID}`)
- emitter.addListener(messageID, () => {
+ emitter.once(messageID, () => {
debugRetrigger(`[retrigger] TRIGGER mid = ${messageID}`)
fn(...rest)
})
From eb98af0ac3eda7405d9f7fb00e33b3a86f243a7d Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sun, 21 Jul 2024 01:30:07 +1200
Subject: [PATCH 036/346] Move packages to npm registry
---
d2m/actions/create-room.test.js | 2 +-
d2m/actions/create-space.test.js | 2 +-
d2m/actions/register-user.js | 2 +-
d2m/converters/lottie.js | 2 +-
d2m/converters/message-to-event.js | 10 +-
m2d/converters/emoji-sheet.js | 4 +-
matrix/kstate.js | 2 +-
matrix/mreq.js | 2 +-
package-lock.json | 481 ++++++++++-------------------
package.json | 14 +-
passthrough.js | 2 +-
11 files changed, 177 insertions(+), 346 deletions(-)
diff --git a/d2m/actions/create-room.test.js b/d2m/actions/create-room.test.js
index be0febb..2a76e2e 100644
--- a/d2m/actions/create-room.test.js
+++ b/d2m/actions/create-room.test.js
@@ -1,6 +1,6 @@
// @ts-check
-const mixin = require("mixin-deep")
+const mixin = require("@cloudrac3r/mixin-deep")
const {channelToKState, _convertNameAndTopic} = require("./create-room")
const {kstateStripConditionals} = require("../../matrix/kstate")
const {test} = require("supertape")
diff --git a/d2m/actions/create-space.test.js b/d2m/actions/create-space.test.js
index 368bb32..b1c1f06 100644
--- a/d2m/actions/create-space.test.js
+++ b/d2m/actions/create-space.test.js
@@ -1,6 +1,6 @@
// @ts-check
-const mixin = require("mixin-deep")
+const mixin = require("@cloudrac3r/mixin-deep")
const {guildToKState, ensureSpace} = require("./create-space")
const {kstateStripConditionals, kstateUploadMxc} = require("../../matrix/kstate")
const {test} = require("supertape")
diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js
index 2ea0afc..6bd4661 100644
--- a/d2m/actions/register-user.js
+++ b/d2m/actions/register-user.js
@@ -3,7 +3,7 @@
const assert = require("assert").strict
const reg = require("../../matrix/read-registration")
const DiscordTypes = require("discord-api-types/v10")
-const mixin = require("mixin-deep")
+const mixin = require("@cloudrac3r/mixin-deep")
const passthrough = require("../../passthrough")
const {discord, sync, db, select} = passthrough
diff --git a/d2m/converters/lottie.js b/d2m/converters/lottie.js
index 6d13f70..12a311a 100644
--- a/d2m/converters/lottie.js
+++ b/d2m/converters/lottie.js
@@ -2,7 +2,7 @@
const assert = require("assert")
const stream = require("stream")
-const {PNG} = require("pngjs")
+const {PNG} = require("@cloudrac3r/pngjs")
const SIZE = 160 // Discord's display size on 1x displays is 160
diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js
index 45e43dd..45c4032 100644
--- a/d2m/converters/message-to-event.js
+++ b/d2m/converters/message-to-event.js
@@ -1,10 +1,10 @@
// @ts-check
const assert = require("assert").strict
-const markdown = require("discord-markdown")
+const markdown = require("@cloudrac3r/discord-markdown")
const pb = require("prettier-bytes")
const DiscordTypes = require("discord-api-types/v10")
-const {tag} = require("html-template-tag")
+const {tag} = require("@cloudrac3r/html-template-tag")
const passthrough = require("../../passthrough")
const {sync, db, discord, select, from} = passthrough
@@ -396,7 +396,7 @@ async function messageToEvent(message, guild, options = {}, di) {
discordOnly: true,
escapeHTML: false,
...customOptions
- }, null, null)
+ })
return {body, html}
}
@@ -439,12 +439,12 @@ async function messageToEvent(message, guild, options = {}, di) {
else if (!repliedToContent) repliedToContent = "[Replied-to message content wasn't provided by Discord]"
const repliedToHtml = markdown.toHTML(repliedToContent, {
discordCallback: getDiscordParseCallbacks(message, guild, true)
- }, null, null)
+ })
const repliedToBody = markdown.toHTML(repliedToContent, {
discordCallback: getDiscordParseCallbacks(message, guild, false),
discordOnly: true,
escapeHTML: false,
- }, null, null)
+ })
html = `In reply to ${repliedToUserHtml}`
+ `
${repliedToHtml}
`
+ html
diff --git a/m2d/converters/emoji-sheet.js b/m2d/converters/emoji-sheet.js
index 73c7e34..4d9cc07 100644
--- a/m2d/converters/emoji-sheet.js
+++ b/m2d/converters/emoji-sheet.js
@@ -3,8 +3,8 @@
const assert = require("assert").strict
const {pipeline} = require("stream").promises
const sharp = require("sharp")
-const {GIFrame} = require("giframe")
-const {PNG} = require("pngjs")
+const {GIFrame} = require("@cloudrac3r/giframe")
+const {PNG} = require("@cloudrac3r/pngjs")
const streamMimeType = require("stream-mime-type")
const SIZE = 48
diff --git a/matrix/kstate.js b/matrix/kstate.js
index eca9522..67bb063 100644
--- a/matrix/kstate.js
+++ b/matrix/kstate.js
@@ -1,7 +1,7 @@
// @ts-check
const assert = require("assert").strict
-const mixin = require("mixin-deep")
+const mixin = require("@cloudrac3r/mixin-deep")
const {isDeepStrictEqual} = require("util")
const passthrough = require("../passthrough")
diff --git a/matrix/mreq.js b/matrix/mreq.js
index d515846..d6a21ae 100644
--- a/matrix/mreq.js
+++ b/matrix/mreq.js
@@ -1,7 +1,7 @@
// @ts-check
const fetch = require("node-fetch").default
-const mixin = require("mixin-deep")
+const mixin = require("@cloudrac3r/mixin-deep")
const stream = require("stream")
const getStream = require("get-stream")
diff --git a/package-lock.json b/package-lock.json
index 5132540..2d5284a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,21 +10,21 @@
"license": "AGPL-3.0-or-later",
"dependencies": {
"@chriscdn/promise-semaphore": "^2.0.1",
+ "@cloudrac3r/discord-markdown": "^2.6.2",
+ "@cloudrac3r/giframe": "^0.4.3",
+ "@cloudrac3r/html-template-tag": "^5.0.1",
+ "@cloudrac3r/mixin-deep": "^3.0.0",
+ "@cloudrac3r/pngjs": "^7.0.3",
"better-sqlite3": "^9.0.0",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
- "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
- "giframe": "github:cloudrac3r/giframe#v0.4.2",
"heatsync": "^2.5.3",
- "html-template-tag": "github:cloudrac3r/html-template-tag#v5.0",
"js-yaml": "^4.1.0",
"matrix-appservice": "^2.0.0",
"minimist": "^1.2.8",
- "mixin-deep": "github:cloudrac3r/mixin-deep#v3.0.0",
"node-fetch": "^2.6.7",
- "pngjs": "github:cloudrac3r/pngjs#v7.0.2",
"prettier-bytes": "^1.0.4",
"sharp": "^0.32.6",
"snowtransfer": "^0.10.5",
@@ -34,14 +34,14 @@
"xxhash-wasm": "^1.0.2"
},
"devDependencies": {
+ "@cloudrac3r/tap-dot": "^2.0.2",
"@types/node": "^18.16.0",
"@types/node-fetch": "^2.6.3",
"c8": "^8.0.1",
"colorette": "^1.4.0",
"cross-env": "^7.0.3",
"discord-api-types": "^0.37.60",
- "supertape": "^10.4.0",
- "tap-dot": "github:cloudrac3r/tap-dot#9dd7750ececeae3a96afba91905be812b6b2cc2d"
+ "supertape": "^10.4.0"
}
},
"node_modules/@bcoe/v8-coverage": {
@@ -59,7 +59,6 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@cloudcmd/stub/-/stub-4.0.1.tgz",
"integrity": "sha512-7x7tVxJZOdQowHv/VKwHLo9aoNNoVRc6PdKYqyKcDHX+xrF78jSXnqEWrOplnD/gF+tCnyFafu1Is+lFfWCILw==",
- "dev": true,
"dependencies": {
"chalk": "^4.0.0",
"jest-diff": "^27.0.6",
@@ -73,7 +72,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -82,7 +80,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -94,7 +91,6 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
"integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
- "dev": true,
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
@@ -103,7 +99,6 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
"integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==",
- "dev": true,
"dependencies": {
"chalk": "^4.0.0",
"diff-sequences": "^27.5.1",
@@ -118,7 +113,6 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz",
"integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==",
- "dev": true,
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
@@ -127,7 +121,6 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -140,14 +133,12 @@
"node_modules/@cloudcmd/stub/node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
- "dev": true
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/@cloudcmd/stub/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -155,11 +146,77 @@
"node": ">=8"
}
},
+ "node_modules/@cloudrac3r/discord-markdown": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.6.2.tgz",
+ "integrity": "sha512-nHk7HPRK6smrYP+BbEHdLEsv/utXdsylLmdqVgiB4U+PgWnILR7RlcKnKjS5P+K8guIzh+3HvTzWkF0PchO54g==",
+ "dependencies": {
+ "simple-markdown": "^0.7.3",
+ "supertape": "^10.7.2"
+ }
+ },
+ "node_modules/@cloudrac3r/giframe": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/giframe/-/giframe-0.4.3.tgz",
+ "integrity": "sha512-LKuRfdHrhvgPP0heYdlVRecswk/kYaC3fI+X+GQmnkJE36uN1E2dg5l5QdLoukliH7g8S2hgDYk0jsR7sJf8Dg=="
+ },
+ "node_modules/@cloudrac3r/html-template-tag": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/html-template-tag/-/html-template-tag-5.0.1.tgz",
+ "integrity": "sha512-aH+ZdWJf53E63bVb2FiSnpM81qtF2ZNVbrXjrHcfnofyV/GTYJjZHnmPYC2FgXxJ+I8+bZP3DiwYzj7zXYoekw==",
+ "dependencies": {
+ "html-es6cape": "^2.0.0"
+ }
+ },
+ "node_modules/@cloudrac3r/mixin-deep": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/mixin-deep/-/mixin-deep-3.0.0.tgz",
+ "integrity": "sha512-yQz1wHSZbHfbKaGSjrV3wIG0e9MnElKlmekMKJPRdTn2jhF2Mt8wfMPX8U7v6rTyzR/7BTrX8CCUcrJMLgoQqw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@cloudrac3r/pngjs": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/pngjs/-/pngjs-7.0.3.tgz",
+ "integrity": "sha512-Aghuja9XAIqBPmY2jk8dKZSyK90gImxA4hJeEYYAWkZO34bf+zliUAvGBygoBZA0EgXSmfxewVchL+9y3w+rDw==",
+ "engines": {
+ "node": ">=14.19.0"
+ }
+ },
+ "node_modules/@cloudrac3r/tap-dot": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/tap-dot/-/tap-dot-2.0.2.tgz",
+ "integrity": "sha512-q2IzqZvFIIjy8dBnuC5+baZ6KHroxOjWzaaBd+FGPk2NvPpsRdf8dFv0rTTntco8Z62grmCuMPc4/Nblx+Ot3A==",
+ "dev": true,
+ "dependencies": {
+ "@cloudrac3r/tap-out": "^3.2.3",
+ "colorette": "^1.0.5"
+ },
+ "bin": {
+ "tap-dot": "bin/dot"
+ }
+ },
+ "node_modules/@cloudrac3r/tap-out": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/tap-out/-/tap-out-3.2.3.tgz",
+ "integrity": "sha512-WS89ziuTMLZlOVTXArkok32HcpWWxejQmZAUOl6nbB2Y114M8LfSOQ7t/rmgVsYB4oc6Ehe/nzevUMt4GGbCsA==",
+ "dev": true,
+ "dependencies": {
+ "re-emitter": "1.1.4",
+ "split2": "^4.2.0"
+ },
+ "bin": {
+ "tap-in": "bin/tap-in.js"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
@@ -176,7 +233,6 @@
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -187,14 +243,12 @@
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
@@ -211,7 +265,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
@@ -237,7 +290,6 @@
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
"integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
- "dev": true,
"dependencies": {
"@sinclair/typebox": "^0.27.8"
},
@@ -274,7 +326,6 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
"optional": true,
"engines": {
"node": ">=14"
@@ -284,7 +335,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@putout/cli-keypress/-/cli-keypress-2.0.0.tgz",
"integrity": "sha512-EXJv2HaXM+5scjoxE6Tf+o4+pxwL1tYJZJBDMygrF7cocjirGcU05GgNr9WHOaUPaVOpVjVU98ugYD7XJLmMkw==",
- "dev": true,
"dependencies": {
"ci-info": "^4.0.0",
"fullstore": "^3.0.0"
@@ -294,29 +344,26 @@
}
},
"node_modules/@putout/cli-validate-args": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@putout/cli-validate-args/-/cli-validate-args-1.1.1.tgz",
- "integrity": "sha512-AczBS98YyvsDVxvvYjHGyIygFu3i/EJ0xsruU6MlytTuUiCFQIE/QQPDy1bcN5J2Y75BzSYncaYnVrEGcBjeeQ==",
- "dev": true,
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@putout/cli-validate-args/-/cli-validate-args-2.0.0.tgz",
+ "integrity": "sha512-/tl1XiBog6XMb1T9kalFerYU86sYsl6EtrlvGI5RVtlHOQdEEJAIPRxmX4vnKG3uoY5aVEkJOWzbPM5tsncmFQ==",
"dependencies": {
"fastest-levenshtein": "^1.0.12",
- "just-kebab-case": "^1.1.0"
+ "just-kebab-case": "^4.2.0"
},
"engines": {
- "node": ">=14"
+ "node": ">=18"
}
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
- "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
- "dev": true
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="
},
"node_modules/@supertape/engine-loader": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@supertape/engine-loader/-/engine-loader-2.0.0.tgz",
"integrity": "sha512-1G2MmfZnSxx546omLPAVNgvG/iqOQZGiXHnjJ2JXKvuf2lpPdDRnNm5eLl81lvEG473zE9neX979TzeFcr3Dxw==",
- "dev": true,
"dependencies": {
"try-catch": "^3.0.0"
},
@@ -328,7 +375,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@supertape/formatter-fail/-/formatter-fail-3.0.2.tgz",
"integrity": "sha512-mSBnNprfLFmGvZkP+ODGroPLFCIN5BWE/06XaD5ghiTVWqek7eH8IDqvKyEduvuQu1O5tvQiaTwQsyxvikF+2w==",
- "dev": true,
"dependencies": {
"@supertape/formatter-tap": "^3.0.3",
"fullstore": "^3.0.0"
@@ -341,7 +387,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@supertape/formatter-json-lines/-/formatter-json-lines-2.0.1.tgz",
"integrity": "sha512-9LWOCu4yOF9orf4QJseS8lP3hXkYn24qn57VqYt/3r2aRJv4vWTPfaL1ot5JRHCZs0qXrV1sqPmN6E05rRLDYA==",
- "dev": true,
"dependencies": {
"fullstore": "^3.0.0"
},
@@ -350,10 +395,9 @@
}
},
"node_modules/@supertape/formatter-progress-bar": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/@supertape/formatter-progress-bar/-/formatter-progress-bar-5.0.2.tgz",
- "integrity": "sha512-thJlWFQLVeZjK/YZktUNBU69LFaEjBNvRcg6otuXn0RHhorRrgNWHHkA7JLDHRExzc+xaGJJvrWwsslh47vN2g==",
- "dev": true,
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@supertape/formatter-progress-bar/-/formatter-progress-bar-6.1.0.tgz",
+ "integrity": "sha512-BVnLW08BMbF/Xf9DNxTtc5V5Ong4VCj0w46Ts2cc1EboX+RQGuxGO0/wrzTBTt4t30iUzFhG/t2g280MfLHutQ==",
"dependencies": {
"chalk": "^5.3.0",
"ci-info": "^4.0.0",
@@ -369,7 +413,6 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
@@ -381,7 +424,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@supertape/formatter-short/-/formatter-short-2.0.1.tgz",
"integrity": "sha512-zxFrZfCccFV+bf6A7MCEqT/Xsf0Elc3qa0P3jShfdEfrpblEcpSo0T/Wd9jFwc7uHA3ABgxgcHy7LNIpyrFTCg==",
- "dev": true,
"engines": {
"node": ">=16"
}
@@ -390,7 +432,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@supertape/formatter-tap/-/formatter-tap-3.0.3.tgz",
"integrity": "sha512-U5OuMotfYhGo9cZ8IgdAXRTH5Yy8yfLDZzYo1upTPTwlJJquKwtvuz7ptiB7BN3OFr5YakkDYlFxOYPcLo7urg==",
- "dev": true,
"engines": {
"node": ">=16"
}
@@ -399,7 +440,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@supertape/formatter-time/-/formatter-time-1.0.2.tgz",
"integrity": "sha512-QihQWA/3LSNuODHrL8MGNHkdRunaEqNQkuMUDGNgEQO8MYBB0d83WGlNxDFGjn4kRlq47hovw3Skq7Btb2i2JA==",
- "dev": true,
"dependencies": {
"chalk": "^5.3.0",
"ci-info": "^4.0.0",
@@ -416,7 +456,6 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
@@ -428,7 +467,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@supertape/operator-stub/-/operator-stub-3.1.0.tgz",
"integrity": "sha512-jzC56u1k+3DLRo854+J6v/DP/4SjRV2mAqfR6qzsyaAocC9OFe7NHYQQMmlJ4cUJwgFjUh7AVnjFfC0Z0XuH+g==",
- "dev": true,
"dependencies": {
"@cloudcmd/stub": "^4.0.0"
},
@@ -483,18 +521,6 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
},
- "node_modules/abort-controller": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
- "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
- "dev": true,
- "dependencies": {
- "event-target-shim": "^5.0.0"
- },
- "engines": {
- "node": ">=6.5"
- }
- },
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -511,7 +537,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -523,7 +548,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -548,7 +572,6 @@
"version": "1.0.55",
"resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz",
"integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==",
- "dev": true,
"dependencies": {
"printable-characters": "^1.0.42"
}
@@ -572,8 +595,7 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64-js": {
"version": "1.5.1",
@@ -701,35 +723,10 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
- "node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -786,7 +783,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -819,7 +815,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz",
"integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -834,7 +829,6 @@
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz",
"integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==",
- "dev": true,
"dependencies": {
"string-width": "^4.2.3"
},
@@ -1010,7 +1004,6 @@
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -1028,8 +1021,7 @@
"node_modules/data-uri-to-buffer": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
- "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==",
- "dev": true
+ "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="
},
"node_modules/debug": {
"version": "2.6.9",
@@ -1115,7 +1107,6 @@
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
"integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
- "dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
@@ -1125,14 +1116,6 @@
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.70.tgz",
"integrity": "sha512-8EtfZR0KwOK+yP5q/llWILdUAPmGmF1LmcVUYf7+gtGigz2pu6WR38ZN+IWtMzohY1Ujl2u3KOdbFvrEz9EC8w=="
},
- "node_modules/discord-markdown": {
- "version": "2.6.1",
- "resolved": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
- "license": "MIT",
- "dependencies": {
- "simple-markdown": "^0.7.2"
- }
- },
"node_modules/domino": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
@@ -1141,8 +1124,7 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/ee-first": {
"version": "1.1.1",
@@ -1152,8 +1134,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
@@ -1223,24 +1204,6 @@
"node": ">= 0.6"
}
},
- "node_modules/event-target-shim": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
- "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "dev": true,
- "engines": {
- "node": ">=0.8.x"
- }
- },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -1299,7 +1262,6 @@
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
"integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
- "dev": true,
"engines": {
"node": ">= 4.9.1"
}
@@ -1358,6 +1320,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="
+ },
"node_modules/foreground-child": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
@@ -1416,7 +1383,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/fullstore/-/fullstore-3.0.0.tgz",
"integrity": "sha512-EEIdG+HWpyygWRwSLIZy+x4u0xtghjHNfhQb0mI5825Mmjq6oFESFUY0hoZigEgd3KH8GX+ZOCK9wgmOiS7VBQ==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -1460,7 +1426,6 @@
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz",
"integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==",
- "dev": true,
"dependencies": {
"data-uri-to-buffer": "^2.0.0",
"source-map": "^0.6.1"
@@ -1477,43 +1442,37 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/giframe": {
- "version": "0.4.2",
- "resolved": "git+ssh://git@github.com/cloudrac3r/giframe.git#39b9d9af4184ea9df72c0ccd4db96da51bd1082c",
- "license": "MIT"
- },
"node_modules/github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
},
"node_modules/glob": {
- "version": "10.3.10",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
- "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
- "dev": true,
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
+ "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"dependencies": {
"foreground-child": "^3.1.0",
- "jackspeak": "^2.3.5",
- "minimatch": "^9.0.1",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
- "path-scurry": "^1.10.1"
+ "jackspeak": "^4.0.1",
+ "minimatch": "^10.0.0",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob/node_modules/foreground-child": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
- "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
- "dev": true,
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
+ "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
@@ -1529,7 +1488,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
"engines": {
"node": ">=14"
},
@@ -1552,7 +1510,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -1620,14 +1577,6 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
- "node_modules/html-template-tag": {
- "version": "5.0.0",
- "resolved": "git+ssh://git@github.com/cloudrac3r/html-template-tag.git#9b2ec9efd344119997495c7889c11527cc6a35ed",
- "license": "MIT",
- "dependencies": {
- "html-es6cape": "^2.0.0"
- }
- },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -1710,7 +1659,6 @@
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
- "dev": true,
"dependencies": {
"hasown": "^2.0.0"
},
@@ -1722,7 +1670,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -1730,8 +1677,7 @@
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/istanbul-lib-coverage": {
"version": "3.2.0",
@@ -1770,15 +1716,14 @@
}
},
"node_modules/jackspeak": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
- "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
- "dev": true,
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz",
+ "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
- "node": ">=14"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -1791,7 +1736,6 @@
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
"integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
- "dev": true,
"dependencies": {
"chalk": "^4.0.0",
"diff-sequences": "^29.6.3",
@@ -1806,7 +1750,6 @@
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
"integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
- "dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
@@ -1823,10 +1766,9 @@
}
},
"node_modules/just-kebab-case": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/just-kebab-case/-/just-kebab-case-1.1.0.tgz",
- "integrity": "sha512-QkuwuBMQ9BQHMUEkAtIA4INLrkmnnveqlFB1oFi09gbU0wBdZo6tTnyxNWMR84zHxBuwK7GLAwqN8nrvVxOLTA==",
- "dev": true
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/just-kebab-case/-/just-kebab-case-4.2.0.tgz",
+ "integrity": "sha512-p2BdO7o4BI+pMun3J+dhaOfYan5JsZrw9wjshRjkWY9+p+u+kKSMhNWYnot2yHDR9CSahZ9iT3dcqJ+V72qHMw=="
},
"node_modules/locate-path": {
"version": "6.0.0",
@@ -1946,15 +1888,14 @@
}
},
"node_modules/minimatch": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
- "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
- "dev": true,
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+ "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -1969,22 +1910,13 @@
}
},
"node_modules/minipass": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
- "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
- "dev": true,
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
- "node_modules/mixin-deep": {
- "version": "3.0.0",
- "resolved": "git+ssh://git@github.com/cloudrac3r/mixin-deep.git#2dd70d6b8644263f7ed2c1620506c9eb3f11d32a",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
@@ -2134,6 +2066,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
+ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw=="
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -2164,7 +2101,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2172,32 +2108,29 @@
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-scurry": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
- "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
- "dev": true,
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+ "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"dependencies": {
- "lru-cache": "^9.1.1 || ^10.0.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
- "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
- "dev": true,
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz",
+ "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==",
"engines": {
- "node": "14 || >=16.14"
+ "node": "20 || >=22"
}
},
"node_modules/path-to-regexp": {
@@ -2217,14 +2150,6 @@
"url": "https://github.com/sponsors/Borewit"
}
},
- "node_modules/pngjs": {
- "version": "7.0.2",
- "resolved": "git+ssh://git@github.com/cloudrac3r/pngjs.git#0295be509ed56dcf2f1d11b3af0b3108ad699dfe",
- "license": "MIT",
- "engines": {
- "node": ">=14.19.0"
- }
- },
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@@ -2259,7 +2184,6 @@
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
"integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
- "dev": true,
"dependencies": {
"@jest/schemas": "^29.6.3",
"ansi-styles": "^5.0.0",
@@ -2273,7 +2197,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -2284,17 +2207,7 @@
"node_modules/printable-characters": {
"version": "1.0.42",
"resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz",
- "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
- "dev": true
- },
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "dev": true,
- "engines": {
- "node": ">= 0.6.0"
- }
+ "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="
},
"node_modules/proxy-addr": {
"version": "2.0.7",
@@ -2381,24 +2294,7 @@
"node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
- "dev": true
- },
- "node_modules/readable-stream": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
- "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
- "dev": true,
- "dependencies": {
- "abort-controller": "^3.0.0",
- "buffer": "^6.0.3",
- "events": "^3.3.0",
- "process": "^0.11.10",
- "string_decoder": "^1.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/readable-web-to-node-stream": {
"version": "3.0.2",
@@ -2441,7 +2337,6 @@
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
- "dev": true,
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
@@ -2666,7 +2561,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
"dependencies": {
"shebang-regex": "^3.0.0"
},
@@ -2678,7 +2572,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2777,28 +2670,23 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/split": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
- "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"dev": true,
- "dependencies": {
- "through": "2"
- },
"engines": {
- "node": "*"
+ "node": ">= 10.x"
}
},
"node_modules/stacktracey": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz",
"integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==",
- "dev": true,
"dependencies": {
"as-table": "^1.0.36",
"get-source": "^2.0.12"
@@ -2857,7 +2745,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -2872,7 +2759,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -2886,7 +2772,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2895,7 +2780,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -2907,7 +2791,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2916,7 +2799,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -2928,7 +2810,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
@@ -2944,7 +2825,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -2956,7 +2836,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2986,25 +2865,25 @@
}
},
"node_modules/supertape": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/supertape/-/supertape-10.4.0.tgz",
- "integrity": "sha512-mQbcPU3jyDQsbncbS2flHELhZ7qEIF9q4Swnn/0782aN+rMQBzcJR3yapVn+9k3pUoUi64IcTaGxs24WSLDCvQ==",
- "dev": true,
+ "version": "10.7.2",
+ "resolved": "https://registry.npmjs.org/supertape/-/supertape-10.7.2.tgz",
+ "integrity": "sha512-pBWvzBtefVgokjJRk2ks+6q8/Sy1fIIvMBL8nXYaXk3100cgcPsw4iYhFSW41tg/cEe4IOlV/G+FZFN4kSMtOg==",
"dependencies": {
"@cloudcmd/stub": "^4.0.0",
"@putout/cli-keypress": "^2.0.0",
- "@putout/cli-validate-args": "^1.0.1",
+ "@putout/cli-validate-args": "^2.0.0",
"@supertape/engine-loader": "^2.0.0",
"@supertape/formatter-fail": "^3.0.0",
"@supertape/formatter-json-lines": "^2.0.0",
- "@supertape/formatter-progress-bar": "^5.0.0",
+ "@supertape/formatter-progress-bar": "^6.0.0",
"@supertape/formatter-short": "^2.0.0",
"@supertape/formatter-tap": "^3.0.0",
"@supertape/formatter-time": "^1.0.0",
"@supertape/operator-stub": "^3.0.0",
"cli-progress": "^3.8.2",
+ "flatted": "^3.3.1",
"fullstore": "^3.0.0",
- "glob": "^10.3.10",
+ "glob": "^11.0.0",
"jest-diff": "^29.0.1",
"once": "^1.4.0",
"resolve": "^1.17.0",
@@ -3026,7 +2905,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -3038,7 +2916,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -3046,38 +2923,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/tap-dot": {
- "version": "2.0.0",
- "resolved": "git+ssh://git@github.com/cloudrac3r/tap-dot.git#9dd7750ececeae3a96afba91905be812b6b2cc2d",
- "integrity": "sha512-SLg6KF3cSkKII+5hA/we9FjnMCrL5uk0wYap7RXD9KJziy7xqZolvEOamt3CJlm5LSzRXIGblm3nmhY/EBE3AA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "colorette": "^1.0.5",
- "tap-out": "github:cloudrac3r/tap-out#1b4ec6084aedb9f44ccaa0c7185ff9bfd83da771"
- },
- "bin": {
- "tap-dot": "bin/dot"
- }
- },
- "node_modules/tap-out": {
- "version": "3.2.1",
- "resolved": "git+ssh://git@github.com/cloudrac3r/tap-out.git#1b4ec6084aedb9f44ccaa0c7185ff9bfd83da771",
- "integrity": "sha512-55eUSaX5AeEOqJMRlj9XSqUlLV/yYPOPeC3kOFqjmorq6/jlH5kIeqpgLNW5PlPEAuggzYREYYXqrN8E37ZPfQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "re-emitter": "1.1.4",
- "readable-stream": "^4.3.0",
- "split": "^1.0.1"
- },
- "bin": {
- "tap-in": "bin/tap-in.js"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
"node_modules/tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
@@ -3173,12 +3018,6 @@
"node": "*"
}
},
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "dev": true
- },
"node_modules/through2": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
@@ -3203,8 +3042,7 @@
"node_modules/timer-node": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/timer-node/-/timer-node-5.0.7.tgz",
- "integrity": "sha512-M1aP6ASmuVD0PSxl5fqjCAGY9WyND3DHZ8RwT5I8o7469XE53Lb5zbPai20Dhj7TProyaapfVj3TaT0P+LoSEA==",
- "dev": true
+ "integrity": "sha512-M1aP6ASmuVD0PSxl5fqjCAGY9WyND3DHZ8RwT5I8o7469XE53Lb5zbPai20Dhj7TProyaapfVj3TaT0P+LoSEA=="
},
"node_modules/toidentifier": {
"version": "1.0.1",
@@ -3239,7 +3077,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/try-catch/-/try-catch-3.0.1.tgz",
"integrity": "sha512-91yfXw1rr/P6oLpHSyHDOHm0vloVvUoo9FVdw8YwY05QjJQG9OT0LUxe2VRAzmHG+0CUOmI3nhxDUMLxDN/NEQ==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -3284,9 +3121,9 @@
}
},
"node_modules/undici": {
- "version": "6.18.2",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.2.tgz",
- "integrity": "sha512-o/MQLTwRm9IVhOqhZ0NQ9oXax1ygPjw6Vs+Vq/4QRjbOAC3B1GCHy7TYxxbExKlb7bzDRzt9vBWU6BDz0RFfYg==",
+ "version": "6.19.2",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.2.tgz",
+ "integrity": "sha512-JfjKqIauur3Q6biAtHJ564e3bWa8VvT+7cSiOJHFbX4Erv6CLGDpg8z+Fmg/1OI/47RA+GI2QZaF48SSaLvyBA==",
"engines": {
"node": ">=18.17"
}
@@ -3352,7 +3189,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
@@ -3385,7 +3221,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -3402,7 +3237,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -3411,7 +3245,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -3448,8 +3281,7 @@
"node_modules/wraptile": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/wraptile/-/wraptile-3.0.0.tgz",
- "integrity": "sha512-23LJhkIw940uTcDFyJZmNyO0z8lEINOTGCr4vR5YCG3urkdXwduRIhivBm9wKaVynLHYvxoHHYbKsDiafCLp6w==",
- "dev": true
+ "integrity": "sha512-23LJhkIw940uTcDFyJZmNyO0z8lEINOTGCr4vR5YCG3urkdXwduRIhivBm9wKaVynLHYvxoHHYbKsDiafCLp6w=="
},
"node_modules/xxhash-wasm": {
"version": "1.0.2",
@@ -3492,7 +3324,6 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
"engines": {
"node": ">=12"
}
diff --git a/package.json b/package.json
index 5d6192c..806785c 100644
--- a/package.json
+++ b/package.json
@@ -16,21 +16,21 @@
"license": "AGPL-3.0-or-later",
"dependencies": {
"@chriscdn/promise-semaphore": "^2.0.1",
+ "@cloudrac3r/discord-markdown": "^2.6.2",
+ "@cloudrac3r/giframe": "^0.4.3",
+ "@cloudrac3r/html-template-tag": "^5.0.1",
+ "@cloudrac3r/mixin-deep": "^3.0.0",
+ "@cloudrac3r/pngjs": "^7.0.3",
"better-sqlite3": "^9.0.0",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
- "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#2881b447954fcea10510f212fa4c1dbbdc0a57a3",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
- "giframe": "github:cloudrac3r/giframe#v0.4.2",
"heatsync": "^2.5.3",
- "html-template-tag": "github:cloudrac3r/html-template-tag#v5.0",
"js-yaml": "^4.1.0",
"matrix-appservice": "^2.0.0",
"minimist": "^1.2.8",
- "mixin-deep": "github:cloudrac3r/mixin-deep#v3.0.0",
"node-fetch": "^2.6.7",
- "pngjs": "github:cloudrac3r/pngjs#v7.0.2",
"prettier-bytes": "^1.0.4",
"sharp": "^0.32.6",
"snowtransfer": "^0.10.5",
@@ -40,14 +40,14 @@
"xxhash-wasm": "^1.0.2"
},
"devDependencies": {
+ "@cloudrac3r/tap-dot": "^2.0.2",
"@types/node": "^18.16.0",
"@types/node-fetch": "^2.6.3",
"c8": "^8.0.1",
"colorette": "^1.4.0",
"cross-env": "^7.0.3",
"discord-api-types": "^0.37.60",
- "supertape": "^10.4.0",
- "tap-dot": "github:cloudrac3r/tap-dot#9dd7750ececeae3a96afba91905be812b6b2cc2d"
+ "supertape": "^10.4.0"
},
"scripts": {
"addbot": "node addbot.js",
diff --git a/passthrough.js b/passthrough.js
index fd21381..ec80004 100644
--- a/passthrough.js
+++ b/passthrough.js
@@ -5,7 +5,7 @@
* @property {import("repl").REPLServer} repl
* @property {typeof import("./config")} config
* @property {import("./d2m/discord-client")} discord
- * @property {import("heatsync")} sync
+ * @property {import("heatsync").default} sync
* @property {import("better-sqlite3/lib/database")} db
* @property {import("matrix-appservice").AppService} as
* @property {import("./db/orm").from} from
From 541c5e1eb524e50c4bbe319e995a9718df4a37a7 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sun, 21 Jul 2024 14:56:58 +1200
Subject: [PATCH 037/346] Add include_user_id_in_mxid setting
---
d2m/converters/user-to-mxid.js | 5 +++++
d2m/converters/user-to-mxid.test.js | 8 ++++++++
registration.example.yaml | 1 +
types.d.ts | 1 +
4 files changed, 15 insertions(+)
diff --git a/d2m/converters/user-to-mxid.js b/d2m/converters/user-to-mxid.js
index 6b3bbbd..97b655e 100644
--- a/d2m/converters/user-to-mxid.js
+++ b/d2m/converters/user-to-mxid.js
@@ -1,6 +1,7 @@
// @ts-check
const assert = require("assert")
+const registration = require("../../matrix/read-registration")
const passthrough = require("../../passthrough")
const {select} = passthrough
@@ -24,6 +25,10 @@ function downcaseUsername(user) {
.replace(/[^a-z0-9._=/-]*/g, "")
// remove leading and trailing dashes and underscores...
.replace(/(?:^[_-]*|[_-]*$)/g, "")
+ // If requested, also make the Discord user ID part of the username
+ if (registration.ooye.include_user_id_in_mxid) {
+ downcased = user.id + "_" + downcased
+ }
// The new length must be at least 2 characters (in other words, it should have some content)
if (downcased.length < 2) {
downcased = user.id
diff --git a/d2m/converters/user-to-mxid.test.js b/d2m/converters/user-to-mxid.test.js
index b080115..4576205 100644
--- a/d2m/converters/user-to-mxid.test.js
+++ b/d2m/converters/user-to-mxid.test.js
@@ -44,3 +44,11 @@ test("user2name: uses ID when name has only disallowed characters", t => {
test("user2name: works on special user", t => {
t.equal(userToSimName(data.user.clyde_ai), "clyde_ai")
})
+
+test("user2name: includes ID if requested in config", t => {
+ const reg = require("../../matrix/read-registration")
+ reg.ooye.include_user_id_in_mxid = true
+ t.equal(userToSimName({username: "Harry Styles!", discriminator: "0001", id: "123456"}), "123456_harry_styles")
+ t.equal(userToSimName({username: "f***", discriminator: "0001", id: "123456"}), "123456_f")
+ reg.ooye.include_user_id_in_mxid = false
+})
diff --git a/registration.example.yaml b/registration.example.yaml
index dd217db..d38f5ae 100644
--- a/registration.example.yaml
+++ b/registration.example.yaml
@@ -19,6 +19,7 @@ ooye:
server_name: [the part after the colon in your matrix id, like cadence.moe]
server_origin: [the full protocol and domain of your actual matrix server's location, with no trailing slash, like https://matrix.cadence.moe]
content_length_workaround: false
+ include_user_id_in_mxid: false
invite:
# uncomment this to auto-invite the named user to newly created spaces and mark them as admin (PL 100) everywhere
# - '@cadence:cadence.moe'
diff --git a/types.d.ts b/types.d.ts
index 68430d9..6036867 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -22,6 +22,7 @@ export type AppServiceRegistrationConfig = {
server_name: string
server_origin: string
content_length_workaround: boolean
+ include_user_id_in_mxid: boolean
invite: string[]
}
old_bridge?: {
From a6251e850c75a938462c30db83efd5d31df451bb Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 30 Jul 2024 23:45:26 +1200
Subject: [PATCH 038/346] Use small text for m->d replies
---
m2d/converters/event-to-message.js | 6 +--
m2d/converters/event-to-message.test.js | 72 ++++++++++++-------------
2 files changed, 39 insertions(+), 39 deletions(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index c22e1a8..7b88adb 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -541,7 +541,7 @@ async function eventToMessage(event, guild, di) {
.replace(/]*data-mx-spoiler\b[^>]*>.*?<\/span>/g, "[spoiler]") // Good enough method of removing spoiler content. (I don't want to break out the HTML parser unless I have to.)
.replace(/<[^>]+>/g, "") // Completely strip all HTML tags and formatting.
), 50)
- replyLine = "> " + contentPreviewChunks[0]
+ replyLine = "> -# " + contentPreviewChunks[0]
if (contentPreviewChunks.length > 1) replyLine = replyLine.replace(/[,.']$/, "") + "..."
replyLine += "\n"
return
@@ -595,14 +595,14 @@ async function eventToMessage(event, guild, di) {
repliedToContent = entities.decodeHTML5Strict(repliedToContent) // Remove entities like & "
const contentPreviewChunks = chunk(repliedToContent, 50)
if (contentPreviewChunks.length) {
- contentPreview = ":\n> " + contentPreviewChunks[0]
+ contentPreview = ":\n> -# " + contentPreviewChunks[0]
if (contentPreviewChunks.length > 1) contentPreview = contentPreview.replace(/[,.']$/, "") + "..."
} else {
console.log("Unable to generate reply preview for this replied-to event because we stripped all of it:", repliedToEvent)
contentPreview = ""
}
}
- replyLine = `> ${replyLine}${contentPreview}\n`
+ replyLine = `> -# ${replyLine}${contentPreview}\n`
})()
if (event.content.format === "org.matrix.custom.html" && event.content.formatted_body) {
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 6d750a5..c054abc 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -999,8 +999,8 @@ test("event2message: rich reply to a sim user", async t => {
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
- + "\n> Slow news day."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ + "\n> -# Slow news day."
+ "\nTesting this reply, ignore",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1071,8 +1071,8 @@ test("event2message: rich reply to a rich reply to a multi-line message should c
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
- + "\n> I just checked in a fix that will probably work..."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ + "\n> -# I just checked in a fix that will probably work..."
+ "\nwill try later (tomorrow if I don't forgor)",
avatar_url: undefined,
allowed_mentions: {
@@ -1151,8 +1151,8 @@ test("event2message: rich reply to an already-edited message will quote the new
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647><@111604486476181504>:"
- + "\n> this is the new content. heya!"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647><@111604486476181504>:"
+ + "\n> -# this is the new content. heya!"
+ "\nhiiiii....",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1205,7 +1205,7 @@ test("event2message: rich reply to a missing event will quote from formatted_bod
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> But who sees the seashells she sells sitting..."
+ content: "> -# But who sees the seashells she sells sitting..."
+ "\nWhat a tongue-bender...",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1356,8 +1356,8 @@ test("event2message: should avoid using blockquote contents as reply preview in
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
- + "\n> that can't be true! there's no way :o"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ + "\n> -# that can't be true! there's no way :o"
+ "\nI agree!",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1445,8 +1445,8 @@ test("event2message: should include a reply preview when message ends with a blo
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**_ooye_cookie**:"
- + "\n> https://tootsuite.net/Warp-Gate2.gif tanget: @..."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**_ooye_cookie**:"
+ + "\n> -# https://tootsuite.net/Warp-Gate2.gif tanget: @..."
+ "\naichmophobia",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1529,8 +1529,8 @@ test("event2message: should include a reply preview when replying to a descripti
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/497161350934560778/1162625810109317170 <@1109360903096369153>:"
- + "\n> It looks like this queue has ended."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/497161350934560778/1162625810109317170 <@1109360903096369153>:"
+ + "\n> -# It looks like this queue has ended."
+ `\nso you're saying on matrix side I would have to edit ^this^ to add "Timed out" before the blockquote?`,
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1582,8 +1582,8 @@ test("event2message: entities are not escaped in main message or reply preview",
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
- + "\n> Testing? \"':.`[]&things"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ + "\n> -# Testing? \"':.`[]&things"
+ "\n_Testing?_ \"':.\\`\\[\\]&things",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -1632,8 +1632,8 @@ test("event2message: reply preview converts emoji formatting when replying to a
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
- + "\n> <:hippo:230201364309868544>"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ + "\n> -# <:hippo:230201364309868544>"
+ "\nreply",
avatar_url: undefined,
allowed_mentions: {
@@ -1682,8 +1682,8 @@ test("event2message: reply preview can guess custom emoji based on the name if i
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
- + "\n> <:hippo:230201364309868544>"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ + "\n> -# <:hippo:230201364309868544>"
+ "\nreply",
avatar_url: undefined,
allowed_mentions: {
@@ -1732,8 +1732,8 @@ test("event2message: reply preview uses emoji title text when replying to an unk
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
- + "\n> :svkftngur_gkdne:"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ + "\n> -# :svkftngur_gkdne:"
+ "\nreply",
avatar_url: undefined,
allowed_mentions: {
@@ -1782,8 +1782,8 @@ test("event2message: reply preview ignores garbage image", async t => {
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
- + "\n> I am having a nice day"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**:"
+ + "\n> -# I am having a nice day"
+ "\nreply",
avatar_url: undefined,
allowed_mentions: {
@@ -1832,7 +1832,7 @@ test("event2message: reply to empty message doesn't show an extra line or anythi
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**cadence [they]**"
+ "\nreply",
avatar_url: undefined,
allowed_mentions: {
@@ -1914,8 +1914,8 @@ test("event2message: editing a rich reply to a sim user", async t => {
id: "1144874214311067708",
message: {
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
- + "\n> Slow news day."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ + "\n> -# Slow news day."
+ "\nEditing this reply, which is also a test",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -2205,8 +2205,8 @@ test("event2message: rich reply to a matrix user's long message with formatting"
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence [they]**:"
- + "\n> i should have a little happy test list bold em..."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence [they]**:"
+ + "\n> -# i should have a little happy test list bold em..."
+ "\n**no you can't!!!**",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -2268,7 +2268,7 @@ test("event2message: rich reply to an image", async t => {
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504> 🖼️"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504> 🖼️"
+ "\nCaught in 8K UHD VR QLED Epic Edition",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -2323,8 +2323,8 @@ test("event2message: rich reply to a spoiler should ensure the spoiler is hidden
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
- + "\n> [spoiler] cw crossword spoilers you'll never..."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ + "\n> -# [spoiler] cw crossword spoilers you'll never..."
+ "\nomg NO WAY!!",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -2378,8 +2378,8 @@ test("event2message: with layered rich replies, the preview should only be the r
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence [they]**:"
- + "\n> two"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence [they]**:"
+ + "\n> -# two"
+ "\nthree",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
@@ -2434,8 +2434,8 @@ test("event2message: if event is a reply and starts with a quote, they should be
messagesToEdit: [],
messagesToSend: [{
username: "Rose",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**Rose**:"
- + "\n> i have a feeling that clients are meant to strip..."
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**Rose**:"
+ + "\n> -# i have a feeling that clients are meant to strip..."
+ "\n"
+ "\n> To strip the fallback on the `body`, the client should iterate over each line of the string, removing any lines that start with the fallback prefix (\"> “, including the space, without quotes) and stopping when a line is encountered without the prefix. This prefix is known as the “fallback prefix sequence”.",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/syndicated.gay/ZkBUPXCiXTjdJvONpLJmcbKP",
@@ -2494,7 +2494,7 @@ test("event2message: rich reply to a deleted event", async t => {
messagesToEdit: [],
messagesToSend: [{
username: "Ampflower 🌺",
- content: "> <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**Ampflower 🌺** (in reply to a deleted message)"
+ content: "> -# <:L1:1144820033948762203><:L2:1144820084079087647>Ⓜ️**Ampflower 🌺** (in reply to a deleted message)"
+ "\nHuh it did the same thing here too",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/PRfhXYBTOalvgQYtmCLeUXko",
allowed_mentions: {
From 742d34f15ee3401e65e132c6d333f5b2a253c16f Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Tue, 30 Jul 2024 23:45:44 +1200
Subject: [PATCH 039/346] Fork turndown for Discord-like link escaping
---
m2d/converters/event-to-message.js | 2 +-
m2d/converters/event-to-message.test.js | 39 +++++++++++++++++++++++++
package-lock.json | 19 ++++++------
package.json | 3 +-
4 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index 7b88adb..a266f12 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -4,7 +4,7 @@ const Ty = require("../../types")
const DiscordTypes = require("discord-api-types/v10")
const {Readable} = require("stream")
const chunk = require("chunk-text")
-const TurndownService = require("turndown")
+const TurndownService = require("@cloudrac3r/turndown")
const domino = require("domino")
const assert = require("assert").strict
const entities = require("entities")
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index c054abc..7acad93 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -263,6 +263,45 @@ test("event2message: links in formatted body where the text & href are the same,
)
})
+test("event2message: markdown in link text does not attempt to be escaped because that doesn't work", async t => {
+ t.deepEqual(
+ await eventToMessage({
+ content: {
+ body: "hey mario sports mix [she/her], is it possible to listen on a unix socket?",
+ format: "org.matrix.custom.html",
+ formatted_body: "hey mario sports mix [she/her], is it possible to listen on a unix socket?",
+ "m.mentions": {
+ "user_ids": [
+ "@cadence:cadence.moe"
+ ]
+ },
+ msgtype: "m.text"
+ },
+ event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU",
+ origin_server_ts: 1688301929913,
+ room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
+ sender: "@cadence:cadence.moe",
+ type: "m.room.message",
+ unsigned: {
+ age: 405299
+ }
+ }),
+ {
+ ensureJoined: [],
+ messagesToDelete: [],
+ messagesToEdit: [],
+ messagesToSend: [{
+ username: "cadence [they]",
+ content: "hey [mario sports mix [she/her]](), is it possible to listen on a unix socket?",
+ avatar_url: undefined,
+ allowed_mentions: {
+ parse: ["users", "roles"]
+ }
+ }]
+ }
+ )
+})
+
test("event2message: basic html is converted to markdown", async t => {
t.deepEqual(
await eventToMessage({
diff --git a/package-lock.json b/package-lock.json
index 2d5284a..f7d6553 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,9 +15,11 @@
"@cloudrac3r/html-template-tag": "^5.0.1",
"@cloudrac3r/mixin-deep": "^3.0.0",
"@cloudrac3r/pngjs": "^7.0.3",
+ "@cloudrac3r/turndown": "^7.1.4",
"better-sqlite3": "^9.0.0",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
+ "domino": "^2.1.6",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
"heatsync": "^2.5.3",
@@ -30,7 +32,6 @@
"snowtransfer": "^0.10.5",
"stream-mime-type": "^1.0.2",
"try-to-catch": "^3.0.1",
- "turndown": "^7.1.2",
"xxhash-wasm": "^1.0.2"
},
"devDependencies": {
@@ -213,6 +214,14 @@
"node": ">=8.0.0"
}
},
+ "node_modules/@cloudrac3r/turndown": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/turndown/-/turndown-7.1.4.tgz",
+ "integrity": "sha512-bQAwcvcSqBTdEHPMt+IAZWIoDh+2eRuy9TgD0FUdxVurbvj3CUHTxLfzlmsO0UTi+GHpgYqDSsVdV7kYTNq5Qg==",
+ "dependencies": {
+ "domino": "^2.1.6"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -3100,14 +3109,6 @@
"node": "*"
}
},
- "node_modules/turndown": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz",
- "integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
- "dependencies": {
- "domino": "^2.1.6"
- }
- },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
diff --git a/package.json b/package.json
index 806785c..1349673 100644
--- a/package.json
+++ b/package.json
@@ -21,9 +21,11 @@
"@cloudrac3r/html-template-tag": "^5.0.1",
"@cloudrac3r/mixin-deep": "^3.0.0",
"@cloudrac3r/pngjs": "^7.0.3",
+ "@cloudrac3r/turndown": "^7.1.4",
"better-sqlite3": "^9.0.0",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
+ "domino": "^2.1.6",
"entities": "^4.5.0",
"get-stream": "^6.0.1",
"heatsync": "^2.5.3",
@@ -36,7 +38,6 @@
"snowtransfer": "^0.10.5",
"stream-mime-type": "^1.0.2",
"try-to-catch": "^3.0.1",
- "turndown": "^7.1.2",
"xxhash-wasm": "^1.0.2"
},
"devDependencies": {
From f9eb043c10123432d86bb886221b32c90d0d6bbb Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 31 Jul 2024 00:00:48 +1200
Subject: [PATCH 040/346] Update dependencies
---
m2d/converters/event-to-message.test.js | 8 +-
package-lock.json | 892 ++++++++++++++++--------
package.json | 8 +-
3 files changed, 621 insertions(+), 287 deletions(-)
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 7acad93..7d1f09d 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -4136,7 +4136,7 @@ slow()("event2message: unknown emoji at the end is reuploaded as a sprite sheet"
t.deepEqual(testResult, {
content: "a b",
fileName: "emojis.png",
- fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAPoAAAD6AG1e1JrAAALkklEQVR4nM1ZeWyUxxV/azAGwn0JMJUppPhce++1Oc1i"
+ fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAPoAAAD6AG1e1JrAAALoklEQVR4nM1ZaVBU2RU+LZSIGnAvFUtcRkSk6abpbkDH"
})
})
@@ -4161,7 +4161,7 @@ slow()("event2message: known emoji from an unreachable server at the end is reup
t.deepEqual(testResult, {
content: "a b",
fileName: "emojis.png",
- fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAOnUlEQVR4nM1aCXCb1Z3/kig+5NjWaeu+LOuWLFnHJ8l2"
+ fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAOoUlEQVR4nM1aCXBbx3l+Eu8bN0CAuO+TAHGTFAmAJHgT"
})
})
@@ -4186,7 +4186,7 @@ slow()("event2message: known and unknown emojis in the end are reuploaded as a s
t.deepEqual(testResult, {
content: "known unknown: <:hippo:230201364309868544> [:ms_robot_dress:](https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/wcouHVjbKJJYajkhJLsyeJAA) and known unknown:",
fileName: "emojis.png",
- fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAAGAAAAAwCAYAAADuFn/PAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAT5UlEQVR4nOVbCXSVRZauR9gMsoYlvKwvARKSkPUlJOyL"
+ fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAAGAAAAAwCAYAAADuFn/PAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAeXRFWHRSYXcACklQVEMgcHJvZmlsZQogICAgICA0Ngoz"
})
})
@@ -4211,6 +4211,6 @@ slow()("event2message: all unknown chess emojis are reuploaded as a sprite sheet
t.deepEqual(testResult, {
content: "testing",
fileName: "emojis.png",
- fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAAYAAAABgCAYAAAAU9KWJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAgAElEQVR4nOx9B3xT1/W/UkImYKZtLdt4a0uWMaQkzS9t"
+ fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAAYAAAABgCAYAAAAU9KWJAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48"
})
})
diff --git a/package-lock.json b/package-lock.json
index f7d6553..9b97e23 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,11 +16,11 @@
"@cloudrac3r/mixin-deep": "^3.0.0",
"@cloudrac3r/pngjs": "^7.0.3",
"@cloudrac3r/turndown": "^7.1.4",
- "better-sqlite3": "^9.0.0",
+ "better-sqlite3": "^11.1.2",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
"domino": "^2.1.6",
- "entities": "^4.5.0",
+ "entities": "^5.0.0",
"get-stream": "^6.0.1",
"heatsync": "^2.5.3",
"js-yaml": "^4.1.0",
@@ -28,7 +28,7 @@
"minimist": "^1.2.8",
"node-fetch": "^2.6.7",
"prettier-bytes": "^1.0.4",
- "sharp": "^0.32.6",
+ "sharp": "^0.33.4",
"snowtransfer": "^0.10.5",
"stream-mime-type": "^1.0.2",
"try-to-catch": "^3.0.1",
@@ -38,7 +38,7 @@
"@cloudrac3r/tap-dot": "^2.0.2",
"@types/node": "^18.16.0",
"@types/node-fetch": "^2.6.3",
- "c8": "^8.0.1",
+ "c8": "^10.1.2",
"colorette": "^1.4.0",
"cross-env": "^7.0.3",
"discord-api-types": "^0.37.60",
@@ -52,9 +52,9 @@
"dev": true
},
"node_modules/@chriscdn/promise-semaphore": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@chriscdn/promise-semaphore/-/promise-semaphore-2.0.7.tgz",
- "integrity": "sha512-xsa5SAYSBnYjqvGnzmaLca4X/RFeOl+ziCsIHl5iHkFBgE4NgWupB4z3A1rVMBM2I8TEKaah+5iu9Cm7gQu9JQ=="
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/@chriscdn/promise-semaphore/-/promise-semaphore-2.0.9.tgz",
+ "integrity": "sha512-kKXJcm5gM8FN8O8U20H19/85b8R33K0Q2u5cnm9mfblK/7QcNChlOhCTWgnrr8wYiuF1ZbYIZcioxW79QfjnmQ=="
},
"node_modules/@cloudcmd/stub": {
"version": "4.0.1",
@@ -222,6 +222,446 @@
"domino": "^2.1.6"
}
},
+ "node_modules/@emnapi/runtime": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz",
+ "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.4.tgz",
+ "integrity": "sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "glibc": ">=2.26",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.4.tgz",
+ "integrity": "sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "glibc": ">=2.26",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz",
+ "integrity": "sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "macos": ">=11",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.2.tgz",
+ "integrity": "sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "macos": ">=10.13",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.2.tgz",
+ "integrity": "sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.28",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.2.tgz",
+ "integrity": "sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.26",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz",
+ "integrity": "sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.28",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz",
+ "integrity": "sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.26",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.2.tgz",
+ "integrity": "sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "musl": ">=1.2.2",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.2.tgz",
+ "integrity": "sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "musl": ">=1.2.2",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.4.tgz",
+ "integrity": "sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.28",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.4.tgz",
+ "integrity": "sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.26",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.4.tgz",
+ "integrity": "sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.31",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.4.tgz",
+ "integrity": "sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "glibc": ">=2.26",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.4.tgz",
+ "integrity": "sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "musl": ">=1.2.2",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.4.tgz",
+ "integrity": "sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "musl": ">=1.2.2",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.2"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.4.tgz",
+ "integrity": "sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.1.1"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.4.tgz",
+ "integrity": "sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.4.tgz",
+ "integrity": "sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0",
+ "yarn": ">=3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -495,15 +935,18 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "18.18.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.5.tgz",
- "integrity": "sha512-4slmbtwV59ZxitY4ixUZdy1uRLf9eSIvBWPQxNjhHYWEtn0FryfKpyS2cvADYXTayWdKEIsJengncrVvkI4I6A==",
- "dev": true
+ "version": "18.19.42",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz",
+ "integrity": "sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
},
"node_modules/@types/node-fetch": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz",
- "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==",
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
+ "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
"dev": true,
"dependencies": {
"@types/node": "*",
@@ -591,11 +1034,6 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true
},
- "node_modules/b4a": {
- "version": "1.6.4",
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
- "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw=="
- },
"node_modules/backtracker": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/backtracker/-/backtracker-4.0.0.tgz",
@@ -642,9 +1080,9 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/better-sqlite3": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.0.0.tgz",
- "integrity": "sha512-lDxQ9qg/XuUHZG6xzrQaMHkNWl37t35/LPB/VJGV8DdScSuGFNfFSqgscXEd8UIuyk/d9wU8iaMxQa4If5Wqog==",
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz",
+ "integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==",
"hasInstallScript": true,
"dependencies": {
"bindings": "^1.5.0",
@@ -745,20 +1183,19 @@
}
},
"node_modules/c8": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/c8/-/c8-8.0.1.tgz",
- "integrity": "sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w==",
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz",
+ "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==",
"dev": true,
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
"@istanbuljs/schema": "^0.1.3",
"find-up": "^5.0.0",
- "foreground-child": "^2.0.0",
+ "foreground-child": "^3.1.1",
"istanbul-lib-coverage": "^3.2.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.1.6",
- "rimraf": "^3.0.2",
- "test-exclude": "^6.0.0",
+ "test-exclude": "^7.0.1",
"v8-to-istanbul": "^9.0.0",
"yargs": "^17.7.2",
"yargs-parser": "^21.1.1"
@@ -767,7 +1204,15 @@
"c8": "bin/c8.js"
},
"engines": {
- "node": ">=12"
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "monocart-coverage-reports": "^2"
+ },
+ "peerDependenciesMeta": {
+ "monocart-coverage-reports": {
+ "optional": true
+ }
}
},
"node_modules/call-bind": {
@@ -881,11 +1326,11 @@
}
},
"node_modules/cloudstorm": {
- "version": "0.10.8",
- "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.10.8.tgz",
- "integrity": "sha512-ZVy4HbEiNRyRO0p0d0DtIMoVCg8rxoRpA07hflq2MQpPpmFpostkF7nd+zOsQ+piAfhUdvPsgtQLHdGFmTZVPQ==",
+ "version": "0.10.9",
+ "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.10.9.tgz",
+ "integrity": "sha512-LLWCDn8CORM9iCFyWq3sIRK/7zJU7Jw14wLit3p5zWlD9Ihixv2nqjBbnWqEuq97zWh/xA+abACz2CvTVBlIWQ==",
"dependencies": {
- "discord-api-types": "^0.37.70",
+ "discord-api-types": "^0.37.90",
"snowtransfer": "^0.10.5"
},
"engines": {
@@ -947,12 +1392,6 @@
"node": ">= 0.8"
}
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -1105,9 +1544,9 @@
}
},
"node_modules/detect-libc": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
- "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"engines": {
"node": ">=8"
}
@@ -1121,9 +1560,9 @@
}
},
"node_modules/discord-api-types": {
- "version": "0.37.70",
- "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.70.tgz",
- "integrity": "sha512-8EtfZR0KwOK+yP5q/llWILdUAPmGmF1LmcVUYf7+gtGigz2pu6WR38ZN+IWtMzohY1Ujl2u3KOdbFvrEz9EC8w=="
+ "version": "0.37.93",
+ "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.93.tgz",
+ "integrity": "sha512-M5jn0x3bcXk8EI2c6F6V6LeOWq10B/cJf+YJSyqNmg7z4bdXK+Z7g9zGJwHS0h9Bfgs0nun2LQISFOzwck7G9A=="
},
"node_modules/domino": {
"version": "2.1.6",
@@ -1162,9 +1601,9 @@
}
},
"node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-5.0.0.tgz",
+ "integrity": "sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==",
"engines": {
"node": ">=0.12"
},
@@ -1262,11 +1701,6 @@
"node": ">= 0.10.0"
}
},
- "node_modules/fast-fifo": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
- "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
- },
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
@@ -1335,16 +1769,18 @@
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="
},
"node_modules/foreground-child": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
- "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
- "dev": true,
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
+ "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
"dependencies": {
"cross-spawn": "^7.0.0",
- "signal-exit": "^3.0.2"
+ "signal-exit": "^4.0.1"
},
"engines": {
- "node": ">=8.0.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/form-data": {
@@ -1382,12 +1818,6 @@
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
"node_modules/fullstore": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/fullstore/-/fullstore-3.0.0.tgz",
@@ -1478,32 +1908,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/glob/node_modules/foreground-child": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
- "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
- "dependencies": {
- "cross-spawn": "^7.0.0",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob/node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -1568,9 +1972,9 @@
}
},
"node_modules/heatsync": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.5.3.tgz",
- "integrity": "sha512-NvR6wZZquJqDO/Tl1JGMGdNph0TTfhgWdj3sMWOkdQa9rs4fspHV+kGiZEgZQ0j8AQiYUEPQgRI7vdNZCKH+uw==",
+ "version": "2.5.4",
+ "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.5.4.tgz",
+ "integrity": "sha512-KzsM+wR0MIykD80kCHNZCpNvFY4uC1Yze8R37eehJyGIvEepJd+7ubczh6FVoBFtK0nVEszt5Hl8AbzUvb+vMQ==",
"dependencies": {
"backtracker": "^4.0.0"
}
@@ -1631,16 +2035,6 @@
}
]
},
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -1794,17 +2188,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
@@ -1986,11 +2369,6 @@
"node": ">=10"
}
},
- "node_modules/node-addon-api": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
- "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
- },
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@@ -2097,15 +2475,6 @@
"node": ">=8"
}
},
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -2253,11 +2622,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/queue-tick": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
- "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
- },
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -2358,63 +2722,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/rimraf/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/rimraf/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/rimraf/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/runes": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/runes/-/runes-0.4.3.tgz",
@@ -2448,12 +2755,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"bin": {
"semver": "bin/semver.js"
},
@@ -2525,45 +2829,42 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/sharp": {
- "version": "0.32.6",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz",
- "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==",
+ "version": "0.33.4",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.4.tgz",
+ "integrity": "sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==",
"hasInstallScript": true,
"dependencies": {
"color": "^4.2.3",
- "detect-libc": "^2.0.2",
- "node-addon-api": "^6.1.0",
- "prebuild-install": "^7.1.1",
- "semver": "^7.5.4",
- "simple-get": "^4.0.1",
- "tar-fs": "^3.0.4",
- "tunnel-agent": "^0.6.0"
+ "detect-libc": "^2.0.3",
+ "semver": "^7.6.0"
},
"engines": {
- "node": ">=14.15.0"
+ "libvips": ">=8.15.2",
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/sharp/node_modules/tar-fs": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz",
- "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==",
- "dependencies": {
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^3.1.5"
- }
- },
- "node_modules/sharp/node_modules/tar-stream": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz",
- "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==",
- "dependencies": {
- "b4a": "^1.6.4",
- "fast-fifo": "^1.2.0",
- "streamx": "^2.15.0"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.33.4",
+ "@img/sharp-darwin-x64": "0.33.4",
+ "@img/sharp-libvips-darwin-arm64": "1.0.2",
+ "@img/sharp-libvips-darwin-x64": "1.0.2",
+ "@img/sharp-libvips-linux-arm": "1.0.2",
+ "@img/sharp-libvips-linux-arm64": "1.0.2",
+ "@img/sharp-libvips-linux-s390x": "1.0.2",
+ "@img/sharp-libvips-linux-x64": "1.0.2",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.2",
+ "@img/sharp-linux-arm": "0.33.4",
+ "@img/sharp-linux-arm64": "0.33.4",
+ "@img/sharp-linux-s390x": "0.33.4",
+ "@img/sharp-linux-x64": "0.33.4",
+ "@img/sharp-linuxmusl-arm64": "0.33.4",
+ "@img/sharp-linuxmusl-x64": "0.33.4",
+ "@img/sharp-wasm32": "0.33.4",
+ "@img/sharp-win32-ia32": "0.33.4",
+ "@img/sharp-win32-x64": "0.33.4"
}
},
"node_modules/shebang-command": {
@@ -2599,10 +2900,15 @@
}
},
"node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
},
"node_modules/simple-concat": {
"version": "1.0.1",
@@ -2733,15 +3039,6 @@
"node": ">=10"
}
},
- "node_modules/streamx": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz",
- "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==",
- "dependencies": {
- "fast-fifo": "^1.1.0",
- "queue-tick": "^1.0.1"
- }
- },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -2972,59 +3269,89 @@
}
},
"node_modules/test-exclude": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
- "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
+ "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==",
"dev": true,
"dependencies": {
"@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
+ "glob": "^10.4.1",
+ "minimatch": "^9.0.4"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/test-exclude/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "node": ">=18"
}
},
"node_modules/test-exclude/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
},
- "engines": {
- "node": "*"
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/test-exclude/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "node_modules/test-exclude/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
"dependencies": {
- "brace-expansion": "^1.1.7"
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/test-exclude/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true
+ },
+ "node_modules/test-exclude/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
},
"engines": {
- "node": "*"
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/test-exclude/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/through2": {
@@ -3098,6 +3425,12 @@
"node": ">=6"
}
},
+ "node_modules/tslib": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+ "optional": true
+ },
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -3129,6 +3462,12 @@
"node": ">=18.17"
}
},
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -3298,11 +3637,6 @@
"node": ">=10"
}
},
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
- },
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
diff --git a/package.json b/package.json
index 1349673..10486ac 100644
--- a/package.json
+++ b/package.json
@@ -22,11 +22,11 @@
"@cloudrac3r/mixin-deep": "^3.0.0",
"@cloudrac3r/pngjs": "^7.0.3",
"@cloudrac3r/turndown": "^7.1.4",
- "better-sqlite3": "^9.0.0",
+ "better-sqlite3": "^11.1.2",
"chunk-text": "^2.0.1",
"cloudstorm": "^0.10.8",
"domino": "^2.1.6",
- "entities": "^4.5.0",
+ "entities": "^5.0.0",
"get-stream": "^6.0.1",
"heatsync": "^2.5.3",
"js-yaml": "^4.1.0",
@@ -34,7 +34,7 @@
"minimist": "^1.2.8",
"node-fetch": "^2.6.7",
"prettier-bytes": "^1.0.4",
- "sharp": "^0.32.6",
+ "sharp": "^0.33.4",
"snowtransfer": "^0.10.5",
"stream-mime-type": "^1.0.2",
"try-to-catch": "^3.0.1",
@@ -44,7 +44,7 @@
"@cloudrac3r/tap-dot": "^2.0.2",
"@types/node": "^18.16.0",
"@types/node-fetch": "^2.6.3",
- "c8": "^8.0.1",
+ "c8": "^10.1.2",
"colorette": "^1.4.0",
"cross-env": "^7.0.3",
"discord-api-types": "^0.37.60",
From 2c3b653b540e6eea37e130104aece48c1f094d71 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Wed, 31 Jul 2024 00:06:32 +1200
Subject: [PATCH 041/346] Consistently add @ to m->d matrix mentions
---
m2d/converters/event-to-message.js | 2 +-
m2d/converters/event-to-message.test.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index a266f12..86975ab 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -129,7 +129,7 @@ turndownService.addRule("inlineLink", {
const href = node.getAttribute("href")
content = content.replace(/ @.*/, "")
if (href === content) return href
- if (href.startsWith("https://matrix.to/#/@") && content[0] !== "@") content = "@" + content
+ if (decodeURIComponent(href).startsWith("https://matrix.to/#/@") && content[0] !== "@") content = "@" + content
return "[" + content + "](" + href + ")"
}
})
diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js
index 7d1f09d..3a187c3 100644
--- a/m2d/converters/event-to-message.test.js
+++ b/m2d/converters/event-to-message.test.js
@@ -292,7 +292,7 @@ test("event2message: markdown in link text does not attempt to be escaped becaus
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
- content: "hey [mario sports mix [she/her]](), is it possible to listen on a unix socket?",
+ content: "hey [@mario sports mix [she/her]](), is it possible to listen on a unix socket?",
avatar_url: undefined,
allowed_mentions: {
parse: ["users", "roles"]
From 87cad6c61312fdcb4f4d0cefbb91a613d5ca4d4f Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sat, 3 Aug 2024 22:45:34 +1200
Subject: [PATCH 042/346] Update and unminify rlottie
---
d2m/converters/rlottie-wasm.js | 2636 +++++++++++++++++++++++++++++-
d2m/converters/rlottie-wasm.wasm | Bin 504120 -> 608159 bytes
test/res/lottie-bee.png | Bin 5492 -> 5510 bytes
3 files changed, 2635 insertions(+), 1 deletion(-)
diff --git a/d2m/converters/rlottie-wasm.js b/d2m/converters/rlottie-wasm.js
index 4abf45d..986a299 100644
--- a/d2m/converters/rlottie-wasm.js
+++ b/d2m/converters/rlottie-wasm.js
@@ -1 +1,2635 @@
-var Module=typeof Module!="undefined"?Module:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}process.on("uncaughtException",ex=>{if(ex!=="unwind"&&!(ex instanceof ExitStatus)&&!(ex.context instanceof ExitStatus)){throw ex}});quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module["inspect"]=()=>"[Emscripten Module object]"}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="rlottie-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(binaryFile)){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinarySync(binaryFile))}else if(readAsync){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),reject)})}}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(instance=>instance).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"env":wasmImports,"wasi_snapshot_preview1":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;wasmExports=exports;wasmMemory=wasmExports["memory"];updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];addOnInit(wasmExports["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var SYSCALLS={varargs:undefined,get(){var ret=HEAP32[SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret},getp(){return SYSCALLS.get()},getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;return 0}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs}var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{};var embind_init_charCodes=()=>{var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes};var embind_charCodes=undefined;var readLatin1String=ptr=>{var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret};var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var BindingError=undefined;var throwBindingError=message=>{throw new BindingError(message)};var InternalError=undefined;var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}return sharedRegisterType(rawType,registeredInstance,options)}var GenericWireTypeSize=8;var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(wt){return!!wt},"toWireType":function(destructors,o){return o?trueValue:falseValue},"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":function(pointer){return this["fromWireType"](HEAPU8[pointer])},destructorFunction:null})};function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var finalizationRegistry=false;var detachFinalizer=handle=>{};var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var registeredPointers={};var getInheritedInstanceCount=()=>Object.keys(registeredInstances).length;var getLiveInheritedInstances=()=>{var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction=undefined;var setDelayFunction=fn=>{delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}};var init_embind=()=>{Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var attachFinalizer=handle=>{if("undefined"===typeof FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$:$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}var init_ClassHandle=()=>{ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater};function ClassHandle(){}var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function createNamedFunction(name,body){name=makeLegalFunctionName(name);return{[name]:function(){return body.apply(this,arguments)}}[name]}var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function readPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}var RegisteredPointer_deleteObject=handle=>{if(handle!==null){handle["delete"]()}};var init_RegisteredPointer=()=>{RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=GenericWireTypeSize;RegisteredPointer.prototype["readValueFromPointer"]=readPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var dynCallLegacy=(sig,ptr,args)=>{var f=Module["dynCall_"+sig];return args&&args.length?f.apply(null,[ptr].concat(args)):f.call(null,ptr)};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var dynCall=(sig,ptr,args)=>{if(sig.includes("j")){return dynCallLegacy(sig,ptr,args)}var rtn=getWasmTableEntry(ptr).apply(null,args);return rtn};var getDynCaller=(sig,ptr)=>{var argCache=[];return function(){argCache.length=0;Object.assign(argCache,arguments);return dynCall(sig,ptr,argCache)}};var embind__requireFunction=(signature,rawFunction)=>{signature=readLatin1String(signature);function makeDynCaller(){if(signature.includes("j")){return getDynCaller(signature,rawFunction)}return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};var extendError=(baseErrorType,errorName)=>{var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass};var UnboundTypeError=undefined;var getTypeName=type=>{var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv};var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);if(upcast){upcast=embind__requireFunction(upcastSignature,upcast)}if(downcast){downcast=embind__requireFunction(downcastSignature,downcast)}rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],function(base){base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(legalFunctionName,function(){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError("Use 'new' to construct "+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+" has no accessible constructor")}var body=registeredClass.constructor_body[arguments.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${arguments.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,arguments)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){if(registeredClass.baseClass.__derivedClasses===undefined){registeredClass.baseClass.__derivedClasses=[]}registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};var heap32VectorToArray=(count,firstElement)=>{var array=[];for(var i=0;i>2])}return array};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function newFunc(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError(`new_ called with constructor type ${typeof constructor} which is not a function`)}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc,isAsync){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns||isAsync?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};function handleAllocatorInit(){Object.assign(HandleAllocator.prototype,{get(id){return this.allocated[id]},has(id){return this.allocated[id]!==undefined},allocate(handle){var id=this.freelist.pop()||this.allocated.length;this.allocated[id]=handle;return id},free(id){this.allocated[id]=undefined;this.freelist.push(id)}})}function HandleAllocator(){this.allocated=[undefined];this.freelist=[]}var emval_handles=new HandleAllocator;var __emval_decref=handle=>{if(handle>=emval_handles.reserved&&0===--emval_handles.get(handle).refcount){emval_handles.free(handle)}};var count_emval_handles=()=>{var count=0;for(var i=emval_handles.reserved;i{emval_handles.allocated.push({value:undefined},{value:null},{value:true},{value:false});emval_handles.reserved=emval_handles.allocated.length;Module["count_emval_handles"]=count_emval_handles};var Emval={toValue:handle=>{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handles.get(handle).value},toHandle:value=>{switch(value){case undefined:return 1;case null:return 2;case true:return 3;case false:return 4;default:{return emval_handles.allocate({refcount:1,value:value})}}}};function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAP32[pointer>>2])}var __embind_register_emval=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},"toWireType":(destructors,value)=>Emval.toHandle(value),"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 8:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":value=>value,"toWireType":(destructors,value)=>value,"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":floatReadValueFromPointer(name,size),destructorFunction:null})};var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer>>0]:pointer=>HEAPU8[pointer>>0];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":toWireType,"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var __embind_register_std_string=(rawType,name)=>{name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":value=>{var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i{if(value instanceof ArrayBuffer){value=new Uint8Array(value)}var length;var valueIsOfTypeString=typeof value=="string";if(!(valueIsOfTypeString||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int8Array)){throwBindingError("Cannot pass non-string to std::string")}if(stdStringIsUTF8&&valueIsOfTypeString){length=lengthBytesUTF8(value)}else{length=value.length}var base=_malloc(4+length+1);var ptr=base+4;HEAPU32[base>>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i_free(ptr)})};var UTF16Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead)=>{var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead)=>{var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=readLatin1String(name);var decodeString,encodeString,getHeap,lengthBytesUTF,shift;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;getHeap=()=>HEAPU16;shift=1}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;getHeap=()=>HEAPU32;shift=2}registerType(rawType,{name:name,"fromWireType":value=>{var length=HEAPU32[value>>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:ptr=>_free(ptr)})};var __embind_register_void=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":()=>undefined,"toWireType":(destructors,o)=>undefined})};var __emscripten_throw_longjmp=()=>{throw Infinity};var __emval_incref=handle=>{if(handle>4){emval_handles.get(handle).refcount+=1}};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl};var __emval_take_value=(type,arg)=>{type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](arg);return Emval.toHandle(v)};var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function __localtime_js(time_low,time_high,tmPtr){var time=convertI32PairToI53Checked(time_low,time_high);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var __mktime_js=function(tmPtr){var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3})();return setTempRet0((tempDouble=ret,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)),ret>>>0};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var __tzset_js=(timezone,daylight,tzname)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=stringToNewUTF8(winterName);var summerNamePtr=stringToNewUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAPU32[tzname+4>>2]=summerNamePtr}else{HEAPU32[tzname>>2]=summerNamePtr;HEAPU32[tzname+4>>2]=winterNamePtr}};var _abort=()=>{abort("")};var _emscripten_memcpy_big=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var getHeapMax=()=>2147483648;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var _fd_close=fd=>52;var _fd_read=(fd,iov,iovcnt,pnum)=>52;function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);return 70}var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var _strftime=(s,maxsize,format,tm)=>{var tm_zone=HEAPU32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":date=>WEEKDAYS[date.tm_wday].substring(0,3),"%A":date=>WEEKDAYS[date.tm_wday],"%b":date=>MONTHS[date.tm_mon].substring(0,3),"%B":date=>MONTHS[date.tm_mon],"%C":date=>{var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":date=>leadingNulls(date.tm_mday,2),"%e":date=>leadingSomething(date.tm_mday,2," "),"%g":date=>getWeekBasedYear(date).toString().substring(2),"%G":date=>getWeekBasedYear(date),"%H":date=>leadingNulls(date.tm_hour,2),"%I":date=>{var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":date=>leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3),"%m":date=>leadingNulls(date.tm_mon+1,2),"%M":date=>leadingNulls(date.tm_min,2),"%n":()=>"\n","%p":date=>{if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":date=>leadingNulls(date.tm_sec,2),"%t":()=>"\t","%u":date=>date.tm_wday||7,"%U":date=>{var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":date=>{var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":date=>date.tm_wday,"%W":date=>{var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":date=>(date.tm_year+1900).toString().substring(2),"%Y":date=>date.tm_year+1900,"%z":date=>{var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":date=>date.tm_zone,"%%":()=>"%"};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1};var _strftime_l=(s,maxsize,format,tm,loc)=>_strftime(s,maxsize,format,tm);embind_init_charCodes();BindingError=Module["BindingError"]=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};InternalError=Module["InternalError"]=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};init_ClassHandle();init_embind();init_RegisteredPointer();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");handleAllocatorInit();init_emval();var wasmImports={__assert_fail:___assert_fail,__cxa_throw:___cxa_throw,__syscall_ioctl:___syscall_ioctl,__syscall_openat:___syscall_openat,_embind_register_bigint:__embind_register_bigint,_embind_register_bool:__embind_register_bool,_embind_register_class:__embind_register_class,_embind_register_class_constructor:__embind_register_class_constructor,_embind_register_class_function:__embind_register_class_function,_embind_register_emval:__embind_register_emval,_embind_register_float:__embind_register_float,_embind_register_integer:__embind_register_integer,_embind_register_memory_view:__embind_register_memory_view,_embind_register_std_string:__embind_register_std_string,_embind_register_std_wstring:__embind_register_std_wstring,_embind_register_void:__embind_register_void,_emscripten_throw_longjmp:__emscripten_throw_longjmp,_emval_decref:__emval_decref,_emval_incref:__emval_incref,_emval_take_value:__emval_take_value,_localtime_js:__localtime_js,_mktime_js:__mktime_js,_tzset_js:__tzset_js,abort:_abort,emscripten_memcpy_big:_emscripten_memcpy_big,emscripten_resize_heap:_emscripten_resize_heap,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,fd_close:_fd_close,fd_read:_fd_read,fd_seek:_fd_seek,fd_write:_fd_write,invoke_vi:invoke_vi,invoke_viii:invoke_viii,invoke_viiii:invoke_viiii,invoke_viiiii:invoke_viiiii,strftime_l:_strftime_l};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["__wasm_call_ctors"])();var _free=a0=>(_free=wasmExports["free"])(a0);var _malloc=a0=>(_malloc=wasmExports["malloc"])(a0);var ___getTypeName=a0=>(___getTypeName=wasmExports["__getTypeName"])(a0);var __embind_initialize_bindings=Module["__embind_initialize_bindings"]=()=>(__embind_initialize_bindings=Module["__embind_initialize_bindings"]=wasmExports["_embind_initialize_bindings"])();var ___errno_location=()=>(___errno_location=wasmExports["__errno_location"])();var _setThrew=(a0,a1)=>(_setThrew=wasmExports["setThrew"])(a0,a1);var setTempRet0=a0=>(setTempRet0=wasmExports["setTempRet0"])(a0);var stackSave=()=>(stackSave=wasmExports["stackSave"])();var stackRestore=a0=>(stackRestore=wasmExports["stackRestore"])(a0);var stackAlloc=a0=>(stackAlloc=wasmExports["stackAlloc"])(a0);var ___cxa_increment_exception_refcount=a0=>(___cxa_increment_exception_refcount=wasmExports["__cxa_increment_exception_refcount"])(a0);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["__cxa_is_pointer_type"])(a0);var dynCall_iijii=Module["dynCall_iijii"]=(a0,a1,a2,a3,a4,a5)=>(dynCall_iijii=Module["dynCall_iijii"]=wasmExports["dynCall_iijii"])(a0,a1,a2,a3,a4,a5);var dynCall_jiji=Module["dynCall_jiji"]=(a0,a1,a2,a3,a4)=>(dynCall_jiji=Module["dynCall_jiji"]=wasmExports["dynCall_jiji"])(a0,a1,a2,a3,a4);var dynCall_viijii=Module["dynCall_viijii"]=(a0,a1,a2,a3,a4,a5,a6)=>(dynCall_viijii=Module["dynCall_viijii"]=wasmExports["dynCall_viijii"])(a0,a1,a2,a3,a4,a5,a6);var dynCall_iiiiij=Module["dynCall_iiiiij"]=(a0,a1,a2,a3,a4,a5,a6)=>(dynCall_iiiiij=Module["dynCall_iiiiij"]=wasmExports["dynCall_iiiiij"])(a0,a1,a2,a3,a4,a5,a6);var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>(dynCall_iiiiijj=Module["dynCall_iiiiijj"]=wasmExports["dynCall_iiiiijj"])(a0,a1,a2,a3,a4,a5,a6,a7,a8);var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)=>(dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=wasmExports["dynCall_iiiiiijj"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();
+var Module = typeof Module != "undefined" ? Module : {};
+
+var moduleOverrides = Object.assign({}, Module);
+
+var arguments_ = [];
+
+var thisProgram = "./this.program";
+
+var quit_ = (status, toThrow) => {
+ throw toThrow;
+};
+
+var ENVIRONMENT_IS_WEB = false;
+
+var ENVIRONMENT_IS_WORKER = false;
+
+var ENVIRONMENT_IS_NODE = true;
+
+var scriptDirectory = "";
+
+function locateFile(path) {
+ if (Module["locateFile"]) {
+ return Module["locateFile"](path, scriptDirectory);
+ }
+ return scriptDirectory + path;
+}
+
+var read_, readAsync, readBinary;
+
+if (ENVIRONMENT_IS_NODE) {
+ var fs = require("fs");
+ var nodePath = require("path");
+ if (ENVIRONMENT_IS_WORKER) {
+ scriptDirectory = nodePath.dirname(scriptDirectory) + "/";
+ } else {
+ scriptDirectory = __dirname + "/";
+ }
+ read_ = (filename, binary) => {
+ filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
+ return fs.readFileSync(filename, binary ? undefined : "utf8");
+ };
+ readBinary = filename => {
+ var ret = read_(filename, true);
+ if (!ret.buffer) {
+ ret = new Uint8Array(ret);
+ }
+ return ret;
+ };
+ readAsync = (filename, onload, onerror, binary = true) => {
+ filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
+ fs.readFile(filename, binary ? undefined : "utf8", (err, data) => {
+ if (err) onerror(err); else onload(binary ? data.buffer : data);
+ });
+ };
+ if (!Module["thisProgram"] && process.argv.length > 1) {
+ thisProgram = process.argv[1].replace(/\\/g, "/");
+ }
+ arguments_ = process.argv.slice(2);
+ if (typeof module != "undefined") {
+ module["exports"] = Module;
+ }
+ quit_ = (status, toThrow) => {
+ process.exitCode = status;
+ throw toThrow;
+ };
+ Module["inspect"] = () => "[Emscripten Module object]";
+} else {}
+
+var out = Module["print"] || console.log.bind(console);
+
+var err = Module["printErr"] || console.error.bind(console);
+
+Object.assign(Module, moduleOverrides);
+
+moduleOverrides = null;
+
+if (Module["arguments"]) arguments_ = Module["arguments"];
+
+if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
+
+if (Module["quit"]) quit_ = Module["quit"];
+
+var wasmBinary;
+
+if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
+
+var noExitRuntime = Module["noExitRuntime"] || true;
+
+if (typeof WebAssembly != "object") {
+ abort("no native wasm support detected");
+}
+
+var wasmMemory;
+
+var ABORT = false;
+
+var EXITSTATUS;
+
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+
+function updateMemoryViews() {
+ var b = wasmMemory.buffer;
+ Module["HEAP8"] = HEAP8 = new Int8Array(b);
+ Module["HEAP16"] = HEAP16 = new Int16Array(b);
+ Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
+ Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
+ Module["HEAP32"] = HEAP32 = new Int32Array(b);
+ Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
+ Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
+ Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
+}
+
+var wasmTable;
+
+var __ATPRERUN__ = [];
+
+var __ATINIT__ = [];
+
+var __ATPOSTRUN__ = [];
+
+var runtimeInitialized = false;
+
+var runtimeKeepaliveCounter = 0;
+
+function preRun() {
+ if (Module["preRun"]) {
+ if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
+ while (Module["preRun"].length) {
+ addOnPreRun(Module["preRun"].shift());
+ }
+ }
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+
+function initRuntime() {
+ runtimeInitialized = true;
+ callRuntimeCallbacks(__ATINIT__);
+}
+
+function postRun() {
+ if (Module["postRun"]) {
+ if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
+ while (Module["postRun"].length) {
+ addOnPostRun(Module["postRun"].shift());
+ }
+ }
+ callRuntimeCallbacks(__ATPOSTRUN__);
+}
+
+function addOnPreRun(cb) {
+ __ATPRERUN__.unshift(cb);
+}
+
+function addOnInit(cb) {
+ __ATINIT__.unshift(cb);
+}
+
+function addOnPostRun(cb) {
+ __ATPOSTRUN__.unshift(cb);
+}
+
+var runDependencies = 0;
+
+var runDependencyWatcher = null;
+
+var dependenciesFulfilled = null;
+
+function addRunDependency(id) {
+ runDependencies++;
+ if (Module["monitorRunDependencies"]) {
+ Module["monitorRunDependencies"](runDependencies);
+ }
+}
+
+function removeRunDependency(id) {
+ runDependencies--;
+ if (Module["monitorRunDependencies"]) {
+ Module["monitorRunDependencies"](runDependencies);
+ }
+ if (runDependencies == 0) {
+ if (runDependencyWatcher !== null) {
+ clearInterval(runDependencyWatcher);
+ runDependencyWatcher = null;
+ }
+ if (dependenciesFulfilled) {
+ var callback = dependenciesFulfilled;
+ dependenciesFulfilled = null;
+ callback();
+ }
+ }
+}
+
+function abort(what) {
+ if (Module["onAbort"]) {
+ Module["onAbort"](what);
+ }
+ what = "Aborted(" + what + ")";
+ err(what);
+ ABORT = true;
+ EXITSTATUS = 1;
+ what += ". Build with -sASSERTIONS for more info.";
+ var e = new WebAssembly.RuntimeError(what);
+ throw e;
+}
+
+var dataURIPrefix = "data:application/octet-stream;base64,";
+
+function isDataURI(filename) {
+ return filename.startsWith(dataURIPrefix);
+}
+
+function isFileURI(filename) {
+ return filename.startsWith("file://");
+}
+
+var wasmBinaryFile;
+
+wasmBinaryFile = "rlottie-wasm.wasm";
+
+if (!isDataURI(wasmBinaryFile)) {
+ wasmBinaryFile = locateFile(wasmBinaryFile);
+}
+
+function getBinarySync(file) {
+ if (file == wasmBinaryFile && wasmBinary) {
+ return new Uint8Array(wasmBinary);
+ }
+ if (readBinary) {
+ return readBinary(file);
+ }
+ throw "both async and sync fetching of the wasm failed";
+}
+
+function getBinaryPromise(binaryFile) {
+ if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
+ if (typeof fetch == "function") {
+ return fetch(binaryFile, {
+ credentials: "same-origin"
+ }).then(response => {
+ if (!response["ok"]) {
+ throw "failed to load wasm binary file at '" + binaryFile + "'";
+ }
+ return response["arrayBuffer"]();
+ }).catch(() => getBinarySync(binaryFile));
+ }
+ }
+ return Promise.resolve().then(() => getBinarySync(binaryFile));
+}
+
+function instantiateArrayBuffer(binaryFile, imports, receiver) {
+ return getBinaryPromise(binaryFile).then(binary => WebAssembly.instantiate(binary, imports)).then(instance => instance).then(receiver, reason => {
+ err(`failed to asynchronously prepare wasm: ${reason}`);
+ abort(reason);
+ });
+}
+
+function instantiateAsync(binary, binaryFile, imports, callback) {
+ if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") {
+ return fetch(binaryFile, {
+ credentials: "same-origin"
+ }).then(response => {
+ var result = WebAssembly.instantiateStreaming(response, imports);
+ return result.then(callback, function(reason) {
+ err(`wasm streaming compile failed: ${reason}`);
+ err("falling back to ArrayBuffer instantiation");
+ return instantiateArrayBuffer(binaryFile, imports, callback);
+ });
+ });
+ }
+ return instantiateArrayBuffer(binaryFile, imports, callback);
+}
+
+function createWasm() {
+ var info = {
+ "env": wasmImports,
+ "wasi_snapshot_preview1": wasmImports
+ };
+ function receiveInstance(instance, module) {
+ var exports = instance.exports;
+ wasmExports = exports;
+ wasmMemory = wasmExports["memory"];
+ updateMemoryViews();
+ wasmTable = wasmExports["__indirect_function_table"];
+ addOnInit(wasmExports["__wasm_call_ctors"]);
+ removeRunDependency("wasm-instantiate");
+ return exports;
+ }
+ addRunDependency("wasm-instantiate");
+ function receiveInstantiationResult(result) {
+ receiveInstance(result["instance"]);
+ }
+ if (Module["instantiateWasm"]) {
+ try {
+ return Module["instantiateWasm"](info, receiveInstance);
+ } catch (e) {
+ err(`Module.instantiateWasm callback failed with error: ${e}`);
+ return false;
+ }
+ }
+ instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
+ return {};
+}
+
+var tempDouble;
+
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = `Program terminated with exit(${status})`;
+ this.status = status;
+}
+
+var callRuntimeCallbacks = callbacks => {
+ while (callbacks.length > 0) {
+ callbacks.shift()(Module);
+ }
+};
+
+var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
+
+var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
+ var endIdx = idx + maxBytesToRead;
+ var endPtr = idx;
+ while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
+ if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
+ return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
+ }
+ var str = "";
+ while (idx < endPtr) {
+ var u0 = heapOrArray[idx++];
+ if (!(u0 & 128)) {
+ str += String.fromCharCode(u0);
+ continue;
+ }
+ var u1 = heapOrArray[idx++] & 63;
+ if ((u0 & 224) == 192) {
+ str += String.fromCharCode((u0 & 31) << 6 | u1);
+ continue;
+ }
+ var u2 = heapOrArray[idx++] & 63;
+ if ((u0 & 240) == 224) {
+ u0 = (u0 & 15) << 12 | u1 << 6 | u2;
+ } else {
+ u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
+ }
+ if (u0 < 65536) {
+ str += String.fromCharCode(u0);
+ } else {
+ var ch = u0 - 65536;
+ str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
+ }
+ }
+ return str;
+};
+
+var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
+
+var ___assert_fail = (condition, filename, line, func) => {
+ abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
+};
+
+function ExceptionInfo(excPtr) {
+ this.excPtr = excPtr;
+ this.ptr = excPtr - 24;
+ this.set_type = function(type) {
+ HEAPU32[this.ptr + 4 >> 2] = type;
+ };
+ this.get_type = function() {
+ return HEAPU32[this.ptr + 4 >> 2];
+ };
+ this.set_destructor = function(destructor) {
+ HEAPU32[this.ptr + 8 >> 2] = destructor;
+ };
+ this.get_destructor = function() {
+ return HEAPU32[this.ptr + 8 >> 2];
+ };
+ this.set_caught = function(caught) {
+ caught = caught ? 1 : 0;
+ HEAP8[this.ptr + 12 >> 0] = caught;
+ };
+ this.get_caught = function() {
+ return HEAP8[this.ptr + 12 >> 0] != 0;
+ };
+ this.set_rethrown = function(rethrown) {
+ rethrown = rethrown ? 1 : 0;
+ HEAP8[this.ptr + 13 >> 0] = rethrown;
+ };
+ this.get_rethrown = function() {
+ return HEAP8[this.ptr + 13 >> 0] != 0;
+ };
+ this.init = function(type, destructor) {
+ this.set_adjusted_ptr(0);
+ this.set_type(type);
+ this.set_destructor(destructor);
+ };
+ this.set_adjusted_ptr = function(adjustedPtr) {
+ HEAPU32[this.ptr + 16 >> 2] = adjustedPtr;
+ };
+ this.get_adjusted_ptr = function() {
+ return HEAPU32[this.ptr + 16 >> 2];
+ };
+ this.get_exception_ptr = function() {
+ var isPointer = ___cxa_is_pointer_type(this.get_type());
+ if (isPointer) {
+ return HEAPU32[this.excPtr >> 2];
+ }
+ var adjusted = this.get_adjusted_ptr();
+ if (adjusted !== 0) return adjusted;
+ return this.excPtr;
+ };
+}
+
+var exceptionLast = 0;
+
+var uncaughtExceptionCount = 0;
+
+var ___cxa_throw = (ptr, type, destructor) => {
+ var info = new ExceptionInfo(ptr);
+ info.init(type, destructor);
+ exceptionLast = ptr;
+ uncaughtExceptionCount++;
+ throw exceptionLast;
+};
+
+var SYSCALLS = {
+ varargs: undefined,
+ get() {
+ var ret = HEAP32[SYSCALLS.varargs >> 2];
+ SYSCALLS.varargs += 4;
+ return ret;
+ },
+ getp() {
+ return SYSCALLS.get();
+ },
+ getStr(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ }
+};
+
+function ___syscall_ioctl(fd, op, varargs) {
+ SYSCALLS.varargs = varargs;
+ return 0;
+}
+
+function ___syscall_openat(dirfd, path, flags, varargs) {
+ SYSCALLS.varargs = varargs;
+}
+
+var __embind_register_bigint = (primitiveType, name, size, minRange, maxRange) => {};
+
+var embind_init_charCodes = () => {
+ var codes = new Array(256);
+ for (var i = 0; i < 256; ++i) {
+ codes[i] = String.fromCharCode(i);
+ }
+ embind_charCodes = codes;
+};
+
+var embind_charCodes = undefined;
+
+var readLatin1String = ptr => {
+ var ret = "";
+ var c = ptr;
+ while (HEAPU8[c]) {
+ ret += embind_charCodes[HEAPU8[c++]];
+ }
+ return ret;
+};
+
+var awaitingDependencies = {};
+
+var registeredTypes = {};
+
+var typeDependencies = {};
+
+var BindingError = undefined;
+
+var throwBindingError = message => {
+ throw new BindingError(message);
+};
+
+var InternalError = undefined;
+
+var throwInternalError = message => {
+ throw new InternalError(message);
+};
+
+var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => {
+ myTypes.forEach(function(type) {
+ typeDependencies[type] = dependentTypes;
+ });
+ function onComplete(typeConverters) {
+ var myTypeConverters = getTypeConverters(typeConverters);
+ if (myTypeConverters.length !== myTypes.length) {
+ throwInternalError("Mismatched type converter count");
+ }
+ for (var i = 0; i < myTypes.length; ++i) {
+ registerType(myTypes[i], myTypeConverters[i]);
+ }
+ }
+ var typeConverters = new Array(dependentTypes.length);
+ var unregisteredTypes = [];
+ var registered = 0;
+ dependentTypes.forEach((dt, i) => {
+ if (registeredTypes.hasOwnProperty(dt)) {
+ typeConverters[i] = registeredTypes[dt];
+ } else {
+ unregisteredTypes.push(dt);
+ if (!awaitingDependencies.hasOwnProperty(dt)) {
+ awaitingDependencies[dt] = [];
+ }
+ awaitingDependencies[dt].push(() => {
+ typeConverters[i] = registeredTypes[dt];
+ ++registered;
+ if (registered === unregisteredTypes.length) {
+ onComplete(typeConverters);
+ }
+ });
+ }
+ });
+ if (0 === unregisteredTypes.length) {
+ onComplete(typeConverters);
+ }
+};
+
+function sharedRegisterType(rawType, registeredInstance, options = {}) {
+ var name = registeredInstance.name;
+ if (!rawType) {
+ throwBindingError(`type "${name}" must have a positive integer typeid pointer`);
+ }
+ if (registeredTypes.hasOwnProperty(rawType)) {
+ if (options.ignoreDuplicateRegistrations) {
+ return;
+ } else {
+ throwBindingError(`Cannot register type '${name}' twice`);
+ }
+ }
+ registeredTypes[rawType] = registeredInstance;
+ delete typeDependencies[rawType];
+ if (awaitingDependencies.hasOwnProperty(rawType)) {
+ var callbacks = awaitingDependencies[rawType];
+ delete awaitingDependencies[rawType];
+ callbacks.forEach(cb => cb());
+ }
+}
+
+function registerType(rawType, registeredInstance, options = {}) {
+ if (!("argPackAdvance" in registeredInstance)) {
+ throw new TypeError("registerType registeredInstance requires argPackAdvance");
+ }
+ return sharedRegisterType(rawType, registeredInstance, options);
+}
+
+var GenericWireTypeSize = 8;
+
+var __embind_register_bool = (rawType, name, trueValue, falseValue) => {
+ name = readLatin1String(name);
+ registerType(rawType, {
+ name: name,
+ "fromWireType": function(wt) {
+ return !!wt;
+ },
+ "toWireType": function(destructors, o) {
+ return o ? trueValue : falseValue;
+ },
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": function(pointer) {
+ return this["fromWireType"](HEAPU8[pointer]);
+ },
+ destructorFunction: null
+ });
+};
+
+function ClassHandle_isAliasOf(other) {
+ if (!(this instanceof ClassHandle)) {
+ return false;
+ }
+ if (!(other instanceof ClassHandle)) {
+ return false;
+ }
+ var leftClass = this.$$.ptrType.registeredClass;
+ var left = this.$$.ptr;
+ var rightClass = other.$$.ptrType.registeredClass;
+ var right = other.$$.ptr;
+ while (leftClass.baseClass) {
+ left = leftClass.upcast(left);
+ leftClass = leftClass.baseClass;
+ }
+ while (rightClass.baseClass) {
+ right = rightClass.upcast(right);
+ rightClass = rightClass.baseClass;
+ }
+ return leftClass === rightClass && left === right;
+}
+
+var shallowCopyInternalPointer = o => ({
+ count: o.count,
+ deleteScheduled: o.deleteScheduled,
+ preservePointerOnDelete: o.preservePointerOnDelete,
+ ptr: o.ptr,
+ ptrType: o.ptrType,
+ smartPtr: o.smartPtr,
+ smartPtrType: o.smartPtrType
+});
+
+var throwInstanceAlreadyDeleted = obj => {
+ function getInstanceTypeName(handle) {
+ return handle.$$.ptrType.registeredClass.name;
+ }
+ throwBindingError(getInstanceTypeName(obj) + " instance already deleted");
+};
+
+var finalizationRegistry = false;
+
+var detachFinalizer = handle => {};
+
+var runDestructor = $$ => {
+ if ($$.smartPtr) {
+ $$.smartPtrType.rawDestructor($$.smartPtr);
+ } else {
+ $$.ptrType.registeredClass.rawDestructor($$.ptr);
+ }
+};
+
+var releaseClassHandle = $$ => {
+ $$.count.value -= 1;
+ var toDelete = 0 === $$.count.value;
+ if (toDelete) {
+ runDestructor($$);
+ }
+};
+
+var downcastPointer = (ptr, ptrClass, desiredClass) => {
+ if (ptrClass === desiredClass) {
+ return ptr;
+ }
+ if (undefined === desiredClass.baseClass) {
+ return null;
+ }
+ var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass);
+ if (rv === null) {
+ return null;
+ }
+ return desiredClass.downcast(rv);
+};
+
+var registeredPointers = {};
+
+var getInheritedInstanceCount = () => Object.keys(registeredInstances).length;
+
+var getLiveInheritedInstances = () => {
+ var rv = [];
+ for (var k in registeredInstances) {
+ if (registeredInstances.hasOwnProperty(k)) {
+ rv.push(registeredInstances[k]);
+ }
+ }
+ return rv;
+};
+
+var deletionQueue = [];
+
+var flushPendingDeletes = () => {
+ while (deletionQueue.length) {
+ var obj = deletionQueue.pop();
+ obj.$$.deleteScheduled = false;
+ obj["delete"]();
+ }
+};
+
+var delayFunction = undefined;
+
+var setDelayFunction = fn => {
+ delayFunction = fn;
+ if (deletionQueue.length && delayFunction) {
+ delayFunction(flushPendingDeletes);
+ }
+};
+
+var init_embind = () => {
+ Module["getInheritedInstanceCount"] = getInheritedInstanceCount;
+ Module["getLiveInheritedInstances"] = getLiveInheritedInstances;
+ Module["flushPendingDeletes"] = flushPendingDeletes;
+ Module["setDelayFunction"] = setDelayFunction;
+};
+
+var registeredInstances = {};
+
+var getBasestPointer = (class_, ptr) => {
+ if (ptr === undefined) {
+ throwBindingError("ptr should not be undefined");
+ }
+ while (class_.baseClass) {
+ ptr = class_.upcast(ptr);
+ class_ = class_.baseClass;
+ }
+ return ptr;
+};
+
+var getInheritedInstance = (class_, ptr) => {
+ ptr = getBasestPointer(class_, ptr);
+ return registeredInstances[ptr];
+};
+
+var makeClassHandle = (prototype, record) => {
+ if (!record.ptrType || !record.ptr) {
+ throwInternalError("makeClassHandle requires ptr and ptrType");
+ }
+ var hasSmartPtrType = !!record.smartPtrType;
+ var hasSmartPtr = !!record.smartPtr;
+ if (hasSmartPtrType !== hasSmartPtr) {
+ throwInternalError("Both smartPtrType and smartPtr must be specified");
+ }
+ record.count = {
+ value: 1
+ };
+ return attachFinalizer(Object.create(prototype, {
+ $$: {
+ value: record
+ }
+ }));
+};
+
+function RegisteredPointer_fromWireType(ptr) {
+ var rawPointer = this.getPointee(ptr);
+ if (!rawPointer) {
+ this.destructor(ptr);
+ return null;
+ }
+ var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer);
+ if (undefined !== registeredInstance) {
+ if (0 === registeredInstance.$$.count.value) {
+ registeredInstance.$$.ptr = rawPointer;
+ registeredInstance.$$.smartPtr = ptr;
+ return registeredInstance["clone"]();
+ } else {
+ var rv = registeredInstance["clone"]();
+ this.destructor(ptr);
+ return rv;
+ }
+ }
+ function makeDefaultHandle() {
+ if (this.isSmartPointer) {
+ return makeClassHandle(this.registeredClass.instancePrototype, {
+ ptrType: this.pointeeType,
+ ptr: rawPointer,
+ smartPtrType: this,
+ smartPtr: ptr
+ });
+ } else {
+ return makeClassHandle(this.registeredClass.instancePrototype, {
+ ptrType: this,
+ ptr: ptr
+ });
+ }
+ }
+ var actualType = this.registeredClass.getActualType(rawPointer);
+ var registeredPointerRecord = registeredPointers[actualType];
+ if (!registeredPointerRecord) {
+ return makeDefaultHandle.call(this);
+ }
+ var toType;
+ if (this.isConst) {
+ toType = registeredPointerRecord.constPointerType;
+ } else {
+ toType = registeredPointerRecord.pointerType;
+ }
+ var dp = downcastPointer(rawPointer, this.registeredClass, toType.registeredClass);
+ if (dp === null) {
+ return makeDefaultHandle.call(this);
+ }
+ if (this.isSmartPointer) {
+ return makeClassHandle(toType.registeredClass.instancePrototype, {
+ ptrType: toType,
+ ptr: dp,
+ smartPtrType: this,
+ smartPtr: ptr
+ });
+ } else {
+ return makeClassHandle(toType.registeredClass.instancePrototype, {
+ ptrType: toType,
+ ptr: dp
+ });
+ }
+}
+
+var attachFinalizer = handle => {
+ if ("undefined" === typeof FinalizationRegistry) {
+ attachFinalizer = handle => handle;
+ return handle;
+ }
+ finalizationRegistry = new FinalizationRegistry(info => {
+ releaseClassHandle(info.$$);
+ });
+ attachFinalizer = handle => {
+ var $$ = handle.$$;
+ var hasSmartPtr = !!$$.smartPtr;
+ if (hasSmartPtr) {
+ var info = {
+ $$: $$
+ };
+ finalizationRegistry.register(handle, info, handle);
+ }
+ return handle;
+ };
+ detachFinalizer = handle => finalizationRegistry.unregister(handle);
+ return attachFinalizer(handle);
+};
+
+function ClassHandle_clone() {
+ if (!this.$$.ptr) {
+ throwInstanceAlreadyDeleted(this);
+ }
+ if (this.$$.preservePointerOnDelete) {
+ this.$$.count.value += 1;
+ return this;
+ } else {
+ var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), {
+ $$: {
+ value: shallowCopyInternalPointer(this.$$)
+ }
+ }));
+ clone.$$.count.value += 1;
+ clone.$$.deleteScheduled = false;
+ return clone;
+ }
+}
+
+function ClassHandle_delete() {
+ if (!this.$$.ptr) {
+ throwInstanceAlreadyDeleted(this);
+ }
+ if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {
+ throwBindingError("Object already scheduled for deletion");
+ }
+ detachFinalizer(this);
+ releaseClassHandle(this.$$);
+ if (!this.$$.preservePointerOnDelete) {
+ this.$$.smartPtr = undefined;
+ this.$$.ptr = undefined;
+ }
+}
+
+function ClassHandle_isDeleted() {
+ return !this.$$.ptr;
+}
+
+function ClassHandle_deleteLater() {
+ if (!this.$$.ptr) {
+ throwInstanceAlreadyDeleted(this);
+ }
+ if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {
+ throwBindingError("Object already scheduled for deletion");
+ }
+ deletionQueue.push(this);
+ if (deletionQueue.length === 1 && delayFunction) {
+ delayFunction(flushPendingDeletes);
+ }
+ this.$$.deleteScheduled = true;
+ return this;
+}
+
+var init_ClassHandle = () => {
+ ClassHandle.prototype["isAliasOf"] = ClassHandle_isAliasOf;
+ ClassHandle.prototype["clone"] = ClassHandle_clone;
+ ClassHandle.prototype["delete"] = ClassHandle_delete;
+ ClassHandle.prototype["isDeleted"] = ClassHandle_isDeleted;
+ ClassHandle.prototype["deleteLater"] = ClassHandle_deleteLater;
+};
+
+function ClassHandle() {}
+
+var char_0 = 48;
+
+var char_9 = 57;
+
+var makeLegalFunctionName = name => {
+ if (undefined === name) {
+ return "_unknown";
+ }
+ name = name.replace(/[^a-zA-Z0-9_]/g, "$");
+ var f = name.charCodeAt(0);
+ if (f >= char_0 && f <= char_9) {
+ return `_${name}`;
+ }
+ return name;
+};
+
+function createNamedFunction(name, body) {
+ name = makeLegalFunctionName(name);
+ return {
+ [name]: function() {
+ return body.apply(this, arguments);
+ }
+ }[name];
+}
+
+var ensureOverloadTable = (proto, methodName, humanName) => {
+ if (undefined === proto[methodName].overloadTable) {
+ var prevFunc = proto[methodName];
+ proto[methodName] = function() {
+ if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) {
+ throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`);
+ }
+ return proto[methodName].overloadTable[arguments.length].apply(this, arguments);
+ };
+ proto[methodName].overloadTable = [];
+ proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
+ }
+};
+
+var exposePublicSymbol = (name, value, numArguments) => {
+ if (Module.hasOwnProperty(name)) {
+ if (undefined === numArguments || undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments]) {
+ throwBindingError(`Cannot register public name '${name}' twice`);
+ }
+ ensureOverloadTable(Module, name, name);
+ if (Module.hasOwnProperty(numArguments)) {
+ throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`);
+ }
+ Module[name].overloadTable[numArguments] = value;
+ } else {
+ Module[name] = value;
+ if (undefined !== numArguments) {
+ Module[name].numArguments = numArguments;
+ }
+ }
+};
+
+function RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast) {
+ this.name = name;
+ this.constructor = constructor;
+ this.instancePrototype = instancePrototype;
+ this.rawDestructor = rawDestructor;
+ this.baseClass = baseClass;
+ this.getActualType = getActualType;
+ this.upcast = upcast;
+ this.downcast = downcast;
+ this.pureVirtualFunctions = [];
+}
+
+var upcastPointer = (ptr, ptrClass, desiredClass) => {
+ while (ptrClass !== desiredClass) {
+ if (!ptrClass.upcast) {
+ throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`);
+ }
+ ptr = ptrClass.upcast(ptr);
+ ptrClass = ptrClass.baseClass;
+ }
+ return ptr;
+};
+
+function constNoSmartPtrRawPointerToWireType(destructors, handle) {
+ if (handle === null) {
+ if (this.isReference) {
+ throwBindingError(`null is not a valid ${this.name}`);
+ }
+ return 0;
+ }
+ if (!handle.$$) {
+ throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`);
+ }
+ if (!handle.$$.ptr) {
+ throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`);
+ }
+ var handleClass = handle.$$.ptrType.registeredClass;
+ var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);
+ return ptr;
+}
+
+function genericPointerToWireType(destructors, handle) {
+ var ptr;
+ if (handle === null) {
+ if (this.isReference) {
+ throwBindingError(`null is not a valid ${this.name}`);
+ }
+ if (this.isSmartPointer) {
+ ptr = this.rawConstructor();
+ if (destructors !== null) {
+ destructors.push(this.rawDestructor, ptr);
+ }
+ return ptr;
+ } else {
+ return 0;
+ }
+ }
+ if (!handle.$$) {
+ throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`);
+ }
+ if (!handle.$$.ptr) {
+ throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`);
+ }
+ if (!this.isConst && handle.$$.ptrType.isConst) {
+ throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name} to parameter type ${this.name}`);
+ }
+ var handleClass = handle.$$.ptrType.registeredClass;
+ ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);
+ if (this.isSmartPointer) {
+ if (undefined === handle.$$.smartPtr) {
+ throwBindingError("Passing raw pointer to smart pointer is illegal");
+ }
+ switch (this.sharingPolicy) {
+ case 0:
+ if (handle.$$.smartPtrType === this) {
+ ptr = handle.$$.smartPtr;
+ } else {
+ throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name} to parameter type ${this.name}`);
+ }
+ break;
+
+ case 1:
+ ptr = handle.$$.smartPtr;
+ break;
+
+ case 2:
+ if (handle.$$.smartPtrType === this) {
+ ptr = handle.$$.smartPtr;
+ } else {
+ var clonedHandle = handle["clone"]();
+ ptr = this.rawShare(ptr, Emval.toHandle(() => clonedHandle["delete"]()));
+ if (destructors !== null) {
+ destructors.push(this.rawDestructor, ptr);
+ }
+ }
+ break;
+
+ default:
+ throwBindingError("Unsupporting sharing policy");
+ }
+ }
+ return ptr;
+}
+
+function nonConstNoSmartPtrRawPointerToWireType(destructors, handle) {
+ if (handle === null) {
+ if (this.isReference) {
+ throwBindingError(`null is not a valid ${this.name}`);
+ }
+ return 0;
+ }
+ if (!handle.$$) {
+ throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`);
+ }
+ if (!handle.$$.ptr) {
+ throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`);
+ }
+ if (handle.$$.ptrType.isConst) {
+ throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`);
+ }
+ var handleClass = handle.$$.ptrType.registeredClass;
+ var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);
+ return ptr;
+}
+
+function readPointer(pointer) {
+ return this["fromWireType"](HEAPU32[pointer >> 2]);
+}
+
+function RegisteredPointer_getPointee(ptr) {
+ if (this.rawGetPointee) {
+ ptr = this.rawGetPointee(ptr);
+ }
+ return ptr;
+}
+
+function RegisteredPointer_destructor(ptr) {
+ if (this.rawDestructor) {
+ this.rawDestructor(ptr);
+ }
+}
+
+var RegisteredPointer_deleteObject = handle => {
+ if (handle !== null) {
+ handle["delete"]();
+ }
+};
+
+var init_RegisteredPointer = () => {
+ RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee;
+ RegisteredPointer.prototype.destructor = RegisteredPointer_destructor;
+ RegisteredPointer.prototype["argPackAdvance"] = GenericWireTypeSize;
+ RegisteredPointer.prototype["readValueFromPointer"] = readPointer;
+ RegisteredPointer.prototype["deleteObject"] = RegisteredPointer_deleteObject;
+ RegisteredPointer.prototype["fromWireType"] = RegisteredPointer_fromWireType;
+};
+
+function RegisteredPointer(name, registeredClass, isReference, isConst, isSmartPointer, pointeeType, sharingPolicy, rawGetPointee, rawConstructor, rawShare, rawDestructor) {
+ this.name = name;
+ this.registeredClass = registeredClass;
+ this.isReference = isReference;
+ this.isConst = isConst;
+ this.isSmartPointer = isSmartPointer;
+ this.pointeeType = pointeeType;
+ this.sharingPolicy = sharingPolicy;
+ this.rawGetPointee = rawGetPointee;
+ this.rawConstructor = rawConstructor;
+ this.rawShare = rawShare;
+ this.rawDestructor = rawDestructor;
+ if (!isSmartPointer && registeredClass.baseClass === undefined) {
+ if (isConst) {
+ this["toWireType"] = constNoSmartPtrRawPointerToWireType;
+ this.destructorFunction = null;
+ } else {
+ this["toWireType"] = nonConstNoSmartPtrRawPointerToWireType;
+ this.destructorFunction = null;
+ }
+ } else {
+ this["toWireType"] = genericPointerToWireType;
+ }
+}
+
+var replacePublicSymbol = (name, value, numArguments) => {
+ if (!Module.hasOwnProperty(name)) {
+ throwInternalError("Replacing nonexistant public symbol");
+ }
+ if (undefined !== Module[name].overloadTable && undefined !== numArguments) {
+ Module[name].overloadTable[numArguments] = value;
+ } else {
+ Module[name] = value;
+ Module[name].argCount = numArguments;
+ }
+};
+
+var dynCallLegacy = (sig, ptr, args) => {
+ var f = Module["dynCall_" + sig];
+ return args && args.length ? f.apply(null, [ ptr ].concat(args)) : f.call(null, ptr);
+};
+
+var wasmTableMirror = [];
+
+var getWasmTableEntry = funcPtr => {
+ var func = wasmTableMirror[funcPtr];
+ if (!func) {
+ if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
+ wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
+ }
+ return func;
+};
+
+var dynCall = (sig, ptr, args) => {
+ if (sig.includes("j")) {
+ return dynCallLegacy(sig, ptr, args);
+ }
+ var rtn = getWasmTableEntry(ptr).apply(null, args);
+ return rtn;
+};
+
+var getDynCaller = (sig, ptr) => {
+ var argCache = [];
+ return function() {
+ argCache.length = 0;
+ Object.assign(argCache, arguments);
+ return dynCall(sig, ptr, argCache);
+ };
+};
+
+var embind__requireFunction = (signature, rawFunction) => {
+ signature = readLatin1String(signature);
+ function makeDynCaller() {
+ if (signature.includes("j")) {
+ return getDynCaller(signature, rawFunction);
+ }
+ return getWasmTableEntry(rawFunction);
+ }
+ var fp = makeDynCaller();
+ if (typeof fp != "function") {
+ throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`);
+ }
+ return fp;
+};
+
+var extendError = (baseErrorType, errorName) => {
+ var errorClass = createNamedFunction(errorName, function(message) {
+ this.name = errorName;
+ this.message = message;
+ var stack = new Error(message).stack;
+ if (stack !== undefined) {
+ this.stack = this.toString() + "\n" + stack.replace(/^Error(:[^\n]*)?\n/, "");
+ }
+ });
+ errorClass.prototype = Object.create(baseErrorType.prototype);
+ errorClass.prototype.constructor = errorClass;
+ errorClass.prototype.toString = function() {
+ if (this.message === undefined) {
+ return this.name;
+ } else {
+ return `${this.name}: ${this.message}`;
+ }
+ };
+ return errorClass;
+};
+
+var UnboundTypeError = undefined;
+
+var getTypeName = type => {
+ var ptr = ___getTypeName(type);
+ var rv = readLatin1String(ptr);
+ _free(ptr);
+ return rv;
+};
+
+var throwUnboundTypeError = (message, types) => {
+ var unboundTypes = [];
+ var seen = {};
+ function visit(type) {
+ if (seen[type]) {
+ return;
+ }
+ if (registeredTypes[type]) {
+ return;
+ }
+ if (typeDependencies[type]) {
+ typeDependencies[type].forEach(visit);
+ return;
+ }
+ unboundTypes.push(type);
+ seen[type] = true;
+ }
+ types.forEach(visit);
+ throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([ ", " ]));
+};
+
+var __embind_register_class = (rawType, rawPointerType, rawConstPointerType, baseClassRawType, getActualTypeSignature, getActualType, upcastSignature, upcast, downcastSignature, downcast, name, destructorSignature, rawDestructor) => {
+ name = readLatin1String(name);
+ getActualType = embind__requireFunction(getActualTypeSignature, getActualType);
+ if (upcast) {
+ upcast = embind__requireFunction(upcastSignature, upcast);
+ }
+ if (downcast) {
+ downcast = embind__requireFunction(downcastSignature, downcast);
+ }
+ rawDestructor = embind__requireFunction(destructorSignature, rawDestructor);
+ var legalFunctionName = makeLegalFunctionName(name);
+ exposePublicSymbol(legalFunctionName, function() {
+ throwUnboundTypeError(`Cannot construct ${name} due to unbound types`, [ baseClassRawType ]);
+ });
+ whenDependentTypesAreResolved([ rawType, rawPointerType, rawConstPointerType ], baseClassRawType ? [ baseClassRawType ] : [], function(base) {
+ base = base[0];
+ var baseClass;
+ var basePrototype;
+ if (baseClassRawType) {
+ baseClass = base.registeredClass;
+ basePrototype = baseClass.instancePrototype;
+ } else {
+ basePrototype = ClassHandle.prototype;
+ }
+ var constructor = createNamedFunction(legalFunctionName, function() {
+ if (Object.getPrototypeOf(this) !== instancePrototype) {
+ throw new BindingError("Use 'new' to construct " + name);
+ }
+ if (undefined === registeredClass.constructor_body) {
+ throw new BindingError(name + " has no accessible constructor");
+ }
+ var body = registeredClass.constructor_body[arguments.length];
+ if (undefined === body) {
+ throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${arguments.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`);
+ }
+ return body.apply(this, arguments);
+ });
+ var instancePrototype = Object.create(basePrototype, {
+ constructor: {
+ value: constructor
+ }
+ });
+ constructor.prototype = instancePrototype;
+ var registeredClass = new RegisteredClass(name, constructor, instancePrototype, rawDestructor, baseClass, getActualType, upcast, downcast);
+ if (registeredClass.baseClass) {
+ if (registeredClass.baseClass.__derivedClasses === undefined) {
+ registeredClass.baseClass.__derivedClasses = [];
+ }
+ registeredClass.baseClass.__derivedClasses.push(registeredClass);
+ }
+ var referenceConverter = new RegisteredPointer(name, registeredClass, true, false, false);
+ var pointerConverter = new RegisteredPointer(name + "*", registeredClass, false, false, false);
+ var constPointerConverter = new RegisteredPointer(name + " const*", registeredClass, false, true, false);
+ registeredPointers[rawType] = {
+ pointerType: pointerConverter,
+ constPointerType: constPointerConverter
+ };
+ replacePublicSymbol(legalFunctionName, constructor);
+ return [ referenceConverter, pointerConverter, constPointerConverter ];
+ });
+};
+
+var heap32VectorToArray = (count, firstElement) => {
+ var array = [];
+ for (var i = 0; i < count; i++) {
+ array.push(HEAPU32[firstElement + i * 4 >> 2]);
+ }
+ return array;
+};
+
+var runDestructors = destructors => {
+ while (destructors.length) {
+ var ptr = destructors.pop();
+ var del = destructors.pop();
+ del(ptr);
+ }
+};
+
+function newFunc(constructor, argumentList) {
+ if (!(constructor instanceof Function)) {
+ throw new TypeError(`new_ called with constructor type ${typeof constructor} which is not a function`);
+ }
+ var dummy = createNamedFunction(constructor.name || "unknownFunctionName", function() {});
+ dummy.prototype = constructor.prototype;
+ var obj = new dummy;
+ var r = constructor.apply(obj, argumentList);
+ return r instanceof Object ? r : obj;
+}
+
+function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc, isAsync) {
+ var argCount = argTypes.length;
+ if (argCount < 2) {
+ throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!");
+ }
+ var isClassMethodFunc = argTypes[1] !== null && classType !== null;
+ var needsDestructorStack = false;
+ for (var i = 1; i < argTypes.length; ++i) {
+ if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) {
+ needsDestructorStack = true;
+ break;
+ }
+ }
+ var returns = argTypes[0].name !== "void";
+ var argsList = "";
+ var argsListWired = "";
+ for (var i = 0; i < argCount - 2; ++i) {
+ argsList += (i !== 0 ? ", " : "") + "arg" + i;
+ argsListWired += (i !== 0 ? ", " : "") + "arg" + i + "Wired";
+ }
+ var invokerFnBody = `\n return function ${makeLegalFunctionName(humanName)}(${argsList}) {\n if (arguments.length !== ${argCount - 2}) {\n throwBindingError('function ${humanName} called with ' + arguments.length + ' arguments, expected ${argCount - 2}');\n }`;
+ if (needsDestructorStack) {
+ invokerFnBody += "var destructors = [];\n";
+ }
+ var dtorStack = needsDestructorStack ? "destructors" : "null";
+ var args1 = [ "throwBindingError", "invoker", "fn", "runDestructors", "retType", "classParam" ];
+ var args2 = [ throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1] ];
+ if (isClassMethodFunc) {
+ invokerFnBody += "var thisWired = classParam.toWireType(" + dtorStack + ", this);\n";
+ }
+ for (var i = 0; i < argCount - 2; ++i) {
+ invokerFnBody += "var arg" + i + "Wired = argType" + i + ".toWireType(" + dtorStack + ", arg" + i + "); // " + argTypes[i + 2].name + "\n";
+ args1.push("argType" + i);
+ args2.push(argTypes[i + 2]);
+ }
+ if (isClassMethodFunc) {
+ argsListWired = "thisWired" + (argsListWired.length > 0 ? ", " : "") + argsListWired;
+ }
+ invokerFnBody += (returns || isAsync ? "var rv = " : "") + "invoker(fn" + (argsListWired.length > 0 ? ", " : "") + argsListWired + ");\n";
+ if (needsDestructorStack) {
+ invokerFnBody += "runDestructors(destructors);\n";
+ } else {
+ for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; ++i) {
+ var paramName = i === 1 ? "thisWired" : "arg" + (i - 2) + "Wired";
+ if (argTypes[i].destructorFunction !== null) {
+ invokerFnBody += paramName + "_dtor(" + paramName + "); // " + argTypes[i].name + "\n";
+ args1.push(paramName + "_dtor");
+ args2.push(argTypes[i].destructorFunction);
+ }
+ }
+ }
+ if (returns) {
+ invokerFnBody += "var ret = retType.fromWireType(rv);\n" + "return ret;\n";
+ } else {}
+ invokerFnBody += "}\n";
+ args1.push(invokerFnBody);
+ return newFunc(Function, args1).apply(null, args2);
+}
+
+var __embind_register_class_constructor = (rawClassType, argCount, rawArgTypesAddr, invokerSignature, invoker, rawConstructor) => {
+ var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
+ invoker = embind__requireFunction(invokerSignature, invoker);
+ whenDependentTypesAreResolved([], [ rawClassType ], function(classType) {
+ classType = classType[0];
+ var humanName = `constructor ${classType.name}`;
+ if (undefined === classType.registeredClass.constructor_body) {
+ classType.registeredClass.constructor_body = [];
+ }
+ if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) {
+ throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount - 1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`);
+ }
+ classType.registeredClass.constructor_body[argCount - 1] = () => {
+ throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`, rawArgTypes);
+ };
+ whenDependentTypesAreResolved([], rawArgTypes, argTypes => {
+ argTypes.splice(1, 0, null);
+ classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction(humanName, argTypes, null, invoker, rawConstructor);
+ return [];
+ });
+ return [];
+ });
+};
+
+var __embind_register_class_function = (rawClassType, methodName, argCount, rawArgTypesAddr, invokerSignature, rawInvoker, context, isPureVirtual, isAsync) => {
+ var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
+ methodName = readLatin1String(methodName);
+ rawInvoker = embind__requireFunction(invokerSignature, rawInvoker);
+ whenDependentTypesAreResolved([], [ rawClassType ], function(classType) {
+ classType = classType[0];
+ var humanName = `${classType.name}.${methodName}`;
+ if (methodName.startsWith("@@")) {
+ methodName = Symbol[methodName.substring(2)];
+ }
+ if (isPureVirtual) {
+ classType.registeredClass.pureVirtualFunctions.push(methodName);
+ }
+ function unboundTypesHandler() {
+ throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`, rawArgTypes);
+ }
+ var proto = classType.registeredClass.instancePrototype;
+ var method = proto[methodName];
+ if (undefined === method || undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2) {
+ unboundTypesHandler.argCount = argCount - 2;
+ unboundTypesHandler.className = classType.name;
+ proto[methodName] = unboundTypesHandler;
+ } else {
+ ensureOverloadTable(proto, methodName, humanName);
+ proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler;
+ }
+ whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {
+ var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context, isAsync);
+ if (undefined === proto[methodName].overloadTable) {
+ memberFunction.argCount = argCount - 2;
+ proto[methodName] = memberFunction;
+ } else {
+ proto[methodName].overloadTable[argCount - 2] = memberFunction;
+ }
+ return [];
+ });
+ return [];
+ });
+};
+
+function handleAllocatorInit() {
+ Object.assign(HandleAllocator.prototype, {
+ get(id) {
+ return this.allocated[id];
+ },
+ has(id) {
+ return this.allocated[id] !== undefined;
+ },
+ allocate(handle) {
+ var id = this.freelist.pop() || this.allocated.length;
+ this.allocated[id] = handle;
+ return id;
+ },
+ free(id) {
+ this.allocated[id] = undefined;
+ this.freelist.push(id);
+ }
+ });
+}
+
+function HandleAllocator() {
+ this.allocated = [ undefined ];
+ this.freelist = [];
+}
+
+var emval_handles = new HandleAllocator;
+
+var __emval_decref = handle => {
+ if (handle >= emval_handles.reserved && 0 === --emval_handles.get(handle).refcount) {
+ emval_handles.free(handle);
+ }
+};
+
+var count_emval_handles = () => {
+ var count = 0;
+ for (var i = emval_handles.reserved; i < emval_handles.allocated.length; ++i) {
+ if (emval_handles.allocated[i] !== undefined) {
+ ++count;
+ }
+ }
+ return count;
+};
+
+var init_emval = () => {
+ emval_handles.allocated.push({
+ value: undefined
+ }, {
+ value: null
+ }, {
+ value: true
+ }, {
+ value: false
+ });
+ emval_handles.reserved = emval_handles.allocated.length;
+ Module["count_emval_handles"] = count_emval_handles;
+};
+
+var Emval = {
+ toValue: handle => {
+ if (!handle) {
+ throwBindingError("Cannot use deleted val. handle = " + handle);
+ }
+ return emval_handles.get(handle).value;
+ },
+ toHandle: value => {
+ switch (value) {
+ case undefined:
+ return 1;
+
+ case null:
+ return 2;
+
+ case true:
+ return 3;
+
+ case false:
+ return 4;
+
+ default:
+ {
+ return emval_handles.allocate({
+ refcount: 1,
+ value: value
+ });
+ }
+ }
+ }
+};
+
+function simpleReadValueFromPointer(pointer) {
+ return this["fromWireType"](HEAP32[pointer >> 2]);
+}
+
+var __embind_register_emval = (rawType, name) => {
+ name = readLatin1String(name);
+ registerType(rawType, {
+ name: name,
+ "fromWireType": handle => {
+ var rv = Emval.toValue(handle);
+ __emval_decref(handle);
+ return rv;
+ },
+ "toWireType": (destructors, value) => Emval.toHandle(value),
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": simpleReadValueFromPointer,
+ destructorFunction: null
+ });
+};
+
+var embindRepr = v => {
+ if (v === null) {
+ return "null";
+ }
+ var t = typeof v;
+ if (t === "object" || t === "array" || t === "function") {
+ return v.toString();
+ } else {
+ return "" + v;
+ }
+};
+
+var floatReadValueFromPointer = (name, width) => {
+ switch (width) {
+ case 4:
+ return function(pointer) {
+ return this["fromWireType"](HEAPF32[pointer >> 2]);
+ };
+
+ case 8:
+ return function(pointer) {
+ return this["fromWireType"](HEAPF64[pointer >> 3]);
+ };
+
+ default:
+ throw new TypeError(`invalid float width (${width}): ${name}`);
+ }
+};
+
+var __embind_register_float = (rawType, name, size) => {
+ name = readLatin1String(name);
+ registerType(rawType, {
+ name: name,
+ "fromWireType": value => value,
+ "toWireType": (destructors, value) => value,
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": floatReadValueFromPointer(name, size),
+ destructorFunction: null
+ });
+};
+
+var integerReadValueFromPointer = (name, width, signed) => {
+ switch (width) {
+ case 1:
+ return signed ? pointer => HEAP8[pointer >> 0] : pointer => HEAPU8[pointer >> 0];
+
+ case 2:
+ return signed ? pointer => HEAP16[pointer >> 1] : pointer => HEAPU16[pointer >> 1];
+
+ case 4:
+ return signed ? pointer => HEAP32[pointer >> 2] : pointer => HEAPU32[pointer >> 2];
+
+ default:
+ throw new TypeError(`invalid integer width (${width}): ${name}`);
+ }
+};
+
+var __embind_register_integer = (primitiveType, name, size, minRange, maxRange) => {
+ name = readLatin1String(name);
+ if (maxRange === -1) {
+ maxRange = 4294967295;
+ }
+ var fromWireType = value => value;
+ if (minRange === 0) {
+ var bitshift = 32 - 8 * size;
+ fromWireType = value => value << bitshift >>> bitshift;
+ }
+ var isUnsignedType = name.includes("unsigned");
+ var checkAssertions = (value, toTypeName) => {};
+ var toWireType;
+ if (isUnsignedType) {
+ toWireType = function(destructors, value) {
+ checkAssertions(value, this.name);
+ return value >>> 0;
+ };
+ } else {
+ toWireType = function(destructors, value) {
+ checkAssertions(value, this.name);
+ return value;
+ };
+ }
+ registerType(primitiveType, {
+ name: name,
+ "fromWireType": fromWireType,
+ "toWireType": toWireType,
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": integerReadValueFromPointer(name, size, minRange !== 0),
+ destructorFunction: null
+ });
+};
+
+var __embind_register_memory_view = (rawType, dataTypeIndex, name) => {
+ var typeMapping = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
+ var TA = typeMapping[dataTypeIndex];
+ function decodeMemoryView(handle) {
+ var size = HEAPU32[handle >> 2];
+ var data = HEAPU32[handle + 4 >> 2];
+ return new TA(HEAP8.buffer, data, size);
+ }
+ name = readLatin1String(name);
+ registerType(rawType, {
+ name: name,
+ "fromWireType": decodeMemoryView,
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": decodeMemoryView
+ }, {
+ ignoreDuplicateRegistrations: true
+ });
+};
+
+var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
+ if (!(maxBytesToWrite > 0)) return 0;
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1;
+ for (var i = 0; i < str.length; ++i) {
+ var u = str.charCodeAt(i);
+ if (u >= 55296 && u <= 57343) {
+ var u1 = str.charCodeAt(++i);
+ u = 65536 + ((u & 1023) << 10) | u1 & 1023;
+ }
+ if (u <= 127) {
+ if (outIdx >= endIdx) break;
+ heap[outIdx++] = u;
+ } else if (u <= 2047) {
+ if (outIdx + 1 >= endIdx) break;
+ heap[outIdx++] = 192 | u >> 6;
+ heap[outIdx++] = 128 | u & 63;
+ } else if (u <= 65535) {
+ if (outIdx + 2 >= endIdx) break;
+ heap[outIdx++] = 224 | u >> 12;
+ heap[outIdx++] = 128 | u >> 6 & 63;
+ heap[outIdx++] = 128 | u & 63;
+ } else {
+ if (outIdx + 3 >= endIdx) break;
+ heap[outIdx++] = 240 | u >> 18;
+ heap[outIdx++] = 128 | u >> 12 & 63;
+ heap[outIdx++] = 128 | u >> 6 & 63;
+ heap[outIdx++] = 128 | u & 63;
+ }
+ }
+ heap[outIdx] = 0;
+ return outIdx - startIdx;
+};
+
+var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
+
+var lengthBytesUTF8 = str => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ var c = str.charCodeAt(i);
+ if (c <= 127) {
+ len++;
+ } else if (c <= 2047) {
+ len += 2;
+ } else if (c >= 55296 && c <= 57343) {
+ len += 4;
+ ++i;
+ } else {
+ len += 3;
+ }
+ }
+ return len;
+};
+
+var __embind_register_std_string = (rawType, name) => {
+ name = readLatin1String(name);
+ var stdStringIsUTF8 = name === "std::string";
+ registerType(rawType, {
+ name: name,
+ "fromWireType": value => {
+ var length = HEAPU32[value >> 2];
+ var payload = value + 4;
+ var str;
+ if (stdStringIsUTF8) {
+ var decodeStartPtr = payload;
+ for (var i = 0; i <= length; ++i) {
+ var currentBytePtr = payload + i;
+ if (i == length || HEAPU8[currentBytePtr] == 0) {
+ var maxRead = currentBytePtr - decodeStartPtr;
+ var stringSegment = UTF8ToString(decodeStartPtr, maxRead);
+ if (str === undefined) {
+ str = stringSegment;
+ } else {
+ str += String.fromCharCode(0);
+ str += stringSegment;
+ }
+ decodeStartPtr = currentBytePtr + 1;
+ }
+ }
+ } else {
+ var a = new Array(length);
+ for (var i = 0; i < length; ++i) {
+ a[i] = String.fromCharCode(HEAPU8[payload + i]);
+ }
+ str = a.join("");
+ }
+ _free(value);
+ return str;
+ },
+ "toWireType": (destructors, value) => {
+ if (value instanceof ArrayBuffer) {
+ value = new Uint8Array(value);
+ }
+ var length;
+ var valueIsOfTypeString = typeof value == "string";
+ if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) {
+ throwBindingError("Cannot pass non-string to std::string");
+ }
+ if (stdStringIsUTF8 && valueIsOfTypeString) {
+ length = lengthBytesUTF8(value);
+ } else {
+ length = value.length;
+ }
+ var base = _malloc(4 + length + 1);
+ var ptr = base + 4;
+ HEAPU32[base >> 2] = length;
+ if (stdStringIsUTF8 && valueIsOfTypeString) {
+ stringToUTF8(value, ptr, length + 1);
+ } else {
+ if (valueIsOfTypeString) {
+ for (var i = 0; i < length; ++i) {
+ var charCode = value.charCodeAt(i);
+ if (charCode > 255) {
+ _free(ptr);
+ throwBindingError("String has UTF-16 code units that do not fit in 8 bits");
+ }
+ HEAPU8[ptr + i] = charCode;
+ }
+ } else {
+ for (var i = 0; i < length; ++i) {
+ HEAPU8[ptr + i] = value[i];
+ }
+ }
+ }
+ if (destructors !== null) {
+ destructors.push(_free, base);
+ }
+ return base;
+ },
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": readPointer,
+ destructorFunction: ptr => _free(ptr)
+ });
+};
+
+var UTF16Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf-16le") : undefined;
+
+var UTF16ToString = (ptr, maxBytesToRead) => {
+ var endPtr = ptr;
+ var idx = endPtr >> 1;
+ var maxIdx = idx + maxBytesToRead / 2;
+ while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
+ endPtr = idx << 1;
+ if (endPtr - ptr > 32 && UTF16Decoder) return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
+ var str = "";
+ for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {
+ var codeUnit = HEAP16[ptr + i * 2 >> 1];
+ if (codeUnit == 0) break;
+ str += String.fromCharCode(codeUnit);
+ }
+ return str;
+};
+
+var stringToUTF16 = (str, outPtr, maxBytesToWrite) => {
+ if (maxBytesToWrite === undefined) {
+ maxBytesToWrite = 2147483647;
+ }
+ if (maxBytesToWrite < 2) return 0;
+ maxBytesToWrite -= 2;
+ var startPtr = outPtr;
+ var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length;
+ for (var i = 0; i < numCharsToWrite; ++i) {
+ var codeUnit = str.charCodeAt(i);
+ HEAP16[outPtr >> 1] = codeUnit;
+ outPtr += 2;
+ }
+ HEAP16[outPtr >> 1] = 0;
+ return outPtr - startPtr;
+};
+
+var lengthBytesUTF16 = str => str.length * 2;
+
+var UTF32ToString = (ptr, maxBytesToRead) => {
+ var i = 0;
+ var str = "";
+ while (!(i >= maxBytesToRead / 4)) {
+ var utf32 = HEAP32[ptr + i * 4 >> 2];
+ if (utf32 == 0) break;
+ ++i;
+ if (utf32 >= 65536) {
+ var ch = utf32 - 65536;
+ str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
+ } else {
+ str += String.fromCharCode(utf32);
+ }
+ }
+ return str;
+};
+
+var stringToUTF32 = (str, outPtr, maxBytesToWrite) => {
+ if (maxBytesToWrite === undefined) {
+ maxBytesToWrite = 2147483647;
+ }
+ if (maxBytesToWrite < 4) return 0;
+ var startPtr = outPtr;
+ var endPtr = startPtr + maxBytesToWrite - 4;
+ for (var i = 0; i < str.length; ++i) {
+ var codeUnit = str.charCodeAt(i);
+ if (codeUnit >= 55296 && codeUnit <= 57343) {
+ var trailSurrogate = str.charCodeAt(++i);
+ codeUnit = 65536 + ((codeUnit & 1023) << 10) | trailSurrogate & 1023;
+ }
+ HEAP32[outPtr >> 2] = codeUnit;
+ outPtr += 4;
+ if (outPtr + 4 > endPtr) break;
+ }
+ HEAP32[outPtr >> 2] = 0;
+ return outPtr - startPtr;
+};
+
+var lengthBytesUTF32 = str => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ var codeUnit = str.charCodeAt(i);
+ if (codeUnit >= 55296 && codeUnit <= 57343) ++i;
+ len += 4;
+ }
+ return len;
+};
+
+var __embind_register_std_wstring = (rawType, charSize, name) => {
+ name = readLatin1String(name);
+ var decodeString, encodeString, getHeap, lengthBytesUTF, shift;
+ if (charSize === 2) {
+ decodeString = UTF16ToString;
+ encodeString = stringToUTF16;
+ lengthBytesUTF = lengthBytesUTF16;
+ getHeap = () => HEAPU16;
+ shift = 1;
+ } else if (charSize === 4) {
+ decodeString = UTF32ToString;
+ encodeString = stringToUTF32;
+ lengthBytesUTF = lengthBytesUTF32;
+ getHeap = () => HEAPU32;
+ shift = 2;
+ }
+ registerType(rawType, {
+ name: name,
+ "fromWireType": value => {
+ var length = HEAPU32[value >> 2];
+ var HEAP = getHeap();
+ var str;
+ var decodeStartPtr = value + 4;
+ for (var i = 0; i <= length; ++i) {
+ var currentBytePtr = value + 4 + i * charSize;
+ if (i == length || HEAP[currentBytePtr >> shift] == 0) {
+ var maxReadBytes = currentBytePtr - decodeStartPtr;
+ var stringSegment = decodeString(decodeStartPtr, maxReadBytes);
+ if (str === undefined) {
+ str = stringSegment;
+ } else {
+ str += String.fromCharCode(0);
+ str += stringSegment;
+ }
+ decodeStartPtr = currentBytePtr + charSize;
+ }
+ }
+ _free(value);
+ return str;
+ },
+ "toWireType": (destructors, value) => {
+ if (!(typeof value == "string")) {
+ throwBindingError(`Cannot pass non-string to C++ string type ${name}`);
+ }
+ var length = lengthBytesUTF(value);
+ var ptr = _malloc(4 + length + charSize);
+ HEAPU32[ptr >> 2] = length >> shift;
+ encodeString(value, ptr + 4, length + charSize);
+ if (destructors !== null) {
+ destructors.push(_free, ptr);
+ }
+ return ptr;
+ },
+ "argPackAdvance": GenericWireTypeSize,
+ "readValueFromPointer": simpleReadValueFromPointer,
+ destructorFunction: ptr => _free(ptr)
+ });
+};
+
+var __embind_register_void = (rawType, name) => {
+ name = readLatin1String(name);
+ registerType(rawType, {
+ isVoid: true,
+ name: name,
+ "argPackAdvance": 0,
+ "fromWireType": () => undefined,
+ "toWireType": (destructors, o) => undefined
+ });
+};
+
+var __emscripten_throw_longjmp = () => {
+ throw Infinity;
+};
+
+var __emval_incref = handle => {
+ if (handle > 4) {
+ emval_handles.get(handle).refcount += 1;
+ }
+};
+
+var requireRegisteredType = (rawType, humanName) => {
+ var impl = registeredTypes[rawType];
+ if (undefined === impl) {
+ throwBindingError(humanName + " has unknown type " + getTypeName(rawType));
+ }
+ return impl;
+};
+
+var __emval_take_value = (type, arg) => {
+ type = requireRegisteredType(type, "_emval_take_value");
+ var v = type["readValueFromPointer"](arg);
+ return Emval.toHandle(v);
+};
+
+var isLeapYear = year => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
+
+var MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
+
+var MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
+
+var ydayFromDate = date => {
+ var leap = isLeapYear(date.getFullYear());
+ var monthDaysCumulative = leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE;
+ var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
+ return yday;
+};
+
+var convertI32PairToI53Checked = (lo, hi) => hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN;
+
+function __localtime_js(time_low, time_high, tmPtr) {
+ var time = convertI32PairToI53Checked(time_low, time_high);
+ var date = new Date(time * 1e3);
+ HEAP32[tmPtr >> 2] = date.getSeconds();
+ HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
+ HEAP32[tmPtr + 8 >> 2] = date.getHours();
+ HEAP32[tmPtr + 12 >> 2] = date.getDate();
+ HEAP32[tmPtr + 16 >> 2] = date.getMonth();
+ HEAP32[tmPtr + 20 >> 2] = date.getFullYear() - 1900;
+ HEAP32[tmPtr + 24 >> 2] = date.getDay();
+ var yday = ydayFromDate(date) | 0;
+ HEAP32[tmPtr + 28 >> 2] = yday;
+ HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60);
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
+ HEAP32[tmPtr + 32 >> 2] = dst;
+}
+
+var __mktime_js = function(tmPtr) {
+ var ret = (() => {
+ var date = new Date(HEAP32[tmPtr + 20 >> 2] + 1900, HEAP32[tmPtr + 16 >> 2], HEAP32[tmPtr + 12 >> 2], HEAP32[tmPtr + 8 >> 2], HEAP32[tmPtr + 4 >> 2], HEAP32[tmPtr >> 2], 0);
+ var dst = HEAP32[tmPtr + 32 >> 2];
+ var guessedOffset = date.getTimezoneOffset();
+ var start = new Date(date.getFullYear(), 0, 1);
+ var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
+ var winterOffset = start.getTimezoneOffset();
+ var dstOffset = Math.min(winterOffset, summerOffset);
+ if (dst < 0) {
+ HEAP32[tmPtr + 32 >> 2] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
+ } else if (dst > 0 != (dstOffset == guessedOffset)) {
+ var nonDstOffset = Math.max(winterOffset, summerOffset);
+ var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
+ date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4);
+ }
+ HEAP32[tmPtr + 24 >> 2] = date.getDay();
+ var yday = ydayFromDate(date) | 0;
+ HEAP32[tmPtr + 28 >> 2] = yday;
+ HEAP32[tmPtr >> 2] = date.getSeconds();
+ HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
+ HEAP32[tmPtr + 8 >> 2] = date.getHours();
+ HEAP32[tmPtr + 12 >> 2] = date.getDate();
+ HEAP32[tmPtr + 16 >> 2] = date.getMonth();
+ HEAP32[tmPtr + 20 >> 2] = date.getYear();
+ return date.getTime() / 1e3;
+ })();
+ return setTempRet0((tempDouble = ret, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)),
+ ret >>> 0;
+};
+
+var stringToNewUTF8 = str => {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8(str, ret, size);
+ return ret;
+};
+
+var __tzset_js = (timezone, daylight, tzname) => {
+ var currentYear = (new Date).getFullYear();
+ var winter = new Date(currentYear, 0, 1);
+ var summer = new Date(currentYear, 6, 1);
+ var winterOffset = winter.getTimezoneOffset();
+ var summerOffset = summer.getTimezoneOffset();
+ var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
+ HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
+ HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
+ function extractZone(date) {
+ var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
+ return match ? match[1] : "GMT";
+ }
+ var winterName = extractZone(winter);
+ var summerName = extractZone(summer);
+ var winterNamePtr = stringToNewUTF8(winterName);
+ var summerNamePtr = stringToNewUTF8(summerName);
+ if (summerOffset < winterOffset) {
+ HEAPU32[tzname >> 2] = winterNamePtr;
+ HEAPU32[tzname + 4 >> 2] = summerNamePtr;
+ } else {
+ HEAPU32[tzname >> 2] = summerNamePtr;
+ HEAPU32[tzname + 4 >> 2] = winterNamePtr;
+ }
+};
+
+var _abort = () => {
+ abort("");
+};
+
+var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
+
+var getHeapMax = () => 2147483648;
+
+var growMemory = size => {
+ var b = wasmMemory.buffer;
+ var pages = (size - b.byteLength + 65535) / 65536;
+ try {
+ wasmMemory.grow(pages);
+ updateMemoryViews();
+ return 1;
+ } catch (e) {}
+};
+
+var _emscripten_resize_heap = requestedSize => {
+ var oldSize = HEAPU8.length;
+ requestedSize >>>= 0;
+ var maxHeapSize = getHeapMax();
+ if (requestedSize > maxHeapSize) {
+ return false;
+ }
+ var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
+ for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
+ overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
+ var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
+ var replacement = growMemory(newSize);
+ if (replacement) {
+ return true;
+ }
+ }
+ return false;
+};
+
+var ENV = {};
+
+var getExecutableName = () => thisProgram || "./this.program";
+
+var getEnvStrings = () => {
+ if (!getEnvStrings.strings) {
+ var lang = (typeof navigator == "object" && navigator.languages && navigator.languages[0] || "C").replace("-", "_") + ".UTF-8";
+ var env = {
+ "USER": "web_user",
+ "LOGNAME": "web_user",
+ "PATH": "/",
+ "PWD": "/",
+ "HOME": "/home/web_user",
+ "LANG": lang,
+ "_": getExecutableName()
+ };
+ for (var x in ENV) {
+ if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];
+ }
+ var strings = [];
+ for (var x in env) {
+ strings.push(`${x}=${env[x]}`);
+ }
+ getEnvStrings.strings = strings;
+ }
+ return getEnvStrings.strings;
+};
+
+var stringToAscii = (str, buffer) => {
+ for (var i = 0; i < str.length; ++i) {
+ HEAP8[buffer++ >> 0] = str.charCodeAt(i);
+ }
+ HEAP8[buffer >> 0] = 0;
+};
+
+var _environ_get = (__environ, environ_buf) => {
+ var bufSize = 0;
+ getEnvStrings().forEach((string, i) => {
+ var ptr = environ_buf + bufSize;
+ HEAPU32[__environ + i * 4 >> 2] = ptr;
+ stringToAscii(string, ptr);
+ bufSize += string.length + 1;
+ });
+ return 0;
+};
+
+var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
+ var strings = getEnvStrings();
+ HEAPU32[penviron_count >> 2] = strings.length;
+ var bufSize = 0;
+ strings.forEach(string => bufSize += string.length + 1);
+ HEAPU32[penviron_buf_size >> 2] = bufSize;
+ return 0;
+};
+
+var _fd_close = fd => 52;
+
+var _fd_read = (fd, iov, iovcnt, pnum) => 52;
+
+function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
+ return 70;
+}
+
+var printCharBuffers = [ null, [], [] ];
+
+var printChar = (stream, curr) => {
+ var buffer = printCharBuffers[stream];
+ if (curr === 0 || curr === 10) {
+ (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));
+ buffer.length = 0;
+ } else {
+ buffer.push(curr);
+ }
+};
+
+var _fd_write = (fd, iov, iovcnt, pnum) => {
+ var num = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAPU32[iov >> 2];
+ var len = HEAPU32[iov + 4 >> 2];
+ iov += 8;
+ for (var j = 0; j < len; j++) {
+ printChar(fd, HEAPU8[ptr + j]);
+ }
+ num += len;
+ }
+ HEAPU32[pnum >> 2] = num;
+ return 0;
+};
+
+var arraySum = (array, index) => {
+ var sum = 0;
+ for (var i = 0; i <= index; sum += array[i++]) {}
+ return sum;
+};
+
+var MONTH_DAYS_LEAP = [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
+
+var MONTH_DAYS_REGULAR = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
+
+var addDays = (date, days) => {
+ var newDate = new Date(date.getTime());
+ while (days > 0) {
+ var leap = isLeapYear(newDate.getFullYear());
+ var currentMonth = newDate.getMonth();
+ var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth];
+ if (days > daysInCurrentMonth - newDate.getDate()) {
+ days -= daysInCurrentMonth - newDate.getDate() + 1;
+ newDate.setDate(1);
+ if (currentMonth < 11) {
+ newDate.setMonth(currentMonth + 1);
+ } else {
+ newDate.setMonth(0);
+ newDate.setFullYear(newDate.getFullYear() + 1);
+ }
+ } else {
+ newDate.setDate(newDate.getDate() + days);
+ return newDate;
+ }
+ }
+ return newDate;
+};
+
+function intArrayFromString(stringy, dontAddNull, length) {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+}
+
+var writeArrayToMemory = (array, buffer) => {
+ HEAP8.set(array, buffer);
+};
+
+var _strftime = (s, maxsize, format, tm) => {
+ var tm_zone = HEAPU32[tm + 40 >> 2];
+ var date = {
+ tm_sec: HEAP32[tm >> 2],
+ tm_min: HEAP32[tm + 4 >> 2],
+ tm_hour: HEAP32[tm + 8 >> 2],
+ tm_mday: HEAP32[tm + 12 >> 2],
+ tm_mon: HEAP32[tm + 16 >> 2],
+ tm_year: HEAP32[tm + 20 >> 2],
+ tm_wday: HEAP32[tm + 24 >> 2],
+ tm_yday: HEAP32[tm + 28 >> 2],
+ tm_isdst: HEAP32[tm + 32 >> 2],
+ tm_gmtoff: HEAP32[tm + 36 >> 2],
+ tm_zone: tm_zone ? UTF8ToString(tm_zone) : ""
+ };
+ var pattern = UTF8ToString(format);
+ var EXPANSION_RULES_1 = {
+ "%c": "%a %b %d %H:%M:%S %Y",
+ "%D": "%m/%d/%y",
+ "%F": "%Y-%m-%d",
+ "%h": "%b",
+ "%r": "%I:%M:%S %p",
+ "%R": "%H:%M",
+ "%T": "%H:%M:%S",
+ "%x": "%m/%d/%y",
+ "%X": "%H:%M:%S",
+ "%Ec": "%c",
+ "%EC": "%C",
+ "%Ex": "%m/%d/%y",
+ "%EX": "%H:%M:%S",
+ "%Ey": "%y",
+ "%EY": "%Y",
+ "%Od": "%d",
+ "%Oe": "%e",
+ "%OH": "%H",
+ "%OI": "%I",
+ "%Om": "%m",
+ "%OM": "%M",
+ "%OS": "%S",
+ "%Ou": "%u",
+ "%OU": "%U",
+ "%OV": "%V",
+ "%Ow": "%w",
+ "%OW": "%W",
+ "%Oy": "%y"
+ };
+ for (var rule in EXPANSION_RULES_1) {
+ pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_1[rule]);
+ }
+ var WEEKDAYS = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
+ var MONTHS = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
+ function leadingSomething(value, digits, character) {
+ var str = typeof value == "number" ? value.toString() : value || "";
+ while (str.length < digits) {
+ str = character[0] + str;
+ }
+ return str;
+ }
+ function leadingNulls(value, digits) {
+ return leadingSomething(value, digits, "0");
+ }
+ function compareByDay(date1, date2) {
+ function sgn(value) {
+ return value < 0 ? -1 : value > 0 ? 1 : 0;
+ }
+ var compare;
+ if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) {
+ if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) {
+ compare = sgn(date1.getDate() - date2.getDate());
+ }
+ }
+ return compare;
+ }
+ function getFirstWeekStartDate(janFourth) {
+ switch (janFourth.getDay()) {
+ case 0:
+ return new Date(janFourth.getFullYear() - 1, 11, 29);
+
+ case 1:
+ return janFourth;
+
+ case 2:
+ return new Date(janFourth.getFullYear(), 0, 3);
+
+ case 3:
+ return new Date(janFourth.getFullYear(), 0, 2);
+
+ case 4:
+ return new Date(janFourth.getFullYear(), 0, 1);
+
+ case 5:
+ return new Date(janFourth.getFullYear() - 1, 11, 31);
+
+ case 6:
+ return new Date(janFourth.getFullYear() - 1, 11, 30);
+ }
+ }
+ function getWeekBasedYear(date) {
+ var thisDate = addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
+ var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
+ var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4);
+ var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
+ var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
+ if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
+ if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
+ return thisDate.getFullYear() + 1;
+ }
+ return thisDate.getFullYear();
+ }
+ return thisDate.getFullYear() - 1;
+ }
+ var EXPANSION_RULES_2 = {
+ "%a": date => WEEKDAYS[date.tm_wday].substring(0, 3),
+ "%A": date => WEEKDAYS[date.tm_wday],
+ "%b": date => MONTHS[date.tm_mon].substring(0, 3),
+ "%B": date => MONTHS[date.tm_mon],
+ "%C": date => {
+ var year = date.tm_year + 1900;
+ return leadingNulls(year / 100 | 0, 2);
+ },
+ "%d": date => leadingNulls(date.tm_mday, 2),
+ "%e": date => leadingSomething(date.tm_mday, 2, " "),
+ "%g": date => getWeekBasedYear(date).toString().substring(2),
+ "%G": date => getWeekBasedYear(date),
+ "%H": date => leadingNulls(date.tm_hour, 2),
+ "%I": date => {
+ var twelveHour = date.tm_hour;
+ if (twelveHour == 0) twelveHour = 12; else if (twelveHour > 12) twelveHour -= 12;
+ return leadingNulls(twelveHour, 2);
+ },
+ "%j": date => leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year + 1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon - 1), 3),
+ "%m": date => leadingNulls(date.tm_mon + 1, 2),
+ "%M": date => leadingNulls(date.tm_min, 2),
+ "%n": () => "\n",
+ "%p": date => {
+ if (date.tm_hour >= 0 && date.tm_hour < 12) {
+ return "AM";
+ }
+ return "PM";
+ },
+ "%S": date => leadingNulls(date.tm_sec, 2),
+ "%t": () => "\t",
+ "%u": date => date.tm_wday || 7,
+ "%U": date => {
+ var days = date.tm_yday + 7 - date.tm_wday;
+ return leadingNulls(Math.floor(days / 7), 2);
+ },
+ "%V": date => {
+ var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7) / 7);
+ if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) {
+ val++;
+ }
+ if (!val) {
+ val = 52;
+ var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7;
+ if (dec31 == 4 || dec31 == 5 && isLeapYear(date.tm_year % 400 - 1)) {
+ val++;
+ }
+ } else if (val == 53) {
+ var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7;
+ if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) val = 1;
+ }
+ return leadingNulls(val, 2);
+ },
+ "%w": date => date.tm_wday,
+ "%W": date => {
+ var days = date.tm_yday + 7 - (date.tm_wday + 6) % 7;
+ return leadingNulls(Math.floor(days / 7), 2);
+ },
+ "%y": date => (date.tm_year + 1900).toString().substring(2),
+ "%Y": date => date.tm_year + 1900,
+ "%z": date => {
+ var off = date.tm_gmtoff;
+ var ahead = off >= 0;
+ off = Math.abs(off) / 60;
+ off = off / 60 * 100 + off % 60;
+ return (ahead ? "+" : "-") + String("0000" + off).slice(-4);
+ },
+ "%Z": date => date.tm_zone,
+ "%%": () => "%"
+ };
+ pattern = pattern.replace(/%%/g, "\0\0");
+ for (var rule in EXPANSION_RULES_2) {
+ if (pattern.includes(rule)) {
+ pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_2[rule](date));
+ }
+ }
+ pattern = pattern.replace(/\0\0/g, "%");
+ var bytes = intArrayFromString(pattern, false);
+ if (bytes.length > maxsize) {
+ return 0;
+ }
+ writeArrayToMemory(bytes, s);
+ return bytes.length - 1;
+};
+
+var _strftime_l = (s, maxsize, format, tm, loc) => _strftime(s, maxsize, format, tm);
+
+embind_init_charCodes();
+
+BindingError = Module["BindingError"] = class BindingError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "BindingError";
+ }
+};
+
+InternalError = Module["InternalError"] = class InternalError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "InternalError";
+ }
+};
+
+init_ClassHandle();
+
+init_embind();
+
+init_RegisteredPointer();
+
+UnboundTypeError = Module["UnboundTypeError"] = extendError(Error, "UnboundTypeError");
+
+handleAllocatorInit();
+
+init_emval();
+
+var wasmImports = {
+ __assert_fail: ___assert_fail,
+ __cxa_throw: ___cxa_throw,
+ __syscall_ioctl: ___syscall_ioctl,
+ __syscall_openat: ___syscall_openat,
+ _embind_register_bigint: __embind_register_bigint,
+ _embind_register_bool: __embind_register_bool,
+ _embind_register_class: __embind_register_class,
+ _embind_register_class_constructor: __embind_register_class_constructor,
+ _embind_register_class_function: __embind_register_class_function,
+ _embind_register_emval: __embind_register_emval,
+ _embind_register_float: __embind_register_float,
+ _embind_register_integer: __embind_register_integer,
+ _embind_register_memory_view: __embind_register_memory_view,
+ _embind_register_std_string: __embind_register_std_string,
+ _embind_register_std_wstring: __embind_register_std_wstring,
+ _embind_register_void: __embind_register_void,
+ _emscripten_throw_longjmp: __emscripten_throw_longjmp,
+ _emval_decref: __emval_decref,
+ _emval_incref: __emval_incref,
+ _emval_take_value: __emval_take_value,
+ _localtime_js: __localtime_js,
+ _mktime_js: __mktime_js,
+ _tzset_js: __tzset_js,
+ abort: _abort,
+ emscripten_memcpy_big: _emscripten_memcpy_big,
+ emscripten_resize_heap: _emscripten_resize_heap,
+ environ_get: _environ_get,
+ environ_sizes_get: _environ_sizes_get,
+ fd_close: _fd_close,
+ fd_read: _fd_read,
+ fd_seek: _fd_seek,
+ fd_write: _fd_write,
+ invoke_vi: invoke_vi,
+ invoke_viii: invoke_viii,
+ invoke_viiii: invoke_viiii,
+ invoke_viiiii: invoke_viiiii,
+ strftime_l: _strftime_l
+};
+
+var wasmExports = createWasm();
+
+var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["__wasm_call_ctors"])();
+
+var _free = a0 => (_free = wasmExports["free"])(a0);
+
+var _malloc = a0 => (_malloc = wasmExports["malloc"])(a0);
+
+var ___getTypeName = a0 => (___getTypeName = wasmExports["__getTypeName"])(a0);
+
+var __embind_initialize_bindings = Module["__embind_initialize_bindings"] = () => (__embind_initialize_bindings = Module["__embind_initialize_bindings"] = wasmExports["_embind_initialize_bindings"])();
+
+var ___errno_location = () => (___errno_location = wasmExports["__errno_location"])();
+
+var _setThrew = (a0, a1) => (_setThrew = wasmExports["setThrew"])(a0, a1);
+
+var setTempRet0 = a0 => (setTempRet0 = wasmExports["setTempRet0"])(a0);
+
+var stackSave = () => (stackSave = wasmExports["stackSave"])();
+
+var stackRestore = a0 => (stackRestore = wasmExports["stackRestore"])(a0);
+
+var stackAlloc = a0 => (stackAlloc = wasmExports["stackAlloc"])(a0);
+
+var ___cxa_increment_exception_refcount = a0 => (___cxa_increment_exception_refcount = wasmExports["__cxa_increment_exception_refcount"])(a0);
+
+var ___cxa_is_pointer_type = a0 => (___cxa_is_pointer_type = wasmExports["__cxa_is_pointer_type"])(a0);
+
+var dynCall_iijii = Module["dynCall_iijii"] = (a0, a1, a2, a3, a4, a5) => (dynCall_iijii = Module["dynCall_iijii"] = wasmExports["dynCall_iijii"])(a0, a1, a2, a3, a4, a5);
+
+var dynCall_jiji = Module["dynCall_jiji"] = (a0, a1, a2, a3, a4) => (dynCall_jiji = Module["dynCall_jiji"] = wasmExports["dynCall_jiji"])(a0, a1, a2, a3, a4);
+
+var dynCall_viijii = Module["dynCall_viijii"] = (a0, a1, a2, a3, a4, a5, a6) => (dynCall_viijii = Module["dynCall_viijii"] = wasmExports["dynCall_viijii"])(a0, a1, a2, a3, a4, a5, a6);
+
+var dynCall_iiiiij = Module["dynCall_iiiiij"] = (a0, a1, a2, a3, a4, a5, a6) => (dynCall_iiiiij = Module["dynCall_iiiiij"] = wasmExports["dynCall_iiiiij"])(a0, a1, a2, a3, a4, a5, a6);
+
+var dynCall_iiiiijj = Module["dynCall_iiiiijj"] = (a0, a1, a2, a3, a4, a5, a6, a7, a8) => (dynCall_iiiiijj = Module["dynCall_iiiiijj"] = wasmExports["dynCall_iiiiijj"])(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+var dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) => (dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = wasmExports["dynCall_iiiiiijj"])(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+function invoke_vi(index, a1) {
+ var sp = stackSave();
+ try {
+ getWasmTableEntry(index)(a1);
+ } catch (e) {
+ stackRestore(sp);
+ if (e !== e + 0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viii(index, a1, a2, a3) {
+ var sp = stackSave();
+ try {
+ getWasmTableEntry(index)(a1, a2, a3);
+ } catch (e) {
+ stackRestore(sp);
+ if (e !== e + 0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viiii(index, a1, a2, a3, a4) {
+ var sp = stackSave();
+ try {
+ getWasmTableEntry(index)(a1, a2, a3, a4);
+ } catch (e) {
+ stackRestore(sp);
+ if (e !== e + 0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+function invoke_viiiii(index, a1, a2, a3, a4, a5) {
+ var sp = stackSave();
+ try {
+ getWasmTableEntry(index)(a1, a2, a3, a4, a5);
+ } catch (e) {
+ stackRestore(sp);
+ if (e !== e + 0) throw e;
+ _setThrew(1, 0);
+ }
+}
+
+var calledRun;
+
+dependenciesFulfilled = function runCaller() {
+ if (!calledRun) run();
+ if (!calledRun) dependenciesFulfilled = runCaller;
+};
+
+function run() {
+ if (runDependencies > 0) {
+ return;
+ }
+ preRun();
+ if (runDependencies > 0) {
+ return;
+ }
+ function doRun() {
+ if (calledRun) return;
+ calledRun = true;
+ Module["calledRun"] = true;
+ if (ABORT) return;
+ initRuntime();
+ if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
+ postRun();
+ }
+ if (Module["setStatus"]) {
+ Module["setStatus"]("Running...");
+ setTimeout(function() {
+ setTimeout(function() {
+ Module["setStatus"]("");
+ }, 1);
+ doRun();
+ }, 1);
+ } else {
+ doRun();
+ }
+}
+
+if (Module["preInit"]) {
+ if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
+ while (Module["preInit"].length > 0) {
+ Module["preInit"].pop()();
+ }
+}
+
+run();
diff --git a/d2m/converters/rlottie-wasm.wasm b/d2m/converters/rlottie-wasm.wasm
index b7778c99eebd14f5fbf655c4a082d8c5562ca351..ca65b5b6ff7139db1ca9106fc194510b1bd6034f 100755
GIT binary patch
delta 104498
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
delta 184
zcmbQ=ue#%r+=l!7jJum3@V7tUX9Qv3DX=K8y74kIJ1{vYuxK$cDDf%q
z#=G(|fH*8l%nH15V2%b8hY~AGtpck8uL9p>1!e`l>HANzC``{h%;L<(Jz0rcfqVO=
d!z^#&8Fx&dugp5T-CBheh}pJVtFSZn0s#6BG4lWb
diff --git a/test/res/lottie-bee.png b/test/res/lottie-bee.png
index 3fdc19a99dd727d13647e9bda65d547daee86775..4586cb50ebc6aa34f4d1acc222322bff7f4ff617 100644
GIT binary patch
delta 5363
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
Rp?UxS002ovPDHLkV1g$tP<;RZ
delta 5337
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
From 7e9005216d316c0f3bb9b8867d75185bfade61ee Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Sat, 3 Aug 2024 22:46:09 +1200
Subject: [PATCH 043/346] Switch to new application service library
---
matrix/appservice.js | 14 +-
package-lock.json | 802 ++++++++-----------------------------------
package.json | 2 +-
passthrough.js | 2 +-
scripts/register.js | 22 --
start.js | 2 +-
6 files changed, 160 insertions(+), 684 deletions(-)
delete mode 100644 scripts/register.js
diff --git a/matrix/appservice.js b/matrix/appservice.js
index e99a822..b239084 100644
--- a/matrix/appservice.js
+++ b/matrix/appservice.js
@@ -1,8 +1,8 @@
-const reg = require("../matrix/read-registration")
-const AppService = require("matrix-appservice").AppService
-const as = new AppService({
- homeserverToken: reg.hs_token
-})
-as.listen(+(new URL(reg.url).port))
+// @ts-check
-module.exports = as
+const reg = require("../matrix/read-registration")
+const {AppService} = require("@cloudrac3r/in-your-element")
+const as = new AppService(reg)
+as.listen()
+
+module.exports.as = as
diff --git a/package-lock.json b/package-lock.json
index 9b97e23..67df9fe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"@cloudrac3r/discord-markdown": "^2.6.2",
"@cloudrac3r/giframe": "^0.4.3",
"@cloudrac3r/html-template-tag": "^5.0.1",
+ "@cloudrac3r/in-your-element": "^1.0.0",
"@cloudrac3r/mixin-deep": "^3.0.0",
"@cloudrac3r/pngjs": "^7.0.3",
"@cloudrac3r/turndown": "^7.1.4",
@@ -24,7 +25,6 @@
"get-stream": "^6.0.1",
"heatsync": "^2.5.3",
"js-yaml": "^4.1.0",
- "matrix-appservice": "^2.0.0",
"minimist": "^1.2.8",
"node-fetch": "^2.6.7",
"prettier-bytes": "^1.0.4",
@@ -45,6 +45,29 @@
"supertape": "^10.4.0"
}
},
+ "../in-your-element": {
+ "name": "@cloudrac3r/in-your-element",
+ "version": "0.0.0",
+ "extraneous": true,
+ "license": "AGPL-3.0-or-later",
+ "dependencies": {
+ "h3": "^1.12.0",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@cloudrac3r/tap-dot": "^2.0.2",
+ "@types/node": "^18.19.42",
+ "c8": "^10.1.2",
+ "cross-env": "^7.0.3",
+ "mock-req": "^0.2.0",
+ "readable-mock-req": "^0.2.2",
+ "supertape": "^10.7.2",
+ "try-to-catch": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@bcoe/v8-coverage": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
@@ -169,6 +192,19 @@
"html-es6cape": "^2.0.0"
}
},
+ "node_modules/@cloudrac3r/in-your-element": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@cloudrac3r/in-your-element/-/in-your-element-1.0.0.tgz",
+ "integrity": "sha512-g6vdxNJtc9+Y0djClrc0xNwL6DFiEQ9ikWHBBDJ3iKAWygdjANnFJ/Q1DVMmNqUYRsQIN3yH1aIQICKA2CDXhQ==",
+ "license": "AGPL-3.0-or-later",
+ "dependencies": {
+ "h3": "^1.12.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@cloudrac3r/mixin-deep": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@cloudrac3r/mixin-deep/-/mixin-deep-3.0.0.tgz",
@@ -973,18 +1009,6 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
},
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
@@ -1015,11 +1039,6 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
- },
"node_modules/as-table": {
"version": "1.0.55",
"resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz",
@@ -1063,22 +1082,6 @@
}
]
},
- "node_modules/basic-auth": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
- "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
- "dependencies": {
- "safe-buffer": "5.1.2"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/basic-auth/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- },
"node_modules/better-sqlite3": {
"version": "11.1.2",
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz",
@@ -1143,29 +1146,6 @@
"node": ">= 6"
}
},
- "node_modules/body-parser": {
- "version": "1.20.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
- "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
- "dependencies": {
- "bytes": "3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.11.0",
- "raw-body": "2.5.2",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@@ -1174,14 +1154,6 @@
"balanced-match": "^1.0.0"
}
},
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/c8": {
"version": "10.1.2",
"resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz",
@@ -1215,24 +1187,6 @@
}
}
},
- "node_modules/call-bind": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
- "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -1392,23 +1346,13 @@
"node": ">= 0.8"
}
},
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
+ "node_modules/consola": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz",
+ "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==",
+ "license": "MIT",
"engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "engines": {
- "node": ">= 0.6"
+ "node": "^14.18.0 || >=16.10.0"
}
},
"node_modules/convert-source-map": {
@@ -1417,18 +1361,11 @@
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"dev": true
},
- "node_modules/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ "node_modules/cookie-es": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz",
+ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==",
+ "license": "MIT"
},
"node_modules/cross-env": {
"version": "7.0.3",
@@ -1461,6 +1398,20 @@
"node": ">= 8"
}
},
+ "node_modules/crossws": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.2.4.tgz",
+ "integrity": "sha512-DAxroI2uSOgUKLz00NX6A8U/8EE3SZHmIND+10jkVSaypvyt57J5JEOxAQOL6lQxyzi/wZbTIwssU1uy69h5Vg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "uWebSockets.js": "*"
+ },
+ "peerDependenciesMeta": {
+ "uWebSockets.js": {
+ "optional": true
+ }
+ }
+ },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@@ -1471,14 +1422,6 @@
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
"integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="
},
- "node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -1501,21 +1444,11 @@
"node": ">=4.0.0"
}
},
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "node_modules/defu": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "license": "MIT"
},
"node_modules/delayed-stream": {
"version": "1.0.0",
@@ -1526,22 +1459,11 @@
"node": ">=0.4.0"
}
},
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
+ "node_modules/destr": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz",
+ "integrity": "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==",
+ "license": "MIT"
},
"node_modules/detect-libc": {
"version": "2.0.3",
@@ -1574,24 +1496,11 @@
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
- },
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
- "node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -1611,25 +1520,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/es-define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
- "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
- "dependencies": {
- "get-intrinsic": "^1.2.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -1639,19 +1529,6 @@
"node": ">=6"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -1660,47 +1537,6 @@
"node": ">=6"
}
},
- "node_modules/express": {
- "version": "4.19.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
- "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "1.20.2",
- "content-disposition": "0.5.4",
- "content-type": "~1.0.4",
- "cookie": "0.6.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "1.2.0",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.7",
- "qs": "6.11.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "0.18.0",
- "serve-static": "1.15.0",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
@@ -1730,23 +1566,6 @@
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
- "node_modules/finalhandler": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
- "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "2.0.1",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -1797,22 +1616,6 @@
"node": ">= 6"
}
},
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -1843,24 +1646,6 @@
"node": "6.* || 8.* || >= 10.*"
}
},
- "node_modules/get-intrinsic": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
- "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/get-source": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz",
@@ -1908,15 +1693,22 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "node_modules/h3": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/h3/-/h3-1.12.0.tgz",
+ "integrity": "sha512-Zi/CcNeWBXDrFNlV0hUBJQR9F7a96RjMeAZweW/ZWkR9fuXrMcvKnSA63f/zZ9l0GgQOZDVHGvXivNN9PWOwhA==",
+ "license": "MIT",
"dependencies": {
- "get-intrinsic": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "cookie-es": "^1.1.0",
+ "crossws": "^0.2.4",
+ "defu": "^6.1.4",
+ "destr": "^2.0.3",
+ "iron-webcrypto": "^1.1.1",
+ "ohash": "^1.1.3",
+ "radix3": "^1.1.2",
+ "ufo": "^1.5.3",
+ "uncrypto": "^0.1.3",
+ "unenv": "^1.9.0"
}
},
"node_modules/has-flag": {
@@ -1927,39 +1719,6 @@
"node": ">=8"
}
},
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
@@ -1990,32 +1749,6 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
- "node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
- "dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -2045,12 +1778,13 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "engines": {
- "node": ">= 0.10"
+ "node_modules/iron-webcrypto": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
+ "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/brc-dd"
}
},
"node_modules/is-arrayish": {
@@ -2203,50 +1937,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/matrix-appservice": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/matrix-appservice/-/matrix-appservice-2.0.0.tgz",
- "integrity": "sha512-HCIuJ5i0YuO8b0dMyGe5dqlsE4f3RzHU0MuMg/2gGAZ4HL3r7aSWOFbyIWStSSUrk1qCa9Eml0i4EnEi0pOtdA==",
- "dependencies": {
- "body-parser": "^1.19.0",
- "express": "^4.18.1",
- "js-yaml": "^4.1.0",
- "morgan": "^1.10.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "license": "MIT",
"bin": {
"mime": "cli.js"
},
"engines": {
- "node": ">=4"
+ "node": ">=10.0.0"
}
},
"node_modules/mime-db": {
@@ -2314,50 +2014,11 @@
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
},
- "node_modules/morgan": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
- "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
- "dependencies": {
- "basic-auth": "~2.0.1",
- "debug": "2.6.9",
- "depd": "~2.0.0",
- "on-finished": "~2.3.0",
- "on-headers": "~1.0.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/morgan/node_modules/on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
- },
"node_modules/napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
},
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/node-abi": {
"version": "3.40.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz",
@@ -2388,32 +2049,17 @@
}
}
},
- "node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "node_modules/node-fetch-native": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz",
+ "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==",
+ "license": "MIT"
},
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/on-headers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
- "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
- "engines": {
- "node": ">= 0.8"
- }
+ "node_modules/ohash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz",
+ "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==",
+ "license": "MIT"
},
"node_modules/once": {
"version": "1.4.0",
@@ -2458,14 +2104,6 @@
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw=="
},
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -2511,10 +2149,11 @@
"node": "20 || >=22"
}
},
- "node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ "node_modules/pathe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+ "license": "MIT"
},
"node_modules/peek-readable": {
"version": "4.1.0",
@@ -2587,18 +2226,6 @@
"resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz",
"integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="
},
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -2608,41 +2235,11 @@
"once": "^1.3.1"
}
},
- "node_modules/qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
- "dependencies": {
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
- "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
- "dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
+ "node_modules/radix3": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
+ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
+ "license": "MIT"
},
"node_modules/rc": {
"version": "1.2.8",
@@ -2749,11 +2346,6 @@
}
]
},
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -2765,69 +2357,6 @@
"node": ">=10"
}
},
- "node_modules/send": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
- "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "2.0.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
- "dependencies": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.18.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/set-function-length": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
- "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
- "dependencies": {
- "define-data-property": "^1.1.2",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.3",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
- },
"node_modules/sharp": {
"version": "0.33.4",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.4.tgz",
@@ -2886,19 +2415,6 @@
"node": ">=8"
}
},
- "node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
@@ -3007,14 +2523,6 @@
"get-source": "^2.0.12"
}
},
- "node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/stream-head": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/stream-head/-/stream-head-2.0.2.tgz",
@@ -3380,14 +2888,6 @@
"resolved": "https://registry.npmjs.org/timer-node/-/timer-node-5.0.7.tgz",
"integrity": "sha512-M1aP6ASmuVD0PSxl5fqjCAGY9WyND3DHZ8RwT5I8o7469XE53Lb5zbPai20Dhj7TProyaapfVj3TaT0P+LoSEA=="
},
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "engines": {
- "node": ">=0.6"
- }
- },
"node_modules/token-types": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz",
@@ -3442,17 +2942,17 @@
"node": "*"
}
},
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
+ "node_modules/ufo": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
+ "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
+ "license": "MIT"
+ },
+ "node_modules/uncrypto": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
+ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
+ "license": "MIT"
},
"node_modules/undici": {
"version": "6.19.2",
@@ -3468,12 +2968,17 @@
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "engines": {
- "node": ">= 0.8"
+ "node_modules/unenv": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.10.0.tgz",
+ "integrity": "sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "consola": "^3.2.3",
+ "defu": "^6.1.4",
+ "mime": "^3.0.0",
+ "node-fetch-native": "^1.6.4",
+ "pathe": "^1.1.2"
}
},
"node_modules/util-deprecate": {
@@ -3481,14 +2986,6 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
"node_modules/v8-to-istanbul": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz",
@@ -3503,14 +3000,6 @@
"node": ">=10.12.0"
}
},
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@@ -3674,6 +3163,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
}
}
}
diff --git a/package.json b/package.json
index 10486ac..31990ed 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@cloudrac3r/discord-markdown": "^2.6.2",
"@cloudrac3r/giframe": "^0.4.3",
"@cloudrac3r/html-template-tag": "^5.0.1",
+ "@cloudrac3r/in-your-element": "^1.0.0",
"@cloudrac3r/mixin-deep": "^3.0.0",
"@cloudrac3r/pngjs": "^7.0.3",
"@cloudrac3r/turndown": "^7.1.4",
@@ -30,7 +31,6 @@
"get-stream": "^6.0.1",
"heatsync": "^2.5.3",
"js-yaml": "^4.1.0",
- "matrix-appservice": "^2.0.0",
"minimist": "^1.2.8",
"node-fetch": "^2.6.7",
"prettier-bytes": "^1.0.4",
diff --git a/passthrough.js b/passthrough.js
index ec80004..18cca6b 100644
--- a/passthrough.js
+++ b/passthrough.js
@@ -7,7 +7,7 @@
* @property {import("./d2m/discord-client")} discord
* @property {import("heatsync").default} sync
* @property {import("better-sqlite3/lib/database")} db
- * @property {import("matrix-appservice").AppService} as
+ * @property {import("@cloudrac3r/in-your-element").AppService} as
* @property {import("./db/orm").from} from
* @property {import("./db/orm").select} select
*/
diff --git a/scripts/register.js b/scripts/register.js
deleted file mode 100644
index e19adb3..0000000
--- a/scripts/register.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// @ts-check
-
-const { AppServiceRegistration } = require("matrix-appservice");
-
-let id = AppServiceRegistration.generateToken()
-try {
- const reg = require("../matrix/read-registration")
- if (reg.id) id = reg.id
-} catch (e) {}
-
-// creating registration files
-const newReg = new AppServiceRegistration(null);
-newReg.setAppServiceUrl("http://localhost:6693");
-newReg.setId(id);
-newReg.setHomeserverToken(AppServiceRegistration.generateToken());
-newReg.setAppServiceToken(AppServiceRegistration.generateToken());
-newReg.setSenderLocalpart("_ooye_bot");
-newReg.addRegexPattern("users", "@_ooye_.*", true);
-newReg.addRegexPattern("aliases", "#_ooye_.*", true);
-newReg.setProtocols(["discord"]); // For 3PID lookups
-newReg.setRateLimited(false);
-newReg.outputAsYaml("registration.yaml");
diff --git a/start.js b/start.js
index 819281f..2b6e3df 100644
--- a/start.js
+++ b/start.js
@@ -17,7 +17,7 @@ const DiscordClient = require("./d2m/discord-client")
const discord = new DiscordClient(config.discordToken, "full")
passthrough.discord = discord
-const as = require("./matrix/appservice")
+const {as} = require("./matrix/appservice")
passthrough.as = as
const orm = sync.require("./db/orm")
From 5e4d5398071f954c7d6815023ec38f18a15437f9 Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Thu, 15 Aug 2024 23:51:34 +1200
Subject: [PATCH 044/346] Fix potential abuse of error retry system
---
m2d/event-dispatcher.js | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/m2d/event-dispatcher.js b/m2d/event-dispatcher.js
index f7e5e1b..5529a26 100644
--- a/m2d/event-dispatcher.js
+++ b/m2d/event-dispatcher.js
@@ -62,15 +62,34 @@ function guard(type, fn) {
}
}
-async function retry(roomID, eventID) {
- const event = await api.getEvent(roomID, eventID)
+/**
+ * @param {Ty.Event.Outer} reactionEvent
+ */
+async function onRetryReactionAdd(reactionEvent) {
+ const roomID = reactionEvent.room_id
+ const event = await api.getEvent(roomID, reactionEvent.content["m.relates_to"]?.event_id)
+
+ // Check that it's a real error from OOYE
const error = event.content["moe.cadence.ooye.error"]
if (event.sender !== `@${reg.sender_localpart}:${reg.ooye.server_name}` || !error) return
+
+ // To stop people injecting misleading messages, the reaction needs to come from either the original sender or a room moderator
+ if (reactionEvent.sender !== event.sender) {
+ // Check if it's a room moderator
+ const powerLevelsStateContent = await api.getStateEvent(roomID, "m.room.power_levels", "")
+ const powerLevel = powerLevelsStateContent.users?.[reactionEvent.sender] || 0
+ if (powerLevel < 50) return
+ }
+
+ // Retry
if (error.source === "matrix") {
- as.emit("type:" + error.payload.type, error.payload)
+ as.emit(`type:${error.payload.type}`, error.payload)
} else if (error.source === "discord") {
discord.cloud.emit("event", error.payload)
}
+
+ // Redact the error to stop people from executing multiple retries
+ api.redactEvent(roomID, event.event_id)
}
sync.addTemporaryListener(as, "type:m.room.message", guard("m.room.message",
@@ -103,7 +122,7 @@ async event => {
if (utils.eventSenderIsFromDiscord(event.sender)) return
if (event.content["m.relates_to"].key === "🔁") {
// Try to bridge a failed event again?
- await retry(event.room_id, event.content["m.relates_to"].event_id)
+ await onRetryReactionAdd(event)
} else {
matrixCommandHandler.onReactionAdd(event)
await addReaction.addReaction(event)
From 283cf669065887b0a224361790fcc47bdc66cf7f Mon Sep 17 00:00:00 2001
From: Cadence Ember
Date: Fri, 16 Aug 2024 01:08:01 +1200
Subject: [PATCH 045/346] Move reply previews to one line, fix android small
text
---
m2d/converters/event-to-message.js | 8 +--
m2d/converters/event-to-message.test.js | 72 ++++++++++++-------------
2 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js
index 86975ab..4047980 100644
--- a/m2d/converters/event-to-message.js
+++ b/m2d/converters/event-to-message.js
@@ -541,7 +541,7 @@ async function eventToMessage(event, guild, di) {
.replace(/