get createRoom and ensureRoom interface working

This commit is contained in:
Cadence Ember 2023-05-09 08:03:57 +12:00
parent 1e7e66dc31
commit 7526d63690
4 changed files with 57 additions and 9 deletions

View file

@ -124,13 +124,15 @@ async function channelToKState(channel, guild) {
} }
/** /**
* Create a bridge room, store the relationship in the database, and add it to the guild's space.
* @param {import("discord-api-types/v10").APIGuildTextChannel} channel * @param {import("discord-api-types/v10").APIGuildTextChannel} channel
* @param guild * @param guild
* @param {string} spaceID * @param {string} spaceID
* @param {any} kstate * @param {any} kstate
* @returns {Promise<string>} room ID
*/ */
async function createRoom(channel, guild, spaceID, kstate) { async function createRoom(channel, guild, spaceID, kstate) {
const root = await api.createRoom({ const roomID = await api.createRoom({
name: channel.name, name: channel.name,
topic: channel.topic || undefined, topic: channel.topic || undefined,
preset: "private_chat", preset: "private_chat",
@ -139,12 +141,14 @@ async function createRoom(channel, guild, spaceID, kstate) {
initial_state: kstateToState(kstate) initial_state: kstateToState(kstate)
}) })
db.prepare("INSERT INTO channel_room (channel_id, room_id) VALUES (?, ?)").run(channel.id, root.room_id) db.prepare("INSERT INTO channel_room (channel_id, room_id) VALUES (?, ?)").run(channel.id, roomID)
// Put the newly created child into the space // Put the newly created child into the space
await api.sendState(spaceID, "m.space.child", root.room_id, { await api.sendState(spaceID, "m.space.child", roomID, { // TODO: should I deduplicate with the equivalent code from syncRoom?
via: ["cadence.moe"] // TODO: use the proper server via: ["cadence.moe"] // TODO: use the proper server
}) })
return roomID
} }
/** /**
@ -158,22 +162,46 @@ function channelToGuild(channel) {
return guild return guild
} }
/*
Ensure flow:
1. Get IDs
2. Does room exist? If so great!
(it doesn't, so it needs to be created)
3. Get kstate for channel
4. Create room, return new ID
New combined flow with ensure / sync:
1. Get IDs
2. Does room exist?
2.5: If room does exist AND don't need to sync: return here
3. Get kstate for channel
4. Create room with kstate if room doesn't exist
5. Get and update room state with kstate if room does exist
*/
/** /**
* @param {string} channelID * @param {string} channelID
* @param {boolean} shouldActuallySync false if just need to ensure room exists (which is a quick database check), true if also want to sync room data when it does exist (slow)
* @returns {Promise<string>} room ID
*/ */
async function syncRoom(channelID) { async function _syncRoom(channelID, shouldActuallySync) {
/** @ts-ignore @type {import("discord-api-types/v10").APIGuildChannel} */ /** @ts-ignore @type {import("discord-api-types/v10").APIGuildChannel} */
const channel = discord.channels.get(channelID) const channel = discord.channels.get(channelID)
assert.ok(channel) assert.ok(channel)
const guild = channelToGuild(channel) const guild = channelToGuild(channel)
const {spaceID, channelKState} = await channelToKState(channel, guild)
/** @type {string?} */ /** @type {string?} */
const existing = db.prepare("SELECT room_id from channel_room WHERE channel_id = ?").pluck().get(channel.id) const existing = db.prepare("SELECT room_id from channel_room WHERE channel_id = ?").pluck().get(channel.id)
if (!existing) { if (!existing) {
const {spaceID, channelKState} = await channelToKState(channel, guild)
return createRoom(channel, guild, spaceID, channelKState) return createRoom(channel, guild, spaceID, channelKState)
} else { } else {
if (!shouldActuallySync) {
return existing // only need to ensure room exists, and it does. return the room ID
}
const {spaceID, channelKState} = await channelToKState(channel, guild)
// sync channel state to room // sync channel state to room
const roomKState = await roomToKState(existing) const roomKState = await roomToKState(existing)
const roomDiff = diffKState(roomKState, channelKState) const roomDiff = diffKState(roomKState, channelKState)
@ -187,10 +215,20 @@ async function syncRoom(channelID) {
} }
}) })
const spaceApply = applyKStateDiffToRoom(spaceID, spaceDiff) const spaceApply = applyKStateDiffToRoom(spaceID, spaceDiff)
return Promise.all([roomApply, spaceApply]) await Promise.all([roomApply, spaceApply])
return existing
} }
} }
function ensureRoom(channelID) {
return _syncRoom(channelID, false)
}
function syncRoom(channelID) {
return _syncRoom(channelID, true)
}
async function createAllForGuild(guildID) { async function createAllForGuild(guildID) {
const channelIDs = discord.guildChannelMap.get(guildID) const channelIDs = discord.guildChannelMap.get(guildID)
assert.ok(channelIDs) assert.ok(channelIDs)
@ -200,6 +238,7 @@ async function createAllForGuild(guildID) {
} }
module.exports.createRoom = createRoom module.exports.createRoom = createRoom
module.exports.ensureRoom = ensureRoom
module.exports.syncRoom = syncRoom module.exports.syncRoom = syncRoom
module.exports.createAllForGuild = createAllForGuild module.exports.createAllForGuild = createAllForGuild
module.exports.kstateToState = kstateToState module.exports.kstateToState = kstateToState

View file

@ -11,13 +11,15 @@ const messageToEvent = sync.require("../converters/message-to-event")
const api = sync.require("../../matrix/api") const api = sync.require("../../matrix/api")
/** @type {import("./register-user")} */ /** @type {import("./register-user")} */
const registerUser = sync.require("./register-user") const registerUser = sync.require("./register-user")
/** @type {import("../actions/create-room")} */
const createRoom = sync.require("../actions/create-room")
/** /**
* @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message * @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message
*/ */
async function sendMessage(message) { async function sendMessage(message) {
const event = messageToEvent.messageToEvent(message) const event = messageToEvent.messageToEvent(message)
const roomID = "!VwVlIAjOjejUpDhlbA:cadence.moe" const roomID = await createRoom.ensureRoom(message.channel_id)
let senderMxid = null let senderMxid = null
if (!message.webhook_id) { if (!message.webhook_id) {
senderMxid = await registerUser.ensureSimJoined(message.author, roomID) senderMxid = await registerUser.ensureSimJoined(message.author, roomID)

View file

@ -16,6 +16,7 @@ module.exports = {
* @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message * @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message
*/ */
onMessageCreate(client, message) { onMessageCreate(client, message) {
if (message.guild_id !== "112760669178241024") return // TODO: activate on other servers (requires the space creation flow to be done first)
sendMessage.sendMessage(message) sendMessage.sendMessage(message)
}, },

View file

@ -11,7 +11,12 @@ const file = sync.require("./file")
/** @type {import("./txnid")} */ /** @type {import("./txnid")} */
const makeTxnId = sync.require("./txnid") const makeTxnId = sync.require("./txnid")
function path(p, mxid = null) { /**
* @param {string} p endpoint to access
* @param {string} [mxid] optional: user to act as, for the ?user_id parameter
* @returns {string} the new endpoint
*/
function path(p, mxid) {
if (!mxid) return p if (!mxid) return p
const u = new URL(p, "http://localhost") const u = new URL(p, "http://localhost")
u.searchParams.set("user_id", mxid) u.searchParams.set("user_id", mxid)
@ -65,6 +70,7 @@ function getAllState(roomID) {
* @param {string} roomID * @param {string} roomID
* @param {string} type * @param {string} type
* @param {string} stateKey * @param {string} stateKey
* @param {string} [mxid]
* @returns {Promise<string>} event ID * @returns {Promise<string>} event ID
*/ */
async function sendState(roomID, type, stateKey, content, mxid) { async function sendState(roomID, type, stateKey, content, mxid) {