diff --git a/d2m/actions/delete-message.js b/d2m/actions/delete-message.js index 440e123..4386ae5 100644 --- a/d2m/actions/delete-message.js +++ b/d2m/actions/delete-message.js @@ -11,7 +11,7 @@ const speedbump = sync.require("./speedbump") * @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data */ async function deleteMessage(data) { - const row = select("channel_room", ["room_id", "speedbump_checked", "thread_parent"], {channel_id: data.channel_id}).get() + const row = select("channel_room", ["room_id", "speedbump_checked"], {channel_id: data.channel_id}).get() if (!row) return const eventsToRedact = select("event_message", "event_id", {message_id: data.id}).pluck().all() @@ -22,7 +22,7 @@ async function deleteMessage(data) { await api.redactEvent(row.room_id, eventID) } - await speedbump.updateCache(row.thread_parent || data.channel_id, row.speedbump_checked) + speedbump.updateCache(data.channel_id, row.speedbump_checked) } /** diff --git a/d2m/actions/speedbump.js b/d2m/actions/speedbump.js index e782ae0..f49a378 100644 --- a/d2m/actions/speedbump.js +++ b/d2m/actions/speedbump.js @@ -2,7 +2,7 @@ const DiscordTypes = require("discord-api-types/v10") const passthrough = require("../../passthrough") -const {discord, select, db} = passthrough +const {discord, db} = passthrough const SPEEDBUMP_SPEED = 4000 // 4 seconds delay const SPEEDBUMP_UPDATE_FREQUENCY = 2 * 60 * 60 // 2 hours @@ -33,7 +33,6 @@ const bumping = new Set() /** * Slow down a message. After it passes the speedbump, return whether it's okay or if it's been deleted. * @param {string} messageID - * @returns whether it was deleted */ async function doSpeedbump(messageID) { bumping.add(messageID) @@ -41,21 +40,6 @@ async function doSpeedbump(messageID) { return !bumping.delete(messageID) } -/** - * Check whether to slow down a message, and do it. After it passes the speedbump, return whether it's okay or if it's been deleted. - * @param {string} channelID - * @param {string} messageID - * @returns whether it was deleted, and data about the channel's (not thread's) speedbump - */ -async function maybeDoSpeedbump(channelID, messageID) { - let row = select("channel_room", ["thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: channelID}).get() - if (row?.thread_parent) row = select("channel_room", ["thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: row.thread_parent}).get() // webhooks belong to the channel, not the thread - if (!row) return {affected: false, row: null}// not affected, no speedbump - // Edits need to go through the speedbump as well. If the message is delayed but the edit isn't, we don't have anything to edit from. - const affected = await doSpeedbump(messageID) - return {affected, row} // maybe affected, and there is a speedbump -} - /** * @param {string} messageID */ @@ -65,5 +49,4 @@ function onMessageDelete(messageID) { module.exports.updateCache = updateCache module.exports.doSpeedbump = doSpeedbump -module.exports.maybeDoSpeedbump = maybeDoSpeedbump module.exports.onMessageDelete = onMessageDelete diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js index 52bed72..c630bfb 100644 --- a/d2m/event-dispatcher.js +++ b/d2m/event-dispatcher.js @@ -246,8 +246,11 @@ module.exports = { if (row) return // The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it. } - const {affected, row} = await speedbump.maybeDoSpeedbump(message.channel_id, message.id) - if (affected) return + const row = select("channel_room", ["speedbump_id", "speedbump_webhook_id"], {channel_id: message.channel_id}).get() + if (row && row.speedbump_id) { + const affected = await speedbump.doSpeedbump(message.id) + if (affected) return + } // @ts-ignore await sendMessage.sendMessage(message, guild, row), @@ -264,8 +267,12 @@ module.exports = { if (row) return // The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it. } - const {affected, row} = await speedbump.maybeDoSpeedbump(data.channel_id, data.id) - if (affected) return + const row = select("channel_room", ["speedbump_id", "speedbump_webhook_id"], {channel_id: data.channel_id}).get() + if (row) { + // Edits need to go through the speedbump as well. If the message is delayed but the edit isn't, we don't have anything to edit from. + const affected = await speedbump.doSpeedbump(data.id) + if (affected) return + } // Based on looking at data they've sent me over the gateway, this is the best way to check for meaningful changes. // If the message content is a string then it includes all interesting fields and is meaningful. diff --git a/matrix/mreq.js b/matrix/mreq.js index d515846..0bd7505 100644 --- a/matrix/mreq.js +++ b/matrix/mreq.js @@ -2,8 +2,6 @@ const fetch = require("node-fetch").default const mixin = require("mixin-deep") -const stream = require("stream") -const getStream = require("get-stream") const passthrough = require("../passthrough") const { sync } = passthrough @@ -29,15 +27,9 @@ class MatrixServerError extends Error { * @param {any} [extra] */ async function mreq(method, url, body, extra = {}) { - if (body == undefined || Object.is(body.constructor, Object)) { - body = JSON.stringify(body) - } else if (body instanceof stream.Readable && reg.ooye.content_length_workaround) { - body = await getStream.buffer(body) - } - const opts = mixin({ method, - body, + body: (body == undefined || Object.is(body.constructor, Object)) ? JSON.stringify(body) : body, headers: { Authorization: `Bearer ${reg.as_token}` } @@ -47,18 +39,7 @@ async function mreq(method, url, body, extra = {}) { const res = await fetch(baseUrl + url, opts) const root = await res.json() - if (!res.ok || root.errcode) { - if (root.error?.includes("Content-Length")) { - console.error(`OOYE cannot stream uploads to Synapse. Please choose one of these workarounds:` - + `\n * Run an nginx reverse proxy to Synapse, and point registration.yaml's` - + `\n \`server_origin\` to nginx` - + `\n * Set \`content_length_workaround: true\` in registration.yaml (this will` - + `\n halve the speed of bridging d->m files)`) - throw new Error("Synapse is not accepting stream uploads, see the message above.") - } - delete opts.headers.Authorization - throw new MatrixServerError(root, {baseUrl, url, ...opts}) - } + if (!res.ok || root.errcode) throw new MatrixServerError(root, {baseUrl, url, ...opts}) return root } diff --git a/package-lock.json b/package-lock.json index e4a0ab2..5bc10cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,6 @@ "deep-equal": "^2.2.3", "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#de519353668c87ecc8c543e9749093481bc72ff8", "entities": "^4.5.0", - "get-stream": "^6.0.1", "giframe": "github:cloudrac3r/giframe#v0.4.1", "heatsync": "^2.4.1", "html-template-tag": "github:cloudrac3r/html-template-tag#v5.0", @@ -1457,17 +1456,6 @@ "source-map": "^0.6.1" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/giframe": { "version": "0.3.0", "resolved": "git+ssh://git@github.com/cloudrac3r/giframe.git#1630f4d3b2bf5acd197409c85edd11e0da72d0a1", diff --git a/package.json b/package.json index 33d3064..c9d3910 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "deep-equal": "^2.2.3", "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#de519353668c87ecc8c543e9749093481bc72ff8", "entities": "^4.5.0", - "get-stream": "^6.0.1", "giframe": "github:cloudrac3r/giframe#v0.4.1", "heatsync": "^2.4.1", "html-template-tag": "github:cloudrac3r/html-template-tag#v5.0", diff --git a/readme.md b/readme.md index 49c2e66..e7baf18 100644 --- a/readme.md +++ b/readme.md @@ -2,9 +2,9 @@ -Modern Matrix-to-Discord appservice bridge, created by [@cadence:cadence.moe](https://matrix.to/#/@cadence:cadence.moe) +Modern Matrix-to-Discord appservice bridge. -[![Releases](https://img.shields.io/gitea/v/release/cadence/out-of-your-element?gitea_url=https%3A%2F%2Fgitdab.com&style=plastic&color=green)](https://gitdab.com/cadence/out-of-your-element/releases) [![Discuss on Matrix](https://img.shields.io/badge/discuss-%23out--of--your--element-white?style=plastic)](https://matrix.to/#/#out-of-your-element:cadence.moe) +Created by [@cadence:cadence.moe](https://matrix.to/#/@cadence:cadence.moe) // Discuss in [#out-of-your-element:cadence.moe](https://matrix.to/#/#out-of-your-element:cadence.moe) ## Docs @@ -76,8 +76,7 @@ Follow these steps: 1. [Get Node.js version 18 or later](https://nodejs.org/en/download/releases) (the version is required by the better-sqlite3 and matrix-appservice dependencies) -1. Clone this repo and checkout a specific tag. (Development happens on main. Stable versions are tagged.) - * The latest release tag is ![](https://img.shields.io/gitea/v/release/cadence/out-of-your-element?gitea_url=https%3A%2F%2Fgitdab.com&style=flat-square&label=%20&color=black). +1. Clone this repo and checkout a specific tag. (Development happens on main. Stabler versions are tagged.) 1. Install dependencies: `npm install --save-dev` (omit --save-dev if you will not run the automated tests) @@ -97,10 +96,6 @@ Follow these steps: * $ `npm run addbot` * $ `./addbot.sh` -Now any message on Discord will create the corresponding rooms on Matrix-side. After the rooms have been created, Matrix and Discord users can chat back and forth. - -To get into the rooms on your Matrix account, either add yourself to `invite` in `registration.yaml`, or use the `//invite [your mxid here]` command on Discord. - # Development setup * Be sure to install dependencies with `--save-dev` so you can run the tests. @@ -169,7 +164,6 @@ To get into the rooms on your Matrix account, either add yourself to `invite` in * (8) snowtransfer: Discord API library with bring-your-own-caching that I trust. * (0) deep-equal: It's already pulled in by supertape. * (1) discord-markdown: This is my fork! -* (0) get-stream: Only needed if content_length_workaround is true. * (0) giframe: This is my fork! * (1) heatsync: Module hot-reloader that I trust. * (0) entities: Looks fine. No dependencies. diff --git a/registration.example.yaml b/registration.example.yaml index dd217db..9e7cd2c 100644 --- a/registration.example.yaml +++ b/registration.example.yaml @@ -18,7 +18,6 @@ ooye: max_file_size: 5000000 server_name: [the part after the colon in your matrix id, like cadence.moe] server_origin: [the full protocol and domain of your actual matrix server's location, with no trailing slash, like https://matrix.cadence.moe] - content_length_workaround: false invite: # uncomment this to auto-invite the named user to newly created spaces and mark them as admin (PL 100) everywhere - # - '@cadence:cadence.moe' + # - @cadence:cadence.moe diff --git a/scripts/seed.js b/scripts/seed.js index 1a21490..4dc08e0 100644 --- a/scripts/seed.js +++ b/scripts/seed.js @@ -71,11 +71,7 @@ async function uploadAutoEmoji(guild, name, filename) { try { await api.register(reg.sender_localpart) } catch (e) { - if (e.errcode === "M_USER_IN_USE" || e.data?.error === "Internal server error") { - // "Internal server error" is the only OK error because older versions of Synapse say this if you try to register the same username twice. - } else { - throw e - } + if (e.errcode === "M_USER_IN_USE" || e.data?.error !== "Internal server error") throw e // "Internal server error" is the only OK error because Synapse says this if you try to register the same username twice. } // upload initial images... diff --git a/test/test.js b/test/test.js index 42b1a0e..95daf5b 100644 --- a/test/test.js +++ b/test/test.js @@ -14,7 +14,6 @@ const db = new sqlite(":memory:") const reg = require("../matrix/read-registration") reg.ooye.server_origin = "https://matrix.cadence.moe" // so that tests will pass even when hard-coded -reg.ooye.server_name = "cadence.moe" reg.ooye.invite = ["@test_auto_invite:example.org"] const sync = new HeatSync({watchFS: false}) diff --git a/types.d.ts b/types.d.ts index 2788f60..e9946d7 100644 --- a/types.d.ts +++ b/types.d.ts @@ -21,7 +21,6 @@ export type AppServiceRegistrationConfig = { max_file_size: number server_name: string server_origin: string - content_length_workaround: boolean invite: string[] } old_bridge?: {