workaround synapse bug that would make broken PLs
This commit is contained in:
		
							parent
							
								
									8d536d5ef2
								
							
						
					
					
						commit
						a8fab062a4
					
				
					 4 changed files with 72 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -95,6 +95,11 @@ async function channelToKState(channel, guild) {
 | 
			
		|||
				type: "m.room_membership",
 | 
			
		||||
				room_id: spaceID
 | 
			
		||||
			}]
 | 
			
		||||
		},
 | 
			
		||||
		"m.room.power_levels/": {
 | 
			
		||||
			events: {
 | 
			
		||||
				"m.room.avatar": 0
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -114,24 +119,56 @@ async function createRoom(channel, guild, spaceID, kstate) {
 | 
			
		|||
	if (channel.type === DiscordTypes.ChannelType.PublicThread) threadParent = channel.parent_id
 | 
			
		||||
	const invite = threadParent ? [] : ["@cadence:cadence.moe"] // TODO
 | 
			
		||||
 | 
			
		||||
	const [convertedName, convertedTopic] = convertNameAndTopic(channel, guild, null)
 | 
			
		||||
	const roomID = await api.createRoom({
 | 
			
		||||
		name: convertedName,
 | 
			
		||||
		topic: convertedTopic,
 | 
			
		||||
		preset: "private_chat",
 | 
			
		||||
		visibility: "private",
 | 
			
		||||
		invite,
 | 
			
		||||
		initial_state: ks.kstateToState(kstate)
 | 
			
		||||
	const roomID = await postApplyPowerLevels(kstate, async kstate => {
 | 
			
		||||
		const [convertedName, convertedTopic] = convertNameAndTopic(channel, guild, null)
 | 
			
		||||
		const roomID = await api.createRoom({
 | 
			
		||||
			name: convertedName,
 | 
			
		||||
			topic: convertedTopic,
 | 
			
		||||
			preset: "private_chat",
 | 
			
		||||
			visibility: "private",
 | 
			
		||||
			invite,
 | 
			
		||||
			initial_state: ks.kstateToState(kstate)
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		db.prepare("INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent) VALUES (?, ?, ?, NULL, ?)").run(channel.id, roomID, channel.name, threadParent)
 | 
			
		||||
 | 
			
		||||
		return roomID
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	db.prepare("INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent) VALUES (?, ?, ?, NULL, ?)").run(channel.id, roomID, channel.name, threadParent)
 | 
			
		||||
 | 
			
		||||
	// Put the newly created child into the space
 | 
			
		||||
	// Put the newly created child into the space, no need to await this
 | 
			
		||||
	_syncSpaceMember(channel, spaceID, roomID)
 | 
			
		||||
 | 
			
		||||
	return roomID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handling power levels separately. The spec doesn't specify what happens, Dendrite differs,
 | 
			
		||||
 * and Synapse does an absolutely insane *shallow merge* of what I provide on top of what it creates.
 | 
			
		||||
 * We don't want the `events` key to be overridden completely.
 | 
			
		||||
 * https://github.com/matrix-org/synapse/blob/develop/synapse/handlers/room.py#L1170-L1210
 | 
			
		||||
 * https://github.com/matrix-org/matrix-spec/issues/492
 | 
			
		||||
 * @param {any} kstate
 | 
			
		||||
 * @param {(_: any) => Promise<string>} callback must return room ID
 | 
			
		||||
 * @returns {Promise<string>} room ID
 | 
			
		||||
 */
 | 
			
		||||
async function postApplyPowerLevels(kstate, callback) {
 | 
			
		||||
	const powerLevelContent = kstate["m.room.power_levels/"]
 | 
			
		||||
	const kstateWithoutPowerLevels = {...kstate}
 | 
			
		||||
	delete kstateWithoutPowerLevels["m.room.power_levels/"]
 | 
			
		||||
 | 
			
		||||
	/** @type {string} */
 | 
			
		||||
	const roomID = await callback(kstateWithoutPowerLevels)
 | 
			
		||||
 | 
			
		||||
	// Now *really* apply the power level overrides on top of what Synapse *really* set
 | 
			
		||||
	if (powerLevelContent) {
 | 
			
		||||
		const newRoomKState = await roomToKState(roomID)
 | 
			
		||||
		const newRoomPowerLevelsDiff = ks.diffKState(newRoomKState, {"m.room.power_levels/": powerLevelContent})
 | 
			
		||||
		await applyKStateDiffToRoom(roomID, newRoomPowerLevelsDiff)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return roomID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {DiscordTypes.APIGuildChannel} channel
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -290,5 +327,6 @@ module.exports.createAllForGuild = createAllForGuild
 | 
			
		|||
module.exports.channelToKState = channelToKState
 | 
			
		||||
module.exports.roomToKState = roomToKState
 | 
			
		||||
module.exports.applyKStateDiffToRoom = applyKStateDiffToRoom
 | 
			
		||||
module.exports.postApplyPowerLevels = postApplyPowerLevels
 | 
			
		||||
module.exports._convertNameAndTopic = convertNameAndTopic
 | 
			
		||||
module.exports._unbridgeRoom = _unbridgeRoom
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,23 +21,24 @@ const ks = sync.require("../../matrix/kstate")
 | 
			
		|||
async function createSpace(guild, kstate) {
 | 
			
		||||
	const name = kstate["m.room.name/"].name
 | 
			
		||||
	const topic = kstate["m.room.topic/"]?.topic || undefined
 | 
			
		||||
 | 
			
		||||
	assert(name)
 | 
			
		||||
 | 
			
		||||
	const roomID = await api.createRoom({
 | 
			
		||||
		name,
 | 
			
		||||
		preset: "private_chat", // cannot join space unless invited
 | 
			
		||||
		visibility: "private",
 | 
			
		||||
		power_level_content_override: {
 | 
			
		||||
			events_default: 100, // space can only be managed by bridge
 | 
			
		||||
			invite: 0 // any existing member can invite others
 | 
			
		||||
		},
 | 
			
		||||
		invite: ["@cadence:cadence.moe"], // TODO
 | 
			
		||||
		topic,
 | 
			
		||||
		creation_content: {
 | 
			
		||||
			type: "m.space"
 | 
			
		||||
		},
 | 
			
		||||
		initial_state: ks.kstateToState(kstate)
 | 
			
		||||
	const roomID = await createRoom.postApplyPowerLevels(kstate, async kstate => {
 | 
			
		||||
		return api.createRoom({
 | 
			
		||||
			name,
 | 
			
		||||
			preset: "private_chat", // cannot join space unless invited
 | 
			
		||||
			visibility: "private",
 | 
			
		||||
			power_level_content_override: {
 | 
			
		||||
				events_default: 100, // space can only be managed by bridge
 | 
			
		||||
				invite: 0 // any existing member can invite others
 | 
			
		||||
			},
 | 
			
		||||
			invite: ["@cadence:cadence.moe"], // TODO
 | 
			
		||||
			topic,
 | 
			
		||||
			creation_content: {
 | 
			
		||||
				type: "m.space"
 | 
			
		||||
			},
 | 
			
		||||
			initial_state: ks.kstateToState(kstate)
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
	db.prepare("INSERT INTO guild_space (guild_id, space_id) VALUES (?, ?)").run(guild.id, roomID)
 | 
			
		||||
	return roomID
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,10 +47,8 @@ function diffKState(actual, 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.
 | 
			
		||||
			console.log(actual[key])
 | 
			
		||||
			if (!(key in actual)) throw new Error(`want to apply a power levels diff, but original power level data is missing\nstarted with:  ${JSON.stringify(actual)}\nwant to apply: ${JSON.stringify(target)}`)
 | 
			
		||||
			const temp = mixin({}, actual[key], target[key])
 | 
			
		||||
			console.log(actual[key])
 | 
			
		||||
			console.log(temp)
 | 
			
		||||
			try {
 | 
			
		||||
				assert.deepEqual(actual[key], temp)
 | 
			
		||||
			} catch (e) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ module.exports = {
 | 
			
		|||
			"m.room.guest_access/": {guest_access: "can_join"},
 | 
			
		||||
			"m.room.history_visibility/": {history_visibility: "invited"},
 | 
			
		||||
			"m.space.parent/!jjWAGMeQdNrVZSSfvz:cadence.moe": {
 | 
			
		||||
				via: ["cadence.moe"], // TODO: put the proper server here
 | 
			
		||||
				via: ["cadence.moe"],
 | 
			
		||||
				canonical: true
 | 
			
		||||
			},
 | 
			
		||||
			"m.room.join_rules/": {
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +40,11 @@ module.exports = {
 | 
			
		|||
			"m.room.avatar/": {
 | 
			
		||||
				discord_path: "/icons/112760669178241024/a_f83622e09ead74f0c5c527fe241f8f8c.png?size=1024",
 | 
			
		||||
				url: "mxc://cadence.moe/zKXGZhmImMHuGQZWJEFKJbsF"
 | 
			
		||||
			},
 | 
			
		||||
			"m.room.power_levels/": {
 | 
			
		||||
				events: {
 | 
			
		||||
					"m.room.avatar": 0
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue