should create guilds on-demand now
This commit is contained in:
		
							parent
							
								
									9263bdb754
								
							
						
					
					
						commit
						671f1300ba
					
				
					 3 changed files with 43 additions and 9 deletions
				
			
		| 
						 | 
					@ -12,6 +12,8 @@ const file = sync.require("../../matrix/file")
 | 
				
			||||||
const api = sync.require("../../matrix/api")
 | 
					const api = sync.require("../../matrix/api")
 | 
				
			||||||
/** @type {import("../../matrix/kstate")} */
 | 
					/** @type {import("../../matrix/kstate")} */
 | 
				
			||||||
const ks = sync.require("../../matrix/kstate")
 | 
					const ks = sync.require("../../matrix/kstate")
 | 
				
			||||||
 | 
					/** @type {import("./create-space")}) */
 | 
				
			||||||
 | 
					const createSpace = sync.require("./create-space") // watch out for the require loop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @type {Map<string, Promise<string>>} channel ID -> Promise<room ID> */
 | 
					/** @type {Map<string, Promise<string>>} channel ID -> Promise<room ID> */
 | 
				
			||||||
const inflightRoomCreate = new Map()
 | 
					const inflightRoomCreate = new Map()
 | 
				
			||||||
| 
						 | 
					@ -61,12 +63,12 @@ function convertNameAndTopic(channel, guild, customName) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Async because it may upload the guild icon to mxc.
 | 
					 * Async because it may create the guild and/or upload the guild icon to mxc.
 | 
				
			||||||
 * @param {DiscordTypes.APIGuildTextChannel | DiscordTypes.APIThreadChannel} channel
 | 
					 * @param {DiscordTypes.APIGuildTextChannel | DiscordTypes.APIThreadChannel} channel
 | 
				
			||||||
 * @param {DiscordTypes.APIGuild} guild
 | 
					 * @param {DiscordTypes.APIGuild} guild
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
async function channelToKState(channel, guild) {
 | 
					async function channelToKState(channel, guild) {
 | 
				
			||||||
	const spaceID = db.prepare("SELECT space_id FROM guild_space WHERE guild_id = ?").pluck().get(guild.id)
 | 
						const spaceID = await createSpace.ensureSpace(guild.id)
 | 
				
			||||||
	assert.ok(typeof spaceID === "string")
 | 
						assert.ok(typeof spaceID === "string")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const row = db.prepare("SELECT nick, custom_avatar FROM channel_room WHERE channel_id = ?").get(channel.id)
 | 
						const row = db.prepare("SELECT nick, custom_avatar FROM channel_room WHERE channel_id = ?").get(channel.id)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,9 @@ const createRoom = sync.require("./create-room")
 | 
				
			||||||
/** @type {import("../../matrix/kstate")} */
 | 
					/** @type {import("../../matrix/kstate")} */
 | 
				
			||||||
const ks = sync.require("../../matrix/kstate")
 | 
					const ks = sync.require("../../matrix/kstate")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @type {Map<string, Promise<string>>} guild ID -> Promise<space ID> */
 | 
				
			||||||
 | 
					const inflightSpaceCreate = new Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {import("discord-api-types/v10").RESTGetAPIGuildResult} guild
 | 
					 * @param {import("discord-api-types/v10").RESTGetAPIGuildResult} guild
 | 
				
			||||||
 * @param {any} kstate
 | 
					 * @param {any} kstate
 | 
				
			||||||
| 
						 | 
					@ -68,24 +71,43 @@ async function guildToKState(guild) {
 | 
				
			||||||
	return guildKState
 | 
						return guildKState
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Efficiently update space name, space avatar, and child room avatars. */
 | 
					/**
 | 
				
			||||||
async function syncSpace(guildID) {
 | 
					 * @param {string} guildID
 | 
				
			||||||
 | 
					 * @param {boolean} shouldActuallySync false if just need to ensure nspace exists (which is a quick database check),
 | 
				
			||||||
 | 
					 *                                     true if also want to efficiently sync space name, space avatar, and child room avatars
 | 
				
			||||||
 | 
					 * @returns {Promise<string>} room ID
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					async function _syncSpace(guildID, shouldActuallySync) {
 | 
				
			||||||
	/** @ts-ignore @type {DiscordTypes.APIGuild} */
 | 
						/** @ts-ignore @type {DiscordTypes.APIGuild} */
 | 
				
			||||||
	const guild = discord.guilds.get(guildID)
 | 
						const guild = discord.guilds.get(guildID)
 | 
				
			||||||
	assert.ok(guild)
 | 
						assert.ok(guild)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (inflightSpaceCreate.has(guildID)) {
 | 
				
			||||||
 | 
							await inflightSpaceCreate.get(guildID) // just waiting, and then doing a new db query afterwards, is the simplest way of doing it
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** @type {string?} */
 | 
						/** @type {string?} */
 | 
				
			||||||
	const spaceID = db.prepare("SELECT space_id from guild_space WHERE guild_id = ?").pluck().get(guildID)
 | 
						const spaceID = db.prepare("SELECT space_id from guild_space WHERE guild_id = ?").pluck().get(guildID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const guildKState = await guildToKState(guild)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!spaceID) {
 | 
						if (!spaceID) {
 | 
				
			||||||
		const spaceID = await createSpace(guild, guildKState)
 | 
							const creation = (async () => {
 | 
				
			||||||
		return spaceID // Naturally, the newly created space is already up to date, so we can always skip syncing here.
 | 
								const guildKState = await guildToKState(guild)
 | 
				
			||||||
 | 
								const spaceID = await createSpace(guild, guildKState)
 | 
				
			||||||
 | 
								inflightSpaceCreate.delete(guildID)
 | 
				
			||||||
 | 
								return spaceID
 | 
				
			||||||
 | 
							})()
 | 
				
			||||||
 | 
							inflightSpaceCreate.set(guildID, creation)
 | 
				
			||||||
 | 
							return creation // Naturally, the newly created space is already up to date, so we can always skip syncing here.
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!shouldActuallySync) {
 | 
				
			||||||
 | 
							return spaceID // only need to ensure space exists, and it does. return the space ID
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	console.log(`[space sync] to matrix: ${guild.name}`)
 | 
						console.log(`[space sync] to matrix: ${guild.name}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const guildKState = await guildToKState(guild) // calling this in both branches because we don't want to calculate this if not syncing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// sync guild state to space
 | 
						// sync guild state to space
 | 
				
			||||||
	const spaceKState = await createRoom.roomToKState(spaceID)
 | 
						const spaceKState = await createRoom.roomToKState(spaceID)
 | 
				
			||||||
	const spaceDiff = ks.diffKState(spaceKState, guildKState)
 | 
						const spaceDiff = ks.diffKState(spaceKState, guildKState)
 | 
				
			||||||
| 
						 | 
					@ -113,6 +135,16 @@ async function syncSpace(guildID) {
 | 
				
			||||||
	return spaceID
 | 
						return spaceID
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Ensures the space exists. If it doesn't, creates the space with an accurate initial state. */
 | 
				
			||||||
 | 
					function ensureSpace(guildID) {
 | 
				
			||||||
 | 
						return _syncSpace(guildID, false)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Actually syncs. Efficiently updates the space name, space avatar, and child room avatars. */
 | 
				
			||||||
 | 
					function syncSpace(guildID) {
 | 
				
			||||||
 | 
						return _syncSpace(guildID, true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Inefficiently force the space and its existing child rooms to be fully updated.
 | 
					 * Inefficiently force the space and its existing child rooms to be fully updated.
 | 
				
			||||||
 * Should not need to be called as part of the bridge's normal operation.
 | 
					 * Should not need to be called as part of the bridge's normal operation.
 | 
				
			||||||
| 
						 | 
					@ -157,6 +189,7 @@ async function syncSpaceFully(guildID) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports.createSpace = createSpace
 | 
					module.exports.createSpace = createSpace
 | 
				
			||||||
 | 
					module.exports.ensureSpace = ensureSpace
 | 
				
			||||||
module.exports.syncSpace = syncSpace
 | 
					module.exports.syncSpace = syncSpace
 | 
				
			||||||
module.exports.syncSpaceFully = syncSpaceFully
 | 
					module.exports.syncSpaceFully = syncSpaceFully
 | 
				
			||||||
module.exports.guildToKState = guildToKState
 | 
					module.exports.guildToKState = guildToKState
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
const {channelToKState} = require("./create-room")
 | 
					 | 
				
			||||||
const {_memberToStateContent} = require("./register-user")
 | 
					const {_memberToStateContent} = require("./register-user")
 | 
				
			||||||
const {test} = require("supertape")
 | 
					const {test} = require("supertape")
 | 
				
			||||||
const testData = require("../../test/data")
 | 
					const testData = require("../../test/data")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue