Compare commits

..

2 commits

Author SHA1 Message Date
7f7a366cd5 Fix tests for command emoji change 2026-05-22 14:34:59 +12:00
99eacd8c47 Generate letter avatars if no avatar 2026-05-22 14:34:32 +12:00
5 changed files with 235 additions and 110 deletions

View file

@ -8,9 +8,9 @@ test("message2event embeds: interaction loading", async t => {
const events = await messageToEvent(data.interaction_message.thinking_interaction, data.guild.general, {}) const events = await messageToEvent(data.interaction_message.thinking_interaction, data.guild.general, {})
t.deepEqual(events, [{ t.deepEqual(events, [{
$type: "m.room.message", $type: "m.room.message",
body: "↪️ Brad used `/stats` — interaction loading...", body: " Brad used `/stats` — interaction loading...",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: "<blockquote><sub>↪️ <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">Brad</a> used <code>/stats</code> — interaction loading...</sub></blockquote>", formatted_body: "<blockquote><sub> <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">Brad</a> used <code>/stats</code> — interaction loading...</sub></blockquote>",
"m.mentions": {}, "m.mentions": {},
msgtype: "m.notice", msgtype: "m.notice",
}]) }])
@ -22,12 +22,12 @@ test("message2event embeds: nothing but a field", async t => {
$type: "m.room.message", $type: "m.room.message",
"m.mentions": {}, "m.mentions": {},
msgtype: "m.notice", msgtype: "m.notice",
body: "↪️ PapiOphidian used `/stats`" body: " PapiOphidian used `/stats`"
+ "\n| ### Amanda 🎵#2192 :online:" + "\n| ### Amanda 🎵#2192 :online:"
+ "\n| willow tree, branch 0" + "\n| willow tree, branch 0"
+ "\n| ** Uptime:**\n| 3m 55s\n| ** Memory:**\n| 64.45MB", + "\n| ** Uptime:**\n| 3m 55s\n| ** Memory:**\n| 64.45MB",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: '<blockquote><sub>↪️ <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>' formatted_body: '<blockquote><sub> <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>'
+ '<blockquote><p><strong>Amanda 🎵#2192 <img data-mx-emoticon height=\"32\" src=\"mxc://cadence.moe/LCEqjStXCxvRQccEkuslXEyZ\" title=\":online:\" alt=\":online:\">' + '<blockquote><p><strong>Amanda 🎵#2192 <img data-mx-emoticon height=\"32\" src=\"mxc://cadence.moe/LCEqjStXCxvRQccEkuslXEyZ\" title=\":online:\" alt=\":online:\">'
+ '<br>willow tree, branch 0</strong>' + '<br>willow tree, branch 0</strong>'
+ '<br><strong> Uptime:</strong><br>3m 55s' + '<br><strong> Uptime:</strong><br>3m 55s'
@ -153,10 +153,10 @@ test("message2event embeds: title without url", async t => {
t.deepEqual(events, [{ t.deepEqual(events, [{
$type: "m.room.message", $type: "m.room.message",
msgtype: "m.notice", msgtype: "m.notice",
body: "↪️ PapiOphidian used `/stats`" body: " PapiOphidian used `/stats`"
+ "\n| ## Hi, I'm Amanda!\n| \n| I condone pirating music!", + "\n| ## Hi, I'm Amanda!\n| \n| I condone pirating music!",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: '<blockquote><sub>↪️ <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>' formatted_body: '<blockquote><sub> <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>'
+ `<blockquote><p><strong>Hi, I'm Amanda!</strong></p><p>I condone pirating music!</p></blockquote>`, + `<blockquote><p><strong>Hi, I'm Amanda!</strong></p><p>I condone pirating music!</p></blockquote>`,
"m.mentions": {} "m.mentions": {}
}]) }])
@ -167,10 +167,10 @@ test("message2event embeds: url without title", async t => {
t.deepEqual(events, [{ t.deepEqual(events, [{
$type: "m.room.message", $type: "m.room.message",
msgtype: "m.notice", msgtype: "m.notice",
body: "↪️ PapiOphidian used `/stats`" body: " PapiOphidian used `/stats`"
+ "\n| I condone pirating music!", + "\n| I condone pirating music!",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: '<blockquote><sub>↪️ <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>' formatted_body: '<blockquote><sub> <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>'
+ `<blockquote><p>I condone pirating music!</p></blockquote>`, + `<blockquote><p>I condone pirating music!</p></blockquote>`,
"m.mentions": {} "m.mentions": {}
}]) }])
@ -181,10 +181,10 @@ test("message2event embeds: author without url", async t => {
t.deepEqual(events, [{ t.deepEqual(events, [{
$type: "m.room.message", $type: "m.room.message",
msgtype: "m.notice", msgtype: "m.notice",
body: "↪️ PapiOphidian used `/stats`" body: " PapiOphidian used `/stats`"
+ "\n| ## Amanda\n| \n| I condone pirating music!", + "\n| ## Amanda\n| \n| I condone pirating music!",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: '<blockquote><sub>↪️ <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>' formatted_body: '<blockquote><sub> <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>'
+ `<blockquote><p><strong>Amanda</strong></p><p>I condone pirating music!</p></blockquote>`, + `<blockquote><p><strong>Amanda</strong></p><p>I condone pirating music!</p></blockquote>`,
"m.mentions": {} "m.mentions": {}
}]) }])
@ -195,10 +195,10 @@ test("message2event embeds: author url without name", async t => {
t.deepEqual(events, [{ t.deepEqual(events, [{
$type: "m.room.message", $type: "m.room.message",
msgtype: "m.notice", msgtype: "m.notice",
body: "↪️ PapiOphidian used `/stats`" body: " PapiOphidian used `/stats`"
+ "\n| I condone pirating music!", + "\n| I condone pirating music!",
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
formatted_body: '<blockquote><sub>↪️ <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>' formatted_body: '<blockquote><sub> <a href=\"https://matrix.to/#/@_ooye_papiophidian:cadence.moe\">PapiOphidian</a> used <code>/stats</code></sub></blockquote>'
+ `<blockquote><p>I condone pirating music!</p></blockquote>`, + `<blockquote><p>I condone pirating music!</p></blockquote>`,
"m.mentions": {} "m.mentions": {}
}]) }])

View file

@ -29,6 +29,8 @@ const pollComponents = sync.require("./poll-components")
const setupEmojis = sync.require("../actions/setup-emojis") const setupEmojis = sync.require("../actions/setup-emojis")
/** @type {import("../../d2m/converters/user-to-mxid")} */ /** @type {import("../../d2m/converters/user-to-mxid")} */
const userToMxid = sync.require("../../d2m/converters/user-to-mxid") const userToMxid = sync.require("../../d2m/converters/user-to-mxid")
/** @type {import("../../web/routes/letter-avatar")} */
const letterAvatar = sync.require("../../web/routes/letter-avatar")
/** @type {[RegExp, string][]} */ /** @type {[RegExp, string][]} */
const markdownEscapes = [ const markdownEscapes = [
@ -582,6 +584,11 @@ async function eventToMessage(event, guild, channel, di) {
displayNameRunoff = "" displayNameRunoff = ""
} }
// If undefined, generate letter avatar instead of using Discord default
if (avatarURL == undefined) {
avatarURL = letterAvatar.getLetterAvatarURL(event.sender, displayNameShortened)
}
let content = event.content["body"] || "" // ultimate fallback let content = event.content["body"] || "" // ultimate fallback
/** @type {{id: string, filename: string}[]} */ /** @type {{id: string, filename: string}[]} */
const attachments = [] const attachments = []

View file

@ -61,7 +61,7 @@ test("event2message: body is used when there is no formatted_body", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "testing plaintext", content: "testing plaintext",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -99,7 +99,7 @@ test("event2message: any markdown in body is escaped, except strikethrough", asy
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "testing \\*\\*special\\*\\* ~~things~~ which \\_should\\_ \\*not\\* \\`trigger\\` @any <effects>, except strikethrough", content: "testing \\*\\*special\\*\\* ~~things~~ which \\_should\\_ \\*not\\* \\`trigger\\` @any <effects>, except strikethrough",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -134,7 +134,7 @@ test("event2message: links in formatted body are not broken", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", 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", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -167,7 +167,7 @@ test("event2message: links in plaintext body are not broken", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", 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", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -195,7 +195,7 @@ test("event2message: links in plaintext body are not broken when preceded by a n
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "java redstoners will be like \"I hate bedrock edition redstone!!\" meanwhile java edition:\nhttps://youtu.be/g_ORb7bN3CM", content: "java redstoners will be like \"I hate bedrock edition redstone!!\" meanwhile java edition:\nhttps://youtu.be/g_ORb7bN3CM",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -225,7 +225,7 @@ test("event2message: links in formatted body where the text & href are the same,
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "https://privatebin.net/?9111cb16f28da21b#62CKkEr6WvXZ1gQv2M6agazsA7tGYX8ZP8drETYujYZr", content: "https://privatebin.net/?9111cb16f28da21b#62CKkEr6WvXZ1gQv2M6agazsA7tGYX8ZP8drETYujYZr",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -264,7 +264,7 @@ test("event2message: markdown in link text does not attempt to be escaped becaus
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "hey [@mario sports mix [she/her]](<https://matrix.to/#/%40cadence%3Acadence.moe>), is it possible to listen on a unix socket?", content: "hey [@mario sports mix [she/her]](<https://matrix.to/#/%40cadence%3Acadence.moe>), is it possible to listen on a unix socket?",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["roles"], parse: ["roles"],
users: [] users: []
@ -293,7 +293,7 @@ test("event2message: markdown in link url does not attempt to be escaped (plaint
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "the wikimedia commons freaks are gonna love this one https://commons.wikimedia.org/wiki/File:Car_covered_in_traffic_cones.jpg", content: "the wikimedia commons freaks are gonna love this one https://commons.wikimedia.org/wiki/File:Car_covered_in_traffic_cones.jpg",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -328,7 +328,7 @@ test("event2message: markdown in link url does not attempt to be escaped (plaint
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "the wikimedia commons freaks are gonna love this one <https://commons.wikimedia.org/wiki/File:Car_covered_in_traffic_cones.jpg>", content: "the wikimedia commons freaks are gonna love this one <https://commons.wikimedia.org/wiki/File:Car_covered_in_traffic_cones.jpg>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -366,7 +366,7 @@ test("event2message: embeds are suppressed if the guild does not have embed link
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>", content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -402,7 +402,7 @@ test("event2message: embeds are suppressed if the guild does not have embed link
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>", content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -445,7 +445,7 @@ test("event2message: embeds are suppressed if the channel does not have embed li
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>", content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -476,7 +476,7 @@ test("event2message: links retain angle brackets (formatted body)", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>", content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -505,7 +505,7 @@ test("event2message: links retain angle brackets (plaintext body)", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>", content: "posting one of my favourite songs recently (starts at timestamp) <https://youtu.be/RhV2X7WQMPA?t=364>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -546,7 +546,7 @@ test("event2message: links don't have angle brackets added by accident", async t
messagesToSend: [{ messagesToSend: [{
username: "Erquint", username: "Erquint",
content: "Wanted to automate WG→AWG config enrichment and ended up basically coding a batch INI processor.\nhttps://github.com/Erquint/wgcbp", content: "Wanted to automate WG→AWG config enrichment and ended up basically coding a batch INI processor.\nhttps://github.com/Erquint/wgcbp",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=E&hue=180",
allowed_mentions: { allowed_mentions: {
parse: ["roles"], parse: ["roles"],
users: [] users: []
@ -581,7 +581,7 @@ test("event2message: basic html is converted to markdown", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "this **is** a _**test** __of___ ~~_formatting_~~", content: "this **is** a _**test** __of___ ~~_formatting_~~",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -615,7 +615,7 @@ test("event2message: spoilers work", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "this **is** a ||_test_|| of ||spoilers||", content: "this **is** a ||_test_|| of ||spoilers||",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -649,7 +649,7 @@ test("event2message: spoiler reasons work", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "\\(cw crossword spoilers you'll never believe. don't tell anybody\\) ||zoe kills a 5 letter noun at the end||", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -689,7 +689,7 @@ test("event2message: media spoilers work", async t => {
messagesToSend: [{ messagesToSend: [{
username: "underscore_x", username: "underscore_x",
content: "", content: "",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=U&hue=270",
attachments: [{id: "0", filename: "SPOILER_pitstop.png"}], attachments: [{id: "0", filename: "SPOILER_pitstop.png"}],
pendingFiles: [{ pendingFiles: [{
mxc: "mxc://agiadn.org/JY5NvEFojTvYDp5znjGIkkQ7Ez7GwsdT", mxc: "mxc://agiadn.org/JY5NvEFojTvYDp5znjGIkkQ7Ez7GwsdT",
@ -735,7 +735,7 @@ test("event2message: media spoilers with reason work", async t => {
parse: ["users", "roles"] parse: ["users", "roles"]
}, },
content: "(Spoiler: golden witch solutions)", content: "(Spoiler: golden witch solutions)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=U&hue=270",
attachments: [{id: "0", filename: "SPOILER_pitstop.png"}], attachments: [{id: "0", filename: "SPOILER_pitstop.png"}],
pendingFiles: [{ pendingFiles: [{
mxc: "mxc://agiadn.org/JY5NvEFojTvYDp5znjGIkkQ7Ez7GwsdT", mxc: "mxc://agiadn.org/JY5NvEFojTvYDp5znjGIkkQ7Ez7GwsdT",
@ -781,7 +781,7 @@ test("event2message: spoiler files too large for Discord are linked and retain r
parse: ["users", "roles"] parse: ["users", "roles"]
}, },
content: "(Spoiler: golden witch secrets)\n🖼 _Uploaded **SPOILER** file: ||[pitstop.png](https://bridge.example.org/download/matrix/agiadn.org/JY5NvEFojTvYDp5znjGIkkQ7Ez7GwsdT )|| (40 MB)_", content: "(Spoiler: golden witch secrets)\n🖼 _Uploaded **SPOILER** file: ||[pitstop.png](https://bridge.example.org/download/matrix/agiadn.org/JY5NvEFojTvYDp5znjGIkkQ7Ez7GwsdT )|| (40 MB)_",
avatar_url: undefined avatar_url: "https://bridge.example.org/download/letter-avatar?letter=U&hue=270"
}] }]
} }
) )
@ -812,7 +812,7 @@ test("event2message: markdown syntax is escaped", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "this \\*\\*is\\*\\* an **_extreme_** \\\\\\*test\\\\\\* of", content: "this \\*\\*is\\*\\* an **_extreme_** \\\\\\*test\\\\\\* of",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -846,7 +846,7 @@ test("event2message: html lines are bridged correctly", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", 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", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -880,7 +880,7 @@ test("event2message: html lines are bridged correctly", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\n line five", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -915,7 +915,7 @@ test("event2message: whitespace is collapsed", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\nline five", content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\nline five",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -951,7 +951,7 @@ test("event2message: lists are bridged correctly", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four", content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -983,14 +983,14 @@ test("event2message: long messages are split", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: (("a".repeat(130) + " ").repeat(15)).slice(0, -1), content: (("a".repeat(130) + " ").repeat(15)).slice(0, -1),
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
}, { }, {
username: "cadence [they]", username: "cadence [they]",
content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1), content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1),
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1024,7 +1024,7 @@ test("event2message: code blocks work", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline", content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1054,7 +1054,7 @@ test("event2message: code block contents are formatted correctly and not escaped
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "```\ninput = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n_input_ = input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n```\n\n`input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,`", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1084,7 +1084,7 @@ test("event2message: code blocks use double backtick as delimiter when necessary
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "``backtick in ` the middle``, `` backtick at the edge` ``", content: "``backtick in ` the middle``, `` backtick at the edge` ``",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1114,7 +1114,7 @@ test("event2message: inline code is converted to code block if it contains both
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "``` ` one two `` ```", content: "``` ` one two `` ```",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1146,7 +1146,7 @@ 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", 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"}], attachments: [{id: "0", filename: "inline_code.java"}],
pendingFiles: [{name: "inline_code.java", buffer: Buffer.from('System.out.println("```");')}], pendingFiles: [{name: "inline_code.java", buffer: Buffer.from('System.out.println("```");')}],
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1178,7 +1178,7 @@ test("event2message: code blocks are uploaded as attachments instead if they con
content: "So if you run code like this `[inline_code.txt]` it should print a markdown formatted code block", content: "So if you run code like this `[inline_code.txt]` it should print a markdown formatted code block",
attachments: [{id: "0", filename: "inline_code.txt"}], attachments: [{id: "0", filename: "inline_code.txt"}],
pendingFiles: [{name: "inline_code.txt", buffer: Buffer.from('System.out.println("```");')}], pendingFiles: [{name: "inline_code.txt", buffer: Buffer.from('System.out.println("```");')}],
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1210,7 +1210,7 @@ test("event2message: code blocks are uploaded as attachments instead if they con
content: "So if you run code like this `[inline_code.txt]` it should print a markdown formatted code block", content: "So if you run code like this `[inline_code.txt]` it should print a markdown formatted code block",
attachments: [{id: "0", filename: "inline_code.txt"}], attachments: [{id: "0", filename: "inline_code.txt"}],
pendingFiles: [{name: "inline_code.txt", buffer: Buffer.from('System.out.println("```");')}], pendingFiles: [{name: "inline_code.txt", buffer: Buffer.from('System.out.println("```");')}],
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1242,7 +1242,7 @@ test("event2message: code blocks are uploaded as attachments instead if they are
content: "So if you run code like this `[inline_code.js]` it should print a markdown formatted code block", content: "So if you run code like this `[inline_code.js]` it should print a markdown formatted code block",
attachments: [{id: "0", filename: "inline_code.js"}], attachments: [{id: "0", filename: "inline_code.js"}],
pendingFiles: [{name: "inline_code.js", buffer: Buffer.from("A".repeat(2000))}], pendingFiles: [{name: "inline_code.js", buffer: Buffer.from("A".repeat(2000))}],
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1285,7 +1285,7 @@ test("event2message: characters are encoded properly in code blocks", async t =>
+ '\n .map(|c| c.get(1).unwrap().as_str())' + '\n .map(|c| c.get(1).unwrap().as_str())'
+ '\n .collect::<String>();' + '\n .collect::<String>();'
)}], )}],
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1319,7 +1319,7 @@ test("event2message: quotes have an appropriate amount of whitespace", async t =
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "> Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands\n🤨", content: "> Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands\n🤨",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1360,7 +1360,7 @@ test("event2message: lists have appropriate line breaks", async t => {
messagesToSend: [{ messagesToSend: [{
username: "Milan", 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`, 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: "https://bridge.example.org/download/letter-avatar?letter=M&hue=210",
allowed_mentions: { allowed_mentions: {
parse: ["roles"], parse: ["roles"],
users: [] users: []
@ -1402,7 +1402,7 @@ test("event2message: ordered list start attribute works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "Milan", 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`, 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: "https://bridge.example.org/download/letter-avatar?letter=M&hue=210",
allowed_mentions: { allowed_mentions: {
parse: ["roles"], parse: ["roles"],
users: [] users: []
@ -1435,7 +1435,7 @@ test("event2message: m.emote plaintext works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "\\* cadence \\[they\\] tests an m.emote message", content: "\\* cadence \\[they\\] tests an m.emote message",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1469,7 +1469,7 @@ test("event2message: m.emote markdown syntax is escaped", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "\\* cadence \\[they\\] shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of", content: "\\* cadence \\[they\\] shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -1706,7 +1706,7 @@ test("event2message: rich reply to a rich reply to a multi-line message should c
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:"
+ " I just checked in a fix that will probably work..." + " I just checked in a fix that will probably work..."
+ "\nwill try later (tomorrow if I don't forgor)", + "\nwill try later (tomorrow if I don't forgor)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -2040,7 +2040,7 @@ test("event2message: should suppress embeds for links in reply preview", async t
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1273204543739396116 **Ⓜcadence [they]**:" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1273204543739396116 **Ⓜcadence [they]**:"
+ " <https://www.youtube.com/watch?v=uX32idb1jMw>" + " <https://www.youtube.com/watch?v=uX32idb1jMw>"
+ `\nEveryone in the comments is like "you're so ahead of the curve" and "can't believe this came out before the scandal" but I thought Mr Beast sucking was a common sentiment`, + `\nEveryone in the comments is like "you're so ahead of the curve" and "can't believe this came out before the scandal" but I thought Mr Beast sucking was a common sentiment`,
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=R&hue=240",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -2316,7 +2316,7 @@ test("event2message: reply preview converts emoji formatting when replying to a
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:"
+ " <:hippo:230201364309868544>" + " <:hippo:230201364309868544>"
+ "\nreply", + "\nreply",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -2366,7 +2366,7 @@ test("event2message: reply preview can guess custom emoji based on the name if i
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:"
+ " <:hippo:230201364309868544>" + " <:hippo:230201364309868544>"
+ "\nreply", + "\nreply",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -2416,7 +2416,7 @@ test("event2message: reply preview uses emoji title text when replying to an unk
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:"
+ " :svkftngur_gkdne:" + " :svkftngur_gkdne:"
+ "\nreply", + "\nreply",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -2466,7 +2466,7 @@ test("event2message: reply preview ignores garbage image", async t => {
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:"
+ " I am having a nice day" + " I am having a nice day"
+ "\nreply", + "\nreply",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -2515,7 +2515,7 @@ test("event2message: reply to empty message doesn't show an extra line or anythi
username: "cadence [they]", username: "cadence [they]",
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**" content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**"
+ "\nreply", + "\nreply",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3311,7 +3311,7 @@ test("event2message: rich reply with an image", async t => {
id: "0", id: "0",
}, },
], ],
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
pendingFiles: [ pendingFiles: [
{ {
mxc: "mxc://cadence.moe/yxMobQMbSqNHpajxgSHtaooG", mxc: "mxc://cadence.moe/yxMobQMbSqNHpajxgSHtaooG",
@ -3348,7 +3348,7 @@ test("event2message: raw mentioning discord users in plaintext body works", asyn
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<@114147806469554185> what do you think?", content: "<@114147806469554185> what do you think?",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3382,7 +3382,7 @@ test("event2message: raw mentioning discord users in formatted body works", asyn
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<@114147806469554185> what do you think?", content: "<@114147806469554185> what do you think?",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3416,7 +3416,7 @@ test("event2message: mentioning discord users works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just <@114147806469554185> testing mentions", content: "I'm just <@114147806469554185> testing mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3457,7 +3457,7 @@ test("event2message: mentioning discord users with extra html attributes works",
messagesToEdit: [], messagesToEdit: [],
messagesToSend: [{ messagesToSend: [{
username: "lavender.pet", username: "lavender.pet",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=L&hue=30",
content: "also <@196188877885538304> fun fact at some point there is plans for FTE to have a built in map editor", content: "also <@196188877885538304> fun fact at some point there is plans for FTE to have a built in map editor",
allowed_mentions: { allowed_mentions: {
parse: ["roles"], parse: ["roles"],
@ -3494,7 +3494,7 @@ test("event2message: mentioning discord users works when URL encoded", async t =
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<@771520384671416320> a sample message", content: "<@771520384671416320> a sample message",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3528,7 +3528,7 @@ test("event2message: mentioning PK discord users works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just **@Azalea &flwr; 🌺** (<@196188877885538304>) testing mentions", content: "I'm just **@Azalea &flwr; 🌺** (<@196188877885538304>) testing mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3562,7 +3562,7 @@ test("event2message: mentioning matrix users works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just [@▲](<https://matrix.to/#/@rnl:cadence.moe>) testing mentions", content: "I'm just [@▲](<https://matrix.to/#/@rnl:cadence.moe>) testing mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3603,7 +3603,7 @@ test("event2message: matrix mentions are not double-escaped when embed links per
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just [@▲](<https://matrix.to/#/@rnl:cadence.moe>) testing mentions", content: "I'm just [@▲](<https://matrix.to/#/@rnl:cadence.moe>) testing mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3637,7 +3637,7 @@ test("event2message: multiple mentions are both escaped", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "[@cadence:cadence.moe](<https://matrix.to/#/@cadence:cadence.moe>) can you kick my old account over there [@amyiscoolz:matrix.atiusamy.com](<https://matrix.to/#/@amyiscoolz:matrix.atiusamy.com>)", content: "[@cadence:cadence.moe](<https://matrix.to/#/@cadence:cadence.moe>) can you kick my old account over there [@amyiscoolz:matrix.atiusamy.com](<https://matrix.to/#/@amyiscoolz:matrix.atiusamy.com>)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3667,7 +3667,7 @@ test("event2message: mentioning matrix users works even when Element disambiguat
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "[@unascribed](<https://matrix.to/#/@unascribed:sleeping.town>) 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)", content: "[@unascribed](<https://matrix.to/#/@unascribed:sleeping.town>) 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3701,7 +3701,7 @@ test("event2message: mentioning bridged rooms works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just <#1100319550446252084> testing channel mentions", content: "I'm just <#1100319550446252084> testing channel mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3733,7 +3733,7 @@ test("event2message: mentioning bridged rooms works (plaintext body)", async t =
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just <#1100319550446252084> testing channel mentions", content: "I'm just <#1100319550446252084> testing channel mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3776,7 +3776,7 @@ test("event2message: mentioning bridged rooms by alias works", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just <#1100319550446252084> testing channel mentions", content: "I'm just <#1100319550446252084> testing channel mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3818,7 +3818,7 @@ test("event2message: mentioning bridged rooms by alias works (plaintext body)",
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just <#1100319550446252084> testing channel mentions", content: "I'm just <#1100319550446252084> testing channel mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3859,7 +3859,7 @@ test("event2message: mentioning bridged rooms by alias skips the link when alias
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "I'm just <https://matrix.to/#/#worm-farm:cadence.moe?via=cadence.moe> and <#1100319550446252084> testing channel mentions", content: "I'm just <https://matrix.to/#/#worm-farm:cadence.moe?via=cadence.moe> and <#1100319550446252084> testing channel mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3892,7 +3892,7 @@ test("event2message: mentioning known bridged events works (plaintext body)", as
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020, take a look!", content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020, take a look!",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3926,7 +3926,7 @@ test("event2message: mentioning known bridged events works (partially formatted
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020", content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3960,7 +3960,7 @@ test("event2message: mentioning known bridged events works (formatted body)", as
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020", content: "it was uploaded earlier in https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -3994,7 +3994,7 @@ test("event2message: mentioning known bridged events followed by line break and
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020<@114147806469554185>", content: "https://discord.com/channels/497159726455455754/497161350934560778/1141619794500649020<@114147806469554185>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4040,7 +4040,7 @@ test("event2message: mentioning unknown bridged events can approximate with time
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "it was uploaded years ago in https://discord.com/channels/497159726455455754/497161350934560778/753895613661184000", content: "it was uploaded years ago in https://discord.com/channels/497159726455455754/497161350934560778/753895613661184000",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4085,7 +4085,7 @@ test("event2message: mentioning events falls back to original link when server d
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "it was uploaded years ago in [amanda-spam](<https://matrix.to/#/!CzvdIdUQXgUjDVKxeU:cadence.moe/$zpzx6ABetMl8BrpsFbdZ7AefVU1Y_-t97bJRJM2JyW1?via=cadence.moe>)", content: "it was uploaded years ago in [amanda-spam](<https://matrix.to/#/!CzvdIdUQXgUjDVKxeU:cadence.moe/$zpzx6ABetMl8BrpsFbdZ7AefVU1Y_-t97bJRJM2JyW1?via=cadence.moe>)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4129,7 +4129,7 @@ test("event2message: mentioning events falls back to original link when the chan
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "it was uploaded years ago in [ex-room-doesnt-exist-any-more](<https://matrix.to/#/!tnedrGVYKFNUdnegvf:tchncs.de/$zpzx6ABetMl8BrpsFbdZ7AefVU1Y_-t97bJRJM2JyW2?via=tchncs.de>)", content: "it was uploaded years ago in [ex-room-doesnt-exist-any-more](<https://matrix.to/#/!tnedrGVYKFNUdnegvf:tchncs.de/$zpzx6ABetMl8BrpsFbdZ7AefVU1Y_-t97bJRJM2JyW2?via=tchncs.de>)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4159,7 +4159,7 @@ test("event2message: link to event in an unknown room (href link)", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "ah yeah, here's where the bug was reported: <https://matrix.to/#/!QtykxKocfZaZOUrTwp:matrix.org/$1542477546853947KGhZL:matrix.org>", content: "ah yeah, here's where the bug was reported: <https://matrix.to/#/!QtykxKocfZaZOUrTwp:matrix.org/$1542477546853947KGhZL:matrix.org>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4189,7 +4189,7 @@ test("event2message: link to event in an unknown room (bare link)", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "PK API failure, tho idk how you'd handle that <https://matrix.to/#/!SeYQChwXBnZaQLoZfI:sleeping.town/$AAPZ56B2P7TfROYPTtuoJjgvXmaBM11NoNceM8GCJ7s>", content: "PK API failure, tho idk how you'd handle that <https://matrix.to/#/!SeYQChwXBnZaQLoZfI:sleeping.town/$AAPZ56B2P7TfROYPTtuoJjgvXmaBM11NoNceM8GCJ7s>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4217,7 +4217,7 @@ test("event2message: link to event in an unknown room (plaintext)", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "ah yeah, here's where the bug was reported: <https://matrix.to/#/!QtykxKocfZaZOUrTwp:matrix.org/$1542477546853947KGhZL:matrix.org>", content: "ah yeah, here's where the bug was reported: <https://matrix.to/#/!QtykxKocfZaZOUrTwp:matrix.org/$1542477546853947KGhZL:matrix.org>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4251,7 +4251,7 @@ test("event2message: colon after mentions is stripped", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<@114147806469554185> hey, I'm just [@▲](<https://matrix.to/#/@rnl:cadence.moe>) testing mentions", content: "<@114147806469554185> hey, I'm just [@▲](<https://matrix.to/#/@rnl:cadence.moe>) testing mentions",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4392,7 +4392,7 @@ test("event2message: skips caching the member if the member does not exist, some
messagesToSend: [{ messagesToSend: [{
username: "not_real", username: "not_real",
content: "should honestly never happen", content: "should honestly never happen",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=N&hue=180",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4439,7 +4439,7 @@ test("event2message: overly long usernames are shifted into the message content"
messagesToSend: [{ messagesToSend: [{
username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS", 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", content: "**IMPORTANT and I DON'T MATTER**\ntesting the member state cache",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=I&hue=270",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -4475,7 +4475,7 @@ test("event2message: overly long usernames are not treated specially when the ms
messagesToSend: [{ messagesToSend: [{
username: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS", 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", 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: "https://bridge.example.org/download/letter-avatar?letter=I&hue=270",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5000,7 +5000,7 @@ test("event2message: stickers fetch mimetype from server when mimetype not provi
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "[YESYESYES](https://bridge.example.org/download/sticker/cadence.moe/ybOWQCaXysnyUGuUCaQlTGJf/_.webp)", content: "[YESYESYES](https://bridge.example.org/download/sticker/cadence.moe/ybOWQCaXysnyUGuUCaQlTGJf/_.webp)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5030,7 +5030,7 @@ test("event2message: static emojis work", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<:hippo:230201364309868544>", content: "<:hippo:230201364309868544>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5090,7 +5090,7 @@ test("event2message: animated emojis work", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<a:hipposcope:393635038903926784>", content: "<a:hipposcope:393635038903926784>",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5120,7 +5120,7 @@ test("event2message: unknown emojis in the middle are linked", async t => {
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "a [:ms_robot_grin:](https://bridge.example.org/download/matrix/cadence.moe/RLMgJGfgTPjIQtvvWZsYjhjy) b", content: "a [:ms_robot_grin:](https://bridge.example.org/download/matrix/cadence.moe/RLMgJGfgTPjIQtvvWZsYjhjy) b",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5169,7 +5169,7 @@ test("event2message: guessed @mentions in plaintext may join members to mention"
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "hey <@321876634777218072>, what food would you like to order?", content: "hey <@321876634777218072>, what food would you like to order?",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5222,7 +5222,7 @@ test("event2message: guessed @mentions in formatted body may join members to men
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "**_HEY <@321876634777218072>, WHAT FOOD WOULD YOU LIKE TO ORDER??_**", content: "**_HEY <@321876634777218072>, WHAT FOOD WOULD YOU LIKE TO ORDER??_**",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5265,7 +5265,7 @@ test("event2message: guessed @mentions feature will not activate on links or cod
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", 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```", 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: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5295,7 +5295,7 @@ test("event2message: guessed @mentions work with other matrix bridge old users",
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "<@114147806469554185> <@176943908762006200> back me up on this sentiment, if not necessarily the phrasing", content: "<@114147806469554185> <@176943908762006200> back me up on this sentiment, if not necessarily the phrasing",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5352,7 +5352,7 @@ test("event2message: @room converts to @everyone and is allowed when the room do
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "@everyone dinner's ready", content: "@everyone dinner's ready",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles", "everyone"] parse: ["users", "roles", "everyone"]
} }
@ -5409,7 +5409,7 @@ test("event2message: @room converts to @everyone but is not allowed when the roo
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "@room dinner's ready", content: "@room dinner's ready",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5468,7 +5468,7 @@ test("event2message: @room converts to @everyone and is allowed if the user has
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "@everyone dinner's ready", content: "@everyone dinner's ready",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles", "everyone"] parse: ["users", "roles", "everyone"]
} }
@ -5498,7 +5498,7 @@ test("event2message: @room in the middle of a link is not converted", async t =>
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "https://github.com/@room/repositories https://github.com/@room/repositories", content: "https://github.com/@room/repositories https://github.com/@room/repositories",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5534,7 +5534,7 @@ test("event2message: table", async t => {
+ "\nAardvark Bee Crocodile" + "\nAardvark Bee Crocodile"
+ "\nArgon Boron Carbon ```" + "\nArgon Boron Carbon ```"
+ "more content", + "more content",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5564,7 +5564,7 @@ test("event2message: unknown emoji at the end is used for sprite sheet", async t
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "a b [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FRLMgJGfgTPjIQtvvWZsYjhjy)", content: "a b [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FRLMgJGfgTPjIQtvvWZsYjhjy)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5594,7 +5594,7 @@ test("event2message: known emoji from an unreachable server at the end is used f
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "a b [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FbZFuuUSEebJYXUMSxuuSuLTa)", content: "a b [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FbZFuuUSEebJYXUMSxuuSuLTa)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5624,7 +5624,7 @@ test("event2message: known and unknown emojis in the end are used for sprite she
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "known unknown: <:hippo:230201364309868544> [:ms_robot_dress:](https://bridge.example.org/download/matrix/cadence.moe/wcouHVjbKJJYajkhJLsyeJAA) and known unknown: [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FWbYqNlACRuicynBfdnPYtmvc&e=cadence.moe%2FHYcztccFIPgevDvoaWNsEtGJ)", content: "known unknown: <:hippo:230201364309868544> [:ms_robot_dress:](https://bridge.example.org/download/matrix/cadence.moe/wcouHVjbKJJYajkhJLsyeJAA) and known unknown: [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FWbYqNlACRuicynBfdnPYtmvc&e=cadence.moe%2FHYcztccFIPgevDvoaWNsEtGJ)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5691,7 +5691,7 @@ test("event2message: com.beeper.per_message_profile empty avatar_url clears avat
messagesToSend: [{ messagesToSend: [{
username: "No Avatar User", username: "No Avatar User",
content: "hello with cleared avatar", content: "hello with cleared avatar",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=N&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5760,7 +5760,7 @@ test("event2message: displayname prefix is stripped from plain body when per-mes
messagesToSend: [{ messagesToSend: [{
username: "Tidus Herboren", username: "Tidus Herboren",
content: "one more test", content: "one more test",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=T&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }
@ -5789,7 +5789,7 @@ test("event2message: all unknown chess emojis are used for sprite sheet", async
messagesToSend: [{ messagesToSend: [{
username: "cadence [they]", username: "cadence [they]",
content: "testing [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FlHfmJpzgoNyNtYHdAmBHxXix&e=cadence.moe%2FMtRdXixoKjKKOyHJGWLsWLNU&e=cadence.moe%2FHXfFuougamkURPPMflTJRxGc&e=cadence.moe%2FikYKbkhGhMERAuPPbsnQzZiX&e=cadence.moe%2FAYPpqXzVJvZdzMQJGjioIQBZ&e=cadence.moe%2FUVuzvpVUhqjiueMxYXJiFEAj&e=cadence.moe%2FlHfmJpzgoNyNtYHdAmBHxXix&e=cadence.moe%2FMtRdXixoKjKKOyHJGWLsWLNU&e=cadence.moe%2FHXfFuougamkURPPMflTJRxGc&e=cadence.moe%2FikYKbkhGhMERAuPPbsnQzZiX&e=cadence.moe%2FAYPpqXzVJvZdzMQJGjioIQBZ&e=cadence.moe%2FUVuzvpVUhqjiueMxYXJiFEAj)", content: "testing [\u2800](https://bridge.example.org/download/sheet?e=cadence.moe%2FlHfmJpzgoNyNtYHdAmBHxXix&e=cadence.moe%2FMtRdXixoKjKKOyHJGWLsWLNU&e=cadence.moe%2FHXfFuougamkURPPMflTJRxGc&e=cadence.moe%2FikYKbkhGhMERAuPPbsnQzZiX&e=cadence.moe%2FAYPpqXzVJvZdzMQJGjioIQBZ&e=cadence.moe%2FUVuzvpVUhqjiueMxYXJiFEAj&e=cadence.moe%2FlHfmJpzgoNyNtYHdAmBHxXix&e=cadence.moe%2FMtRdXixoKjKKOyHJGWLsWLNU&e=cadence.moe%2FHXfFuougamkURPPMflTJRxGc&e=cadence.moe%2FikYKbkhGhMERAuPPbsnQzZiX&e=cadence.moe%2FAYPpqXzVJvZdzMQJGjioIQBZ&e=cadence.moe%2FUVuzvpVUhqjiueMxYXJiFEAj)",
avatar_url: undefined, avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
allowed_mentions: { allowed_mentions: {
parse: ["users", "roles"] parse: ["users", "roles"]
} }

View file

@ -0,0 +1,117 @@
// @ts-check
const h3 = require("h3")
const {defineEventHandler, getValidatedQuery, setResponseHeader} = h3
const sharp = require("sharp")
const {z} = require("zod")
const {as} = require("../../passthrough")
const {reg} = require("../../matrix/read-registration")
/*
Create a 300x300 avatar image consisting of a dark coloured background, and a single character in a lighter colour centered in the middle.
Note: Where dimensions are changed, font size must also be changed too to produce an identical image as before.
Simply put, 100px = 60pt for font.
*/
const SIZE = 300
const POSSIBLE_HUES = 12
/** Helper function: To get accurate complimenting colours we need to work in HSL, then convert back to RGB at the end */
function hslToRgb(h, s, l) {
s /= 100;
l /= 100;
const a = s * Math.min(l, 1 - l);
const f = n => {
const k = (n + h / 30) % 12;
return l - a * Math.max(-1, Math.min(Math.min(k - 3, 9 - k), 1));
};
return {
r: Math.round(255 * f(0)),
g: Math.round(255 * f(8)),
b: Math.round(255 * f(4))
};
}
/**
* Use the MXID to generate deterministic avatar colours for each user.
* Here, we use the string hash code as a hue value, with a 360 wrap modulo.
* @param {string} mxid
*/
function mxidToHue(mxid) {
// Element Classic string hasher
let hash = 0;
let i;
let chr;
if (mxid.length === 0) {
return hash;
}
for (i = 0; i < mxid.length; i++) {
chr = mxid.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0;
}
hash = Math.abs(hash)
return (hash % POSSIBLE_HUES) * (360 / POSSIBLE_HUES)
}
/**
* Get first useful character in username to put in the avatar.
* @param {string} username
*/
function usernameToLetter(username) {
return (username.match(/[a-z0-9]/i)?.[0] || "#").toUpperCase()
}
/**
* @param {string} mxid
* @param {string} username
*/
function getLetterAvatarURL(mxid, username) {
const p = new URLSearchParams({letter: usernameToLetter(username), hue: String(mxidToHue(mxid))})
return `${reg.ooye.bridge_origin}/download/letter-avatar?${p}`
}
const schema = {
letterAvatar: z.object({
hue: z.coerce.number().min(0).max(360),
letter: z.string().regex(/^[A-Z0-9#]$/)
})
}
/**
* Produce a PNG letter-avatar from given parameters.
* @param {string} letter
* @param {number} hue
*/
as.router.get("/download/letter-avatar", defineEventHandler(async event => {
const {letter, hue} = await getValidatedQuery(event, schema.letterAvatar.parse)
const bg_rgb = hslToRgb(hue, 65, 18);
const text_rgb = hslToRgb(hue, 70, 65);
const text_rgbahex = `#${text_rgb.r.toString(16).padStart(2, "0")}${text_rgb.g.toString(16).padStart(2, "0")}${text_rgb.b.toString(16).padStart(2, "0")}ff`
const streamOut = sharp({
create: {
width: SIZE, height: SIZE, channels: 4,
background: {
r: bg_rgb.r, g: bg_rgb.g, b: bg_rgb.b, alpha: 1
}
}
}).composite([{
input: {
text: {
text: `<span foreground="${text_rgbahex}">${letter}</span>`,
font: "Noto Sans Bold 180", align: "center", rgba: true
}
}
}]).png()
setResponseHeader(event, "content-type", "image/png")
return streamOut
}))
module.exports.getLetterAvatarURL = getLetterAvatarURL

View file

@ -130,6 +130,7 @@ sync.require("./routes/download-discord")
sync.require("./routes/guild-settings") sync.require("./routes/guild-settings")
sync.require("./routes/guild") sync.require("./routes/guild")
sync.require("./routes/info") sync.require("./routes/info")
sync.require("./routes/letter-avatar")
sync.require("./routes/link") sync.require("./routes/link")
sync.require("./routes/log-in-with-matrix") sync.require("./routes/log-in-with-matrix")
sync.require("./routes/oauth") sync.require("./routes/oauth")