124 lines
3.4 KiB
JavaScript
124 lines
3.4 KiB
JavaScript
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';
|
|
|
|
// 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();
|
|
|
|
// 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;
|
|
|
|
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 => {
|
|
console.log(`[main] Successfully initialized ${clients.length} Discord clients`);
|
|
}).catch(error => {
|
|
console.error(`[main] Failed to start bot: ${error.message}`);
|
|
process.exit(1);
|
|
});
|