diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js index bccc7ac..00a985c 100644 --- a/d2m/actions/register-user.js +++ b/d2m/actions/register-user.js @@ -72,16 +72,8 @@ async function ensureSimJoined(user, roomID) { // Ensure joined const existing = db.prepare("SELECT * FROM sim_member WHERE room_id = ? and mxid = ?").get(roomID, mxid) if (!existing) { - try { - await api.inviteToRoom(roomID, mxid) - await api.joinRoom(roomID, mxid) - } catch (e) { - if (e.message.includes("is already in the room.")) { - // Sweet! - } else { - throw e - } - } + await api.inviteToRoom(roomID, mxid) + await api.joinRoom(roomID, mxid) db.prepare("INSERT INTO sim_member (room_id, mxid) VALUES (?, ?)").run(roomID, mxid) } return mxid diff --git a/m2d/actions/send-event.js b/m2d/actions/send-event.js index 08670a9..e870675 100644 --- a/m2d/actions/send-event.js +++ b/m2d/actions/send-event.js @@ -1,9 +1,6 @@ // @ts-check const assert = require("assert").strict -const crypto = require("crypto") -const {pipeline} = require("stream") -const {promisify} = require("util") const Ty = require("../../types") const DiscordTypes = require("discord-api-types/v10") const passthrough = require("../../passthrough") @@ -17,29 +14,16 @@ const eventToMessage = sync.require("../converters/event-to-message") const api = sync.require("../../matrix/api") /** - * @param {DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {pendingFiles?: ({name: string, url: string} | {name: string, url: string, key: string, iv: string})[]}} message + * @param {DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {pendingFiles?: {name: string, url: string}[]}} message * @returns {Promise} */ async function resolvePendingFiles(message) { if (!message.pendingFiles) return message const files = await Promise.all(message.pendingFiles.map(async p => { - let fileBuffer - if ("key" in p) { - // Encrypted - const d = crypto.createDecipheriv("aes-256-ctr", Buffer.from(p.key, "base64url"), Buffer.from(p.iv, "base64url")) - fileBuffer = await fetch(p.url).then(res => res.arrayBuffer()).then(x => { - return Buffer.concat([ - d.update(Buffer.from(x)), - d.final() - ]) - }) - } else { - // Unencrypted - fileBuffer = await fetch(p.url).then(res => res.arrayBuffer()).then(x => Buffer.from(x)) - } + const file = await fetch(p.url).then(res => res.arrayBuffer()).then(x => Buffer.from(x)) return { name: p.name, - file: fileBuffer // TODO: Once SnowTransfer supports ReadableStreams for attachment uploads, pass in those instead of Buffers + file } })) const newMessage = { @@ -50,7 +34,7 @@ async function resolvePendingFiles(message) { return newMessage } -/** @param {Ty.Event.Outer_M_Room_Message | Ty.Event.Outer_M_Room_Message_File | Ty.Event.Outer_M_Sticker} event */ +/** @param {Ty.Event.M_Outer_M_Room_Message | Ty.Event.M_Outer_M_Room_Message_File | Ty.Event.M_Outer_M_Sticker} event */ async function sendEvent(event) { // TODO: we just assume the bridge has already been created, is that really ok? const row = db.prepare("SELECT channel_id, thread_parent FROM channel_room WHERE room_id = ?").get(event.room_id) diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index 5ad62c1..a8a5b65 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -125,7 +125,7 @@ async function getMemberFromCacheOrHomeserver(roomID, mxid, api) { } /** - * @param {Ty.Event.Outer_M_Room_Message | Ty.Event.Outer_M_Room_Message_File | Ty.Event.Outer_M_Sticker | Ty.Event.Outer_M_Room_Message_Encrypted_File} event + * @param {Ty.Event.M_Outer_M_Room_Message | Ty.Event.M_Outer_M_Room_Message_File | Ty.Event.M_Outer_M_Sticker} event * @param {import("discord-api-types/v10").APIGuild} guild * @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API */ @@ -148,7 +148,7 @@ async function eventToMessage(event, guild, di) { let content = event.content.body // ultimate fallback const attachments = [] - /** @type {({name: string, url: string} | {name: string, url: string, key: string, iv: string})[]} */ + /** @type {{name: string, url: string}[]} */ const pendingFiles = [] // Convert content depending on what the message is @@ -281,20 +281,10 @@ async function eventToMessage(event, guild, di) { } else if (event.type === "m.room.message" && (event.content.msgtype === "m.file" || event.content.msgtype === "m.video" || event.content.msgtype === "m.audio" || event.content.msgtype === "m.image")) { content = "" const filename = event.content.body - if ("url" in event.content) { - // Unencrypted - const url = utils.getPublicUrlForMxc(event.content.url) - assert(url) - attachments.push({id: "0", filename}) - pendingFiles.push({name: filename, url}) - } else { - // Encrypted - const url = utils.getPublicUrlForMxc(event.content.file.url) - assert(url) - assert.equal(event.content.file.key.alg, "A256CTR") - attachments.push({id: "0", filename}) - pendingFiles.push({name: filename, url, key: event.content.file.key.k, iv: event.content.file.iv}) - } + const url = utils.getPublicUrlForMxc(event.content.url) + assert(url) + attachments.push({id: "0", filename}) + pendingFiles.push({name: filename, url}) } else if (event.type === "m.sticker") { content = "" let filename = event.content.body diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index 565d8c4..5a83f0c 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -1176,60 +1176,6 @@ test("event2message: image attachments work", async t => { ) }) -test("event2message: encrypted image attachments work", async t => { - t.deepEqual( - await eventToMessage({ - type: "m.room.message", - sender: "@cadence:cadence.moe", - content: { - info: { - mimetype: "image/png", - size: 105691, - w: 1192, - h: 309, - "xyz.amorgan.blurhash": "U17USN~q9FtQ-;Rjxuj[9FIUoMM|-=WB9Ft7" - }, - msgtype: "m.image", - body: "image.png", - file: { - v: "v2", - key: { - alg: "A256CTR", - ext: true, - k: "QTo-oMPnN1Rbc7vBFg9WXMgoctscdyxdFEIYm8NYceo", - key_ops: ["encrypt", "decrypt"], - kty: "oct" - }, - iv: "Va9SHZpIn5kAAAAAAAAAAA", - hashes: { - sha256: "OUZqZFBcANFt42iAKET9YXfWMCdT0BX7QO0Eyk9q4Js" - }, - url: "mxc://heyquark.com/LOGkUTlVFrqfiExlGZNgCJJX", - mimetype: "image/png" - } - }, - event_id: "$JNhONhXO-5jrztZz8b7mbTMJasbU78TwQr4tog-3Mnk", - room_id: "!PnyBKvUBOhjuCucEfk:cadence.moe" - }), - { - messagesToDelete: [], - messagesToEdit: [], - messagesToSend: [{ - username: "cadence [they]", - content: "", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU", - attachments: [{id: "0", filename: "image.png"}], - pendingFiles: [{ - name: "image.png", - url: "https://matrix.cadence.moe/_matrix/media/r0/download/heyquark.com/LOGkUTlVFrqfiExlGZNgCJJX", - key: "QTo-oMPnN1Rbc7vBFg9WXMgoctscdyxdFEIYm8NYceo", - iv: "Va9SHZpIn5kAAAAAAAAAAA" - }] - }] - } - ) -}) - test("event2message: stickers work", async t => { t.deepEqual( await eventToMessage({ diff --git a/m2d/event-dispatcher.js b/m2d/event-dispatcher.js index 29319d8..026b067 100644 --- a/m2d/event-dispatcher.js +++ b/m2d/event-dispatcher.js @@ -54,7 +54,7 @@ function guard(type, fn) { sync.addTemporaryListener(as, "type:m.room.message", guard("m.room.message", /** - * @param {Ty.Event.Outer_M_Room_Message | Ty.Event.Outer_M_Room_Message_File} event it is a m.room.message because that's what this listener is filtering for + * @param {Ty.Event.M_Outer_M_Room_Message | Ty.Event.M_Outer_M_Room_Message_File} event it is a m.room.message because that's what this listener is filtering for */ async event => { if (utils.eventSenderIsFromDiscord(event.sender)) return @@ -63,7 +63,7 @@ async event => { sync.addTemporaryListener(as, "type:m.sticker", guard("m.sticker", /** - * @param {Ty.Event.Outer_M_Sticker} event it is a m.sticker because that's what this listener is filtering for + * @param {Ty.Event.M_Outer_M_Sticker} event it is a m.sticker because that's what this listener is filtering for */ async event => { if (utils.eventSenderIsFromDiscord(event.sender)) return diff --git a/matrix/api.js b/matrix/api.js index 5bbafff..7253a1a 100644 --- a/matrix/api.js +++ b/matrix/api.js @@ -171,12 +171,13 @@ async function setUserPower(roomID, mxid, power) { assert(mxid[0] === "@") // Yes there's no shortcut https://github.com/matrix-org/matrix-appservice-bridge/blob/2334b0bae28a285a767fe7244dad59f5a5963037/src/components/intent.ts#L352 const powerLevels = await getStateEvent(roomID, "m.room.power_levels", "") - powerLevels.users = powerLevels.users || {} + const users = powerLevels.users || {} if (power != null) { - powerLevels.users[mxid] = power + users[mxid] = power } else { - delete powerLevels.users[mxid] + delete users[mxid] } + powerLevels.users = users await sendState(roomID, "m.room.power_levels", "", powerLevels) return powerLevels } diff --git a/types.d.ts b/types.d.ts index a8c7e68..b74172b 100644 --- a/types.d.ts +++ b/types.d.ts @@ -80,7 +80,7 @@ export namespace Event { } } - export type Outer_M_Room_Message = Outer & {type: "m.room.message"} + export type M_Outer_M_Room_Message = Outer & {type: "m.room.message"} export type M_Room_Message_File = { msgtype: "m.file" | "m.image" | "m.video" | "m.audio" @@ -96,39 +96,7 @@ export namespace Event { } } - export type Outer_M_Room_Message_File = Outer & {type: "m.room.message"} - - export type M_Room_Message_Encrypted_File = { - msgtype: "m.file" | "m.image" | "m.video" | "m.audio" - body: string - file: { - url: string - iv: string - hashes: { - sha256: string - } - v: "v2" - key: { - /** :3 */ - kty: "oct" - /** must include at least "encrypt" and "decrypt" */ - key_ops: string[] - alg: "A256CTR" - k: string - ext: true - } - }, - info?: any - "m.relates_to"?: { - "m.in_reply_to": { - event_id: string - } - rel_type?: "m.replace" - event_id?: string - } - } - - export type Outer_M_Room_Message_Encrypted_File = Outer & {type: "m.room.message"} + export type M_Outer_M_Room_Message_File = Outer & {type: "m.room.message"} export type M_Sticker = { body: string @@ -143,7 +111,7 @@ export namespace Event { } } - export type Outer_M_Sticker = Outer & {type: "m.sticker"} + export type M_Outer_M_Sticker = Outer & {type: "m.sticker"} export type M_Room_Member = { membership: string