From 73b717b9e36ba1915a4e32ec3176f88d133613d3 Mon Sep 17 00:00:00 2001 From: Wiktoria Van Harneveldt Date: Sun, 19 Oct 2025 20:07:26 +0200 Subject: [PATCH 1/2] feat: add guildCreate event and server guard utilities --- src/events/guild-create.ts | 13 +++++++++++++ src/events/index.ts | 2 ++ src/events/interaction-create.ts | 13 +++++++++++++ src/events/ready.ts | 8 ++++++++ src/util/server-guard.ts | 24 ++++++++++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 src/events/guild-create.ts create mode 100644 src/util/server-guard.ts diff --git a/src/events/guild-create.ts b/src/events/guild-create.ts new file mode 100644 index 0000000..6e868f4 --- /dev/null +++ b/src/events/guild-create.ts @@ -0,0 +1,13 @@ +import { Events } from 'discord.js'; +import { createEvent } from '../util/events.js'; +import { leaveIfNotAllowedServer } from '../util/server-guard.js'; + +export const guildCreateEvent = createEvent( + { + name: Events.GuildCreate, + }, + async (guild) => { + // Leave the server if it's not the allowed one + await leaveIfNotAllowedServer(guild); + } +); diff --git a/src/events/index.ts b/src/events/index.ts index f4c5fd0..86d64fa 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,3 +1,4 @@ +import { guildCreateEvent } from './guild-create.js'; import { hasVarEvent } from './has-var.js'; import { interactionCreateEvent } from './interaction-create.js'; import { justAskEvent } from './just-ask.js'; @@ -6,6 +7,7 @@ import type { DiscordEvent } from './types.js'; export const events = [ readyEvent, + guildCreateEvent, justAskEvent, hasVarEvent, interactionCreateEvent, diff --git a/src/events/interaction-create.ts b/src/events/interaction-create.ts index 98a82c5..17c8f9b 100644 --- a/src/events/interaction-create.ts +++ b/src/events/interaction-create.ts @@ -1,6 +1,7 @@ import { Events } from 'discord.js'; import { commands } from '../commands/index.js'; import { createEvent } from '../util/events.js'; +import { isAllowedServer } from '../util/server-guard.js'; export const interactionCreateEvent = createEvent( { @@ -8,6 +9,18 @@ export const interactionCreateEvent = createEvent( }, async (interaction) => { if (interaction.isChatInputCommand() || interaction.isMessageContextMenuCommand()) { + // Block commands from unauthorized servers + if (!interaction.guildId || !isAllowedServer(interaction.guildId)) { + console.log(`⚠️ Command blocked from unauthorized server: ${interaction.guildId}`); + if (interaction.isRepliable()) { + await interaction.reply({ + content: '❌ This bot is not authorized to operate in this server.', + ephemeral: true, + }); + } + return; + } + console.log(`Interaction received: ${interaction.commandName}`); const command = commands.get(interaction.commandName); diff --git a/src/events/ready.ts b/src/events/ready.ts index dd9127a..17304e0 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -3,6 +3,7 @@ import { config } from '../env.js'; import { fetchAndCachePublicChannelsMessages } from '../util/cache.js'; import { createEvent } from '../util/events.js'; import { syncGuidesToChannel } from '../util/post-guides.js'; +import { leaveIfNotAllowedServer } from '../util/server-guard.js'; export const readyEvent = createEvent( { @@ -11,6 +12,13 @@ export const readyEvent = createEvent( }, async (client) => { console.log(`Ready! Logged in as ${client.user.tag}`); + + // Check all guilds and leave any unauthorized ones + console.log(`🔍 Checking ${client.guilds.cache.size} guild(s)...`); + for (const guild of client.guilds.cache.values()) { + await leaveIfNotAllowedServer(guild); + } + if (config.fetchAndSyncMessages) { const guild = client.guilds.cache.get(config.serverId); if (guild) { diff --git a/src/util/server-guard.ts b/src/util/server-guard.ts new file mode 100644 index 0000000..4c16b7d --- /dev/null +++ b/src/util/server-guard.ts @@ -0,0 +1,24 @@ +import type { Guild } from 'discord.js'; +import { config } from '../env.js'; + +/** + * Checks if a guild is the allowed server + */ +export function isAllowedServer(guildId: string): boolean { + return guildId === config.serverId; +} + +/** + * Leaves a guild if it's not the allowed server + * @returns true if the bot left the guild, false if it stayed + */ +export async function leaveIfNotAllowedServer(guild: Guild): Promise { + if (!isAllowedServer(guild.id)) { + console.log(`⚠️ Bot added to unauthorized server: ${guild.name} (${guild.id})`); + console.log(`🚪 Leaving server...`); + await guild.leave(); + console.log(`✅ Left unauthorized server: ${guild.name}`); + return true; + } + return false; +} From bd6fd04cb2e38ab95857a22954a912c163b9b551 Mon Sep 17 00:00:00 2001 From: Wiktoria Van Harneveldt Date: Sun, 19 Oct 2025 20:12:28 +0200 Subject: [PATCH 2/2] fix: update ephemeral reply flag to use MessageFlags.Ephemeral for better compatibility with Discord.js --- src/events/interaction-create.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/interaction-create.ts b/src/events/interaction-create.ts index 17c8f9b..889a874 100644 --- a/src/events/interaction-create.ts +++ b/src/events/interaction-create.ts @@ -1,4 +1,4 @@ -import { Events } from 'discord.js'; +import { Events, MessageFlags } from 'discord.js'; import { commands } from '../commands/index.js'; import { createEvent } from '../util/events.js'; import { isAllowedServer } from '../util/server-guard.js'; @@ -15,7 +15,7 @@ export const interactionCreateEvent = createEvent( if (interaction.isRepliable()) { await interaction.reply({ content: '❌ This bot is not authorized to operate in this server.', - ephemeral: true, + flags: MessageFlags.Ephemeral, }); } return;