const { Client, GatewayIntentBits, Collection, ActivityType } = require('discord.js'); const { readdirSync } = require('fs'); const { join } = require('path'); const chalk = require('chalk'); const cron = require('node-cron'); require('dotenv').config(); // Configuration des couleurs pour les logs const colors = { success: chalk.green.bold, error: chalk.red.bold, warning: chalk.yellow.bold, info: chalk.blue.bold, debug: chalk.magenta.bold, system: chalk.cyan.bold, command: chalk.white.bold, event: chalk.greenBright.bold, database: chalk.blueBright.bold, api: chalk.yellowBright.bold, discord: chalk.hex('#5865F2').bold, clash: chalk.hex('#FFD700').bold, trophy: chalk.hex('#FF6B35').bold }; // Fonction de logging avec couleurs const logger = { success: (msg) => console.log(`${colors.success('✅ SUCCESS')} ${chalk.white(msg)}`), error: (msg) => console.log(`${colors.error('❌ ERROR')} ${chalk.white(msg)}`), warning: (msg) => console.log(`${colors.warning('⚠️ WARNING')} ${chalk.white(msg)}`), info: (msg) => console.log(`${colors.info('ℹ️ INFO')} ${chalk.white(msg)}`), debug: (msg) => console.log(`${colors.debug('🔍 DEBUG')} ${chalk.white(msg)}`), system: (msg) => console.log(`${colors.system('⚙️ SYSTEM')} ${chalk.white(msg)}`), command: (msg) => console.log(`${colors.command('🔧 COMMAND')} ${chalk.white(msg)}`), event: (msg) => console.log(`${colors.event('📡 EVENT')} ${chalk.white(msg)}`), database: (msg) => console.log(`${colors.database('🗄️ DATABASE')} ${chalk.white(msg)}`), api: (msg) => console.log(`${colors.api('🌐 API')} ${chalk.white(msg)}`), discord: (msg) => console.log(`${colors.discord('🎮 DISCORD')} ${chalk.white(msg)}`), clash: (msg) => console.log(`${colors.clash('⚔️ CLASH')} ${chalk.white(msg)}`), trophy: (msg) => console.log(`${colors.trophy('🏆 TROPHY')} ${chalk.white(msg)}`) }; // Banner d'initialisation function displayBanner() { console.clear(); console.log(colors.clash('╔══════════════════════════════════════════════════════════════════╗')); console.log(colors.clash('║ 🏰 CLASH ROYALE DISCORD BOT 🏰 ║')); console.log(colors.clash('║ By Neptunia Team ║')); console.log(colors.clash('╠══════════════════════════════════════════════════════════════════╣')); console.log(colors.clash('║ 🎮 Discord Integration | ⚔️ Clash Royale API | 🏆 Rankings ║')); console.log(colors.clash('╚══════════════════════════════════════════════════════════════════╝')); console.log(); } // Initialisation du client Discord const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessageReactions ] }); // Collections pour stocker les handlers client.commands = new Collection(); client.events = new Collection(); client.components = new Collection(); client.logger = logger; // Fonction pour charger les handlers async function loadHandlers() { const handlerFiles = readdirSync(join(__dirname, 'src', 'handlers')).filter(file => file.endsWith('.js')); logger.system('Chargement des handlers...'); for (const file of handlerFiles) { try { const handler = require(join(__dirname, 'src', 'handlers', file)); await handler(client); logger.success(`Handler chargé: ${colors.command(file)}`); } catch (error) { logger.error(`Erreur lors du chargement du handler ${file}: ${error.message}`); } } } // Fonction pour initialiser la base de données async function initializeDatabase() { try { const { initDB } = require('./src/utils/database'); await initDB(); logger.database('Base de données initialisée avec succès'); } catch (error) { logger.error(`Erreur lors de l'initialisation de la base de données: ${error.message}`); process.exit(1); } } // Fonction pour programmer les tâches automatiques function scheduleTasks() { // Vérification des trophées toutes les 30 minutes cron.schedule('*/30 * * * *', async () => { try { const { checkTrophyMilestones } = require('./src/services/trophyService'); await checkTrophyMilestones(client); logger.system('Vérification des trophées effectuée'); } catch (error) { logger.error(`Erreur lors de la vérification des trophées: ${error.message}`); } }); logger.system('Tâches automatiques programmées (trophées uniquement)'); } // Fonction principale d'initialisation async function initialize() { displayBanner(); logger.system('🚀 Initialisation du bot en cours...'); try { // Vérification des variables d'environnement if (!process.env.DISCORD_TOKEN) { throw new Error('DISCORD_TOKEN manquant dans le fichier .env'); } if (!process.env.CLASH_ROYALE_TOKEN) { throw new Error('CLASH_ROYALE_TOKEN manquant dans le fichier .env'); } logger.success('Variables d\'environnement validées'); // Initialisation de la base de données await initializeDatabase(); // Chargement des handlers await loadHandlers(); // Connexion à Discord logger.discord('Connexion à Discord en cours...'); await client.login(process.env.DISCORD_TOKEN); } catch (error) { logger.error(`Erreur fatale lors de l'initialisation: ${error.message}`); process.exit(1); } } // L'événement ready est géré par src/events/ready.js // Programmation des tâches automatiques (trophées uniquement) client.once('ready', () => { scheduleTasks(); }); // Gestion des erreurs globales process.on('unhandledRejection', (reason, promise) => { logger.error(`Promesse rejetée non gérée: ${reason}`); console.error(promise); }); process.on('uncaughtException', (error) => { logger.error(`Exception non capturée: ${error.message}`); console.error(error); }); // Gestion de l'arrêt propre process.on('SIGINT', () => { logger.warning('Signal SIGINT reçu, arrêt du bot...'); client.destroy(); process.exit(0); }); process.on('SIGTERM', () => { logger.warning('Signal SIGTERM reçu, arrêt du bot...'); client.destroy(); process.exit(0); }); // Démarrage du bot initialize();