ClientX/index.js

130 lines
3.5 KiB
JavaScript
Raw Normal View History

2025-04-25 21:27:00 -04:00
import { Client, Collection, GatewayIntentBits } from 'discord.js';
import { createLogger } from './_src/logger.js';
import { initializePocketbase } from './_src/pocketbase.js';
import { loadModules } from './_src/loader.js';
import config from './config.js';
// For deprecated ephemeral option: convert to flags
import { ansi, wrapAnsi } from './_src/ansiColors.js';
2025-04-25 21:27:00 -04:00
// Initialize Discord client
const initializeClient = async (clientConfig) => {
// Create Discord client with intents
const client = new Client({
// Include GuildMembers intent to allow fetching all guild members
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers
]
});
// Attach config to client
client.config = clientConfig;
// Set up Winston logger
client.logger = createLogger(clientConfig);
client.logger.info(`Initializing client: ${clientConfig.id}`);
// Set up Pocketbase
client.pb = await initializePocketbase(clientConfig, client.logger);
// Commands collection
client.commands = new Collection();
// ANSI helper attached to client
client.ansi = ansi;
client.wrapAnsi = wrapAnsi;
2025-04-25 21:27:00 -04:00
// Load optional modules
await loadModules(clientConfig, client);
// TODO: If the logger level is debug, create event binds to raw and debug.
// Discord client events
client.on('interactionCreate', async (interaction) => {
if (!interaction.isChatInputCommand()) return;
2025-04-25 21:27:00 -04:00
const commandName = interaction.commandName;
try {
// Find command in collection
const command = client.commands.get(commandName);
if (!command) {
client.logger.warn(`Command not found: ${commandName}`);
await interaction.reply({
content: 'Sorry, this command is not properly registered.',
ephemeral: true
});
return;
}
// Execute the command
client.logger.debug(`Executing command: ${commandName}`);
await command.execute(interaction, client);
} catch (error) {
client.logger.error(`Error executing command ${commandName}: ${error.message}`);
// Handle already replied interactions
const replyContent = {
content: 'There was an error while executing this command.',
ephemeral: true
};
if (interaction.replied || interaction.deferred) {
await interaction.followUp(replyContent).catch(err => {
client.logger.error(`Failed to send followUp: ${err.message}`);
});
} else {
await interaction.reply(replyContent).catch(err => {
client.logger.error(`Failed to reply: ${err.message}`);
});
}
}
});
client.on('ready', () => {
client.logger.info(`Logged in as ${client.user.tag}`);
});
client.on('error', (error) => {
client.logger.error(`Client error: ${error.message}`);
});
// Login to Discord
try {
await client.login(clientConfig.discord.token);
return client;
} catch (error) {
client.logger.error(`Failed to login: ${error.message}`);
throw error;
}
};
// Main function to start bot
const startBot = async () => {
const clients = [];
// Initialize each client from config
for (const clientConfig of config.clients) {
try {
const client = await initializeClient(clientConfig);
clients.push(client);
} catch (error) {
console.error(`Failed to initialize client ${clientConfig.id}:`, error);
}
}
return clients;
};
// Launch the bot
startBot().then(clients => {
2025-05-02 16:45:36 +00:00
console.log(`[main] Successfully initialized ${clients.length} Discord clients`);
2025-04-25 21:27:00 -04:00
}).catch(error => {
2025-05-02 16:45:36 +00:00
console.error(`[main] Failed to start bot: ${error.message}`);
process.exit(1);
2025-04-25 21:27:00 -04:00
});