forked from cadence/out-of-your-element
		
	Check hierarchy instead of m.space.child
This commit is contained in:
		
							parent
							
								
									efaa59ca92
								
							
						
					
					
						commit
						50a047249b
					
				
					 4 changed files with 84 additions and 82 deletions
				
			
		| 
						 | 
				
			
			@ -129,16 +129,10 @@ async function _syncSpace(guild, shouldActuallySync) {
 | 
			
		|||
		// don't try to update rooms with custom avatars though
 | 
			
		||||
		const roomsWithCustomAvatars = select("channel_room", "room_id", {}, "WHERE custom_avatar IS NOT NULL").pluck().all()
 | 
			
		||||
 | 
			
		||||
		const state = await ks.kstateToState(spaceKState)
 | 
			
		||||
		const childRooms = state.filter(({type, state_key, content}) => {
 | 
			
		||||
			return type === "m.space.child" && "via" in content && !roomsWithCustomAvatars.includes(state_key)
 | 
			
		||||
		}).map(({state_key}) => state_key)
 | 
			
		||||
 | 
			
		||||
		for (const roomID of childRooms) {
 | 
			
		||||
			const avatarEventContent = await api.getStateEvent(roomID, "m.room.avatar", "")
 | 
			
		||||
			if (avatarEventContent.url !== newAvatarState.url) {
 | 
			
		||||
				await api.sendState(roomID, "m.room.avatar", "", newAvatarState)
 | 
			
		||||
			}
 | 
			
		||||
		for await (const room of api.generateFullHierarchy(spaceID)) {
 | 
			
		||||
			if (room.avatar_url === newAvatarState.url) continue
 | 
			
		||||
			if (roomsWithCustomAvatars.includes(room.room_id)) continue
 | 
			
		||||
			await api.sendState(room.room_id, "m.room.avatar", "", newAvatarState)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -181,6 +181,23 @@ async function getFullHierarchy(roomID) {
 | 
			
		|||
	return rooms
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Like `getFullHierarchy` but reveals a page at a time through an async iterator.
 | 
			
		||||
 * @param {string} roomID
 | 
			
		||||
 */
 | 
			
		||||
async function* generateFullHierarchy(roomID) {
 | 
			
		||||
	/** @type {string | undefined} */
 | 
			
		||||
	let nextBatch = undefined
 | 
			
		||||
	do {
 | 
			
		||||
		/** @type {Ty.HierarchyPagination<Ty.R.Hierarchy>} */
 | 
			
		||||
		const res = await getHierarchy(roomID, {from: nextBatch})
 | 
			
		||||
		for (const room of res.rooms) {
 | 
			
		||||
			yield room
 | 
			
		||||
		}
 | 
			
		||||
		nextBatch = res.next_batch
 | 
			
		||||
	} while (nextBatch)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} roomID
 | 
			
		||||
 * @param {string} eventID
 | 
			
		||||
| 
						 | 
				
			
			@ -442,6 +459,7 @@ module.exports.getJoinedMembers = getJoinedMembers
 | 
			
		|||
module.exports.getMembers = getMembers
 | 
			
		||||
module.exports.getHierarchy = getHierarchy
 | 
			
		||||
module.exports.getFullHierarchy = getFullHierarchy
 | 
			
		||||
module.exports.generateFullHierarchy = generateFullHierarchy
 | 
			
		||||
module.exports.getRelations = getRelations
 | 
			
		||||
module.exports.getFullRelations = getFullRelations
 | 
			
		||||
module.exports.sendState = sendState
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -134,12 +134,14 @@ 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`})
 | 
			
		||||
 | 
			
		||||
	// Check room is part of the guild's space
 | 
			
		||||
	/** @type {Ty.Event.M_Space_Child?} */
 | 
			
		||||
	let spaceChildEvent = null
 | 
			
		||||
	try {
 | 
			
		||||
		spaceChildEvent = await api.getStateEvent(spaceID, "m.space.child", parsedBody.matrix)
 | 
			
		||||
	} catch (e) {}
 | 
			
		||||
	if (!Array.isArray(spaceChildEvent?.via)) throw createError({status: 400, message: "Bad Request", data: "Matrix room needs to be part of the bridged space"})
 | 
			
		||||
	let found = false
 | 
			
		||||
	for await (const room of api.generateFullHierarchy(spaceID)) {
 | 
			
		||||
		if (room.room_id === parsedBody.matrix && !room.room_type) {
 | 
			
		||||
			found = true
 | 
			
		||||
			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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -233,13 +233,7 @@ test("web link space: successfully adds entry to database and loads page", async
 | 
			
		|||
			mxid: "@cadence:cadence.moe"
 | 
			
		||||
		},
 | 
			
		||||
		api: {
 | 
			
		||||
			async getStateEvent(roomID, type, key) {
 | 
			
		||||
				return {}
 | 
			
		||||
			},
 | 
			
		||||
			async getMembers(roomID, membership) {
 | 
			
		||||
				return {chunk: []}
 | 
			
		||||
			},
 | 
			
		||||
			async getFullHierarchy(roomID) {
 | 
			
		||||
			async getFullHierarchy(spaceID) {
 | 
			
		||||
				return []
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -344,7 +338,7 @@ test("web link room: checks the autocreate setting if the space doesn't exist ye
 | 
			
		|||
	t.equal(called, 1)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("web link room: check that room is part of space (event missing)", async t => {
 | 
			
		||||
test("web link room: check that room is part of space (not in hierarchy)", async t => {
 | 
			
		||||
	let called = 0
 | 
			
		||||
	const [error] = await tryToCatch(() => router.test("post", "/api/link", {
 | 
			
		||||
		sessionData: {
 | 
			
		||||
| 
						 | 
				
			
			@ -356,37 +350,9 @@ test("web link room: check that room is part of space (event missing)", async t
 | 
			
		|||
			guild_id: "665289423482519565"
 | 
			
		||||
		},
 | 
			
		||||
		api: {
 | 
			
		||||
			async getStateEvent(roomID, type, key) {
 | 
			
		||||
			async *generateFullHierarchy(spaceID) {
 | 
			
		||||
				called++
 | 
			
		||||
				t.equal(roomID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
				t.equal(type, "m.space.child")
 | 
			
		||||
				t.equal(key, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
				throw new MatrixServerError({errcode: "M_NOT_FOUND", error: "what if I told you there was no such thing as a space"})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}))
 | 
			
		||||
	t.equal(error.data, "Matrix room needs to be part of the bridged space")
 | 
			
		||||
	t.equal(called, 1)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("web link room: check that room is part of space (event empty)", 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 getStateEvent(roomID, type, key) {
 | 
			
		||||
				called++
 | 
			
		||||
				t.equal(roomID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
				t.equal(type, "m.space.child")
 | 
			
		||||
				t.equal(key, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
				return {}
 | 
			
		||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}))
 | 
			
		||||
| 
						 | 
				
			
			@ -410,12 +376,16 @@ test("web link room: check that bridge can join room", async t => {
 | 
			
		|||
				called++
 | 
			
		||||
				throw new MatrixServerError({errcode: "M_FORBIDDEN", error: "not allowed to join I guess"})
 | 
			
		||||
			},
 | 
			
		||||
			async getStateEvent(roomID, type, key) {
 | 
			
		||||
			async *generateFullHierarchy(spaceID) {
 | 
			
		||||
				called++
 | 
			
		||||
				t.equal(type, "m.space.child")
 | 
			
		||||
				t.equal(roomID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
				t.equal(key, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
				return {via: ["cadence.moe"]}
 | 
			
		||||
				t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
				yield {
 | 
			
		||||
					room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
 | 
			
		||||
					children_state: {},
 | 
			
		||||
					guest_can_join: false,
 | 
			
		||||
					num_joined_members: 2
 | 
			
		||||
				}
 | 
			
		||||
				/* c8 ignore next */
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}))
 | 
			
		||||
| 
						 | 
				
			
			@ -439,17 +409,23 @@ test("web link room: check that bridge has PL 100 in target room (event missing)
 | 
			
		|||
				called++
 | 
			
		||||
				return roomID
 | 
			
		||||
			},
 | 
			
		||||
			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
 | 
			
		||||
				}
 | 
			
		||||
				/* c8 ignore next */
 | 
			
		||||
			},
 | 
			
		||||
			async getStateEvent(roomID, type, key) {
 | 
			
		||||
				called++
 | 
			
		||||
				if (type === "m.space.child") {
 | 
			
		||||
					t.equal(roomID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
					t.equal(key, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
					return {via: ["cadence.moe"]}
 | 
			
		||||
				} else if (type === "m.room.power_levels") {
 | 
			
		||||
					t.equal(roomID, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
					t.equal(key, "")
 | 
			
		||||
					throw new MatrixServerError({errcode: "M_NOT_FOUND", error: "what if I told you there's no such thing as power levels"})
 | 
			
		||||
				}
 | 
			
		||||
				t.equal(roomID, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
				t.equal(type, "m.room.power_levels")
 | 
			
		||||
				t.equal(key, "")
 | 
			
		||||
				throw new MatrixServerError({errcode: "M_NOT_FOUND", error: "what if I told you there's no such thing as power levels"})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}))
 | 
			
		||||
| 
						 | 
				
			
			@ -473,17 +449,23 @@ test("web link room: check that bridge has PL 100 in target room (users default)
 | 
			
		|||
				called++
 | 
			
		||||
				return roomID
 | 
			
		||||
			},
 | 
			
		||||
			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
 | 
			
		||||
				}
 | 
			
		||||
				/* c8 ignore next */
 | 
			
		||||
			},
 | 
			
		||||
			async getStateEvent(roomID, type, key) {
 | 
			
		||||
				called++
 | 
			
		||||
				if (type === "m.space.child") {
 | 
			
		||||
					t.equal(roomID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
					t.equal(key, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
					return {via: ["cadence.moe"]}
 | 
			
		||||
				} else if (type === "m.room.power_levels") {
 | 
			
		||||
					t.equal(roomID, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
					t.equal(key, "")
 | 
			
		||||
					return {users_default: 50}
 | 
			
		||||
				}
 | 
			
		||||
				t.equal(roomID, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
				t.equal(type, "m.room.power_levels")
 | 
			
		||||
				t.equal(key, "")
 | 
			
		||||
				return {users_default: 50}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}))
 | 
			
		||||
| 
						 | 
				
			
			@ -507,17 +489,23 @@ test("web link room: successfully calls createRoom", async t => {
 | 
			
		|||
				called++
 | 
			
		||||
				return roomID
 | 
			
		||||
			},
 | 
			
		||||
			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
 | 
			
		||||
				}
 | 
			
		||||
				/* c8 ignore next */
 | 
			
		||||
			},
 | 
			
		||||
			async getStateEvent(roomID, type, key) {
 | 
			
		||||
				if (type === "m.room.power_levels") {
 | 
			
		||||
					called++
 | 
			
		||||
					t.equal(roomID, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
					t.equal(key, "")
 | 
			
		||||
					return {users: {"@_ooye_bot:cadence.moe": 100}}
 | 
			
		||||
				} else if (type === "m.space.child") {
 | 
			
		||||
					called++
 | 
			
		||||
					t.equal(roomID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
 | 
			
		||||
					t.equal(key, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
					return {via: ["cadence.moe"]}
 | 
			
		||||
				} else if (type === "m.room.name") {
 | 
			
		||||
					called++
 | 
			
		||||
					t.equal(roomID, "!NDbIqNpJyPvfKRnNcr:cadence.moe")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue