diff --git a/docs/developer-orientation.md b/docs/developer-orientation.md index 02b5c52..dfc1319 100644 --- a/docs/developer-orientation.md +++ b/docs/developer-orientation.md @@ -93,7 +93,7 @@ Total transitive production dependencies: 137 ### 🦕 -* (31) better-sqlite3: SQLite is the best database, and this is the best library for it. +* (31) better-sqlite3: SQLite3 is the best database, and this is the best library for it. * (27) @cloudrac3r/pug: Language for dynamic web pages. This is my fork. (I released code that hadn't made it to npm, and removed the heavy pug-filters feature.) * (16) stream-mime-type@1: This seems like the best option. Version 1 is used because version 2 is ESM-only. * (9) h3: Web server. OOYE needs this for the appservice listener, authmedia proxy, self-service, and more. diff --git a/src/d2m/actions/update-pins.js b/src/d2m/actions/update-pins.js index 6ef477f..692081a 100644 --- a/src/d2m/actions/update-pins.js +++ b/src/d2m/actions/update-pins.js @@ -25,14 +25,7 @@ function convertTimestamp(timestamp) { * @param {number?} convertedTimestamp */ async function updatePins(channelID, roomID, convertedTimestamp) { - try { - var discordPins = await discord.snow.channel.getChannelPinnedMessages(channelID) - } catch (e) { - if (e.message === `{"message": "Missing Access", "code": 50001}`) { - return // Discord sends channel pins update events even for channels that the bot can't view/get pins in, just ignore it - } - throw e - } + const discordPins = await discord.snow.channel.getChannelPinnedMessages(channelID) const pinned = pinsToList.pinsToList(discordPins) const kstate = await ks.roomToKState(roomID) diff --git a/src/d2m/event-dispatcher.js b/src/d2m/event-dispatcher.js index b98abfc..fdb6c93 100644 --- a/src/d2m/event-dispatcher.js +++ b/src/d2m/event-dispatcher.js @@ -35,8 +35,6 @@ const speedbump = sync.require("./actions/speedbump") const retrigger = sync.require("./actions/retrigger") /** @type {import("./actions/set-presence")} */ const setPresence = sync.require("./actions/set-presence") -/** @type {import("../m2d/event-dispatcher")} */ -const matrixEventDispatcher = sync.require("../m2d/event-dispatcher") /** @type {any} */ // @ts-ignore bad types from semaphore const Semaphore = require("@chriscdn/promise-semaphore") @@ -68,19 +66,22 @@ module.exports = { const roomID = select("channel_room", "room_id", {channel_id: channelID}).pluck().get() if (!roomID) return + let stackLines = null + if (e.stack) { + stackLines = e.stack.split("\n") + let cloudstormLine = stackLines.findIndex(l => l.includes("/node_modules/cloudstorm/")) + if (cloudstormLine !== -1) { + stackLines = stackLines.slice(0, cloudstormLine - 2) + } + } + const builder = new mxUtils.MatrixStringBuilder() builder.addLine("\u26a0 Bridged event from Discord not delivered", "\u26a0 Bridged event from Discord not delivered") builder.addLine(`Gateway event: ${gatewayMessage.t}`) - - let errorIntroLine = e.toString() - if (e.cause) { - errorIntroLine += ` (cause: ${e.cause})` + builder.addLine(e.toString()) + if (stackLines) { + builder.addLine(`Error trace:\n${stackLines.join("\n")}`, `
Error trace
${stackLines.join("\n")}
`) } - builder.addLine(errorIntroLine) - - const stack = matrixEventDispatcher.stringifyErrorStack(e) - builder.addLine(`Error trace:\n${stack}`, `
Error trace
${stack}
`) - builder.addLine("", `
Original payload
${util.inspect(gatewayMessage.d, false, 4, false)}
`) await api.sendEvent(roomID, "m.room.message", { ...builder.get(), diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index 7044859..fee74f4 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -546,7 +546,7 @@ async function eventToMessage(event, guild, di) { if (!messageIDsToEdit.length) return // Ok, it's an edit. - event = {...event, content: event.content["m.new_content"]} + event.content = event.content["m.new_content"] // Is it editing a reply? We need special handling if it is. // Get the original event, then check if it was a reply diff --git a/src/m2d/event-dispatcher.js b/src/m2d/event-dispatcher.js index 1bc97de..5f8cb2b 100644 --- a/src/m2d/event-dispatcher.js +++ b/src/m2d/event-dispatcher.js @@ -28,58 +28,6 @@ const {reg} = require("../matrix/read-registration") let lastReportedEvent = 0 -/** - * This function is adapted from Evan Kaufman's fantastic work. - * The original function and my adapted function are both MIT licensed. - * @url https://github.com/EvanK/npm-loggable-error/ - * @param {number} [depth] - * @returns {string} -*/ -function stringifyErrorStack(err, depth = 0) { - let collapsed = " ".repeat(depth); - if (!(err instanceof Error)) { - return collapsed + err - } - - // add full stack trace if one exists, otherwise convert to string - let stackLines = ( err?.stack ?? `${err}` ).replace(/^/gm, " ".repeat(depth)).trim().split("\n") - let cloudstormLine = stackLines.findIndex(l => l.includes("/node_modules/cloudstorm/")) - if (cloudstormLine !== -1) { - stackLines = stackLines.slice(0, cloudstormLine - 2) - } - collapsed += stackLines.join("\n") - - const props = Object.getOwnPropertyNames(err).filter(p => !["message", "stack"].includes(p)) - - // only break into object notation if we have addtl props to dump - if (props.length) { - const dedent = " ".repeat(depth); - const indent = " ".repeat(depth + 2); - - collapsed += " {\n"; - - // loop and print each (indented) prop name - for (let property of props) { - collapsed += `${indent}[${property}]: `; - - // if another error object, stringify it too - if (err[property] instanceof Error) { - collapsed += stringifyErrorStack(err[property], depth + 2).trimStart(); - } - // otherwise stringify as JSON - else { - collapsed += JSON.stringify(err[property]); - } - - collapsed += "\n"; - } - - collapsed += `${dedent}}\n`; - } - - return collapsed; -} - function guard(type, fn) { return async function(event, ...args) { try { @@ -91,12 +39,7 @@ function guard(type, fn) { if (Date.now() - lastReportedEvent < 5000) return lastReportedEvent = Date.now() - let errorIntroLine = e.toString() - if (e.cause) { - errorIntroLine += ` (cause: ${e.cause})` - } - - const cloudflareErrorTitle = errorIntroLine.match(/.*?discord\.com \| ([^<]*)<\/title>/s)?.[1] + const cloudflareErrorTitle = e.toString().match(/<!DOCTYPE html>.*?<title>discord\.com \| ([^<]*)<\/title>/s)?.[1] if (cloudflareErrorTitle) { return api.sendEvent(event.room_id, "m.room.message", { msgtype: "m.text", @@ -110,16 +53,16 @@ function guard(type, fn) { }) } - const stack = stringifyErrorStack(e) + let stackLines = e.stack.split("\n") api.sendEvent(event.room_id, "m.room.message", { msgtype: "m.text", body: "\u26a0 Matrix event not delivered to Discord. See formatted content for full details.", format: "org.matrix.custom.html", formatted_body: "\u26a0 <strong>Matrix event not delivered to Discord</strong>" + `<br>Event type: ${type}` - + `<br>${errorIntroLine}` + + `<br>${e.toString()}` + `<br><details><summary>Error trace</summary>` - + `<pre>${stack}</pre></details>` + + `<pre>${stackLines.join("\n")}</pre></details>` + `<details><summary>Original payload</summary>` + `<pre>${util.inspect(event, false, 4, false)}</pre></details>`, "moe.cadence.ooye.error": { @@ -354,5 +297,3 @@ async event => { db.prepare("UPDATE member_cache SET power_level = ? WHERE room_id = ? AND mxid = ?").run(newPower[mxid] || 0, event.room_id, mxid) } })) - -module.exports.stringifyErrorStack = stringifyErrorStack diff --git a/test/test.js b/test/test.js index 2d02cbb..35c12ed 100644 --- a/test/test.js +++ b/test/test.js @@ -29,7 +29,7 @@ reg.ooye.bridge_origin = "https://bridge.example.org" const sync = new HeatSync({watchFS: false}) const discord = { - // @ts-ignore - ignore guilds, because my data dump is missing random properties + // @ts-ignore - only ignore guilds, because my data dump is missing random properties guilds: new Map([ [data.guild.general.id, data.guild.general], [data.guild.fna.id, data.guild.fna], @@ -43,7 +43,6 @@ const discord = { application: { id: "684280192553844747" }, - // @ts-ignore - ignore channels, because my data dump is missing random properties channels: new Map([ [data.channel.general.id, data.channel.general], [data.channel.updates.id, data.channel.updates], @@ -128,13 +127,6 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not require("./addbot.test") require("../src/db/orm.test") - require("../src/web/server.test") - require("../src/web/routes/download-discord.test") - require("../src/web/routes/download-matrix.test") - require("../src/web/routes/guild.test") - require("../src/web/routes/guild-settings.test") - require("../src/web/routes/link.test") - require("../src/web/routes/log-in-with-matrix.test") require("../src/discord/utils.test") require("../src/matrix/kstate.test") require("../src/matrix/api.test") @@ -155,7 +147,6 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not require("../src/d2m/converters/remove-reaction.test") require("../src/d2m/converters/thread-to-announcement.test") require("../src/d2m/converters/user-to-mxid.test") - require("../src/m2d/event-dispatcher.test") require("../src/m2d/converters/diff-pins.test") require("../src/m2d/converters/event-to-message.test") require("../src/m2d/converters/emoji.test") @@ -166,4 +157,11 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not require("../src/discord/interactions/permissions.test") require("../src/discord/interactions/privacy.test") require("../src/discord/interactions/reactions.test") + require("../src/web/server.test") + require("../src/web/routes/download-discord.test") + require("../src/web/routes/download-matrix.test") + require("../src/web/routes/guild.test") + require("../src/web/routes/guild-settings.test") + require("../src/web/routes/link.test") + require("../src/web/routes/log-in-with-matrix.test") })() diff --git a/test/web.js b/test/web.js index eb2b876..0595a96 100644 --- a/test/web.js +++ b/test/web.js @@ -96,7 +96,7 @@ class Router { const router = new Router() -passthrough.as = {router, on() {}} +passthrough.as = {router} module.exports.router = router module.exports.test = test