diff --git a/d2m/actions/create-room.js b/d2m/actions/create-room.js index 322f8be..051e889 100644 --- a/d2m/actions/create-room.js +++ b/d2m/actions/create-room.js @@ -142,8 +142,6 @@ async function channelToKState(channel, guild) { const everyonePermissions = utils.getPermissions([], guild.roles, undefined, channel.permission_overwrites) const everyoneCanMentionEveryone = utils.hasAllPermissions(everyonePermissions, ["MentionEveryone"]) - const globalAdmins = select("member_power", ["mxid", "power_level"], {room_id: "*"}).all() - const channelKState = { "m.room.name/": {name: convertedName}, "m.room.topic/": {topic: convertedTopic}, @@ -163,7 +161,7 @@ async function channelToKState(channel, guild) { notifications: { room: everyoneCanMentionEveryone ? 0 : 20 }, - users: globalAdmins.reduce((a, c) => (a[c.mxid] = c.power_level, a), {}) + users: reg.ooye.invite.reduce((a, c) => (a[c] = 100, a), {}) }, "chat.schildi.hide_ui/read_receipts": { hidden: true diff --git a/d2m/actions/create-space.js b/d2m/actions/create-space.js index 44d0206..dbefd6d 100644 --- a/d2m/actions/create-space.js +++ b/d2m/actions/create-space.js @@ -31,8 +31,6 @@ async function createSpace(guild, kstate) { const topic = kstate["m.room.topic/"]?.topic || undefined assert(name) - const globalAdmins = select("member_power", "mxid", {room_id: "*"}).pluck().all() - const roomID = await createRoom.postApplyPowerLevels(kstate, async kstate => { return api.createRoom({ name, @@ -42,7 +40,7 @@ async function createSpace(guild, kstate) { events_default: 100, // space can only be managed by bridge invite: 0 // any existing member can invite others }, - invite: globalAdmins, + invite: reg.ooye.invite, topic, creation_content: { type: "m.space" @@ -60,7 +58,6 @@ async function createSpace(guild, kstate) { */ async function guildToKState(guild, privacyLevel) { assert.equal(typeof privacyLevel, "number") - const globalAdmins = select("member_power", ["mxid", "power_level"], {room_id: "*"}).all() const guildKState = { "m.room.name/": {name: guild.name}, "m.room.avatar/": { @@ -71,7 +68,7 @@ async function guildToKState(guild, privacyLevel) { "m.room.guest_access/": {guest_access: createRoom.PRIVACY_ENUMS.GUEST_ACCESS[privacyLevel]}, "m.room.history_visibility/": {history_visibility: createRoom.PRIVACY_ENUMS.SPACE_HISTORY_VISIBILITY[privacyLevel]}, "m.room.join_rules/": {join_rule: createRoom.PRIVACY_ENUMS.SPACE_JOIN_RULES[privacyLevel]}, - "m.room.power_levels/": {users: globalAdmins.reduce((a, c) => (a[c.mxid] = c.power_level, a), {})} // used in guild initial creation postApplyPowerLevels + "m.room.power_levels/": {users: reg.ooye.invite.reduce((a, c) => (a[c] = 100, a), {})} } return guildKState diff --git a/db/migrations/0012-add-member-power.sql b/db/migrations/0012-add-member-power.sql deleted file mode 100644 index b0bb8d6..0000000 --- a/db/migrations/0012-add-member-power.sql +++ /dev/null @@ -1,14 +0,0 @@ -BEGIN TRANSACTION; - --- the power we want them to have -CREATE TABLE IF NOT EXISTS member_power ( - mxid TEXT NOT NULL, - room_id TEXT NOT NULL, - power_level INTEGER NOT NULL, - PRIMARY KEY(mxid, room_id) -) WITHOUT ROWID; - --- the power they have -ALTER TABLE member_cache ADD COLUMN power_level INTEGER NOT NULL DEFAULT 0; - -COMMIT; diff --git a/db/orm-defs.d.ts b/db/orm-defs.d.ts index e481f95..0223058 100644 --- a/db/orm-defs.d.ts +++ b/db/orm-defs.d.ts @@ -42,14 +42,7 @@ export type Models = { room_id: string mxid: string displayname: string | null - avatar_url: string | null, - power_level: number - } - - member_power: { - mxid: string - room_id: string - power_level: number + avatar_url: string | null } message_channel: { diff --git a/db/orm.js b/db/orm.js index 09e4bc7..c6cab96 100644 --- a/db/orm.js +++ b/db/orm.js @@ -44,8 +44,6 @@ class From { /** @private */ this.cols = [] /** @private */ - this.makeColsSafe = true - /** @private */ this.using = [] /** @private */ this.isPluck = false @@ -80,12 +78,6 @@ class From { return r } - selectUnsafe(...cols) { - this.cols = cols - this.makeColsSafe = false - return this - } - /** * @template {Col} Select * @param {Select} col @@ -120,8 +112,7 @@ class From { } prepare() { - if (this.makeColsSafe) this.cols = this.cols.map(k => `"${k}"`) - let sql = `SELECT ${this.cols.join(", ")} FROM ${this.tables[0]} ` + let sql = `SELECT ${this.cols.map(k => `"${k}"`).join(", ")} FROM ${this.tables[0]} ` for (let i = 1; i < this.tables.length; i++) { const table = this.tables[i] const col = this.using[i-1] diff --git a/m2d/event-dispatcher.js b/m2d/event-dispatcher.js index 7aa3b70..5529a26 100644 --- a/m2d/event-dispatcher.js +++ b/m2d/event-dispatcher.js @@ -6,7 +6,7 @@ const util = require("util") const Ty = require("../types") -const {discord, db, sync, as, select} = require("../passthrough") +const {discord, db, sync, as} = require("../passthrough") /** @type {import("./actions/send-event")} */ const sendEvent = sync.require("./actions/send-event") @@ -167,29 +167,5 @@ sync.addTemporaryListener(as, "type:m.room.member", guard("m.room.member", async event => { if (event.state_key[0] !== "@") return if (utils.eventSenderIsFromDiscord(event.state_key)) return - if (event.content.membership === "leave" || event.content.membership === "ban") { - // Member is gone - db.prepare("DELETE FROM member_cache WHERE room_id = ? and mxid = ?").run(event.room_id, event.state_key) - } else { - // Member is here - db.prepare("INSERT INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES (?, ?, ?, ?) ON CONFLICT DO UPDATE SET displayname = ?, avatar_url = ?") - .run( - event.room_id, event.state_key, - event.content.displayname || null, event.content.avatar_url || null, - event.content.displayname || null, event.content.avatar_url || null - ) - } -})) - -sync.addTemporaryListener(as, "type:m.room.power_levels", guard("m.room.power_levels", -/** - * @param {Ty.Event.StateOuter} event - */ -async event => { - if (event.state_key !== "") return - const existingPower = select("member_cache", "mxid", {room_id: event.room_id}).pluck().all() - const newPower = event.content.users || {} - for (const mxid of existingPower) { - db.prepare("UPDATE member_cache SET power_level = ? WHERE room_id = ? AND mxid = ?").run(newPower[mxid] || 0, event.room_id, mxid) - } + db.prepare("REPLACE INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES (?, ?, ?, ?)").run(event.room_id, event.state_key, event.content.displayname || null, event.content.avatar_url || null) })) diff --git a/matrix/api.js b/matrix/api.js index 65ec891..82b1c10 100644 --- a/matrix/api.js +++ b/matrix/api.js @@ -70,7 +70,6 @@ async function inviteToRoom(roomID, mxidToInvite, mxid) { } async function leaveRoom(roomID, mxid) { - console.log(`[api] leave: ${roomID}: ${mxid}`) await mreq.mreq("POST", path(`/client/v3/rooms/${roomID}/leave`, mxid), {}) } diff --git a/matrix/power.js b/matrix/power.js deleted file mode 100644 index 5dac550..0000000 --- a/matrix/power.js +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-check - -const {db, from} = require("../passthrough") -const api = require("./api") -const reg = require("./read-registration") -const ks = require("./kstate") -const {applyKStateDiffToRoom, roomToKState} = require("../d2m/actions/create-room") - -// Migrate reg.ooye.invite setting to database -for (const mxid of reg.ooye.invite) { - db.prepare("INSERT OR IGNORE INTO member_power (mxid, room_id, power_level) VALUES (?, ?, 100)").run(mxid, "*") -} - -// Apply global power level requests across ALL rooms where the member cache entry exists but the power level has not been applied yet. -const rows = from("member_cache").join("member_power", "mxid") - .and("where member_power.room_id = '*' and member_cache.power_level != member_power.power_level") - .selectUnsafe("mxid", "member_cache.room_id", "member_power.power_level") - .all() - -;(async () => { - for (const row of rows) { - const kstate = await roomToKState(row.room_id) - const diff = ks.diffKState(kstate, {"m.room.power_levels/": {users: {[row.mxid]: row.power_level}}}) - await applyKStateDiffToRoom(row.room_id, diff) - // There is a listener on m.room.power_levels to do this same update, - // but we update it here anyway since the homeserver does not always deliver the event round-trip. - db.prepare("UPDATE member_cache SET power_level = ? WHERE room_id = ? AND mxid = ?").run(row.power_level, row.room_id, row.mxid) - } -})() diff --git a/start.js b/start.js index c7ae0eb..2b6e3df 100644 --- a/start.js +++ b/start.js @@ -34,7 +34,6 @@ discord.snow.requestHandler.on("requestError", data => { await migrate.migrate(db) await discord.cloud.connect() console.log("Discord gateway started") - require("./matrix/power.js") require("./stdin") })() diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql index 1fb9e24..328c4b3 100644 --- a/test/ooye-test-data.sql +++ b/test/ooye-test-data.sql @@ -139,9 +139,6 @@ INSERT INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES ('!TqlyQmifxGUggEmdBN:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', NULL), ('!BnKuBPCvyfOkhcUjEu:cadence.moe', '@ami:the-apothecary.club', 'Ami (she/her)', NULL); -INSERT INTO member_power (mxid, room_id, power_level) VALUES -('@test_auto_invite:example.org', '*', 100); - INSERT INTO lottie (sticker_id, mxc_url) VALUES ('860171525772279849', 'mxc://cadence.moe/ZtvvVbwMIdUZeovWVyGVFCeR'); diff --git a/test/test.js b/test/test.js index b5977f1..396dea9 100644 --- a/test/test.js +++ b/test/test.js @@ -20,6 +20,7 @@ const db = new sqlite(":memory:") const reg = require("../matrix/read-registration") reg.ooye.server_origin = "https://matrix.cadence.moe" // so that tests will pass even when hard-coded reg.ooye.server_name = "cadence.moe" +reg.ooye.invite = ["@test_auto_invite:example.org"] reg.id = "baby" // don't actually take authenticated actions on the server reg.as_token = "baby" reg.hs_token = "baby" diff --git a/types.d.ts b/types.d.ts index c710e12..6036867 100644 --- a/types.d.ts +++ b/types.d.ts @@ -209,36 +209,6 @@ export namespace Event { name?: string } - export type M_Power_Levels = { - /** The level required to ban a user. Defaults to 50 if unspecified. */ - ban?: number, - /** The level required to send specific event types. This is a mapping from event type to power level required. */ - events?: { - [event_id: string]: number - }, - /** The default level required to send message events. Can be overridden by the `events` key. Defaults to 0 if unspecified. */ - events_default?: number, - /** The level required to invite a user. Defaults to 0 if unspecified. */ - invite?: number, - /** The level required to kick a user. Defaults to 50 if unspecified. */ - kick?: number, - /** The power level requirements for specific notification types. This is a mapping from `key` to power level for that notifications key. */ - notifications?: { - room: number, - [key: string]: number - }, - /** The level required to redact an event sent by another user. Defaults to 50 if unspecified. */ - redact?: number, - /** The default level required to send state events. Can be overridden by the `events` key. Defaults to 50 if unspecified. */ - state_default?: number, - /** The power levels for specific users. This is a mapping from `user_id` to power level for that user. */ - users?: { - [mxid: string]: number - }, - /**The power level for users in the room whose `user_id` is not mentioned in the `users` key. Defaults to 0 if unspecified. */ - users_default?: number - } - export type M_Reaction = { "m.relates_to": { rel_type: "m.annotation"