sync child room avatars when guild is updated
This commit is contained in:
parent
9f717dc24f
commit
20cd7ab38e
2 changed files with 38 additions and 13 deletions
|
@ -17,6 +17,7 @@ const ks = sync.require("../../matrix/kstate")
|
||||||
const inflightRoomCreate = new Map()
|
const inflightRoomCreate = new Map()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Async because it gets all room state from the homeserver.
|
||||||
* @param {string} roomID
|
* @param {string} roomID
|
||||||
*/
|
*/
|
||||||
async function roomToKState(roomID) {
|
async function roomToKState(roomID) {
|
||||||
|
@ -60,6 +61,7 @@ function convertNameAndTopic(channel, guild, customName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Async because it may 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
|
||||||
*/
|
*/
|
||||||
|
@ -200,10 +202,10 @@ function channelToGuild(channel) {
|
||||||
3. Get kstate for channel
|
3. Get kstate for channel
|
||||||
4. Create room, return new ID
|
4. Create room, return new ID
|
||||||
|
|
||||||
New combined flow with ensure / sync:
|
Ensure + sync flow:
|
||||||
1. Get IDs
|
1. Get IDs
|
||||||
2. Does room exist?
|
2. Does room exist?
|
||||||
2.5: If room does exist AND don't need to sync: return here
|
2.5: If room does exist AND wasn't asked to sync: return here
|
||||||
3. Get kstate for channel
|
3. Get kstate for channel
|
||||||
4. Create room with kstate if room doesn't exist
|
4. Create room with kstate if room doesn't exist
|
||||||
5. Get and update room state with kstate if room does exist
|
5. Get and update room state with kstate if room does exist
|
||||||
|
@ -246,7 +248,7 @@ async function _syncRoom(channelID, shouldActuallySync) {
|
||||||
|
|
||||||
console.log(`[room sync] to matrix: ${channel.name}`)
|
console.log(`[room sync] to matrix: ${channel.name}`)
|
||||||
|
|
||||||
const {spaceID, channelKState} = await channelToKState(channel, guild)
|
const {spaceID, channelKState} = await channelToKState(channel, guild) // calling this in both branches because we don't want to calculate this if not syncing
|
||||||
|
|
||||||
// sync channel state to room
|
// sync channel state to room
|
||||||
const roomKState = await roomToKState(roomID)
|
const roomKState = await roomToKState(roomID)
|
||||||
|
@ -261,6 +263,16 @@ async function _syncRoom(channelID, shouldActuallySync) {
|
||||||
return roomID
|
return roomID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Ensures the room exists. If it doesn't, creates the room with an accurate initial state. */
|
||||||
|
function ensureRoom(channelID) {
|
||||||
|
return _syncRoom(channelID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually syncs. Gets all room state from the homeserver in order to diff, and uploads the icon to mxc if it has changed. */
|
||||||
|
function syncRoom(channelID) {
|
||||||
|
return _syncRoom(channelID, true)
|
||||||
|
}
|
||||||
|
|
||||||
async function _unbridgeRoom(channelID) {
|
async function _unbridgeRoom(channelID) {
|
||||||
/** @ts-ignore @type {DiscordTypes.APIGuildChannel} */
|
/** @ts-ignore @type {DiscordTypes.APIGuildChannel} */
|
||||||
const channel = discord.channels.get(channelID)
|
const channel = discord.channels.get(channelID)
|
||||||
|
@ -289,6 +301,7 @@ async function _unbridgeRoom(channelID) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Async because it gets all space state from the homeserver, then if necessary sends one state event back.
|
||||||
* @param {DiscordTypes.APIGuildTextChannel} channel
|
* @param {DiscordTypes.APIGuildTextChannel} channel
|
||||||
* @param {string} spaceID
|
* @param {string} spaceID
|
||||||
* @param {string} roomID
|
* @param {string} roomID
|
||||||
|
@ -311,14 +324,6 @@ async function _syncSpaceMember(channel, spaceID, roomID) {
|
||||||
return applyKStateDiffToRoom(spaceID, spaceDiff)
|
return applyKStateDiffToRoom(spaceID, spaceDiff)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const assert = require("assert")
|
const assert = require("assert").strict
|
||||||
const DiscordTypes = require("discord-api-types/v10")
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
|
|
||||||
const passthrough = require("../../passthrough")
|
const passthrough = require("../../passthrough")
|
||||||
|
@ -84,11 +84,31 @@ async function syncSpace(guildID) {
|
||||||
|
|
||||||
console.log(`[space sync] to matrix: ${guild.name}`)
|
console.log(`[space sync] to matrix: ${guild.name}`)
|
||||||
|
|
||||||
// sync channel state to room
|
// 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)
|
||||||
await createRoom.applyKStateDiffToRoom(spaceID, spaceDiff)
|
await createRoom.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
|
||||||
|
const newAvatarState = spaceDiff["m.room.avatar/"]
|
||||||
|
if (guild.icon && newAvatarState?.url) {
|
||||||
|
// don't try to update rooms with custom avatars though
|
||||||
|
const roomsWithCustomAvatars = db.prepare("SELECT room_id FROM channel_room WHERE custom_avatar IS NOT NULL").pluck().all()
|
||||||
|
|
||||||
|
const childRooms = ks.kstateToState(spaceKState).filter(({type, state_key, content}) => {
|
||||||
|
return type === "m.space.child" && "via" in content && roomsWithCustomAvatars.includes(state_key)
|
||||||
|
}).map(({state_key}) => state_key)
|
||||||
|
|
||||||
|
for (const roomID of childRooms) {
|
||||||
|
const avatarEventContent = await api.getStateEvent(roomID, "m.room.avatar", "")
|
||||||
|
if (avatarEventContent.url !== newAvatarState.url) {
|
||||||
|
await api.sendState(roomID, "m.room.avatar", "", newAvatarState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return spaceID
|
return spaceID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue