should create guilds on-demand now
This commit is contained in:
		| @@ -12,6 +12,8 @@ const file = sync.require("../../matrix/file") | ||||
| const api = sync.require("../../matrix/api") | ||||
| /** @type {import("../../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> */ | ||||
| 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.APIGuild} 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") | ||||
|  | ||||
| 	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")} */ | ||||
| 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 {any} kstate | ||||
| @@ -68,24 +71,43 @@ async function guildToKState(guild) { | ||||
| 	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} */ | ||||
| 	const guild = discord.guilds.get(guildID) | ||||
| 	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?} */ | ||||
| 	const spaceID = db.prepare("SELECT space_id from guild_space WHERE guild_id = ?").pluck().get(guildID) | ||||
|  | ||||
| 	const guildKState = await guildToKState(guild) | ||||
|  | ||||
| 	if (!spaceID) { | ||||
| 		const spaceID = await createSpace(guild, guildKState) | ||||
| 		return spaceID // Naturally, the newly created space is already up to date, so we can always skip syncing here. | ||||
| 		const creation = (async () => { | ||||
| 			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}`) | ||||
|  | ||||
| 	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 | ||||
| 	const spaceKState = await createRoom.roomToKState(spaceID) | ||||
| 	const spaceDiff = ks.diffKState(spaceKState, guildKState) | ||||
| @@ -113,6 +135,16 @@ async function syncSpace(guildID) { | ||||
| 	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. | ||||
|  * 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.ensureSpace = ensureSpace | ||||
| module.exports.syncSpace = syncSpace | ||||
| module.exports.syncSpaceFully = syncSpaceFully | ||||
| module.exports.guildToKState = guildToKState | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| const {channelToKState} = require("./create-room") | ||||
| const {_memberToStateContent} = require("./register-user") | ||||
| const {test} = require("supertape") | ||||
| const testData = require("../../test/data") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Cadence Ember
					Cadence Ember