Only offer to link channels the bridge can access

This commit is contained in:
Cadence Ember
2025-02-24 02:14:46 +13:00
parent 5631b7e956
commit 20dabf4ad5
4 changed files with 38 additions and 12 deletions

View File

@@ -1,5 +1,6 @@
// @ts-check
const DiscordTypes = require("discord-api-types/v10")
const {Endpoints, SnowTransfer} = require("snowtransfer")
const {reg} = require("../matrix/read-registration")
const {Client: CloudStorm} = require("cloudstorm")
@@ -36,15 +37,15 @@ class DiscordClient {
}
})
this.ready = false
/** @type {import("discord-api-types/v10").APIUser} */
/** @type {DiscordTypes.APIUser} */
// @ts-ignore avoid setting as or null because we know we need to wait for ready anyways
this.user = null
/** @type {Pick<import("discord-api-types/v10").APIApplication, "id" | "flags">} */
/** @type {Pick<DiscordTypes.APIApplication, "id" | "flags">} */
// @ts-ignore
this.application = null
/** @type {Map<string, import("discord-api-types/v10").APIChannel>} */
/** @type {Map<string, DiscordTypes.APIChannel>} */
this.channels = new Map()
/** @type {Map<string, import("discord-api-types/v10").APIGuild>} */
/** @type {Map<string, DiscordTypes.APIGuild & {members: DiscordTypes.APIGuildMember[]}>} */ // we get members from the GUILD_CREATE and we do maintain it
this.guilds = new Map()
/** @type {Map<string, Array<string>>} */
this.guildChannelMap = new Map()

View File

