97 lines
3.9 KiB
JavaScript
97 lines
3.9 KiB
JavaScript
// @ts-check
|
|
|
|
const assert = require("assert/strict")
|
|
const Ty = require("../types")
|
|
const {Semaphore} = require("@chriscdn/promise-semaphore")
|
|
const {tag} = require("@cloudrac3r/html-template-tag")
|
|
const {db, sync, select, from} = require("../passthrough")
|
|
|
|
/** @type {import("./utils")}) */
|
|
const utils = sync.require("./utils")
|
|
|
|
const roomUpgradeSema = new Semaphore()
|
|
|
|
/**
|
|
* @param {Ty.Event.StateOuter<Ty.Event.M_Room_Tombstone>} event
|
|
* @param {import("./api")} api
|
|
*/
|
|
async function onTombstone(event, api) {
|
|
// Preconditions (checked by event-dispatcher, enforced here)
|
|
assert.equal(event.state_key, "")
|
|
assert.ok(event.content.replacement_room)
|
|
|
|
// Set up
|
|
const oldRoomID = event.room_id
|
|
const newRoomID = event.content.replacement_room
|
|
const channel = select("channel_room", ["name", "channel_id"], {room_id: oldRoomID}).get()
|
|
if (!channel) return
|
|
db.prepare("REPLACE INTO room_upgrade_pending (new_room_id, old_room_id) VALUES (?, ?)").run(newRoomID, oldRoomID)
|
|
|
|
// Try joining
|
|
try {
|
|
await api.joinRoom(newRoomID)
|
|
} catch (e) {
|
|
const message = new utils.MatrixStringBuilder()
|
|
message.add(
|
|
`You upgraded the bridged room ${channel.name}. To keep bridging, I need you to invite me to the new room: https://matrix.to/#/${newRoomID}`,
|
|
tag`You upgraded the bridged room <strong>${channel.name}</strong>. To keep bridging, I need you to invite me to the new room: <a href="https://matrix.to/#/${newRoomID}">https://matrix.to/#/${newRoomID}</a>`
|
|
)
|
|
const privateRoomID = await api.usePrivateChat(event.sender)
|
|
await api.sendEvent(privateRoomID, "m.room.message", message.get())
|
|
}
|
|
|
|
// Now wait to be invited to/join the room that has the upgrade pending...
|
|
}
|
|
|
|
/**
|
|
* @param {Ty.Event.StateOuter<Ty.Event.M_Room_Member>} event
|
|
* @param {import("./api")} api
|
|
* @param {import("../d2m/actions/create-room")} createRoom
|
|
* @returns {Promise<boolean>} whether to cancel other membership actions
|
|
*/
|
|
async function onBotMembership(event, api, createRoom) {
|
|
// Preconditions (checked by event-dispatcher, enforced here)
|
|
assert.equal(event.type, "m.room.member")
|
|
assert.equal(event.state_key, utils.bot)
|
|
|
|
return await roomUpgradeSema.request(async () => {
|
|
// Check if an upgrade is pending for this room
|
|
const newRoomID = event.room_id
|
|
const oldRoomID = select("room_upgrade_pending", "old_room_id", {new_room_id: newRoomID}).pluck().get()
|
|
if (!oldRoomID) return false
|
|
const channelRow = from("channel_room").join("guild_space", "guild_id").where({room_id: oldRoomID}).select("space_id", "guild_id", "channel_id").get()
|
|
assert(channelRow) // this could only fail if the channel was unbridged or something between upgrade and joining
|
|
|
|
// Check if is join/invite
|
|
if (event.content.membership !== "invite" && event.content.membership !== "join") return false
|
|
|
|
// If invited, join
|
|
if (event.content.membership === "invite") {
|
|
await api.joinRoom(newRoomID)
|
|
}
|
|
|
|
// Remove old room from space
|
|
await api.sendState(channelRow.space_id, "m.space.child", oldRoomID, {})
|
|
// await api.sendState(oldRoomID, "m.space.parent", spaceID, {}) // keep this - the room isn't advertised but should still be grouped if opened
|
|
|
|
// Remove declaration that old room is bridged (if able)
|
|
try {
|
|
await api.sendState(oldRoomID, "uk.half-shot.bridge", `moe.cadence.ooye://discord/${channelRow.guild_id}/${channelRow.channel_id}`, {})
|
|
} catch (e) { /* c8 ignore next */ }
|
|
|
|
// Update database
|
|
db.transaction(() => {
|
|
db.prepare("DELETE FROM room_upgrade_pending WHERE new_room_id = ?").run(newRoomID)
|
|
db.prepare("UPDATE channel_room SET room_id = ? WHERE channel_id = ?").run(newRoomID, channelRow.channel_id)
|
|
db.prepare("INSERT INTO historical_channel_room (room_id, reference_channel_id, upgraded_timestamp) VALUES (?, ?, ?)").run(newRoomID, channelRow.channel_id, Date.now())
|
|
})()
|
|
|
|
// Sync
|
|
await createRoom.syncRoom(channelRow.channel_id)
|
|
return true
|
|
}, event.room_id)
|
|
}
|
|
|
|
module.exports.onTombstone = onTombstone
|
|
module.exports.onBotMembership = onBotMembership
|