From 42b331135d2f444db0c49520456d325ab38617e9 Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 8 Sep 2025 22:16:17 -0400 Subject: [PATCH 1/9] allow overriding ooye data directory --- scripts/backfill.js | 4 +++- scripts/check-migrate.js | 5 ++--- scripts/migrate-from-old-bridge.js | 3 ++- scripts/remove-old-bridged-users.js | 4 ++-- scripts/save-channel-names-to-db.js | 4 ++-- scripts/save-event-types-to-db.js | 4 ++-- scripts/setup.js | 3 ++- scripts/start-server.js | 4 ++-- scripts/wal.js | 4 ++-- src/db/database.js | 16 ++++++++++++++++ start.js | 4 ++-- 11 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 src/db/database.js diff --git a/scripts/backfill.js b/scripts/backfill.js index 12d9da3..0e0e4c6 100644 --- a/scripts/backfill.js +++ b/scripts/backfill.js @@ -12,6 +12,7 @@ if (!channelID) { const assert = require("assert/strict") const sqlite = require("better-sqlite3") +const path = require("path") const backfill = new sqlite("scripts/backfill.db") backfill.prepare("CREATE TABLE IF NOT EXISTS backfill (channel_id TEXT NOT NULL, message_id INTEGER NOT NULL, PRIMARY KEY (channel_id, message_id))").run() @@ -19,9 +20,10 @@ const HeatSync = require("heatsync") const {reg} = require("../src/matrix/read-registration") const passthrough = require("../src/passthrough") +const {getDatabase} = require("../src/db/database") const sync = new HeatSync({watchFS: false}) -const db = new sqlite("ooye.db") +const db = getDatabase() Object.assign(passthrough, {sync, db}) const DiscordClient = require("../src/d2m/discord-client") diff --git a/scripts/check-migrate.js b/scripts/check-migrate.js index 04a4402..dd31ec6 100755 --- a/scripts/check-migrate.js +++ b/scripts/check-migrate.js @@ -4,10 +4,9 @@ // Trigger the database migration flow and exit after committing. // You can use this to run migrations locally and check the result using sqlitebrowser. -const sqlite = require("better-sqlite3") - const passthrough = require("../src/passthrough") -const db = new sqlite("ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() const migrate = require("../src/db/migrate") Object.assign(passthrough, {db}) diff --git a/scripts/migrate-from-old-bridge.js b/scripts/migrate-from-old-bridge.js index 36cf884..5a71ab0 100755 --- a/scripts/migrate-from-old-bridge.js +++ b/scripts/migrate-from-old-bridge.js @@ -16,7 +16,8 @@ const oldAT = reg.old_bridge.as_token const newAT = reg.as_token const oldDB = new sqlite(reg.old_bridge.database) -const db = new sqlite("ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() db.exec(`CREATE TABLE IF NOT EXISTS half_shot_migration ( discord_channel TEXT NOT NULL, diff --git a/scripts/remove-old-bridged-users.js b/scripts/remove-old-bridged-users.js index d8910bd..8252893 100644 --- a/scripts/remove-old-bridged-users.js +++ b/scripts/remove-old-bridged-users.js @@ -3,8 +3,8 @@ const HeatSync = require("heatsync") const sync = new HeatSync({watchFS: false}) -const sqlite = require("better-sqlite3") -const db = new sqlite("db/ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() const passthrough = require("../src/passthrough") Object.assign(passthrough, {db, sync}) diff --git a/scripts/save-channel-names-to-db.js b/scripts/save-channel-names-to-db.js index 1f36a73..e90e567 100755 --- a/scripts/save-channel-names-to-db.js +++ b/scripts/save-channel-names-to-db.js @@ -1,12 +1,12 @@ #!/usr/bin/env node // @ts-check -const sqlite = require("better-sqlite3") const HeatSync = require("heatsync") const {reg} = require("../src/matrix/read-registration") const passthrough = require("../src/passthrough") -const db = new sqlite("ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() const sync = new HeatSync({watchFS: false}) diff --git a/scripts/save-event-types-to-db.js b/scripts/save-event-types-to-db.js index edfbb9c..dd84866 100755 --- a/scripts/save-event-types-to-db.js +++ b/scripts/save-event-types-to-db.js @@ -1,11 +1,11 @@ #!/usr/bin/env node // @ts-check -const sqlite = require("better-sqlite3") const HeatSync = require("heatsync") const passthrough = require("../src/passthrough") -const db = new sqlite("ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() const sync = new HeatSync({watchFS: false}) diff --git a/scripts/setup.js b/scripts/setup.js index 6bff293..b980ef1 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -34,7 +34,8 @@ if (fs.existsSync("db")) { } const passthrough = require("../src/passthrough") -const db = new sqlite("ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() const migrate = require("../src/db/migrate") const sync = new HeatSync({watchFS: false}) diff --git a/scripts/start-server.js b/scripts/start-server.js index 0d4753a..86e11ca 100755 --- a/scripts/start-server.js +++ b/scripts/start-server.js @@ -4,13 +4,13 @@ const {createServer} = require("http") const EventEmitter = require("events") const {createApp, createRouter, toNodeListener} = require("h3") -const sqlite = require("better-sqlite3") const migrate = require("../src/db/migrate") const HeatSync = require("heatsync") const {reg} = require("../src/matrix/read-registration") const passthrough = require("../src/passthrough") -const db = new sqlite("ooye.db") +const {getDatabase} = require("../src/db/database") +const db = getDatabase() const sync = new HeatSync() diff --git a/scripts/wal.js b/scripts/wal.js index 625f2ba..3f8cec9 100755 --- a/scripts/wal.js +++ b/scripts/wal.js @@ -1,7 +1,7 @@ #!/usr/bin/env node // @ts-check -const sqlite = require("better-sqlite3") -const db = new sqlite("ooye.db", {fileMustExist: true}) +const {getDatabase} = require("../src/db/database") +const db = getDatabase({fileMustExist: true}) db.pragma("journal_mode = wal") db.close() diff --git a/src/db/database.js b/src/db/database.js new file mode 100644 index 0000000..861fda8 --- /dev/null +++ b/src/db/database.js @@ -0,0 +1,16 @@ +// @ts-check + +const sqlite = require("better-sqlite3") +const path = require("path") + +/** + * Create a new SQLite database instance + * @param {import("better-sqlite3").Options} [options] - SQLite options + * @returns {import("better-sqlite3").Database} Database instance + */ +function getDatabase(options = {}) { + const dataDir = process.env.OOYE_DATA_DIR || process.cwd() + return new sqlite(path.join(dataDir, "ooye.db"), options) +} + +module.exports = {getDatabase} \ No newline at end of file diff --git a/start.js b/start.js index ca6212b..66fb920 100755 --- a/start.js +++ b/start.js @@ -2,13 +2,13 @@ // @ts-check const fs = require("fs") -const sqlite = require("better-sqlite3") const migrate = require("./src/db/migrate") const HeatSync = require("heatsync") const {reg} = require("./src/matrix/read-registration") const passthrough = require("./src/passthrough") -const db = new sqlite("ooye.db") +const {getDatabase} = require("./src/db/database") +const db = getDatabase() const sync = new HeatSync({watchFunction: fs.watchFile}) From e19703ef03d471f7ce9f2cb441eaf928a9bd72ba Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 8 Sep 2025 22:21:13 -0400 Subject: [PATCH 2/9] configurable read_only_room_events_default_power --- src/d2m/actions/create-room.js | 8 +++++--- src/d2m/actions/register-user.js | 2 +- src/matrix/read-registration.js | 3 ++- src/types.d.ts | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/d2m/actions/create-room.js b/src/d2m/actions/create-room.js index ff5782d..07c7237 100644 --- a/src/d2m/actions/create-room.js +++ b/src/d2m/actions/create-room.js @@ -40,7 +40,9 @@ const PRIVACY_ENUMS = { const DEFAULT_PRIVACY_LEVEL = 0 -const READ_ONLY_ROOM_EVENTS_DEFAULT_POWER = 50 +function getReadOnlyRoomEventsDefaultPower() { + return reg.ooye.read_only_room_events_default_power ?? 50 +} /** @type {Map>} channel ID -> Promise */ const inflightRoomCreate = new Map() @@ -148,7 +150,7 @@ async function channelToKState(channel, guild, di) { "m.room.join_rules/": join_rules, /** @type {Ty.Event.M_Power_Levels} */ "m.room.power_levels/": { - events_default: everyoneCanSend ? 0 : READ_ONLY_ROOM_EVENTS_DEFAULT_POWER, + events_default: everyoneCanSend ? 0 : getReadOnlyRoomEventsDefaultPower(), events: { "m.reaction": 0, "m.room.redaction": 0 // only affects redactions of own events, required to be able to un-react @@ -559,7 +561,7 @@ async function createAllForGuild(guildID) { } module.exports.DEFAULT_PRIVACY_LEVEL = DEFAULT_PRIVACY_LEVEL -module.exports.READ_ONLY_ROOM_EVENTS_DEFAULT_POWER = READ_ONLY_ROOM_EVENTS_DEFAULT_POWER +module.exports.getReadOnlyRoomEventsDefaultPower = getReadOnlyRoomEventsDefaultPower module.exports.PRIVACY_ENUMS = PRIVACY_ENUMS module.exports.createRoom = createRoom module.exports.ensureRoom = ensureRoom diff --git a/src/d2m/actions/register-user.js b/src/d2m/actions/register-user.js index 674853a..8f2a9b5 100644 --- a/src/d2m/actions/register-user.js +++ b/src/d2m/actions/register-user.js @@ -165,7 +165,7 @@ function memberToPowerLevel(user, member, guild, channel) { /* PL 50 = if room is read-only but the user has been specially allowed to send messages */ const everyoneCanSend = utils.hasPermission(everyonePermissions, DiscordTypes.PermissionFlagsBits.SendMessages) const userCanSend = utils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.SendMessages) - if (!everyoneCanSend && userCanSend) return createRoom.READ_ONLY_ROOM_EVENTS_DEFAULT_POWER + if (!everyoneCanSend && userCanSend) return createRoom.getReadOnlyRoomEventsDefaultPower() /* PL 20 = Mention Everyone for technical reasons. */ const everyoneCanMentionEveryone = utils.hasPermission(everyonePermissions, DiscordTypes.PermissionFlagsBits.MentionEveryone) const userCanMentionEveryone = utils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.MentionEveryone) diff --git a/src/matrix/read-registration.js b/src/matrix/read-registration.js index d126851..6c713ba 100644 --- a/src/matrix/read-registration.js +++ b/src/matrix/read-registration.js @@ -57,7 +57,8 @@ function getTemplateRegistration(serverName) { max_file_size: 5000000, content_length_workaround: false, include_user_id_in_mxid: false, - invite: [] + invite: [], + read_only_room_events_default_power: 50 } } } diff --git a/src/types.d.ts b/src/types.d.ts index 37da633..e2f45ae 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -31,6 +31,7 @@ export type AppServiceRegistrationConfig = { discord_origin?: string discord_cdn_origin?: string, web_password: string + read_only_room_events_default_power?: number } old_bridge?: { as_token: string From 0f8fee2d33525e88b15d04bbb9347fcc6ff4f045 Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 8 Sep 2025 22:24:42 -0400 Subject: [PATCH 3/9] fix type error --- src/matrix/read-registration.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/matrix/read-registration.js b/src/matrix/read-registration.js index 6c713ba..3e7e358 100644 --- a/src/matrix/read-registration.js +++ b/src/matrix/read-registration.js @@ -58,7 +58,6 @@ function getTemplateRegistration(serverName) { content_length_workaround: false, include_user_id_in_mxid: false, invite: [], - read_only_room_events_default_power: 50 } } } From fd1bf3801b8b72894303c0fbccb40b3058a614ca Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 8 Sep 2025 22:33:21 -0400 Subject: [PATCH 4/9] also allow data dir for registration.yaml --- src/matrix/read-registration.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/matrix/read-registration.js b/src/matrix/read-registration.js index 3e7e358..bb93c5c 100644 --- a/src/matrix/read-registration.js +++ b/src/matrix/read-registration.js @@ -5,7 +5,8 @@ const crypto = require("crypto") const assert = require("assert").strict const path = require("path") -const registrationFilePath = path.join(process.cwd(), "registration.yaml") +const dataDir = process.env.OOYE_DATA_DIR || process.cwd() +const registrationFilePath = path.join(dataDir, "registration.yaml") /** @param {import("../types").AppServiceRegistrationConfig} reg */ function checkRegistration(reg) { @@ -57,7 +58,7 @@ function getTemplateRegistration(serverName) { max_file_size: 5000000, content_length_workaround: false, include_user_id_in_mxid: false, - invite: [], + invite: [] } } } From 389150616395f0fd98b45ad0e13ad531e2ae7ff4 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Tue, 7 Oct 2025 00:46:44 -0500 Subject: [PATCH 5/9] Roll back snowtransfer to avoid issue with pins --- package-lock.json | 28 ++++++++++++++++++++-------- package.json | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa7822f..d82b914 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "lru-cache": "^11.0.2", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", - "snowtransfer": "^0.15.0", + "snowtransfer": "^0.14.2", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", @@ -1464,6 +1464,18 @@ "node": ">=22.0.0" } }, + "node_modules/cloudstorm/node_modules/snowtransfer": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.15.0.tgz", + "integrity": "sha512-kEDGKtFiH5nSkHsDZonEUuDx99lUasJoZ7AGrgvE8HzVG59vjvqc//C+pjWj4DuJqTj4Q+Z1L/M/MYNim8F2VA==", + "license": "MIT", + "dependencies": { + "discord-api-types": "^0.38.21" + }, + "engines": { + "node": ">=16.15.0" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -2719,12 +2731,12 @@ } }, "node_modules/snowtransfer": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.15.0.tgz", - "integrity": "sha512-kEDGKtFiH5nSkHsDZonEUuDx99lUasJoZ7AGrgvE8HzVG59vjvqc//C+pjWj4DuJqTj4Q+Z1L/M/MYNim8F2VA==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.14.2.tgz", + "integrity": "sha512-Fi8OdRmaIgeCj58oVej+tQAoY2I+Xp/6PAYV8X93jE/2E6Anc87SbTbDV6WZXCnuzTQz3gty8JOGz02qI7Qs9A==", "license": "MIT", "dependencies": { - "discord-api-types": "^0.38.21" + "discord-api-types": "^0.38.8" }, "engines": { "node": ">=16.15.0" @@ -3076,9 +3088,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", diff --git a/package.json b/package.json index 2fb21f2..f722066 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "lru-cache": "^11.0.2", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", - "snowtransfer": "^0.15.0", + "snowtransfer": "^0.14.2", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", From 7905802825c6dd03b26770fd32f03d1b77b6bf82 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Tue, 7 Oct 2025 00:48:06 -0500 Subject: [PATCH 6/9] Allow customising port in setup --- scripts/setup.js | 23 ++++++++++++++++++----- src/m2d/actions/setup-emojis.js | 3 +-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/scripts/setup.js b/scripts/setup.js index 6bff293..ecef03d 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -120,16 +120,28 @@ function defineEchoHandler() { /** @type {string} */ // @ts-ignore const serverOrigin = await serverOriginPrompt.run() + console.log("OOYE has its own web server. It needs to be accessible on the public internet.") + console.log("What port would you like OOYE to use? You can connect your reverse proxy to this port later.") + /** @type {{socket: string | number}} */ + const portResponse = await prompt({ + type: "input", + name: "socket", + message: "Web server port", + initial: "6693" + }) + portResponse.socket = +portResponse.socket || portResponse.socket // convert to number if numeric + const app = createApp() app.use(defineEchoHandler()) const server = createServer(toNodeListener(app)) - await server.listen(6693) + await server.listen(portResponse.socket) - console.log("OOYE has its own web server. It needs to be accessible on the public internet.") - console.log("You need to enter a public URL where you will be able to host this web server.") - console.log("OOYE listens on localhost:6693, so you will probably have to set up a reverse proxy.") + console.log("Now you need to enter a public URL that OOYE's web server will live on.") + console.log("Set up your reverse proxy so that this URL accesses OOYE.") console.log("Examples: https://gitdab.com/cadence/out-of-your-element/src/branch/main/docs/get-started.md#appendix") - console.log("Now listening on port 6693. Feel free to send some test requests.") + if (typeof portResponse.socket === "number") { + console.log(`Now listening on http://localhost:${portResponse.socket}. Feel free to send some test requests.`) + } /** @type {{bridge_origin: string}} */ const bridgeOriginResponse = await prompt({ type: "input", @@ -255,6 +267,7 @@ function defineEchoHandler() { reg = { ...template, url: bridgeOriginResponse.bridge_origin, + ...portResponse, ooye: { ...template.ooye, ...bridgeOriginResponse, diff --git a/src/m2d/actions/setup-emojis.js b/src/m2d/actions/setup-emojis.js index ba2c045..1be1d2d 100644 --- a/src/m2d/actions/setup-emojis.js +++ b/src/m2d/actions/setup-emojis.js @@ -5,9 +5,8 @@ const {join} = require("path") const passthrough = require("../../passthrough") -const {id} = require("../../../addbot") - async function setupEmojis() { + const {id} = require("../../../addbot") const {discord, db} = passthrough const emojis = await discord.snow.assets.getAppEmojis(id) for (const name of ["L1", "L2"]) { From 7916f82b55fd81d95abfdea328b5decc75588492 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Tue, 7 Oct 2025 14:09:42 -0500 Subject: [PATCH 7/9] Change thread started message (closes #61) --- src/d2m/converters/thread-to-announcement.js | 3 --- src/d2m/converters/thread-to-announcement.test.js | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/src/d2m/converters/thread-to-announcement.js b/src/d2m/converters/thread-to-announcement.js index 11a067f..98b8f12 100644 --- a/src/d2m/converters/thread-to-announcement.js +++ b/src/d2m/converters/thread-to-announcement.js @@ -32,13 +32,10 @@ async function threadToAnnouncement(parentRoomID, threadRoomID, creatorMxid, thr const template = creatorMxid ? "started a thread:" : "Thread started:" const via = await mxUtils.getViaServersQuery(threadRoomID, di.api) let body = `${template} ${thread.name} https://matrix.to/#/${threadRoomID}?${via.toString()}` - let html = `${template} ${thread.name}` return { msgtype, body, - format: "org.matrix.custom.html", - formatted_body: html, "m.mentions": {}, ...context } diff --git a/src/d2m/converters/thread-to-announcement.test.js b/src/d2m/converters/thread-to-announcement.test.js index 471cd94..3d5d1eb 100644 --- a/src/d2m/converters/thread-to-announcement.test.js +++ b/src/d2m/converters/thread-to-announcement.test.js @@ -55,8 +55,6 @@ test("thread2announcement: no known creator, no branched from event", async t => t.deepEqual(content, { msgtype: "m.text", body: "Thread started: test thread https://matrix.to/#/!thread?via=cadence.moe&via=matrix.org", - format: "org.matrix.custom.html", - formatted_body: `Thread started: test thread`, "m.mentions": {} }) }) @@ -69,8 +67,6 @@ test("thread2announcement: known creator, no branched from event", async t => { t.deepEqual(content, { msgtype: "m.emote", body: "started a thread: test thread https://matrix.to/#/!thread?via=cadence.moe&via=matrix.org", - format: "org.matrix.custom.html", - formatted_body: `started a thread: test thread`, "m.mentions": {} }) }) @@ -95,8 +91,6 @@ test("thread2announcement: no known creator, branched from discord event", async t.deepEqual(content, { msgtype: "m.text", body: "Thread started: test thread https://matrix.to/#/!thread?via=cadence.moe&via=matrix.org", - format: "org.matrix.custom.html", - formatted_body: `Thread started: test thread`, "m.mentions": {}, "m.relates_to": { "m.in_reply_to": { @@ -126,8 +120,6 @@ test("thread2announcement: known creator, branched from discord event", async t t.deepEqual(content, { msgtype: "m.emote", body: "started a thread: test thread https://matrix.to/#/!thread?via=cadence.moe&via=matrix.org", - format: "org.matrix.custom.html", - formatted_body: `started a thread: test thread`, "m.mentions": {}, "m.relates_to": { "m.in_reply_to": { @@ -157,8 +149,6 @@ test("thread2announcement: no known creator, branched from matrix event", async t.deepEqual(content, { msgtype: "m.text", body: "Thread started: test thread https://matrix.to/#/!thread?via=cadence.moe&via=matrix.org", - format: "org.matrix.custom.html", - formatted_body: `Thread started: test thread`, "m.mentions": { user_ids: ["@cadence:cadence.moe"] }, From 5b7433de3260a0504df94f7dcda6a0f0a8ed2884 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Tue, 7 Oct 2025 14:09:50 -0500 Subject: [PATCH 8/9] Make tests time zone independent --- src/d2m/converters/message-to-event.js | 2 +- src/types.d.ts | 1 + test/test.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index 1d6288a..f494123 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -611,7 +611,7 @@ async function messageToEvent(message, guild, options = {}, di) { const event = invite.guild_scheduled_event if (!event) continue // the event ID provided was not valid - const formatter = new Intl.DateTimeFormat("en-NZ", {month: "long", day: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "shortGeneric"}) // 9 June at 3:00 pm NZT + const formatter = new Intl.DateTimeFormat("en-NZ", {month: "long", day: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "shortGeneric", timeZone: reg.ooye.time_zone}) // 9 June at 3:00 pm NZT const rep = new mxUtils.MatrixStringBuilder() // Add time diff --git a/src/types.d.ts b/src/types.d.ts index 37da633..27dfddf 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -31,6 +31,7 @@ export type AppServiceRegistrationConfig = { discord_origin?: string discord_cdn_origin?: string, web_password: string + time_zone?: string } old_bridge?: { as_token: string diff --git a/test/test.js b/test/test.js index 3695a84..233fd94 100644 --- a/test/test.js +++ b/test/test.js @@ -25,6 +25,7 @@ reg.namespaces = { aliases: [{regex: "#_ooye_.*:cadence.moe", exclusive: true}] } reg.ooye.bridge_origin = "https://bridge.example.org" +reg.ooye.time_zone = "Pacific/Auckland" const sync = new HeatSync({watchFS: false}) From cffd3c9f2ea0dc1c6be04f28501f4b59ee88caa2 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Fri, 10 Oct 2025 12:26:01 -0600 Subject: [PATCH 9/9] Fix converting discord channel links --- package-lock.json | 8 +-- package.json | 2 +- src/d2m/converters/message-to-event.js | 4 +- src/d2m/converters/message-to-event.test.js | 38 ++++++++++++++ test/data.js | 57 +++++++++++++++++++++ 5 files changed, 102 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index d82b914..fda73e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "AGPL-3.0-or-later", "dependencies": { "@chriscdn/promise-semaphore": "^3.0.1", - "@cloudrac3r/discord-markdown": "^2.6.6", + "@cloudrac3r/discord-markdown": "^2.6.7", "@cloudrac3r/giframe": "^0.4.3", "@cloudrac3r/html-template-tag": "^5.0.1", "@cloudrac3r/in-your-element": "^1.1.1", @@ -225,9 +225,9 @@ } }, "node_modules/@cloudrac3r/discord-markdown": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.6.6.tgz", - "integrity": "sha512-4FNO7WmACPvcTrQjeLQLr9WRuP7JDUVUGFrRJvmAjiMs2UlUAsShfSRuU2SCqz3QqmX8vyJ06wy2hkjTTyRtbw==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.6.7.tgz", + "integrity": "sha512-bWLmBYWaNEDcQfZHDz4jaAxLKA9161ruEnHo3ms6kfRw8uYku/Uz7U1xTmQ2dQF/q1PiuBvM9I37pLiotlQj8A==", "license": "MIT", "dependencies": { "simple-markdown": "^0.7.3" diff --git a/package.json b/package.json index f722066..85530c1 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@chriscdn/promise-semaphore": "^3.0.1", - "@cloudrac3r/discord-markdown": "^2.6.6", + "@cloudrac3r/discord-markdown": "^2.6.7", "@cloudrac3r/giframe": "^0.4.3", "@cloudrac3r/html-template-tag": "^5.0.1", "@cloudrac3r/in-your-element": "^1.1.1", diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index f494123..30a20fe 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -408,13 +408,13 @@ async function messageToEvent(message, guild, options = {}, di) { async function transformParsedVia(parsed) { for (const node of parsed) { - if (node.type === "discordChannel") { + if (node.type === "discordChannel" || node.type === "discordChannelLink") { node.row = select("channel_room", ["room_id", "name", "nick"], {channel_id: node.id}).get() if (node.row?.room_id) { node.via = await getViaServersMemo(node.row.room_id) } } - ;for (const maybeChildNodesArray of [node, node.content, node.items]) { + for (const maybeChildNodesArray of [node, node.content, node.items]) { if (Array.isArray(maybeChildNodesArray)) { await transformParsedVia(maybeChildNodesArray) } diff --git a/src/d2m/converters/message-to-event.test.js b/src/d2m/converters/message-to-event.test.js index fc933e3..ee4ec03 100644 --- a/src/d2m/converters/message-to-event.test.js +++ b/src/d2m/converters/message-to-event.test.js @@ -100,6 +100,44 @@ test("message2event: simple room mention", async t => { t.equal(called, 2, "should call getStateEvent and getJoinedMembers once each") }) +test("message2event: simple room link", async t => { + let called = 0 + const events = await messageToEvent(data.message.simple_room_link, data.guild.general, {}, { + api: { + async getStateEvent(roomID, type, key) { + called++ + t.equal(roomID, "!BnKuBPCvyfOkhcUjEu:cadence.moe") + t.equal(type, "m.room.power_levels") + t.equal(key, "") + return { + users: { + "@_ooye_bot:cadence.moe": 100 + } + } + }, + async getJoinedMembers(roomID) { + called++ + t.equal(roomID, "!BnKuBPCvyfOkhcUjEu:cadence.moe") + return { + joined: { + "@_ooye_bot:cadence.moe": {display_name: null, avatar_url: null}, + "@user:matrix.org": {display_name: null, avatar_url: null} + } + } + } + } + }) + t.deepEqual(events, [{ + $type: "m.room.message", + "m.mentions": {}, + msgtype: "m.text", + body: "#worm-farm", + format: "org.matrix.custom.html", + formatted_body: '#worm-farm' + }]) + t.equal(called, 2, "should call getStateEvent and getJoinedMembers once each") +}) + test("message2event: nicked room mention", async t => { let called = 0 const events = await messageToEvent(data.message.nicked_room_mention, data.guild.general, {}, { diff --git a/test/data.js b/test/data.js index a8ff8a8..e64b9c2 100644 --- a/test/data.js +++ b/test/data.js @@ -1398,6 +1398,63 @@ module.exports = { attachments: [], guild_id: "112760669178241024" }, + simple_room_link: { + type: 0, + tts: false, + timestamp: "2023-07-10T20:04:25.939000+00:00", + referenced_message: null, + pinned: false, + nonce: "1128054139385806848", + mentions: [], + mention_roles: [], + mention_everyone: false, + member: { + roles: [ + "112767366235959296", "118924814567211009", + "204427286542417920", "199995902742626304", + "222168467627835392", "238028326281805825", + "259806643414499328", "265239342648131584", + "271173313575780353", "287733611912757249", + "225744901915148298", "305775031223320577", + "318243902521868288", "348651574924541953", + "349185088157777920", "378402925128712193", + "392141548932038658", "393912152173576203", + "482860581670486028", "495384759074160642", + "638988388740890635", "373336013109461013", + "530220455085473813", "454567553738473472", + "790724320824655873", "1123518980456452097", + "1040735082610167858", "695946570482450442", + "1123460940935991296", "849737964090556488" + ], + premium_since: null, + pending: false, + nick: null, + mute: false, + joined_at: "2015-11-11T09:55:40.321000+00:00", + flags: 0, + deaf: false, + communication_disabled_until: null, + avatar: null + }, + id: "1128054143064494233", + flags: 0, + embeds: [], + edited_timestamp: null, + content: "https://discord.com/channels/112760669178241024/1100319550446252084", + components: [], + channel_id: "266767590641238027", + author: { + username: "kumaccino", + public_flags: 128, + id: "113340068197859328", + global_name: "kumaccino", + discriminator: "0", + avatar_decoration: null, + avatar: "b48302623a12bc7c59a71328f72ccb39" + }, + attachments: [], + guild_id: "112760669178241024" + }, nicked_room_mention: { type: 0, tts: false,