diff --git a/package-lock.json b/package-lock.json index 7d04cbb..10b4668 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "out-of-your-element", - "version": "3.5.1", + "version": "3.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "out-of-your-element", - "version": "3.5.1", + "version": "3.4.0", "license": "AGPL-3.0-or-later", "dependencies": { "@chriscdn/promise-semaphore": "^3.0.1", @@ -30,7 +30,7 @@ "enquirer": "^2.4.1", "entities": "^5.0.0", "get-relative-path": "^1.0.2", - "h3": "^1.15.10", + "h3": "^1.15.1", "heatsync": "^2.7.2", "htmx.org": "^2.0.4", "lru-cache": "^11.0.2", @@ -276,9 +276,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", - "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz", + "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==", "license": "MIT", "optional": true, "dependencies": { @@ -1163,9 +1163,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, "license": "MIT", "dependencies": { @@ -1488,9 +1488,9 @@ "license": "MIT" }, "node_modules/domino": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.7.tgz", - "integrity": "sha512-3rcXhx0ixJV2nj8J0tljzejTF73A35LVVdnTQu79UAqTBFEgYPMgGtykMuu/BDqaOZphATku1ddRUn/RtqUHYQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz", + "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==", "license": "BSD-2-Clause" }, "node_modules/emoji-regex": { @@ -1587,9 +1587,9 @@ } }, "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", "dev": true, "license": "ISC" }, @@ -1617,9 +1617,9 @@ "license": "MIT" }, "node_modules/fullstore": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fullstore/-/fullstore-4.0.2.tgz", - "integrity": "sha512-syOev4kA0lZy4VkfBJZ99ZL4cIiSgiKt0G8SpP0kla1tpM1c+V/jBOVY/OqqGtR2XLVcM83SjFPFC3R2YIwqjQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fullstore/-/fullstore-4.0.0.tgz", + "integrity": "sha512-Y9hN79Q1CFU8akjGnTZoBnTzlA/o8wmtBijJOI8dKCmdC7GLX7OekpLxmbaeRetTOi4OdFGjfsg4c5dxP3jgPw==", "dev": true, "license": "MIT", "engines": { @@ -1688,9 +1688,9 @@ } }, "node_modules/h3": { - "version": "1.15.10", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.10.tgz", - "integrity": "sha512-YzJeWSkDZxAhvmp8dexjRK5hxziRO7I9m0N53WhvYL5NiWfkUkzssVzY9jvGu0HBoLFW6+duYmNSn6MaZBCCtg==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.6.tgz", + "integrity": "sha512-oi15ESLW5LRthZ+qPCi5GNasY/gvynSKUQxgiovrY63bPAtG59wtM+LSrlcwvOHAXzGrXVLnI97brbkdPF9WoQ==", "license": "MIT", "dependencies": { "cookie-es": "^1.2.2", @@ -1937,9 +1937,9 @@ "license": "MIT" }, "node_modules/json-with-bigint": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.8.tgz", - "integrity": "sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==", + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.7.tgz", + "integrity": "sha512-7ei3MdAI5+fJPVnKlW77TKNKwQ5ppSzWvhPuSuINT/GYW9ZOC1eRKOuhV9yHG5aEsUPj9BBx5JIekkmoLHxZOw==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index c85a362..0e666aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "out-of-your-element", - "version": "3.5.1", + "version": "3.4.0", "description": "A bridge between Matrix and Discord", "main": "index.js", "repository": { @@ -39,7 +39,7 @@ "enquirer": "^2.4.1", "entities": "^5.0.0", "get-relative-path": "^1.0.2", - "h3": "^1.15.10", + "h3": "^1.15.1", "heatsync": "^2.7.2", "htmx.org": "^2.0.4", "lru-cache": "^11.0.2", diff --git a/scripts/reset-web-password.js b/scripts/reset-web-password.js index 7c3a1a2..9131efb 100644 --- a/scripts/reset-web-password.js +++ b/scripts/reset-web-password.js @@ -13,5 +13,5 @@ const {prompt} = require("enquirer") reg.ooye.web_password = passwordResponse.web_password writeRegistration(reg) - console.log("Saved. This change should be applied instantly.") + console.log("Saved. Restart Out Of Your Element to apply this change.") })() diff --git a/src/d2m/actions/create-room.js b/src/d2m/actions/create-room.js index 7f110ad..c2ec01a 100644 --- a/src/d2m/actions/create-room.js +++ b/src/d2m/actions/create-room.js @@ -193,16 +193,6 @@ async function channelToKState(channel, guild, di) { // Don't overwrite room topic if the topic has been customised if (hasCustomTopic) delete channelKState["m.room.topic/"] - // Make voice channels be a Matrix voice room (MSC3417) - if (channel.type === DiscordTypes.ChannelType.GuildVoice) { - creationContent.type = "org.matrix.msc3417.call" - channelKState["org.matrix.msc3401.call/"] = { - "m.intent": "m.room", - "m.type": "m.voice", - "m.name": customName || channel.name - } - } - // Don't add a space parent if it's self service // (The person setting up self-service has already put it in their preferred space to be able to get this far.) const autocreate = select("guild_active", "autocreate", {guild_id: guild.id}).pluck().get() diff --git a/src/d2m/actions/create-room.test.js b/src/d2m/actions/create-room.test.js index c9e098b..36fccba 100644 --- a/src/d2m/actions/create-room.test.js +++ b/src/d2m/actions/create-room.test.js @@ -190,17 +190,6 @@ test("channel2room: read-only discord channel", async t => { t.equal(api.getCalled(), 2) }) -test("channel2room: voice channel", async t => { - const api = mockAPI(t) - const state = kstateStripConditionals(await channelToKState(testData.channel.voice, testData.guild.general, {api}).then(x => x.channelKState)) - t.equal(state["m.room.create/"].type, "org.matrix.msc3417.call") - t.deepEqual(state["org.matrix.msc3401.call/"], { - "m.intent": "m.room", - "m.name": "🍞丨[8user] Piece", - "m.type": "m.voice" - }) -}) - 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/src/d2m/actions/expression.js b/src/d2m/actions/expression.js index 0f714c6..c7ab27a 100644 --- a/src/d2m/actions/expression.js +++ b/src/d2m/actions/expression.js @@ -34,10 +34,7 @@ async function emojisToState(emojis, guild) { if (e.data?.errcode === "M_TOO_LARGE") { // Very unlikely to happen. Only possible for 3x-series emojis uploaded shortly after animated emojis were introduced, when there was no 256 KB size limit. return } - e["emoji"] = { - name: emoji.name, - id: emoji.id - } + console.error(`Trying to handle emoji ${emoji.name} (${emoji.id}), but...`) throw e }) )) diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index 6e9ce7b..3f598f2 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -357,17 +357,6 @@ async function messageToEvent(message, guild, options = {}, di) { }] } - if (message.type === DiscordTypes.MessageType.ChannelFollowAdd) { - return [{ - $type: "m.room.message", - msgtype: "m.emote", - body: `set this room to receive announcements from ${message.content}`, - format: "org.matrix.custom.html", - formatted_body: tag`set this room to receive announcements from ${message.content}`, - "m.mentions": {} - }] - } - let isInteraction = (message.type === DiscordTypes.MessageType.ChatInputCommand || message.type === DiscordTypes.MessageType.ContextMenuCommand) && message.interaction && "name" in message.interaction let isThinkingInteraction = isInteraction && !!((message.flags || 0) & DiscordTypes.MessageFlags.Loading) @@ -669,7 +658,7 @@ async function messageToEvent(message, guild, options = {}, di) { const match = repliedToEventSenderMxid.match(/^@([^:]*)/) assert(match) repliedToDisplayName = referenced.author.username || match[1] || "a Matrix user" // grab the localpart as the display name, whatever - repliedToUserHtml = tag`${repliedToDisplayName}` + repliedToUserHtml = `${repliedToDisplayName}` } else { repliedToDisplayName = referenced.author.global_name || referenced.author.username || "a Discord user" repliedToUserHtml = repliedToDisplayName @@ -694,12 +683,6 @@ async function messageToEvent(message, guild, options = {}, di) { + html body = `${repliedToDisplayName}: ${repliedToBody}`.split("\n").map(line => "> " + line).join("\n") // scenario 1 part B for mentions + "\n\n" + body - } else if (referenced.type === DiscordTypes.MessageType.UserJoin) { - // Discord user join messages are bridged as joins, not text events. Generate substitute text for reply. - const joinerMxid = select("sim", "mxid", {user_id: referenced.author.id}).pluck().get() - const joinerHtml = joinerMxid ? tag`${repliedToDisplayName}` : tag`${repliedToDisplayName}` - html = `
${joinerHtml} joined the room
` + html - body = `> ${repliedToDisplayName} joined the room\n\n` + body } else { // repliedToUnknownEvent const dateDisplay = dUtils.howOldUnbridgedMessage(referenced.timestamp, message.timestamp) html = `
In reply to ${dateDisplay} from ${repliedToDisplayName}:` diff --git a/src/d2m/converters/message-to-event.test.js b/src/d2m/converters/message-to-event.test.js index b7f0867..c4b812d 100644 --- a/src/d2m/converters/message-to-event.test.js +++ b/src/d2m/converters/message-to-event.test.js @@ -4,7 +4,6 @@ const {MatrixServerError} = require("../../matrix/mreq") const data = require("../../../test/data") const {mockGetEffectivePower} = require("../../matrix/utils.test") const Ty = require("../../types") -const {db} = require("../../passthrough") /** * @param {string} roomID @@ -734,31 +733,6 @@ test("message2event: reply to a Discord message that wasn't bridged", async t => }]) }) -test("message2event: reply to a Discord member join (who didn't join on Matrix)", async t => { - const events = await messageToEvent(data.message.reply_to_member_join, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - msgtype: "m.text", - body: "> PEASANT!! joined the room\n\nwhen the broke friend who we pay to bring food shows up at the medieval lord party", - format: "org.matrix.custom.html", - formatted_body: "
PEASANT!! joined the room
when the broke friend who we pay to bring food shows up at the medieval lord party", - "m.mentions": {} - }]) -}) - -test("message2event: reply to a Discord member join (who did join on Matrix)", async t => { - db.prepare("INSERT INTO sim (user_id, username, sim_name, mxid) VALUES ('1461677775554478161', 'peasant321_76775', 'peasant321_76775', '@_ooye_peasant321_76775:cadence.moe')").run() - const events = await messageToEvent(data.message.reply_to_member_join, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - msgtype: "m.text", - body: "> PEASANT!! joined the room\n\nwhen the broke friend who we pay to bring food shows up at the medieval lord party", - format: "org.matrix.custom.html", - formatted_body: `
PEASANT!! joined the room
when the broke friend who we pay to bring food shows up at the medieval lord party`, - "m.mentions": {} - }]) -}) - test("message2event: simple written @mention for matrix user", async t => { const events = await messageToEvent(data.message.simple_written_at_mention_for_matrix, data.guild.general, {}, { api: { @@ -1168,19 +1142,6 @@ test("message2event: type 4 channel name change", async t => { }]) }) -test("message2event: type 12 channel follow add", async t => { - const events = await messageToEvent(data.special_message.channel_follow_add, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - "m.mentions": {}, - msgtype: "m.emote", - body: "set this room to receive announcements from PluralKit #downtime", - format: "org.matrix.custom.html", - formatted_body: "set this room to receive announcements from PluralKit #downtime", - "m.mentions": {} - }]) -}) - test("message2event: thread start message reference", async t => { const events = await messageToEvent(data.special_message.thread_start_context, data.guild.general, {}, { api: { diff --git a/src/d2m/converters/pins-to-list.js b/src/d2m/converters/pins-to-list.js index 4ad8800..5a33c7c 100644 --- a/src/d2m/converters/pins-to-list.js +++ b/src/d2m/converters/pins-to-list.js @@ -22,7 +22,7 @@ function pinsToList(pins, kstate) { /** @type {string[]} */ const result = [] for (const pin of pins.items) { - const eventID = select("event_message", "event_id", {message_id: pin.message.id}, "ORDER BY part ASC").pluck().get() + const eventID = select("event_message", "event_id", {message_id: pin.message.id, part: 0}).pluck().get() if (eventID && !alreadyPinned.includes(eventID)) result.push(eventID) } result.reverse() diff --git a/src/discord/interactions/matrix-info.js b/src/discord/interactions/matrix-info.js index dcc9943..0b9a525 100644 --- a/src/discord/interactions/matrix-info.js +++ b/src/discord/interactions/matrix-info.js @@ -54,7 +54,6 @@ async function _interact({guild_id, data}, {api}) { // from Matrix const event = await api.getEvent(message.room_id, message.event_id) const via = await utils.getViaServersQuery(message.room_id, api) - const channelsInGuild = discord.guildChannelMap.get(guild_id) assert(channelsInGuild) const inChannels = channelsInGuild @@ -62,11 +61,6 @@ async function _interact({guild_id, data}, {api}) { .map(/** @returns {DiscordTypes.APIGuildChannel} */ cid => discord.channels.get(cid)) .sort((a, b) => webGuild._getPosition(a, discord.channels) - webGuild._getPosition(b, discord.channels)) .filter(channel => from("channel_room").join("member_cache", "room_id").select("mxid").where({channel_id: channel.id, mxid: event.sender}).get()) - let inChannelsText = inChannels.map(c => `<#${c.id}>`).join(" β€’ ") - if (inChannelsText.length > 1024) { - inChannelsText = `In ${inChannels.length} channels` - } - const matrixMember = select("member_cache", ["displayname", "avatar_url"], {room_id: message.room_id, mxid: event.sender}).get() let name = matrixMember?.displayname || event.sender let avatar = utils.getPublicUrlForMxc(matrixMember?.avatar_url) @@ -104,7 +98,7 @@ async function _interact({guild_id, data}, {api}) { color: 0x0dbd8b, fields: [{ name: "In Channels", - value: inChannelsText + value: inChannels.map(c => `<#${c.id}>`).join(" β€’ ") }, { name: "\u200b", value: idInfo diff --git a/src/discord/utils.js b/src/discord/utils.js index 0d400f1..aed7068 100644 --- a/src/discord/utils.js +++ b/src/discord/utils.js @@ -182,394 +182,6 @@ function filterTo(xs, fn) { return filtered } -const supportedPlaintextPreviewExtensions = new Set([ - "4d", - "abnf", - "accesslog", - "actionscript", - "ada", - "adoc", - "alan", - "angelscript", - "ansi", - "apache", - "apacheconf", - "applescript", - "arcade", - "arduino", - "arm", - "armasm", - "as", - "asc", - "asciidoc", - "aspectj", - "ass", - "atom", - "autohotkey", - "autoit", - "avrasm", - "awk", - "axapta", - "bash", - "basic", - "bat", - "bbcode", - "bf", - "bind", - "blade", - "bnf", - "brainfuck", - "c", - "c++", - "cal", - "capnp", - "capnproto", - "cc", - "chaos", - "chapel", - "chpl", - "cisco", - "clj", - "clojure", - "cls", - "cmake.in", - "cmake", - "cmd", - "coffee", - "coffeescript", - "console", - "coq", - "cos", - "cpc", - "cpp", - "cr", - "craftcms", - "crm", - "crmsh", - "crystal", - "cs", - "csharp", - "cshtml", - "cson", - "csp", - "css", - "csv", - "cxx", - "cypher", - "d", - "dart", - "delphi", - "dfm", - "diff", - "django", - "dns", - "docker", - "dockerfile", - "dos", - "dpr", - "dsconfig", - "dst", - "dts", - "dust", - "dylan", - "ebnf", - "elixir", - "elm", - "erl", - "erlang", - "ex", - "extempore", - "f90", - "f95", - "fix", - "fortran", - "freepascal", - "fs", - "fsharp", - "gams", - "gauss", - "gawk", - "gcode", - "gdscript", - "gemspec", - "gf", - "gherkin", - "glsl", - "gms", - "gn", - "gni", - "go", - "godot", - "golang", - "golo", - "gololang", - "gradle", - "graph", - "groovy", - "gss", - "gyp", - "h", - "h++", - "haml", - "handlebars", - "haskell", - "haxe", - "hbs", - "hcl", - "hh", - "hpp", - "hs", - "html.handlebars", - "html.hbs", - "html", - "http", - "https", - "hx", - "hxx", - "hy", - "hylang", - "i", - "i7", - "iced", - "iecst", - "inform7", - "ini", - "ino", - "instances", - "iol", - "irb", - "irpf90", - "java", - "javascript", - "jinja", - "jolie", - "js", - "json", - "jsp", - "jsx", - "julia-repl", - "julia", - "k", - "kaos", - "kdb", - "kotlin", - "kt", - "lasso", - "lassoscript", - "lazarus", - "ldif", - "leaf", - "lean", - "less", - "lfm", - "lisp", - "livecodeserver", - "livescript", - "ln", - "lock", - "log", - "lpr", - "ls", - "ls", - "lua", - "mak", - "make", - "makefile", - "markdown", - "mathematica", - "matlab", - "mawk", - "maxima", - "md", - "mel", - "mercury", - "mirc", - "mizar", - "mk", - "mkd", - "mkdown", - "ml", - "ml", - "mm", - "mma", - "mojolicious", - "monkey", - "moon", - "moonscript", - "mrc", - "n1ql", - "nawk", - "nc", - "never", - "nginx", - "nginxconf", - "nim", - "nimrod", - "nix", - "nsis", - "obj-c", - "obj-c++", - "objc", - "objective-c++", - "objectivec", - "ocaml", - "ocl", - "ol", - "openscad", - "osascript", - "oxygene", - "p21", - "parser3", - "pas", - "pascal", - "patch", - "pcmk", - "perl", - "pf.conf", - "pf", - "pgsql", - "php", - "php3", - "php4", - "php5", - "php6", - "php7", - "pl", - "plaintext", - "plist", - "pm", - "podspec", - "pony", - "postgres", - "postgresql", - "powershell", - "pp", - "processing", - "profile", - "prolog", - "properties", - "proto", - "protobuf", - "ps", - "ps1", - "puppet", - "py", - "pycon", - "python-repl", - "python", - "qml", - "r", - "razor-cshtml", - "razor", - "rb", - "re", - "reasonml", - "rebol", - "red-system", - "red", - "redbol", - "rf", - "rib", - "robot", - "rpm-spec", - "rpm-specfile", - "rpm", - "rs", - "rsl", - "rss", - "ruby", - "ruleslanguage", - "rust", - "sas", - "SAS", - "sc", - "scad", - "scala", - "scheme", - "sci", - "scilab", - "scl", - "scss", - "sh", - "shell", - "shexc", - "smali", - "smalltalk", - "sml", - "sol", - "solidity", - "spec", - "specfile", - "sql", - "srt", - "ssa", - "st", - "stan", - "stanfuncs", - "stata", - "step", - "stp", - "structured-text", - "styl", - "stylus", - "subunit", - "supercollider", - "svelte", - "svg", - "swift", - "tao", - "tap", - "tcl", - "terraform", - "tex", - "text", - "tf", - "thor", - "thrift", - "tk", - "toml", - "tp", - "ts", - "tsql", - "tsx", - "ttml", - "twig", - "txt", - "typescript", - "unicorn-rails-log", - "v", - "vala", - "vb", - "vba", - "vbnet", - "vbs", - "vbscript", - "verilog", - "vhdl", - "vim", - "vtt", - "wl", - "x++", - "x86asm", - "xhtml", - "xjb", - "xl", - "xml", - "xpath", - "xq", - "xquery", - "xsd", - "xsl", - "xtlang", - "xtm", - "yaml", - "yml", - "zep", - "zephir", - "zone", - "zsh" -]) - module.exports.getPermissions = getPermissions module.exports.getDefaultPermissions = getDefaultPermissions module.exports.hasPermission = hasPermission @@ -582,4 +194,3 @@ module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact module.exports.getPublicUrlForCdn = getPublicUrlForCdn module.exports.howOldUnbridgedMessage = howOldUnbridgedMessage module.exports.filterTo = filterTo -module.exports.supportedPlaintextPreviewExtensions = supportedPlaintextPreviewExtensions diff --git a/src/m2d/actions/update-pins.js b/src/m2d/actions/update-pins.js index 1ff2bb9..d06f6e8 100644 --- a/src/m2d/actions/update-pins.js +++ b/src/m2d/actions/update-pins.js @@ -13,7 +13,7 @@ async function updatePins(pins, prev) { const diff = diffPins.diffPins(pins, prev) for (const [event_id, added] of diff) { const row = from("event_message").join("message_room", "message_id").join("historical_channel_room", "historical_room_index") - .select("reference_channel_id", "message_id").where({event_id}).and("ORDER BY part ASC").get() + .select("reference_channel_id", "message_id").get() if (!row) continue if (added) { discord.snow.channel.addChannelPinnedMessage(row.reference_channel_id, row.message_id, "Message pinned on Matrix") diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index 31caef0..95e477f 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -816,6 +816,16 @@ async function eventToMessage(event, guild, channel, di) { if (shouldProcessTextEvent) { if (event.content.format === "org.matrix.custom.html" && event.content.formatted_body) { let input = event.content.formatted_body + if (perMessageProfile?.has_fallback) { + // Strip fallback elements added for clients that don't support per-message profiles. + // Deviates from recommended regexp in MSC to be less strict. Avoiding an HTML parser for performance reasons. + // β”Œβ”€β”€β”€β”€A────┐ Opening HTML tag: capture tag name and stay within tag + // ┆ β”†β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€B────────────┐ This text in the tag somewhere, presumably an attribute name + // ┆ ┆┆ β”†β”Œβ”€C──┐ Rest of the opening tag + // ┆ ┆┆ ┆┆ β”†β”Œβ”€D─┐ Tag content (no more tags allowed within) + // ┆ ┆┆ ┆┆ ┆┆ β”†β”Œβ”€E──┐ Closing tag matching opening tag name + input = input.replace(/<(\w+)[^>]*\bdata-mx-profile-fallback\b[^>]*>[^<]*<\/\1>/g, "") + } if (event.content.msgtype === "m.emote") { input = `* ${displayName} ${input}` } @@ -876,9 +886,8 @@ async function eventToMessage(event, guild, channel, di) { const doc = domino.createDocument( // DOM parsers arrange elements in the and . Wrapping in a custom element ensures elements are reliably arranged in a single element. '' + input + '' - ) - const root = doc.getElementById("turndown-root") - assert(root) + ); + const root = doc.getElementById("turndown-root"); async function forEachNode(event, node) { for (; node; node = node.nextSibling) { // Check written mentions @@ -894,8 +903,7 @@ async function eventToMessage(event, guild, channel, di) { let preNode if (node.nodeType === 3 && node.nodeValue.includes("```") && (preNode = nodeIsChildOf(node, ["PRE"]))) { if (preNode.firstChild?.nodeName === "CODE") { - let ext = preNode.firstChild.className.match(/language-(\S+)/)?.[1] - if (!dUtils.supportedPlaintextPreviewExtensions.has(ext)) ext = "txt" + const ext = preNode.firstChild.className.match(/language-(\S+)/)?.[1] || "txt" const filename = `inline_code.${ext}` // Build the replacement node const replacementCode = doc.createElement("code") @@ -932,7 +940,6 @@ async function eventToMessage(event, guild, channel, di) { } } await forEachNode(event, root) - if (perMessageProfile?.has_fallback) root.querySelectorAll("[data-mx-profile-fallback]").forEach(x => x.remove()) // SPRITE SHEET EMOJIS FEATURE: Emojis at the end of the message that we don't know about will be reuploaded as a sprite sheet. // First we need to determine which emojis are at the end. diff --git a/src/m2d/converters/event-to-message.test.js b/src/m2d/converters/event-to-message.test.js index 68d519a..bc73df7 100644 --- a/src/m2d/converters/event-to-message.test.js +++ b/src/m2d/converters/event-to-message.test.js @@ -1155,38 +1155,6 @@ test("event2message: code blocks are uploaded as attachments instead if they con ) }) -test("event2message: code blocks are uploaded as attachments instead if they contain incompatible backticks (use txt extension if discord does not recognise the language)", 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: 'So if you run code like this
System.out.println("```");
it should print a markdown formatted code block' - }, - event_id: "$pGkWQuGVmrPNByrFELxhzI6MCBgJecr5I2J3z88Gc2s", - room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe" - }), - { - ensureJoined: [], - messagesToDelete: [], - messagesToEdit: [], - messagesToSend: [{ - username: "cadence [they]", - 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"}], - pendingFiles: [{name: "inline_code.txt", buffer: Buffer.from('System.out.println("```");')}], - avatar_url: undefined, - allowed_mentions: { - parse: ["users", "roles"] - } - }] - } - ) -}) - test("event2message: code blocks are uploaded as attachments instead if they contain incompatible backticks (default to txt file extension)", async t => { t.deepEqual( await eventToMessage({ diff --git a/src/matrix/read-registration.js b/src/matrix/read-registration.js index d1243a7..114bf75 100644 --- a/src/matrix/read-registration.js +++ b/src/matrix/read-registration.js @@ -78,15 +78,6 @@ function readRegistration() { /** @type {import("../types").AppServiceRegistrationConfig} */ // @ts-ignore let reg = readRegistration() -if (reg) { - fs.watch(registrationFilePath, {persistent: false}, () => { - let newReg = readRegistration() - if (newReg) { - Object.assign(reg, newReg) - } - }) -} - module.exports.registrationFilePath = registrationFilePath module.exports.readRegistration = readRegistration module.exports.getTemplateRegistration = getTemplateRegistration diff --git a/src/stdin.js b/src/stdin.js index 2548d42..fea5fad 100644 --- a/src/stdin.js +++ b/src/stdin.js @@ -23,26 +23,10 @@ const setPresence = sync.require("./d2m/actions/set-presence") const channelWebhook = sync.require("./m2d/actions/channel-webhook") const guildID = "112760669178241024" -async function ping() { - const result = await api.ping().catch(e => ({ok: false, status: "net", root: e.message})) - if (result.ok) { - return "Ping OK. The homeserver and OOYE are talking to each other fine." - } else { - if (typeof result.root === "string") { - var msg = `Cannot reach homeserver: ${result.root}` - } else if (result.root.error) { - var msg = `Homeserver said: [${result.status}] ${result.root.error}` - } else { - var msg = `Homeserver said: [${result.status}] ${JSON.stringify(result.root)}` - } - return msg + "\nMatrix->Discord won't work until you fix this.\nIf your installation has recently changed, consider `npm run setup` again." - } -} - if (process.stdin.isTTY) { setImmediate(() => { if (!passthrough.repl) { - const cli = repl.start({prompt: "", eval: customEval, writer: s => s}) + const cli = repl.start({ prompt: "", eval: customEval, writer: s => s }) Object.assign(cli.context, passthrough) passthrough.repl = cli } diff --git a/test/data.js b/test/data.js index f3092bc..45e0388 100644 --- a/test/data.js +++ b/test/data.js @@ -19,26 +19,6 @@ module.exports = { default_thread_rate_limit_per_user: 0, guild_id: "112760669178241024" }, - voice: { - voice_background_display: null, - version: 1774469910848, - user_limit: 0, - type: 2, - theme_color: null, - status: null, - rtc_region: null, - rate_limit_per_user: 0, - position: 0, - permission_overwrites: [], - parent_id: "805261291908104252", - nsfw: false, - name: "🍞丨[8user] Piece", - last_message_id: "1459912691098325137", - id: "1036840786093953084", - flags: 0, - bitrate: 256000, - guild_id: "112760669178241024" - }, updates: { type: 0, topic: "Updates and release announcements for Out Of Your Element.", @@ -2035,80 +2015,6 @@ module.exports = { tts: false } }, - reply_to_member_join: { - type: 19, - content: "when the broke friend who we pay to bring food shows up at the medieval lord party", - mentions: [], - mention_roles: [], - attachments: [], - embeds: [], - timestamp: "2026-03-30T12:11:04.443000+00:00", - edited_timestamp: null, - flags: 0, - components: [], - id: "1488148556962332692", - channel_id: "475599038536744962", - author: { - id: "576945009408999426", - username: "randomllama121", - avatar: "08510a70f957106dad1580323c40cd7a", - discriminator: "0", - public_flags: 128, - flags: 128, - banner: null, - accent_color: null, - global_name: "random :3", - avatar_decoration_data: null, - collectibles: null, - display_name_styles: null, - banner_color: null, - clan: null, - primary_guild: null - }, - pinned: false, - mention_everyone: false, - tts: false, - message_reference: { - type: 0, - channel_id: "475599038536744962", - message_id: "1488146734352826478", - guild_id: "475599038536744960" - }, - referenced_message: { - type: 7, - content: "", - mentions: [], - mention_roles: [], - attachments: [], - embeds: [], - timestamp: "2026-03-30T12:03:49.899000+00:00", - edited_timestamp: null, - flags: 0, - components: [], - id: "1488146734352826478", - channel_id: "475599038536744962", - author: { - id: "1461677775554478161", - username: "peasant321_76775", - avatar: null, - discriminator: "0", - public_flags: 0, - flags: 0, - banner: null, - accent_color: null, - global_name: "PEASANT!!", - avatar_decoration_data: null, - collectibles: null, - display_name_styles: null, - banner_color: null, - clan: null, - primary_guild: null - }, - pinned: false, - mention_everyone: false, - tts: false - } - }, attachment_no_content: { id: "1124628646670389348", type: 0, @@ -6264,37 +6170,6 @@ module.exports = { components: [], position: 12 }, - channel_follow_add: { - type: 12, - content: "PluralKit #downtime", - attachments: [], - embeds: [], - timestamp: "2026-03-24T23:16:04.097Z", - edited_timestamp: null, - flags: 0, - components: [], - id: "1486141581047369888", - channel_id: "1451125453082591314", - author: { - id: "154058479798059009", - username: "exaptations", - discriminator: "0", - avatar: "57b5cfe09a48a5902f2eb8fa65bb1b80", - bot: false, - flags: 0, - globalName: "Exa", - }, - pinned: false, - mentions: [], - mention_roles: [], - mention_everyone: false, - tts: false, - message_reference: { - type: 0, - channel_id: "1015204661701124206", - guild_id: "466707357099884544" - } - }, updated_to_start_thread_from_here: { t: "MESSAGE_UPDATE", s: 19,