require('dotenv').config(); const { REST, Routes } = require('discord.js'); const chalk = require('chalk'); const fs = require('node:fs'); const path = require('node:path'); const { token, clientId, CLIENT_ID, GUILD_ID } = process.env; const finalClientId = clientId || CLIENT_ID; const guildId = GUILD_ID; if (!token) { console.error(chalk.red('❌ Le TOKEN n\'est pas défini dans les variables d\'environnement !')); console.error(chalk.yellow('💡 Ajoute TOKEN=ton_token dans ton fichier .env')); process.exit(1); } if (!finalClientId) { console.error(chalk.red('❌ Le CLIENT_ID n\'est pas défini dans les variables d\'environnement !')); console.error(chalk.yellow('💡 Pour obtenir ton CLIENT_ID:')); console.error(chalk.yellow(' 1. Va sur https://discord.com/developers/applications')); console.error(chalk.yellow(' 2. Sélectionne ton application')); console.error(chalk.yellow(' 3. Va dans l\'onglet "General Information"')); console.error(chalk.yellow(' 4. Copie "Application ID"')); console.error(chalk.yellow(' 5. Ajoute CLIENT_ID=ton_client_id dans ton fichier .env')); process.exit(1); } const commands = []; const commandsByCategory = new Map(); // Map pour stocker les commandes par catégorie const foldersPath = path.join(__dirname, 'commands'); const commandFolders = fs.readdirSync(foldersPath); for (const folder of commandFolders) { const commandsPath = path.join(foldersPath, folder); const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); for (const file of commandFiles) { const filePath = path.join(commandsPath, file); const command = require(filePath); if ('data' in command && 'execute' in command) { const commandData = command.data.toJSON(); const category = command.category || folder || 'other'; // Ajouter à la liste des commandes commands.push(commandData); // Ajouter à la map par catégorie if (!commandsByCategory.has(category)) { commandsByCategory.set(category, []); } commandsByCategory.get(category).push({ name: commandData.name, description: commandData.description, data: commandData }); } else { console.warn(chalk.yellow(`⚠️ La commande à ${filePath} manque une propriété requise "data" ou "execute".`)); } } } const rest = new REST().setToken(token); (async () => { try { console.log(chalk.blue(`🔄 Déploiement de ${commands.length} commande(s) application (/)...`)); console.log(chalk.cyan('\n📋 Commandes à déployer par catégorie:')); // Trier les catégories par ordre alphabétique const sortedCategories = Array.from(commandsByCategory.keys()).sort(); for (const category of sortedCategories) { const categoryCommands = commandsByCategory.get(category); console.log(chalk.magenta(`\n 📁 ${category.toUpperCase()} (${categoryCommands.length} commande(s)):`)); categoryCommands.forEach(cmd => { console.log(chalk.gray(` - /${cmd.name} - ${cmd.description}`)); }); } // Déployer sur une guild spécifique si GUILD_ID est défini (plus rapide pour tester) // Si GUILD_ID est défini, on déploie SEULEMENT sur la guild (pas de global pour éviter les doublons) if (guildId) { console.log(chalk.yellow(`\n📍 Déploiement sur la guild: ${guildId} (uniquement)`)); console.log(chalk.gray(' (Pas de déploiement global pour éviter les doublons)')); const guildData = await rest.put( Routes.applicationGuildCommands(finalClientId, guildId), { body: commands }, ); console.log(chalk.green(`✅ ${guildData.length} commande(s) déployée(s) sur la guild avec succès !`)); console.log(chalk.cyan('💡 Les commandes sont disponibles immédiatement sur cette guild uniquement.')); console.log(chalk.yellow('💡 Pour déployer globalement, retire GUILD_ID du .env et relance le script.')); } else { // Déployer globalement seulement si pas de GUILD_ID console.log(chalk.yellow(`\n🌍 Déploiement global (tous les serveurs)...`)); const globalData = await rest.put( Routes.applicationCommands(finalClientId), { body: commands }, ); console.log(chalk.green(`✅ ${globalData.length} commande(s) globale(s) rechargée(s) avec succès !`)); console.log(chalk.yellow('\n💡 Note: Les commandes globales peuvent prendre 1-2h à apparaître sur Discord.')); console.log(chalk.yellow(' Pour un déploiement plus rapide sur une guild, ajoute GUILD_ID=ton_guild_id dans .env')); console.log(chalk.yellow(' Si elles n\'apparaissent pas après 2h, redémarre Discord (Ctrl+R).')); } // Afficher les commandes déployées par catégorie console.log(chalk.blue('\n📝 Commandes déployées par catégorie:')); for (const category of sortedCategories) { const categoryCommands = commandsByCategory.get(category); console.log(chalk.magenta(`\n 📁 ${category.toUpperCase()} (${categoryCommands.length} commande(s)):`)); categoryCommands.forEach((cmd, index) => { console.log(chalk.gray(` ${index + 1}. /${cmd.name} - ${cmd.description}`)); }); } } catch (error) { console.error(chalk.red('\n❌ Erreur lors du déploiement des commandes:')); console.error(chalk.red(` Code: ${error.code || 'N/A'}`)); console.error(chalk.red(` Message: ${error.message || error}`)); if (error.code === 50001) { console.error(chalk.red('\n Le bot n\'a pas été trouvé. Vérifie que CLIENT_ID est correct dans .env')); } else if (error.code === 50013) { console.error(chalk.red('\n Le bot n\'a pas les permissions nécessaires dans cette guild.')); } else if (error.code === 50035) { console.error(chalk.red('\n Erreur de validation. Une commande a un format invalide.')); if (error.body?.errors) { console.error(chalk.red(' Détails:')); console.error(JSON.stringify(error.body.errors, null, 2)); } } else if (error.rawError) { console.error(chalk.red('\n Détails complets:')); console.error(JSON.stringify(error.rawError, null, 2)); } if (error.requestBody) { console.error(chalk.yellow('\n Corps de la requête:')); console.error(JSON.stringify(error.requestBody, null, 2)); } process.exit(1); } })();