const { Client, GatewayIntentBits, Partials, Collection, Events } = require("discord.js"); const { LavalinkManager } = require("lavalink-client"); const fs = require("fs"); const path = require("path"); const TicketManager = require("./utils/ticketManager.js"); require("dotenv").config(); const { Guilds, GuildMembers, GuildMessages, GuildVoiceStates, MessageContent, } = GatewayIntentBits; const { User, Message, GuildMember, ThreadMember, Channel } = Partials; const { loadEvents } = require("./Handlers/eventHandler"); const { loadCommands } = require("./Handlers/commandHandler"); const { errorHandler } = require("./utils/errorHandler.js"); const client = new Client({ intents: [Guilds, GuildMembers, GuildMessages, GuildVoiceStates, MessageContent, ], partials: [User, Message, GuildMember, ThreadMember, Channel], }); client.buttons = new Collection(); client.selectMenus = new Collection(); client.commands = new Collection(); client.modals = new Collection(); client.ticketManager = new TicketManager(client); client.lavalink = new LavalinkManager({ nodes: [ { host: 'localhost', port: 2333, authorization: 'yourshallnotpass', secure: false, id: 'main-node' } ], sendToShard: (guildId, payload) => { const guild = client.guilds.cache.get(guildId); if (guild) guild.shard.send(payload); }, client: { id: process.env.CLIENT_ID || '', username: 'Bot' }, autoSkip: true, emitNewSongsOnly: true, playerOptions: { clientBasedPositionUpdateInterval: 150, defaultSearchPlatform: "ytmsearch", volumeDecrementer: 0.75, onDisconnect: { autoReconnect: true, destroyPlayer: false }, onEmptyQueue: { destroyAfterMs: 30_000, }, useUnresolvedData: true } }); client.lavalink.nodeManager .on('connect', (node) => { console.log(`✅ Nœud Lavalink connecté : ${node.options.id}`); }) .on('disconnect', (node, reason) => { console.log(`❌ Nœud Lavalink déconnecté : ${node.options.id}`, reason); }) .on('error', (node, error) => { console.error(`❌ Erreur Lavalink sur ${node.options.id}:`, error); }) .on('reconnecting', (node) => { console.log(`🔄 Reconnexion au nœud ${node.options.id}...`); }); client.lavalink .on('trackStart', (player, track) => { console.log(`🎵 Événement trackStart déclenché pour: ${track.info.title}`); console.log('📊 État du player lors du trackStart:', { playing: player.playing, connected: player.connected, volume: player.volume }); const channel = client.channels.cache.get(player.textChannelId); if (channel) { channel.send(`🎵 Lecture en cours : **${track.info.title}** - ${track.info.author}`); } }) .on('trackEnd', (player, track) => { console.log(`✅ Piste terminée : ${track.info.title}`); }) .on('queueEnd', (player) => { const channel = client.channels.cache.get(player.textChannelId); if (channel) { channel.send('✅ File d\'attente terminée !'); } }) .on('playerCreate', (player) => { console.log(`🎮 Player créé pour le serveur ${player.guildId}`); }) .on('playerDestroy', (player) => { console.log(`💀 Player détruit pour le serveur ${player.guildId}`); }) .on('playerMove', (player, oldChannel, newChannel) => { console.log(`🔀 Player déplacé de ${oldChannel} vers ${newChannel}`); }) .on('playerDisconnect', (player, voiceChannelId) => { console.log(`❌ Player déconnecté du salon ${voiceChannelId}`); }) .on('playerSocketClosed', (player, payload) => { console.log(`🔌 Socket fermé:`, payload); }) .on('trackError', (player, track, payload) => { console.error(`❌ Erreur de lecture pour ${track.info.title}:`, payload); console.error('📋 Exception complète:', JSON.stringify(payload.exception, null, 2)); console.error('📋 Severity:', payload.exception?.severity); console.error('📋 Cause:', payload.exception?.cause); const channel = client.channels.cache.get(player.textChannelId); if (channel) { const errorMsg = payload.exception?.message || 'Erreur inconnue'; const errorCause = payload.exception?.cause || 'Pas de détails disponibles'; channel.send( `❌ **Erreur de lecture**\n` + `🎵 Musique : **${track.info.title}**\n` + `⚠️ Raison : ${errorMsg}\n` + `🔍 Détails : ${errorCause}\n\n` + `💡 **Solutions** :\n` + `• Vérifiez que Lavalink est à jour (v4.0.7)\n` + `• Vérifiez que le plugin YouTube est installé\n` + `• Redémarrez Lavalink si nécessaire` ); } // Passer à la musique suivante automatiquement if (player.queue.tracks.length > 0) { player.skip(); } }); const modalsPath = path.join(__dirname, "Events", "interactions", "modals"); const modalFiles = fs.readdirSync(modalsPath).filter(file => file.endsWith(".js")); for (const file of modalFiles) { try { const modal = require(`./Events/interactions/modals/${file}`); client.modals.set(modal.data.customId, modal); } catch (err) { console.error(`❌ Erreur lors du chargement du modal ${file}:`, err); } } const buttonsPath = path.join(__dirname, "Events", "interactions", "buttons"); const buttonFiles = fs.readdirSync(buttonsPath).filter(file => file.endsWith(".js")); for (const file of buttonFiles) { try { const button = require(`./Events/interactions/buttons/${file}`); client.buttons.set(button.data.customId, button); } catch (err) { console.error(`❌ Erreur lors du chargement du bouton ${file}:`, err); } } const menusPath = path.join(__dirname, "Events", "interactions", "menus"); const menuFiles = fs.readdirSync(menusPath).filter(file => file.endsWith(".js")); for (const file of menuFiles) { try { const menu = require(`./Events/interactions/menus/${file}`); client.selectMenus.set(menu.data.customId, menu); } catch (err) { console.error(`❌ Erreur lors du chargement du menu ${file}:`, err); } } // Charger les events et commands AVANT le lo client.login(process.env.TOKEN) .then(() => { console.log("✅ Bot connecté avec succès !"); loadEvents(client); loadCommands(client); errorHandler(client); }) .catch((err) => console.error("❌ Erreur de connexion :", err));