85 lines
2.3 KiB
TypeScript
85 lines
2.3 KiB
TypeScript
/**
|
|
* Joel Discord Bot - Main Entry Point
|
|
*
|
|
* A well-structured Discord bot with clear separation of concerns:
|
|
* - core/ - Bot client, configuration, logging
|
|
* - commands/ - Slash command definitions and handling
|
|
* - events/ - Discord event handlers
|
|
* - features/ - Feature modules (Joel AI, message logging, etc.)
|
|
* - services/ - External services (AI providers)
|
|
* - database/ - Database schema and repositories
|
|
* - utils/ - Shared utilities
|
|
*/
|
|
|
|
import { GatewayIntentBits } from "discord.js";
|
|
import { BotClient } from "./core/client";
|
|
import { config } from "./core/config";
|
|
import { createLogger } from "./core/logger";
|
|
import { registerEvents } from "./events";
|
|
import { logVoiceDependencyHealth, stopSpontaneousMentionsCron } from "./features/joel";
|
|
import { buildWebCss, startWebCssWatcher, startWebServer } from "./web";
|
|
import { runMigrations } from "./database/migrate";
|
|
import type { FSWatcher } from "fs";
|
|
|
|
const logger = createLogger("Main");
|
|
let webCssWatcher: FSWatcher | null = null;
|
|
const isProduction = Bun.env.NODE_ENV === "production";
|
|
|
|
// Create the Discord client with required intents
|
|
const client = new BotClient({
|
|
intents: [
|
|
GatewayIntentBits.MessageContent,
|
|
GatewayIntentBits.Guilds,
|
|
GatewayIntentBits.DirectMessages,
|
|
GatewayIntentBits.GuildMessages,
|
|
GatewayIntentBits.GuildModeration,
|
|
GatewayIntentBits.GuildMembers,
|
|
GatewayIntentBits.GuildVoiceStates,
|
|
],
|
|
});
|
|
|
|
// Register all event handlers
|
|
registerEvents(client);
|
|
|
|
// Start the bot
|
|
async function main(): Promise<void> {
|
|
logger.info("Starting Joel bot...");
|
|
|
|
try {
|
|
// Run database migrations
|
|
await runMigrations();
|
|
logVoiceDependencyHealth();
|
|
|
|
await client.login(config.discord.token);
|
|
|
|
// Start web server after bot is logged in
|
|
await buildWebCss();
|
|
if (!isProduction) {
|
|
webCssWatcher = startWebCssWatcher();
|
|
}
|
|
await startWebServer(client);
|
|
} catch (error) {
|
|
logger.error("Failed to start bot", error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Handle graceful shutdown
|
|
process.on("SIGINT", () => {
|
|
logger.info("Shutting down...");
|
|
webCssWatcher?.close();
|
|
stopSpontaneousMentionsCron();
|
|
client.destroy();
|
|
process.exit(0);
|
|
});
|
|
|
|
process.on("SIGTERM", () => {
|
|
logger.info("Shutting down...");
|
|
webCssWatcher?.close();
|
|
stopSpontaneousMentionsCron();
|
|
client.destroy();
|
|
process.exit(0);
|
|
});
|
|
|
|
main();
|