diff --git a/package-lock.json b/package-lock.json index fda73e3f..aa7822f7 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.7", + "@cloudrac3r/discord-markdown": "^2.6.6", "@cloudrac3r/giframe": "^0.4.3", "@cloudrac3r/html-template-tag": "^5.0.1", "@cloudrac3r/in-your-element": "^1.1.1", @@ -35,7 +35,7 @@ "lru-cache": "^11.0.2", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", - "snowtransfer": "^0.14.2", + "snowtransfer": "^0.15.0", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", @@ -225,9 +225,9 @@ } }, "node_modules/@cloudrac3r/discord-markdown": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.6.7.tgz", - "integrity": "sha512-bWLmBYWaNEDcQfZHDz4jaAxLKA9161ruEnHo3ms6kfRw8uYku/Uz7U1xTmQ2dQF/q1PiuBvM9I37pLiotlQj8A==", + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.6.6.tgz", + "integrity": "sha512-4FNO7WmACPvcTrQjeLQLr9WRuP7JDUVUGFrRJvmAjiMs2UlUAsShfSRuU2SCqz3QqmX8vyJ06wy2hkjTTyRtbw==", "license": "MIT", "dependencies": { "simple-markdown": "^0.7.3" @@ -1464,18 +1464,6 @@ "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", @@ -2731,12 +2719,12 @@ } }, "node_modules/snowtransfer": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.14.2.tgz", - "integrity": "sha512-Fi8OdRmaIgeCj58oVej+tQAoY2I+Xp/6PAYV8X93jE/2E6Anc87SbTbDV6WZXCnuzTQz3gty8JOGz02qI7Qs9A==", + "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.8" + "discord-api-types": "^0.38.21" }, "engines": { "node": ">=16.15.0" @@ -3088,9 +3076,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", diff --git a/package.json b/package.json index 85530c10..2fb21f24 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@chriscdn/promise-semaphore": "^3.0.1", - "@cloudrac3r/discord-markdown": "^2.6.7", + "@cloudrac3r/discord-markdown": "^2.6.6", "@cloudrac3r/giframe": "^0.4.3", "@cloudrac3r/html-template-tag": "^5.0.1", "@cloudrac3r/in-your-element": "^1.1.1", @@ -44,7 +44,7 @@ "lru-cache": "^11.0.2", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", - "snowtransfer": "^0.14.2", + "snowtransfer": "^0.15.0", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", diff --git a/scripts/setup.js b/scripts/setup.js index ecef03d8..6bff2938 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -120,28 +120,16 @@ 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(portResponse.socket) + await server.listen(6693) - 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("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("Examples: https://gitdab.com/cadence/out-of-your-element/src/branch/main/docs/get-started.md#appendix") - if (typeof portResponse.socket === "number") { - console.log(`Now listening on http://localhost:${portResponse.socket}. Feel free to send some test requests.`) - } + console.log("Now listening on port 6693. Feel free to send some test requests.") /** @type {{bridge_origin: string}} */ const bridgeOriginResponse = await prompt({ type: "input", @@ -267,7 +255,6 @@ function defineEchoHandler() { reg = { ...template, url: bridgeOriginResponse.bridge_origin, - ...portResponse, ooye: { ...template.ooye, ...bridgeOriginResponse, diff --git a/src/d2m/actions/register-pk-user.js b/src/d2m/actions/register-pk-user.js index 27e949ce..b5e44e56 100644 --- a/src/d2m/actions/register-pk-user.js +++ b/src/d2m/actions/register-pk-user.js @@ -146,7 +146,7 @@ async function syncUser(messageID, author, roomID, shouldActuallySync) { try { // API lookup var pkMessage = await fetchMessage(messageID) - db.prepare("REPLACE INTO sim_proxy (user_id, proxy_owner_id, displayname) VALUES (?, ?, ?)").run(pkMessage.member.uuid, pkMessage.sender, author.username) + db.prepare("INSERT OR IGNORE INTO sim_proxy (user_id, proxy_owner_id, displayname) VALUES (?, ?, ?)").run(pkMessage.member.uuid, pkMessage.sender, author.username) } catch (e) { // Fall back to offline cache const senderMxid = from("sim_proxy").join("sim", "user_id").join("sim_member", "mxid").where({displayname: author.username, room_id: roomID}).pluck("mxid").get() diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index 30a20fe2..a8e5a6b7 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -33,10 +33,9 @@ function getDiscordParseCallbacks(message, guild, useHTML) { user: node => { const mxid = select("sim", "mxid", {user_id: node.id}).pluck().get() const interaction = message.interaction_metadata || message.interaction - const username = message.mentions?.find(ment => ment.id === node.id)?.username - || message.referenced_message?.mentions?.find(ment => ment.id === node.id)?.username + const username = message.mentions.find(ment => ment.id === node.id)?.username + || message.referenced_message?.mentions.find(ment => ment.id === node.id)?.username || (interaction?.user.id === node.id ? interaction.user.username : null) - || (message.author.id === node.id ? message.author.username : null) || node.id if (mxid && useHTML) { return `@${username}` @@ -408,13 +407,13 @@ async function messageToEvent(message, guild, options = {}, di) { async function transformParsedVia(parsed) { for (const node of parsed) { - if (node.type === "discordChannel" || node.type === "discordChannelLink") { + if (node.type === "discordChannel") { 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) } @@ -611,7 +610,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", timeZone: reg.ooye.time_zone}) // 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"}) // 9 June at 3:00 pm NZT const rep = new mxUtils.MatrixStringBuilder() // Add time diff --git a/src/d2m/converters/message-to-event.test.js b/src/d2m/converters/message-to-event.test.js index ee4ec037..fc933e35 100644 --- a/src/d2m/converters/message-to-event.test.js +++ b/src/d2m/converters/message-to-event.test.js @@ -100,44 +100,6 @@ 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/src/d2m/converters/thread-to-announcement.js b/src/d2m/converters/thread-to-announcement.js index 98b8f124..11a067fd 100644 --- a/src/d2m/converters/thread-to-announcement.js +++ b/src/d2m/converters/thread-to-announcement.js @@ -32,10 +32,13 @@ 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 3d5d1ebc..471cd943 100644 --- a/src/d2m/converters/thread-to-announcement.test.js +++ b/src/d2m/converters/thread-to-announcement.test.js @@ -55,6 +55,8 @@ 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": {} }) }) @@ -67,6 +69,8 @@ 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": {} }) }) @@ -91,6 +95,8 @@ 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": { @@ -120,6 +126,8 @@ 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": { @@ -149,6 +157,8 @@ 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"] }, diff --git a/src/m2d/actions/emoji-sheet.js b/src/m2d/actions/emoji-sheet.js index ed5ab883..a63f0b0c 100644 --- a/src/m2d/actions/emoji-sheet.js +++ b/src/m2d/actions/emoji-sheet.js @@ -7,8 +7,6 @@ const {sync} = require("../../passthrough") const emojiSheetConverter = sync.require("../converters/emoji-sheet") /** @type {import("../../matrix/api")} */ const api = sync.require("../../matrix/api") -/** @type {import("../../matrix/mreq")} */ -const mreq = sync.require("../../matrix/mreq") /** * Downloads the emoji from the web and converts to uncompressed PNG data. @@ -21,10 +19,6 @@ async function getAndConvertEmoji(mxc) { // If we were using connection pooling, we would be forced to download the entire GIF. // So we set no agent to ensure we are not connection pooling. const res = await api.getMedia(mxc, {signal: abortController.signal}) - if (res.status !== 200) { - const root = await res.json() - throw new mreq.MatrixServerError(root, {mxc}) - } const readable = stream.Readable.fromWeb(res.body) return emojiSheetConverter.convertImageStream(readable, () => { abortController.abort() diff --git a/src/m2d/actions/redact.js b/src/m2d/actions/redact.js index 1d3aa67f..1f6cef89 100644 --- a/src/m2d/actions/redact.js +++ b/src/m2d/actions/redact.js @@ -13,12 +13,10 @@ const utils = sync.require("../converters/utils") */ async function deleteMessage(event) { const rows = from("event_message").join("message_channel", "message_id").select("channel_id", "message_id").where({event_id: event.redacts}).all() - if (!rows.length) return for (const row of rows) { + db.prepare("DELETE FROM message_channel WHERE message_id = ?").run(row.message_id) await discord.snow.channel.deleteMessage(row.channel_id, row.message_id, event.content.reason) - db.prepare("DELETE FROM event_message WHERE message_id = ?").run(row.message_id) } - db.prepare("DELETE FROM message_channel WHERE message_id = ?").run(rows[0].message_id) } /** diff --git a/src/m2d/actions/setup-emojis.js b/src/m2d/actions/setup-emojis.js index 1be1d2d2..ba2c0455 100644 --- a/src/m2d/actions/setup-emojis.js +++ b/src/m2d/actions/setup-emojis.js @@ -5,8 +5,9 @@ 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"]) { diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index 61525e2b..3cf08cf3 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -11,7 +11,6 @@ const entities = require("entities") const passthrough = require("../../passthrough") const {sync, db, discord, select, from} = passthrough -const {reg} = require("../../matrix/read-registration") /** @type {import("../converters/utils")} */ const mxUtils = sync.require("../converters/utils") /** @type {import("../../discord/utils")} */ @@ -239,8 +238,7 @@ function convertEmoji(mxcUrl, nameForGuess, allowSpriteSheetIndicator, allowLink if (!found) row = null } // Or, if we don't have an emoji right now, we search for the name instead. - const isLocalMxc = mxcUrl?.match(/^mxc:\/\/([^/]+)/)?.[1] === reg.ooye.server_name - if (!row && nameForGuess && isLocalMxc) { + if (!row && nameForGuess) { const nameForGuessLower = nameForGuess.toLowerCase() for (const guild of discord.guilds.values()) { /** @type {{name: string, id: string, animated: number}[]} */ diff --git a/src/matrix/api.js b/src/matrix/api.js index 709d70c5..41af63f7 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -384,9 +384,7 @@ async function getMedia(mxc, init = {}) { }, ...init }) - if (init.method !== "HEAD") { - assert(res.body) - } + assert(res.body) // @ts-ignore return res } diff --git a/src/types.d.ts b/src/types.d.ts index 27dfddfb..37da6332 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -31,7 +31,6 @@ 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/data.js b/test/data.js index e64b9c2f..a8ff8a88 100644 --- a/test/data.js +++ b/test/data.js @@ -1398,63 +1398,6 @@ 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, diff --git a/test/test.js b/test/test.js index b01f0ce2..8d9ad16f 100644 --- a/test/test.js +++ b/test/test.js @@ -27,7 +27,6 @@ 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})