@@ -32,6 +32,7 @@ const utils = {
console.log(`Discord logged in as ${client.user.username}#${client.user.discriminator} (${client.user.id})`)
} else if (message.t === "GUILD_CREATE") {
message.d.members = message.d.members.filter(m => m.user.id === client.user.id) // only keep the bot's own member - it's needed to determine private channels on web
client.guilds.set(message.d.id, message.d)
const arr = []
client.guildChannelMap.set(message.d.id, arr)
@@ -101,6 +102,13 @@ const utils = {
}
}
} else if (message.t === "GUILD_MEMBER_UPDATE") {
const guild = client.guilds.get(message.d.guild_id)
const member = guild?.members.find(m => m.user.id === message.d.user.id)
if (member) { // only update existing members (i.e. the bot's own member) - don't want to inflate the cache with new irrelevant ones
Object.assign(member, message.d)
}
} else if (message.t === "THREAD_CREATE") {
client.channels.set(message.d.id, message.d)
if (message.d["guild_id"]) {

View File

@@ -192,12 +192,17 @@ block body
.s-card.p0
ul.my8.ml24
each row in removedUncachedChannels
li: a(href=`https://discord.com/channels/${guild_id}/${row.channel_id}`)= row.nick || row.name
li: a(href=`https://discord.com/channels/${guild_id}/${row.id}`)= row.nick || row.name
h3.mt24 Unavailable channels: Wrong type
.s-card.p0
ul.my8.ml24
each row in removedWrongTypeChannels
li: a(href=`https://discord.com/channels/${guild_id}/${row.channel_id}`) (#{row.type}) #{row.name}
li: a(href=`https://discord.com/channels/${guild_id}/${row.id}`) (#{row.type}) #{row.name}
h3.mt24 Unavailable channels: Bridge can't access
.s-card.p0
ul.my8.ml24
each row in removedPrivateChannels
li: a(href=`https://discord.com/channels/${guild_id}/${row.id}`)= row.name
div- // Rooms
h3.mt24 Unavailable rooms: Already linked
.s-card.p0

View File

@@ -1,5 +1,6 @@
// @ts-check
const DiscordTypes = require("discord-api-types/v10")
const assert = require("assert/strict")
const {z} = require("zod")
const {H3Event, defineEventHandler, sendRedirect, createError, getValidatedQuery, readValidatedBody, setResponseHeader} = require("h3")
@@ -8,6 +9,7 @@ const {LRUCache} = require("lru-cache")
const Ty = require("../../types")
const uqr = require("uqr")
const {id: botID} = require("../../../addbot")
const {discord, as, sync, select, from, db} = require("../../passthrough")
/** @type {import("../pug-sync")} */
const pugSync = sync.require("../pug-sync")
@@ -15,6 +17,8 @@ const pugSync = sync.require("../pug-sync")
const createSpace = sync.require("../../d2m/actions/create-space")
/** @type {import("../auth")} */
const auth = require("../auth")
/** @type {import("../../discord/utils")} */
const utils = sync.require("../../discord/utils")
const {reg} = require("../../matrix/read-registration")
const schema = {
@@ -68,10 +72,11 @@ function filterTo(xs, fn) {
}
/**
* @param {string} guildID
* @param {DiscordTypes.APIGuild} guild
* @param {Ty.R.Hierarchy[]} rooms
* @param {string[]} roles
*/
function getChannelRoomsLinks(guildID, rooms) {
function getChannelRoomsLinks(guild, rooms, roles) {
function getPosition(channel) {
let position = 0
let looking = channel
@@ -83,7 +88,7 @@ function getChannelRoomsLinks(guildID, rooms) {
return position
}
let channelIDs = discord.guildChannelMap.get(guildID)
let channelIDs = discord.guildChannelMap.get(guild.id)
assert(channelIDs)
let linkedChannels = select("channel_room", ["channel_id", "room_id", "name", "nick"], {channel_id: channelIDs}).all()
@@ -93,8 +98,13 @@ function getChannelRoomsLinks(guildID, rooms) {
linkedChannelsWithDetails.sort((a, b) => getPosition(a.channel) - getPosition(b.channel))
let unlinkedChannelIDs = channelIDs.filter(c => !linkedChannelIDs.includes(c))
/** @type {DiscordTypes.APIGuildChannel[]} */ // @ts-ignore
let unlinkedChannels = unlinkedChannelIDs.map(c => discord.channels.get(c))
let removedWrongTypeChannels = filterTo(unlinkedChannels, c => c && [0, 5].includes(c.type))
let removedPrivateChannels = filterTo(unlinkedChannels, c => {
const permissions = utils.getPermissions(roles, guild.roles, botID, c["permission_overwrites"])
return utils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.ViewChannel)
})
unlinkedChannels.sort((a, b) => getPosition(a) - getPosition(b))
let linkedRoomIDs = linkedChannels.map(c => c.room_id)
@@ -107,7 +117,7 @@ function getChannelRoomsLinks(guildID, rooms) {
return {
linkedChannelsWithDetails, unlinkedChannels, unlinkedRooms,
removedUncachedChannels, removedWrongTypeChannels, removedLinkedRooms, removedWrongTypeRooms, removedArchivedThreadRooms
removedUncachedChannels, removedWrongTypeChannels, removedPrivateChannels, removedLinkedRooms, removedWrongTypeRooms, removedArchivedThreadRooms
}
}
@@ -130,16 +140,18 @@ as.router.get("/guild", defineEventHandler(async event => {
return pugSync.render(event, "guild_not_linked.pug", {guild, guild_id, spaces})
}
const roles = guild.members?.find(m => m.user.id === botID)?.roles || []
// Easy mode guild that hasn't been linked yet - need to remove elements that would require an existing space
if (!row.space_id) {
const links = getChannelRoomsLinks(guild_id, [])
const links = getChannelRoomsLinks(guild, [], roles)
return pugSync.render(event, "guild.pug", {guild, guild_id, ...links, ...row})
}
// Linked guild
const api = getAPI(event)
const rooms = await api.getFullHierarchy(row.space_id)
const links = getChannelRoomsLinks(guild_id, rooms)
const links = getChannelRoomsLinks(guild, rooms, roles)
return pugSync.render(event, "guild.pug", {guild, guild_id, ...links, ...row})
}))