This commit is contained in:
Cadence Ember 2025-08-22 21:25:05 +12:00 committed by Elliu
parent 91d62e7b28
commit af79c96aeb
3 changed files with 36 additions and 19 deletions

View file

@ -22,7 +22,11 @@ function path(p, mxid, otherParams = {}) {
const u = new URL(p, "http://localhost") const u = new URL(p, "http://localhost")
if (mxid) u.searchParams.set("user_id", mxid) if (mxid) u.searchParams.set("user_id", mxid)
for (const entry of Object.entries(otherParams)) { for (const entry of Object.entries(otherParams)) {
if (entry[1] != undefined) { if (Array.isArray(entry[1])) {
for (const element of entry[1]) {
u.searchParams.append(entry[0], element)
}
} else if (entry[1] != undefined) {
u.searchParams.set(entry[0], entry[1]) u.searchParams.set(entry[0], entry[1])
} }
} }
@ -62,11 +66,14 @@ async function createRoom(content) {
} }
/** /**
* @param {string} roomIDOrAlias
* @param {string?} [mxid]
* @param {string[]?} [via]
* @returns {Promise<string>} room ID * @returns {Promise<string>} room ID
*/ */
async function joinRoom(roomIDOrAlias, mxid, via) { async function joinRoom(roomIDOrAlias, mxid, via) {
/** @type {Ty.R.RoomJoined} */ /** @type {Ty.R.RoomJoined} */
const root = await mreq.mreq("POST", path(`/client/v3/join/${roomIDOrAlias}`, mxid, via), {}) const root = await mreq.mreq("POST", path(`/client/v3/join/${roomIDOrAlias}`, mxid, {via}), {})
return root.room_id return root.room_id
} }

10
src/types.d.ts vendored
View file

@ -148,6 +148,14 @@ export namespace Event {
prev_content?: any prev_content?: any
} }
export type Outer_StrippedChildStateEvent = {
type: string
state_key: string
sender: string
origin_server_ts: number
content: any
}
export type M_Room_Message = { export type M_Room_Message = {
msgtype: "m.text" | "m.emote" msgtype: "m.text" | "m.emote"
body: string body: string
@ -344,7 +352,7 @@ export namespace R {
export type Hierarchy = { export type Hierarchy = {
avatar_url?: string avatar_url?: string
canonical_alias?: string canonical_alias?: string
children_state: {} children_state: Event.Outer_StrippedChildStateEvent[]
guest_can_join: boolean guest_can_join: boolean
join_rule?: string join_rule?: string
name?: string name?: string

View file

@ -134,32 +134,34 @@ as.router.post("/api/link", defineEventHandler(async event => {
if (row) throw createError({status: 400, message: "Bad Request", data: `Channel ID ${row.channel_id} or room ID ${parsedBody.matrix} are already bridged and cannot be reused`}) if (row) throw createError({status: 400, message: "Bad Request", data: `Channel ID ${row.channel_id} or room ID ${parsedBody.matrix} are already bridged and cannot be reused`})
// Check room is part of the guild's space // Check room is part of the guild's space
let found = false let foundRoom = false
let via = undefined /** @type {string[]?} */
let foundVia = null
for await (const room of api.generateFullHierarchy(spaceID)) { for await (const room of api.generateFullHierarchy(spaceID)) {
if (via === undefined && room.room_type === "m.space") { // When finding a space during iteration, look at space's children state, because we need a `via` to join the room (when we find it later)
for (state of room.children_state) { for (const state of room.children_state) {
if (state.state_key === parsedBody.matrix){ if (state.type === "m.space.child" && state.state_key === parsedBody.matrix) {
via = {via: state.content.via} foundVia = state.content.via
if (found === true)
break
}
} }
} }
if (!found && room.room_id === parsedBody.matrix && !room.room_type) { // When finding a room during iteration, see if it was the requested room (to confirm that the room is in the space)
found = true if (room.room_id === parsedBody.matrix && !room.room_type) {
if (via !== undefined) foundRoom = true
break
} }
if (foundRoom && foundVia) break
} }
if (!found) throw createError({status: 400, message: "Bad Request", data: "Matrix room needs to be part of the bridged space"}) if (!foundRoom) 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 // Check room exists and bridge is joined
try { try {
await api.joinRoom(parsedBody.matrix, null, via ?? {}) await api.joinRoom(parsedBody.matrix, null, foundVia)
} catch (e) { } catch (e) {
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)" : ""}`}) if (!foundVia) {
throw createError({status: 403, message: "Unable To Join", data: `Unable to join the requested Matrix room. Please invite the bridge to the room and try again. (Server said: ${e.errcode} - ${e.message})`})
}
throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`})
} }
// Check bridge has PL 100 // Check bridge has PL 100