diff --git a/d2m/actions/add-reaction.js b/d2m/actions/add-reaction.js deleted file mode 100644 index 82449cd..0000000 --- a/d2m/actions/add-reaction.js +++ /dev/null @@ -1,36 +0,0 @@ -// @ts-check - -const assert = require("assert") - -const passthrough = require("../../passthrough") -const { discord, sync, db } = passthrough -/** @type {import("../../matrix/api")} */ -const api = sync.require("../../matrix/api") -/** @type {import("./register-user")} */ -const registerUser = sync.require("./register-user") -/** @type {import("../actions/create-room")} */ -const createRoom = sync.require("../actions/create-room") - -/** - * @param {import("discord-api-types/v10").GatewayMessageReactionAddDispatchData} data - */ -async function addReaction(data) { - const user = data.member?.user - assert.ok(user && user.username) - // TODO: should add my own sent messages to event_message so they can be reacted to? - const parentID = db.prepare("SELECT event_id FROM event_message WHERE message_id = ? AND part = 0").pluck().get(data.message_id) // 0 = primary - if (!parentID) return // TODO: how to handle reactions for unbridged messages? is there anything I can do? - assert.equal(typeof parentID, "string") - const roomID = await createRoom.ensureRoom(data.channel_id) - const senderMxid = await registerUser.ensureSimJoined(user, roomID) - const eventID = api.sendEvent(roomID, "m.reaction", { - "m.relates_to": { - rel_type: "m.annotation", - event_id: parentID, - key: data.emoji.name - } - }, senderMxid) - return eventID -} - -module.exports.addReaction = addReaction diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js index 04b0998..a5fd0ef 100644 --- a/d2m/actions/register-user.js +++ b/d2m/actions/register-user.js @@ -24,25 +24,16 @@ async function createSim(user) { const mxid = "@" + localpart + ":cadence.moe" // Save chosen name in the database forever - // Making this database change right away so that in a concurrent registration, the 2nd registration will already have generated a different localpart because it can see this row when it generates db.prepare("INSERT INTO sim (discord_id, sim_name, localpart, mxid) VALUES (?, ?, ?, ?)").run(user.id, simName, localpart, mxid) // Register matrix user with that name - try { - await api.register(localpart) - } catch (e) { - // If user creation fails, manually undo the database change. Still isn't perfect, but should help. - // (A transaction would be preferable, but I don't think it's safe to leave transaction open across event loop ticks.) - db.prepare("DELETE FROM sim WHERE discord_id = ?").run(user.id) - throw e - } + await api.register(localpart) return mxid } /** * Ensure a sim is registered for the user. * If there is already a sim, use that one. If there isn't one yet, register a new sim. - * @param {import("discord-api-types/v10").APIUser} user * @returns mxid */ async function ensureSim(user) { @@ -58,7 +49,6 @@ async function ensureSim(user) { /** * Ensure a sim is registered for the user and is joined to the room. - * @param {import("discord-api-types/v10").APIUser} user * @returns mxid */ async function ensureSimJoined(user, roomID) { diff --git a/d2m/actions/send-message.js b/d2m/actions/send-message.js index fb181d2..630cf48 100644 --- a/d2m/actions/send-message.js +++ b/d2m/actions/send-message.js @@ -1,5 +1,8 @@ // @ts-check +const fetch = require("node-fetch").default +const reg = require("../../matrix/read-registration.js") + const passthrough = require("../../passthrough") const { discord, sync, db } = passthrough /** @type {import("../converters/message-to-event")} */ @@ -21,8 +24,7 @@ async function sendMessage(message) { if (!message.webhook_id) { senderMxid = await registerUser.ensureSimJoined(message.author, roomID) } - const eventID = await api.sendEvent(roomID, "m.room.message", event, senderMxid) - db.prepare("INSERT INTO event_message (event_id, message_id, part) VALUES (?, ?, ?)").run(eventID, message.id, 0) // 0 is primary, 1 is supporting + const eventID = api.sendEvent(roomID, "m.room.message", event, senderMxid) return eventID } diff --git a/d2m/converters/user-to-mxid.js b/d2m/converters/user-to-mxid.js index 89e47a4..35d9368 100644 --- a/d2m/converters/user-to-mxid.js +++ b/d2m/converters/user-to-mxid.js @@ -44,7 +44,6 @@ function* generateLocalpartAlternatives(preferences) { /** * Whole process for checking the database and generating the right sim name. - * It is very important this is not an async function: once the name has been chosen, the calling function should be able to immediately claim that name into the database in the same event loop tick. * @param {import("discord-api-types/v10").APIUser} user * @returns {string} */ diff --git a/d2m/converters/user-to-mxid.test.js b/d2m/converters/user-to-mxid.test.js index 8c4c430..4c721fc 100644 --- a/d2m/converters/user-to-mxid.test.js +++ b/d2m/converters/user-to-mxid.test.js @@ -31,7 +31,3 @@ test("user2name: adds number suffix if name is unavailable (new username format) test("user2name: uses ID if name becomes too short", t => { t.equal(userToSimName({username: "f***", discriminator: "0001", id: "9"}), "9") }) - -test("user2name: uses ID when name has only disallowed characters", t => { - t.equal(userToSimName({username: "!@#$%^&*", discriminator: "0001", id: "9"}), "9") -}) \ No newline at end of file diff --git a/d2m/discord-packets.js b/d2m/discord-packets.js index 3786393..0d16cdc 100644 --- a/d2m/discord-packets.js +++ b/d2m/discord-packets.js @@ -6,16 +6,15 @@ const DiscordTypes = require("discord-api-types/v10") const passthrough = require("../passthrough") const { sync } = passthrough +/** @type {typeof import("./event-dispatcher")} */ +const eventDispatcher = sync.require("./event-dispatcher") + const utils = { /** * @param {import("./discord-client")} client * @param {import("cloudstorm").IGatewayMessage} message */ onPacket(client, message) { - // requiring this later so that the client is already constructed by the time event-dispatcher is loaded - /** @type {typeof import("./event-dispatcher")} */ - const eventDispatcher = sync.require("./event-dispatcher") - if (message.t === "READY") { if (client.ready) return client.ready = true diff --git a/d2m/event-dispatcher.js b/d2m/event-dispatcher.js index eeee451..8539044 100644 --- a/d2m/event-dispatcher.js +++ b/d2m/event-dispatcher.js @@ -2,10 +2,11 @@ const {sync} = require("../passthrough") +/** @type {import("./actions/create-space")}) */ +const createSpace = sync.require("./actions/create-space") + /** @type {import("./actions/send-message")}) */ const sendMessage = sync.require("./actions/send-message") -/** @type {import("./actions/add-reaction")}) */ -const addReaction = sync.require("./actions/add-reaction") // Grab Discord events we care about for the bridge, check them, and pass them on @@ -24,8 +25,7 @@ module.exports = { * @param {import("discord-api-types/v10").GatewayMessageReactionAddDispatchData} data */ onReactionAdd(client, data) { - if (data.emoji.id !== null) return // TOOD: image emoji reactions console.log(data) - addReaction.addReaction(data) + return {} } } diff --git a/db/ooye.db b/db/ooye.db index 4408064..c9803f8 100644 Binary files a/db/ooye.db and b/db/ooye.db differ diff --git a/matrix/api.js b/matrix/api.js index dbc39bc..04b7cd1 100644 --- a/matrix/api.js +++ b/matrix/api.js @@ -28,7 +28,6 @@ function path(p, mxid) { * @returns {Promise} */ function register(username) { - console.log(`[api] register: ${username}`) return mreq.mreq("POST", "/client/v3/register", { type: "m.login.application_service", username @@ -39,7 +38,6 @@ function register(username) { * @returns {Promise} room ID */ async function createRoom(content) { - console.log(`[api] create room:`, content) /** @type {import("../types").R.RoomCreated} */ const root = await mreq.mreq("POST", "/client/v3/createRoom", content) return root.room_id @@ -76,7 +74,6 @@ function getAllState(roomID) { * @returns {Promise} event ID */ async function sendState(roomID, type, stateKey, content, mxid) { - console.log(`[api] state: ${roomID}: ${type}/${stateKey}`) assert.ok(type) assert.ok(stateKey) /** @type {import("../types").R.EventSent} */ @@ -85,7 +82,6 @@ async function sendState(roomID, type, stateKey, content, mxid) { } async function sendEvent(roomID, type, content, mxid) { - console.log(`[api] event to ${roomID} as ${mxid || "default sim"}`) /** @type {import("../types").R.EventSent} */ const root = await mreq.mreq("PUT", path(`/client/v3/rooms/${roomID}/send/${type}/${makeTxnId.makeTxnId()}`, mxid), content) return root.event_id diff --git a/matrix/mreq.js b/matrix/mreq.js index df34d91..6c4eaa3 100644 --- a/matrix/mreq.js +++ b/matrix/mreq.js @@ -11,12 +11,11 @@ const reg = sync.require("./read-registration.js") const baseUrl = "https://matrix.cadence.moe/_matrix" class MatrixServerError extends Error { - constructor(data, opts) { + constructor(data) { super(data.error || data.errcode) this.data = data /** @type {string} */ this.errcode = data.errcode - this.opts = opts } } @@ -39,7 +38,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) throw new MatrixServerError(root, opts) + if (!res.ok || root.errcode) throw new MatrixServerError(root) return root } diff --git a/matrix/read-registration.test.js b/matrix/read-registration.test.js deleted file mode 100644 index 9c7f828..0000000 --- a/matrix/read-registration.test.js +++ /dev/null @@ -1,11 +0,0 @@ -const {test} = require("supertape") -const assert = require("assert") -const reg = require("./read-registration") - -test("reg: has necessary parameters", t => { - const propertiesToCheck = ["sender_localpart", "id", "as_token", "namespace_prefix"] - t.deepEqual( - propertiesToCheck.filter(p => p in reg), - propertiesToCheck - ) -}) \ No newline at end of file diff --git a/test/test.js b/test/test.js index 4e01708..1068136 100644 --- a/test/test.js +++ b/test/test.js @@ -12,7 +12,6 @@ const sync = new HeatSync({watchFS: false}) Object.assign(passthrough, { config, sync, db }) -require("../matrix/read-registration.test") require("../d2m/actions/create-room.test") require("../d2m/converters/user-to-mxid.test") require("../matrix/api.test")