forked from syntaxbullet/AuroraBot-discord
Update loaders, handlers, and BotClient to use centralized logger: - CommandLoader.ts and EventLoader.ts - AutocompleteHandler.ts, CommandHandler.ts, ComponentInteractionHandler.ts - BotClient.ts Provides consistent formatting across all core library logging.
98 lines
3.7 KiB
TypeScript
98 lines
3.7 KiB
TypeScript
import { Client as DiscordClient, Collection, GatewayIntentBits, REST, Routes } from "discord.js";
|
|
import { join } from "node:path";
|
|
import type { Command } from "@lib/types";
|
|
import { env } from "@lib/env";
|
|
import { CommandLoader } from "@lib/loaders/CommandLoader";
|
|
import { EventLoader } from "@lib/loaders/EventLoader";
|
|
import { logger } from "@lib/logger";
|
|
|
|
export class Client extends DiscordClient {
|
|
|
|
commands: Collection<string, Command>;
|
|
private commandLoader: CommandLoader;
|
|
private eventLoader: EventLoader;
|
|
|
|
constructor({ intents }: { intents: number[] }) {
|
|
super({ intents });
|
|
this.commands = new Collection<string, Command>();
|
|
this.commandLoader = new CommandLoader(this);
|
|
this.eventLoader = new EventLoader(this);
|
|
}
|
|
|
|
async loadCommands(reload: boolean = false) {
|
|
if (reload) {
|
|
this.commands.clear();
|
|
logger.info("♻️ Reloading commands...");
|
|
}
|
|
|
|
const commandsPath = join(import.meta.dir, '../commands');
|
|
const result = await this.commandLoader.loadFromDirectory(commandsPath, reload);
|
|
|
|
logger.info(`📦 Command loading complete: ${result.loaded} loaded, ${result.skipped} skipped, ${result.errors.length} errors`);
|
|
}
|
|
|
|
async loadEvents(reload: boolean = false) {
|
|
if (reload) {
|
|
this.removeAllListeners();
|
|
logger.info("♻️ Reloading events...");
|
|
}
|
|
|
|
const eventsPath = join(import.meta.dir, '../events');
|
|
const result = await this.eventLoader.loadFromDirectory(eventsPath, reload);
|
|
|
|
logger.info(`📦 Event loading complete: ${result.loaded} loaded, ${result.skipped} skipped, ${result.errors.length} errors`);
|
|
}
|
|
|
|
|
|
|
|
async deployCommands() {
|
|
// We use env.DISCORD_BOT_TOKEN directly so this can run without client.login()
|
|
const token = env.DISCORD_BOT_TOKEN;
|
|
if (!token) {
|
|
logger.error("DISCORD_BOT_TOKEN is not set.");
|
|
return;
|
|
}
|
|
|
|
const rest = new REST().setToken(token);
|
|
const commandsData = this.commands.map(c => c.data.toJSON());
|
|
const guildId = env.DISCORD_GUILD_ID;
|
|
const clientId = env.DISCORD_CLIENT_ID;
|
|
|
|
if (!clientId) {
|
|
logger.error("DISCORD_CLIENT_ID is not set.");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
logger.info(`Started refreshing ${commandsData.length} application (/) commands.`);
|
|
|
|
let data;
|
|
if (guildId) {
|
|
logger.info(`Registering commands to guild: ${guildId}`);
|
|
data = await rest.put(
|
|
Routes.applicationGuildCommands(clientId, guildId),
|
|
{ body: commandsData },
|
|
);
|
|
// Clear global commands to avoid duplicates
|
|
await rest.put(Routes.applicationCommands(clientId), { body: [] });
|
|
} else {
|
|
logger.info('Registering commands globally');
|
|
data = await rest.put(
|
|
Routes.applicationCommands(clientId),
|
|
{ body: commandsData },
|
|
);
|
|
}
|
|
|
|
logger.success(`Successfully reloaded ${(data as any).length} application (/) commands.`);
|
|
} catch (error: any) {
|
|
if (error.code === 50001) {
|
|
logger.warn("Missing Access: The bot is not in the guild or lacks 'applications.commands' scope.");
|
|
logger.warn(" If you are testing locally, make sure you invited the bot with scope 'bot applications.commands'.");
|
|
} else {
|
|
logger.error(error);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export const AuroraClient = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMembers] }); |