diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..53f481b --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +# Configuration Discord +DISCORD_TOKEN=votre_token_discord +GUILD_ID=votre_guild_id +BRIDGE_CHANNEL_ID=1467491354924814411 + +# Configuration Pterodactyl +PTERODACTYL_API_URL=https://votre-panel.com +PTERODACTYL_API_TOKEN=votre_token_pterodactyl +PTERODACTYL_SERVER_ID=votre_server_id + +# Configuration Palworld +PALWORLD_API_TOKEN=votre_token_palworld_api + +# Configuration Base de données +DB_HOST=localhost +DB_PORT=3306 +DB_USER=votre_utilisateur +DB_PASSWORD=votre_mot_de_passe +DB_NAME=nom_de_la_base + +# Configuration DeepL (optionnel) +DEEPL_TOKEN=votre_token_deepl diff --git a/README.md b/README.md index 6188ce3..077f2a3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,58 @@ # rygain_bot +Bot Discord pour la gestion du serveur Palworld Rygainland. + +## Fonctionnalités + +### 🔗 Système de liaison Discord-Palworld +- Liaison automatique des comptes Discord et Palworld via code à 6 chiffres +- Gestion automatique des rôles lors de la liaison/déliaison +- Suivi des dernières connexions + +### 🌉 Pont Discord-Palworld +- Messages Discord → Palworld (broadcast) +- Messages Palworld → Discord (avec avatar et pseudo Discord pour les comptes liés) +- Salon dédié : `1467491354924814411` + +### 📊 Statistiques serveur +- Affichage des joueurs connectés +- Statistiques du serveur Palworld + +### 🔧 Commandes disponibles +- `/lier-rygainland` - Lier votre compte Discord à Palworld +- `/delier-rygainland` - Délier votre compte +- `/lier` (Admin) - Lier manuellement un compte +- `/delier` (Admin) - Délier manuellement un compte +- `/server-stats` - Afficher les stats du serveur +- `/trad` - Traduire un message + +## Installation + +1. Cloner le repo +2. Copier `.env.example` vers `.env` +3. Configurer les variables d'environnement +4. Installer les dépendances : `npm install` +5. Lancer le bot : `node index.js` + +## Configuration + +Voir le fichier `.env.example` pour la liste complète des variables d'environnement. + +Variables importantes : +- `BRIDGE_CHANNEL_ID` - ID du salon Discord pour le pont Palworld (défaut: 1467491354924814411) +- `GUILD_ID` - ID du serveur Discord +- `PALWORLD_API_TOKEN` - Token API REST de Palworld +- `PTERODACTYL_API_TOKEN` - Token API Pterodactyl + +## Débogage + +Le bot affiche des logs détaillés préfixés par : +- `[BRIDGE]` - Logs du pont Discord-Palworld +- `[CONSOLE]` - Logs du monitoring de la console Pterodactyl +- `[LIER-RYGAINLAND]` - Logs de la commande de liaison + +Si le pont ne fonctionne pas, vérifiez : +1. Que le `BRIDGE_CHANNEL_ID` est correct dans `.env` +2. Que le bot a les permissions d'envoyer des messages et créer des webhooks dans le salon +3. Les logs pour voir si les messages sont détectés +4. Que l'API Palworld est accessible (http://play.louismazin.ovh:8212) diff --git a/consoleMonitor.js b/consoleMonitor.js index fc53974..6cd77b7 100644 --- a/consoleMonitor.js +++ b/consoleMonitor.js @@ -339,7 +339,12 @@ const connectWebSocket = async (pterodactylToken, serverId) => { } // Transférer le message de chat vers Discord via le bridge - await handlePalworldChat(log); + console.log(`📋 [CONSOLE] Traitement du log pour le bridge...`); + try { + await handlePalworldChat(log); + } catch (bridgeError) { + console.error('❌ [CONSOLE] Erreur lors du transfert vers le bridge:', bridgeError); + } const linkData = parseLogMessage(log); diff --git a/index.js b/index.js index de6bab2..bacc13b 100644 --- a/index.js +++ b/index.js @@ -64,8 +64,22 @@ client.once('ready', async () => { console.log('📦 Système de liaison activé'); // Initialiser le pont Palworld-Discord - const bridgeChannelId = '1467491354924814411'; - initPalworldBridge(client, bridgeChannelId); + const bridgeChannelId = process.env.BRIDGE_CHANNEL_ID || '1467491354924814411'; + console.log(`🔧 Configuration du pont: Salon ${bridgeChannelId}`); + + // Vérifier que le salon existe + try { + const bridgeChannel = await client.channels.fetch(bridgeChannelId); + if (bridgeChannel) { + console.log(`✅ Salon du pont trouvé: #${bridgeChannel.name}`); + initPalworldBridge(client, bridgeChannelId); + } else { + console.error(`❌ Salon du pont introuvable (ID: ${bridgeChannelId})`); + } + } catch (channelError) { + console.error(`❌ Erreur lors de la récupération du salon du pont:`, channelError.message); + console.error(`⚠️ Le pont Discord-Palworld est désactivé`); + } startConsoleMonitoring(client, process.env.PTERODACTYL_API_TOKEN); } catch (error) { diff --git a/palworld-bridge.js b/palworld-bridge.js index a0e3052..b8c4eea 100644 --- a/palworld-bridge.js +++ b/palworld-bridge.js @@ -3,15 +3,13 @@ const { getUserLink, getAllLinks } = require('./database.js'); let bridgeClient = null; let bridgeChannelId = null; -let wsInstance = null; // Initialiser le bridge -const initPalworldBridge = (client, channelId, ws) => { +const initPalworldBridge = (client, channelId) => { bridgeClient = client; bridgeChannelId = channelId; - wsInstance = ws; - console.log('🌉 Pont Palworld-Discord initialisé'); + console.log(`🌉 Pont Palworld-Discord initialisé (Salon: ${channelId})`); // Écouter les messages du salon Discord client.on('messageCreate', async (message) => { @@ -21,18 +19,24 @@ const initPalworldBridge = (client, channelId, ws) => { // Vérifier que c'est bien le salon du pont if (message.channelId !== bridgeChannelId) return; + console.log(`📨 [BRIDGE] Message Discord détecté de ${message.author.tag}: ${message.content}`); + try { // Récupérer le pseudo Palworld lié const userLink = await getUserLink(message.author.id); + console.log(`🔍 [BRIDGE] Liaison trouvée pour ${message.author.tag}:`, userLink); if (!userLink) { // L'utilisateur n'est pas lié + console.log(`⚠️ [BRIDGE] ${message.author.tag} n'est pas lié`); await message.reply('❌ Vous devez lier votre compte Palworld pour envoyer des messages. Utilisez `/lier-rygainland`'); return; } // Envoyer le message vers Palworld via broadcast + console.log(`🚀 [BRIDGE] Envoi vers Palworld: ${userLink.palworld_username}: ${message.content}`); await sendToPalworld(userLink.palworld_username, message.content); + console.log(`✅ [BRIDGE] Message envoyé avec succès vers Palworld`); } catch (error) { console.error('Erreur lors de l\'envoi du message vers Palworld:', error); @@ -84,7 +88,10 @@ const sendToPalworld = async (palworldUsername, content) => { // Parser les messages de chat Palworld et les envoyer sur Discord const parsePalworldChatAndSend = async (log) => { - if (!bridgeClient || !bridgeChannelId) return; + if (!bridgeClient || !bridgeChannelId) { + console.log('⚠️ [BRIDGE] Bridge non initialisé, impossible de traiter le message'); + return; + } // Format: [2026-02-01 13:08:02] [CHAT] coucou const chatRegex = /\[.*?\]\s*\[CHAT\]\s*<(.+?)>\s*(.+)/i; @@ -92,14 +99,22 @@ const parsePalworldChatAndSend = async (log) => { if (!match) return; + console.log(`📥 [BRIDGE] Message Palworld détecté dans les logs`); + const palworldUsername = match[1].trim(); const messageContent = match[2].trim(); + console.log(`📥 [BRIDGE] Palworld: ${palworldUsername}: ${messageContent}`); + // Ignorer les messages de commande !lier - if (messageContent.toLowerCase().startsWith('!lier')) return; + if (messageContent.toLowerCase().startsWith('!lier')) { + console.log(`⏭️ [BRIDGE] Commande !lier ignorée`); + return; + } try { // Récupérer le salon + console.log(`🔍 [BRIDGE] Récupération du salon ${bridgeChannelId}...`); const channel = await bridgeClient.channels.fetch(bridgeChannelId).catch(() => null); if (!channel) { console.error('❌ Impossible de trouver le salon du pont');