From 0caaa0940b594eedd45ca7893d8ba787d6a0fb9c Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Thu, 7 Sep 2023 11:53:10 +1200 Subject: [PATCH 1/2] allow slashes in state keys --- matrix/api.js | 3 ++- matrix/kstate.js | 9 +++++---- matrix/kstate.test.js | 20 ++++++++++++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/matrix/api.js b/matrix/api.js index 5bbafff..74357d4 100644 --- a/matrix/api.js +++ b/matrix/api.js @@ -121,7 +121,8 @@ async function sendState(roomID, type, stateKey, content, mxid) { assert.ok(type) assert.ok(typeof stateKey === "string") /** @type {Ty.R.EventSent} */ - const root = await mreq.mreq("PUT", path(`/client/v3/rooms/${roomID}/state/${type}/${stateKey}`, mxid), content) + // encodeURIComponent is necessary because state key can contain some special characters like / but you must encode them so they fit in a single component of the URI + const root = await mreq.mreq("PUT", path(`/client/v3/rooms/${roomID}/state/${type}/${encodeURIComponent(stateKey)}`, mxid), content) return root.event_id } diff --git a/matrix/kstate.js b/matrix/kstate.js index e840254..e37fb96 100644 --- a/matrix/kstate.js +++ b/matrix/kstate.js @@ -19,9 +19,10 @@ function kstateToState(kstate) { const events = [] kstateStripConditionals(kstate) for (const [k, content] of Object.entries(kstate)) { - const [type, state_key] = k.split("/") - assert.ok(typeof type === "string") - assert.ok(typeof state_key === "string") + const slashIndex = k.indexOf("/") + assert(slashIndex > 0) + const type = k.slice(0, slashIndex) + const state_key = k.slice(slashIndex + 1) events.push({type, state_key, content}) } return events @@ -43,7 +44,7 @@ function diffKState(actual, target) { const diff = {} // go through each key that it should have for (const key of Object.keys(target)) { - if (!key.includes("/")) throw new Error(`target kstate's key "${key}" does not contain a slash separator; if a blank state_key was intended, add a trailing slash to the kstate key.`) + if (!key.includes("/")) throw new Error(`target kstate's key "${key}" does not contain a slash separator; if a blank state_key was intended, add a trailing slash to the kstate key.\ncontext: ${JSON.stringify(target)}`) if (key === "m.room.power_levels/") { // Special handling for power levels, we want to deep merge the actual and target into the final state. diff --git a/matrix/kstate.test.js b/matrix/kstate.test.js index 11d5131..7ab52db 100644 --- a/matrix/kstate.test.js +++ b/matrix/kstate.test.js @@ -23,7 +23,8 @@ test("kstate strip: keeps true conditions while removing $if", t => { test("kstate2state: general", t => { t.deepEqual(kstateToState({ "m.room.name/": {name: "test name"}, - "m.room.member/@cadence:cadence.moe": {membership: "join"} + "m.room.member/@cadence:cadence.moe": {membership: "join"}, + "uk.half-shot.bridge/org.matrix.appservice-irc://irc/epicord.net/#general": {creator: "@cadence:cadence.moe"} }), [ { type: "m.room.name", @@ -38,6 +39,13 @@ test("kstate2state: general", t => { content: { membership: "join" } + }, + { + type: "uk.half-shot.bridge", + state_key: "org.matrix.appservice-irc://irc/epicord.net/#general", + content: { + creator: "@cadence:cadence.moe" + } } ]) }) @@ -57,10 +65,18 @@ test("state2kstate: general", t => { content: { membership: "join" } + }, + { + type: "uk.half-shot.bridge", + state_key: "org.matrix.appservice-irc://irc/epicord.net/#general", + content: { + creator: "@cadence:cadence.moe" + } } ]), { "m.room.name/": {name: "test name"}, - "m.room.member/@cadence:cadence.moe": {membership: "join"} + "m.room.member/@cadence:cadence.moe": {membership: "join"}, + "uk.half-shot.bridge/org.matrix.appservice-irc://irc/epicord.net/#general": {creator: "@cadence:cadence.moe"} }) }) From 0237d45c60e2a325892c00fed17fc1175374c107 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Thu, 7 Sep 2023 12:07:56 +1200 Subject: [PATCH 2/2] support uk.half-shot.bridge --- d2m/actions/create-room.js | 20 ++++++++++++++++++++ matrix/file.js | 1 + 2 files changed, 21 insertions(+) diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js index 30de4f3..e8284df 100644 --- a/d2m/actions/create-room.js +++ b/d2m/actions/create-room.js @@ -110,6 +110,23 @@ async function channelToKState(channel, guild) { }, "chat.schildi.hide_ui/read_receipts": { hidden: true + }, + [`uk.half-shot.bridge/moe.cadence.ooye://discord/${guild.id}/${channel.id}`]: { + bridgebot: `@${reg.sender_localpart}:${reg.ooye.server_name}`, + protocol: { + id: "discord", + displayname: "Discord" + }, + network: { + id: guild.id, + displayname: guild.name, + avatar_url: file.DISCORD_IMAGES_BASE + file.guildIcon(guild) + }, + channel: { + id: channel.id, + displayname: channel.name, + external_url: `https://discord.com/channels/${guild.id}/${channel.id}` + } } } @@ -295,6 +312,9 @@ async function _unbridgeRoom(channelID) { await api.sendState(roomID, "m.space.parent", spaceID, {}) await api.sendState(spaceID, "m.space.child", roomID, {}) + // remove declaration that the room is bridged + await api.sendState(roomID, "uk.half-shot.bridge", `moe.cadence.ooye://discord/${channel.guild_id}/${channel.id}`, {}) + // send a notification in the room await api.sendEvent(roomID, "m.room.message", { msgtype: "m.notice", diff --git a/matrix/file.js b/matrix/file.js index 7d74d5d..e431a36 100644 --- a/matrix/file.js +++ b/matrix/file.js @@ -99,6 +99,7 @@ function sticker(sticker) { return `/stickers/${sticker.id}.${ext}` } +module.exports.DISCORD_IMAGES_BASE = DISCORD_IMAGES_BASE module.exports.guildIcon = guildIcon module.exports.userAvatar = userAvatar module.exports.memberAvatar = memberAvatar