diff --git a/src/d2m/actions/create-room.js b/src/d2m/actions/create-room.js index 8f8ac00..eeba7aa 100644 --- a/src/d2m/actions/create-room.js +++ b/src/d2m/actions/create-room.js @@ -39,26 +39,6 @@ const DEFAULT_PRIVACY_LEVEL = 0 /** @type {Map>} channel ID -> Promise */ const inflightRoomCreate = new Map() -/** - * Async because it gets all room state from the homeserver. - * @param {string} roomID - */ -async function roomToKState(roomID) { - const root = await api.getAllState(roomID) - return ks.stateToKState(root) -} - -/** - * @param {string} roomID - * @param {any} kstate - */ -async function applyKStateDiffToRoom(roomID, kstate) { - const events = await ks.kstateToState(kstate) - return Promise.all(events.map(({type, state_key, content}) => - api.sendState(roomID, type, state_key, content) - )) -} - /** * @param {{id: string, name: string, topic?: string?, type: number, parent_id?: string?}} channel * @param {{id: string}} guild @@ -253,9 +233,9 @@ async function postApplyPowerLevels(kstate, callback) { // Now *really* apply the power level overrides on top of what Synapse *really* set if (powerLevelContent) { - const newRoomKState = await roomToKState(roomID) + const newRoomKState = await ks.roomToKState(roomID) const newRoomPowerLevelsDiff = ks.diffKState(newRoomKState, {"m.room.power_levels/": powerLevelContent}) - await applyKStateDiffToRoom(roomID, newRoomPowerLevelsDiff) + await ks.applyKStateDiffToRoom(roomID, newRoomPowerLevelsDiff) } return roomID @@ -384,7 +364,7 @@ async function _syncRoom(channelID, shouldActuallySync) { const {spaceID, channelKState} = await channelToKState(channel, guild, {api}) // calling this in both branches because we don't want to calculate this if not syncing // sync channel state to room - const roomKState = await roomToKState(roomID) + const roomKState = await ks.roomToKState(roomID) if (+roomKState["m.room.create/"].room_version <= 8) { // join_rule `restricted` is not available in room version < 8 and not working properly in version == 8 // read more: https://spec.matrix.org/v1.8/rooms/v9/ @@ -392,7 +372,7 @@ async function _syncRoom(channelID, shouldActuallySync) { channelKState["m.room.join_rules/"] = {join_rule: "public"} } const roomDiff = ks.diffKState(roomKState, channelKState) - const roomApply = applyKStateDiffToRoom(roomID, roomDiff) + const roomApply = ks.applyKStateDiffToRoom(roomID, roomDiff) db.prepare("UPDATE channel_room SET name = ? WHERE room_id = ?").run(channel.name, roomID) // sync room as space member @@ -462,7 +442,7 @@ async function unbridgeDeletedChannel(channel, guildID) { * @returns {Promise} */ async function _syncSpaceMember(channel, spaceID, roomID) { - const spaceKState = await roomToKState(spaceID) + const spaceKState = await ks.roomToKState(spaceID) let spaceEventContent = {} if ( channel.type !== DiscordTypes.ChannelType.PrivateThread // private threads do not belong in the space (don't offer people something they can't join) @@ -475,7 +455,7 @@ async function _syncSpaceMember(channel, spaceID, roomID) { const spaceDiff = ks.diffKState(spaceKState, { [`m.space.child/${roomID}`]: spaceEventContent }) - return applyKStateDiffToRoom(spaceID, spaceDiff) + return ks.applyKStateDiffToRoom(spaceID, spaceDiff) } async function createAllForGuild(guildID) { @@ -498,8 +478,6 @@ module.exports.ensureRoom = ensureRoom module.exports.syncRoom = syncRoom module.exports.createAllForGuild = createAllForGuild module.exports.channelToKState = channelToKState -module.exports.roomToKState = roomToKState -module.exports.applyKStateDiffToRoom = applyKStateDiffToRoom module.exports.postApplyPowerLevels = postApplyPowerLevels module.exports._convertNameAndTopic = convertNameAndTopic module.exports._unbridgeRoom = _unbridgeRoom diff --git a/src/d2m/actions/create-space.js b/src/d2m/actions/create-space.js index acd0d8f..edd3ba3 100644 --- a/src/d2m/actions/create-space.js +++ b/src/d2m/actions/create-space.js @@ -116,9 +116,9 @@ async function _syncSpace(guild, shouldActuallySync) { const guildKState = await guildToKState(guild, privacy_level) // 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 spaceKState = await ks.roomToKState(spaceID) const spaceDiff = ks.diffKState(spaceKState, guildKState) - await createRoom.applyKStateDiffToRoom(spaceID, spaceDiff) + await ks.applyKStateDiffToRoom(spaceID, spaceDiff) // guild icon was changed, so room avatars need to be updated as well as the space ones // doing it this way rather than calling syncRoom for great efficiency gains @@ -183,9 +183,9 @@ async function syncSpaceFully(guildID) { const guildKState = await guildToKState(guild, privacy_level) // sync guild state to space - const spaceKState = await createRoom.roomToKState(spaceID) + const spaceKState = await ks.roomToKState(spaceID) const spaceDiff = ks.diffKState(spaceKState, guildKState) - await createRoom.applyKStateDiffToRoom(spaceID, spaceDiff) + await ks.applyKStateDiffToRoom(spaceID, spaceDiff) const childRooms = await api.getFullHierarchy(spaceID) diff --git a/src/d2m/actions/update-pins.js b/src/d2m/actions/update-pins.js index bce3f88..692081a 100644 --- a/src/d2m/actions/update-pins.js +++ b/src/d2m/actions/update-pins.js @@ -6,6 +6,8 @@ const {discord, sync, db} = passthrough const pinsToList = sync.require("../converters/pins-to-list") /** @type {import("../../matrix/api")} */ const api = sync.require("../../matrix/api") +/** @type {import("../../matrix/kstate")} */ +const ks = sync.require("../../matrix/kstate") /** * @template {string | null | undefined} T @@ -23,11 +25,13 @@ function convertTimestamp(timestamp) { * @param {number?} convertedTimestamp */ async function updatePins(channelID, roomID, convertedTimestamp) { - const pins = await discord.snow.channel.getChannelPinnedMessages(channelID) - const eventIDs = pinsToList.pinsToList(pins) - await api.sendState(roomID, "m.room.pinned_events", "", { - pinned: eventIDs - }) + const discordPins = await discord.snow.channel.getChannelPinnedMessages(channelID) + const pinned = pinsToList.pinsToList(discordPins) + + const kstate = await ks.roomToKState(roomID) + const diff = ks.diffKState(kstate, {"m.room.pinned_events/": {pinned}}) + await ks.applyKStateDiffToRoom(roomID, diff) + db.prepare("UPDATE channel_room SET last_bridged_pin_timestamp = ? WHERE channel_id = ?").run(convertedTimestamp || 0, channelID) } diff --git a/src/m2d/event-dispatcher.js b/src/m2d/event-dispatcher.js index c7c725e..a270293 100644 --- a/src/m2d/event-dispatcher.js +++ b/src/m2d/event-dispatcher.js @@ -189,6 +189,7 @@ async event => { } await updatePins.updatePins(pins, prev) + await api.ackEvent(event) })) sync.addTemporaryListener(as, "type:m.room.member", guard("m.room.member", diff --git a/src/matrix/api.js b/src/matrix/api.js index abf264e..f9d3e08 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -6,7 +6,7 @@ const assert = require("assert").strict const fetch = require("node-fetch").default const passthrough = require("../passthrough") -const { discord, sync, db } = passthrough +const {sync} = passthrough /** @type {import("./mreq")} */ const mreq = sync.require("./mreq") /** @type {import("./txnid")} */ diff --git a/src/matrix/kstate.js b/src/matrix/kstate.js index 67bb063..11155f5 100644 --- a/src/matrix/kstate.js +++ b/src/matrix/kstate.js @@ -8,6 +8,8 @@ const passthrough = require("../passthrough") const {sync} = passthrough /** @type {import("./file")} */ const file = sync.require("./file") +/** @type {import("./api")} */ +const api = sync.require("./api") /** Mutates the input. Not recursive - can only include or exclude entire state events. */ function kstateStripConditionals(kstate) { @@ -102,8 +104,32 @@ function diffKState(actual, target) { return diff } +/* c8 ignore start */ + +/** + * Async because it gets all room state from the homeserver. + * @param {string} roomID + */ +async function roomToKState(roomID) { + const root = await api.getAllState(roomID) + return stateToKState(root) +} + +/** + * @param {string} roomID + * @param {any} kstate + */ +async function applyKStateDiffToRoom(roomID, kstate) { + const events = await kstateToState(kstate) + return Promise.all(events.map(({type, state_key, content}) => + api.sendState(roomID, type, state_key, content) + )) +} + module.exports.kstateStripConditionals = kstateStripConditionals module.exports.kstateUploadMxc = kstateUploadMxc module.exports.kstateToState = kstateToState module.exports.stateToKState = stateToKState module.exports.diffKState = diffKState +module.exports.roomToKState = roomToKState +module.exports.applyKStateDiffToRoom = applyKStateDiffToRoom diff --git a/src/matrix/power.js b/src/matrix/power.js index 3e613dd..d323d17 100644 --- a/src/matrix/power.js +++ b/src/matrix/power.js @@ -3,7 +3,6 @@ const {db, from} = require("../passthrough") const {reg} = require("./read-registration") const ks = require("./kstate") -const {applyKStateDiffToRoom, roomToKState} = require("../d2m/actions/create-room") /** Apply global power level requests across ALL rooms where the member cache entry exists but the power level has not been applied yet. */ function _getAffectedRooms() { @@ -23,9 +22,9 @@ async function applyPower() { const rows = _getAffectedRooms() for (const row of rows) { - const kstate = await roomToKState(row.room_id) + const kstate = await ks.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) + await ks.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/src/web/pug/guild.pug b/src/web/pug/guild.pug index 536ea4c..ab61430 100644 --- a/src/web/pug/guild.pug +++ b/src/web/pug/guild.pug @@ -11,7 +11,7 @@ mixin badge-private | Private mixin discord(channel, radio=false) - - let permissions = dUtils.getPermissions([], discord.guilds.get(channel.guild_id).roles, null, channel.permission_overwrites) + - let permissions = dUtils.getPermissions([], guild.roles, null, channel.permission_overwrites) .s-user-card.s-user-card__small if !dUtils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.ViewChannel) != icons.Icons.IconLock