From 131d4b5a21a7e07ba38744cee12074538ac2064e Mon Sep 17 00:00:00 2001 From: Elliu Date: Thu, 21 Aug 2025 21:38:34 +0900 Subject: [PATCH] Fix matrix api joinRoom() for remote rooms When using self-service mode and trying to link with a remote matrix room (room not in the same HS as the bridge user), then we need to add the "via" HSs to join the room with, or else it fails. We get it from the "m.space.child" in the "children_state" of the space hierarchy. It seems like the "via" information can also be stored in the "m.space.parent" in the states of the room, but hopefully this shouldn't be needed in sane implementations --- src/matrix/api.js | 4 ++-- src/web/routes/link.js | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/matrix/api.js b/src/matrix/api.js index 41af63f..355cc0b 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -64,9 +64,9 @@ async function createRoom(content) { /** * @returns {Promise} room ID */ -async function joinRoom(roomIDOrAlias, mxid) { +async function joinRoom(roomIDOrAlias, mxid, via) { /** @type {Ty.R.RoomJoined} */ - const root = await mreq.mreq("POST", path(`/client/v3/join/${roomIDOrAlias}`, mxid), {}) + const root = await mreq.mreq("POST", path(`/client/v3/join/${roomIDOrAlias}`, mxid, via), {}) return root.room_id } diff --git a/src/web/routes/link.js b/src/web/routes/link.js index c5f404e..7654adf 100644 --- a/src/web/routes/link.js +++ b/src/web/routes/link.js @@ -77,7 +77,7 @@ as.router.post("/api/link-space", defineEventHandler(async event => { // Check space exists and bridge is joined try { - await api.joinRoom(parsedBody.space_id) + await api.joinRoom(parsedBody.space_id, null, via) } catch (e) { throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`}) } @@ -135,19 +135,31 @@ as.router.post("/api/link", defineEventHandler(async event => { // Check room is part of the guild's space let found = false + let via = undefined for await (const room of api.generateFullHierarchy(spaceID)) { - if (room.room_id === parsedBody.matrix && !room.room_type) { + if (via === undefined && room.room_type === "m.space") { + for (state of room.children_state) { + if (state.state_key === parsedBody.matrix){ + via = {via: state.content.via} + if (found === true) + break + } + } + } + + if (!found && room.room_id === parsedBody.matrix && !room.room_type) { found = true - break + if (via !== undefined) + break } } if (!found) throw createError({status: 400, message: "Bad Request", data: "Matrix room needs to be part of the bridged space"}) // Check room exists and bridge is joined try { - await api.joinRoom(parsedBody.matrix) + await api.joinRoom(parsedBody.matrix, null, via ?? {}) } catch (e) { - throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`}) + throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}${via === null ? " (hint: couln't find a \"via\" in the space children_state for this room in order to help joining this room)" : ""}`}) } // Check bridge has PL 100