Compare commits
	
		
			6 commits
		
	
	
		
			16309f26b3
			...
			10d14bbdaa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 10d14bbdaa | |||
| 677d899a92 | |||
| 9492137ca6 | |||
| 6aa2bfad13 | |||
| fc8d400b7d | |||
| f1313db028 | 
					 6 changed files with 17 additions and 108 deletions
				
			
		| 
						 | 
					@ -1,9 +0,0 @@
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	"compilerOptions": {
 | 
					 | 
				
			||||||
		"target": "es2024",
 | 
					 | 
				
			||||||
		"module": "nodenext",
 | 
					 | 
				
			||||||
		"strict": true,
 | 
					 | 
				
			||||||
		"noImplicitAny": false,
 | 
					 | 
				
			||||||
		"useUnknownInCatchVariables": false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,6 @@ async function attachmentToEvent(mentions, attachment) {
 | 
				
			||||||
 * - alwaysReturnFormattedBody: false - formatted_body will be skipped if it is the same as body because the message is plaintext. if you want the formatted_body to be returned anyway, for example to merge it with another message, then set this to true.
 | 
					 * - alwaysReturnFormattedBody: false - formatted_body will be skipped if it is the same as body because the message is plaintext. if you want the formatted_body to be returned anyway, for example to merge it with another message, then set this to true.
 | 
				
			||||||
 * - scanTextForMentions: true - needs to be set to false when converting forwarded messages etc which may be from a different channel that can't be scanned.
 | 
					 * - scanTextForMentions: true - needs to be set to false when converting forwarded messages etc which may be from a different channel that can't be scanned.
 | 
				
			||||||
 * @param {{api: import("../../matrix/api"), snow?: import("snowtransfer").SnowTransfer}} di simple-as-nails dependency injection for the matrix API
 | 
					 * @param {{api: import("../../matrix/api"), snow?: import("snowtransfer").SnowTransfer}} di simple-as-nails dependency injection for the matrix API
 | 
				
			||||||
 * @returns {Promise<{$type: string, $sender?: string, [x: string]: any}[]>}
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
async function messageToEvent(message, guild, options = {}, di) {
 | 
					async function messageToEvent(message, guild, options = {}, di) {
 | 
				
			||||||
	const events = []
 | 
						const events = []
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,11 +22,7 @@ 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 (Array.isArray(entry[1])) {
 | 
							if (entry[1] != undefined) {
 | 
				
			||||||
			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])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -66,14 +62,11 @@ 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) {
 | 
				
			||||||
	/** @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), {})
 | 
				
			||||||
	return root.room_id
 | 
						return root.room_id
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/types.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								src/types.d.ts
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -149,14 +149,6 @@ export namespace Event {
 | 
				
			||||||
		prev_content?: any
 | 
							prev_content?: any
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export type 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
 | 
				
			||||||
| 
						 | 
					@ -353,7 +345,7 @@ export namespace R {
 | 
				
			||||||
	export type Hierarchy = {
 | 
						export type Hierarchy = {
 | 
				
			||||||
		avatar_url?: string
 | 
							avatar_url?: string
 | 
				
			||||||
		canonical_alias?: string
 | 
							canonical_alias?: string
 | 
				
			||||||
		children_state: Event.StrippedChildStateEvent[]
 | 
							children_state: {}
 | 
				
			||||||
		guest_can_join: boolean
 | 
							guest_can_join: boolean
 | 
				
			||||||
		join_rule?: string
 | 
							join_rule?: string
 | 
				
			||||||
		name?: string
 | 
							name?: string
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,15 +133,11 @@ as.router.post("/api/link-space", defineEventHandler(async event => {
 | 
				
			||||||
	const existing = select("guild_space", "guild_id", {}, "WHERE guild_id = ? OR space_id = ?").get(guildID, spaceID)
 | 
						const existing = select("guild_space", "guild_id", {}, "WHERE guild_id = ? OR space_id = ?").get(guildID, spaceID)
 | 
				
			||||||
	if (existing) throw createError({status: 400, message: "Bad Request", data: `Guild ID ${guildID} or space ID ${spaceID} are already bridged and cannot be reused`})
 | 
						if (existing) throw createError({status: 400, message: "Bad Request", data: `Guild ID ${guildID} or space ID ${spaceID} are already bridged and cannot be reused`})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const inviteSender = select("invite", "mxid", {mxid: session.data.mxid, room_id: spaceID}).pluck().get()
 | 
					 | 
				
			||||||
	const inviteSenderServer = inviteSender?.match(/:(.*)/)?.[1]
 | 
					 | 
				
			||||||
	const via = [inviteSenderServer || ""]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check space exists and bridge is joined
 | 
						// Check space exists and bridge is joined
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
		await api.joinRoom(parsedBody.space_id, null, via)
 | 
							await api.joinRoom(parsedBody.space_id)
 | 
				
			||||||
	} catch (e) {
 | 
						} catch (e) {
 | 
				
			||||||
		throw createError({status: 400, message: "Unable To Join", data: `Unable to join the requested Matrix space. Please invite the bridge to the space 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
 | 
				
			||||||
| 
						 | 
					@ -189,33 +185,19 @@ 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 foundRoom = false
 | 
						let found = false
 | 
				
			||||||
	/** @type {string[]?} */
 | 
					 | 
				
			||||||
	let foundVia = null
 | 
					 | 
				
			||||||
	for await (const room of api.generateFullHierarchy(spaceID)) {
 | 
						for await (const room of api.generateFullHierarchy(spaceID)) {
 | 
				
			||||||
		// 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 (const state of room.children_state) {
 | 
					 | 
				
			||||||
			if (state.type === "m.space.child" && state.state_key === parsedBody.matrix) {
 | 
					 | 
				
			||||||
				foundVia = state.content.via
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// When finding a room during iteration, see if it was the requested room (to confirm that the room is in the space)
 | 
					 | 
				
			||||||
		if (room.room_id === parsedBody.matrix && !room.room_type) {
 | 
							if (room.room_id === parsedBody.matrix && !room.room_type) {
 | 
				
			||||||
			foundRoom = true
 | 
								found = true
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (foundRoom && foundVia) break
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!foundRoom) throw createError({status: 400, message: "Bad Request", data: "Matrix room needs to be part of the bridged space"})
 | 
						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
 | 
						// Check room exists and bridge is joined
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
		await api.joinRoom(parsedBody.matrix, null, foundVia)
 | 
							await api.joinRoom(parsedBody.matrix)
 | 
				
			||||||
	} catch (e) {
 | 
						} catch (e) {
 | 
				
			||||||
		if (!foundVia) {
 | 
					 | 
				
			||||||
			throw createError({status: 400, 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}`})
 | 
							throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ test("web link space: check that OOYE is joined", async t => {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}))
 | 
						}))
 | 
				
			||||||
	t.equal(error.data, "Unable to join the requested Matrix space. Please invite the bridge to the space and try again. (Server said: M_FORBIDDEN - not allowed to join I guess)")
 | 
						t.equal(error.data, "M_FORBIDDEN - not allowed to join I guess")
 | 
				
			||||||
	t.equal(called, 1)
 | 
						t.equal(called, 1)
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,7 +360,7 @@ test("web link room: check that room is part of space (not in hierarchy)", async
 | 
				
			||||||
	t.equal(called, 1)
 | 
						t.equal(called, 1)
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test("web link room: check that bridge can join room (notices lack of via and asks for invite instead)", async t => {
 | 
					test("web link room: check that bridge can join room", async t => {
 | 
				
			||||||
	let called = 0
 | 
						let called = 0
 | 
				
			||||||
	const [error] = await tryToCatch(() => router.test("post", "/api/link", {
 | 
						const [error] = await tryToCatch(() => router.test("post", "/api/link", {
 | 
				
			||||||
		sessionData: {
 | 
							sessionData: {
 | 
				
			||||||
| 
						 | 
					@ -381,55 +381,7 @@ test("web link room: check that bridge can join room (notices lack of via and as
 | 
				
			||||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
									t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
				
			||||||
				yield {
 | 
									yield {
 | 
				
			||||||
					room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
										room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
				
			||||||
					children_state: [],
 | 
										children_state: {},
 | 
				
			||||||
					guest_can_join: false,
 | 
					 | 
				
			||||||
					num_joined_members: 2
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				/* c8 ignore next */
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}))
 | 
					 | 
				
			||||||
	t.equal(error.data, "Unable to join the requested Matrix room. Please invite the bridge to the room and try again. (Server said: M_FORBIDDEN - not allowed to join I guess)")
 | 
					 | 
				
			||||||
	t.equal(called, 2)
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test("web link room: check that bridge can join room (uses via for join attempt)", async t => {
 | 
					 | 
				
			||||||
	let called = 0
 | 
					 | 
				
			||||||
	const [error] = await tryToCatch(() => router.test("post", "/api/link", {
 | 
					 | 
				
			||||||
		sessionData: {
 | 
					 | 
				
			||||||
			managedGuilds: ["665289423482519565"]
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		body: {
 | 
					 | 
				
			||||||
			discord: "665310973967597573",
 | 
					 | 
				
			||||||
			matrix: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
					 | 
				
			||||||
			guild_id: "665289423482519565"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		api: {
 | 
					 | 
				
			||||||
			async joinRoom(roomID, _, via) {
 | 
					 | 
				
			||||||
				called++
 | 
					 | 
				
			||||||
				t.deepEqual(via, ["cadence.moe", "hashi.re"])
 | 
					 | 
				
			||||||
				throw new MatrixServerError({errcode: "M_FORBIDDEN", error: "not allowed to join I guess"})
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			async *generateFullHierarchy(spaceID) {
 | 
					 | 
				
			||||||
				called++
 | 
					 | 
				
			||||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
					 | 
				
			||||||
				yield {
 | 
					 | 
				
			||||||
					room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
					 | 
				
			||||||
					children_state: [],
 | 
					 | 
				
			||||||
					guest_can_join: false,
 | 
					 | 
				
			||||||
					num_joined_members: 2
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				yield {
 | 
					 | 
				
			||||||
					room_id: "!zTMspHVUBhFLLSdmnS:cadence.moe",
 | 
					 | 
				
			||||||
					children_state: [{
 | 
					 | 
				
			||||||
						type: "m.space.child",
 | 
					 | 
				
			||||||
						state_key: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
					 | 
				
			||||||
						sender: "@elliu:hashi.re",
 | 
					 | 
				
			||||||
						content: {
 | 
					 | 
				
			||||||
							via: ["cadence.moe", "hashi.re"]
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
						origin_server_ts: 0
 | 
					 | 
				
			||||||
					}],
 | 
					 | 
				
			||||||
					guest_can_join: false,
 | 
										guest_can_join: false,
 | 
				
			||||||
					num_joined_members: 2
 | 
										num_joined_members: 2
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -462,7 +414,7 @@ test("web link room: check that bridge has PL 100 in target room (event missing)
 | 
				
			||||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
									t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
				
			||||||
				yield {
 | 
									yield {
 | 
				
			||||||
					room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
										room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
				
			||||||
					children_state: [],
 | 
										children_state: {},
 | 
				
			||||||
					guest_can_join: false,
 | 
										guest_can_join: false,
 | 
				
			||||||
					num_joined_members: 2
 | 
										num_joined_members: 2
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -502,7 +454,7 @@ test("web link room: check that bridge has PL 100 in target room (users default)
 | 
				
			||||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
									t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
				
			||||||
				yield {
 | 
									yield {
 | 
				
			||||||
					room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
										room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
				
			||||||
					children_state: [],
 | 
										children_state: {},
 | 
				
			||||||
					guest_can_join: false,
 | 
										guest_can_join: false,
 | 
				
			||||||
					num_joined_members: 2
 | 
										num_joined_members: 2
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -542,7 +494,7 @@ test("web link room: successfully calls createRoom", async t => {
 | 
				
			||||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
									t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
				
			||||||
				yield {
 | 
									yield {
 | 
				
			||||||
					room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
										room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
				
			||||||
					children_state: [],
 | 
										children_state: {},
 | 
				
			||||||
					guest_can_join: false,
 | 
										guest_can_join: false,
 | 
				
			||||||
					num_joined_members: 2
 | 
										num_joined_members: 2
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue