1
0
Fork 0

should create guilds on-demand now

This commit is contained in:
Cadence Ember 2023-09-12 23:15:55 +12:00
parent 9263bdb754
commit 671f1300ba
3 changed files with 43 additions and 9 deletions

View file

@ -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)

View file

@ -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 creation = (async () => {
const guildKState = await guildToKState(guild)
const spaceID = await createSpace(guild, guildKState) 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. 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

View file

@ -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")