const axios = require('axios'); const { getUserLink, getAllLinks } = require('./database.js'); let bridgeClient = null; let bridgeChannelId = null; // Initialiser le bridge const initPalworldBridge = (client, channelId) => { bridgeClient = client; bridgeChannelId = channelId; console.log(`🌉 [BRIDGE] Pont Palworld-Discord initialisé (Salon: ${channelId})`); // Écouter les messages du salon Discord client.on('messageCreate', async (message) => { // Ignorer les messages du bot lui-même if (message.author.bot) return; // 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é console.log(`🔍 [BRIDGE] Recherche de liaison pour ${message.author.tag} (ID: ${message.author.id})`); 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); await message.reply('❌ Erreur lors de l\'envoi du message vers Palworld').catch(() => {}); } }); }; // Envoyer un message vers Palworld via RCON broadcast const sendToPalworld = async (palworldUsername, content) => { try { // Nettoyer le message (enlever les mentions, emojis personnalisés, etc.) let cleanContent = content .replace(/<@!?\d+>/g, '@utilisateur') // Remplacer les mentions .replace(/<#\d+>/g, '#salon') // Remplacer les mentions de salons .replace(/<:.+?:\d+>/g, '') // Enlever les emojis personnalisés .replace(/\n/g, ' ') // Remplacer les sauts de ligne .trim(); // Limiter la longueur du message if (cleanContent.length > 200) { cleanContent = cleanContent.substring(0, 197) + '...'; } // Format du message pour Palworld const broadcastMessage = `[Discord] ${palworldUsername}: ${cleanContent}`; console.log(`🚀 [BRIDGE] Envoi HTTP vers Palworld: ${broadcastMessage}`); // Envoyer via l'API Palworld avec timeout const response = await axios({ method: 'post', url: 'http://play.louismazin.ovh:8212/v1/api/announce', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': `Basic ${process.env.PALWORLD_API_TOKEN}` }, data: { message: broadcastMessage }, timeout: 10000 // Timeout de 10s }); console.log(`✅ [BRIDGE] Message envoyé à Palworld (statut ${response.status}): ${broadcastMessage}`); } catch (error) { if (error.code === 'ECONNABORTED') { console.error('❌ [BRIDGE] Timeout lors de l\'envoi vers Palworld (10s)'); } else if (error.code === 'ECONNREFUSED') { console.error('❌ [BRIDGE] Connexion refusée par le serveur Palworld'); } else if (error.response) { console.error(`❌ [BRIDGE] Erreur HTTP ${error.response.status}:`, error.response.data); } else { console.error('❌ [BRIDGE] Erreur lors de l\'envoi vers Palworld:', error.message); } throw error; } }; // Parser les messages de chat Palworld et les envoyer sur Discord const parsePalworldChatAndSend = async (log) => { 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; const match = log.match(chatRegex); 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')) { console.log(`⏭️ [BRIDGE] Commande !lier ignorée`); return; } if (messageContent.toLowerCase().startsWith('!')) { console.log(`⏭️ [BRIDGE] Message ignoré (commence par !)`); 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'); return; } // Chercher si le joueur a un compte Discord lié const allLinks = await getAllLinks(); const linkedUser = allLinks.find(link => link.palworld_username === palworldUsername); if (linkedUser) { // Utilisateur lié : utiliser webhook pour afficher sa PP et son pseudo Discord try { const discordUser = await bridgeClient.users.fetch(linkedUser.discord_id).catch(() => null); if (discordUser) { // Récupérer le membre du serveur pour avoir son displayName const guild = channel.guild; const member = await guild.members.fetch(linkedUser.discord_id).catch(() => null); const displayName = member ? member.displayName : discordUser.username; // Créer ou récupérer un webhook pour ce salon const webhooks = await channel.fetchWebhooks(); let webhook = webhooks.find(wh => wh.name === 'Palworld Bridge'); if (!webhook) { webhook = await channel.createWebhook({ name: 'Palworld Bridge', avatar: 'https://i.imgur.com/AfFp7pu.png' // Logo Palworld }); } // Envoyer via webhook avec le pseudo Discord du serveur et l'avatar await webhook.send({ content: messageContent, username: displayName, avatarURL: discordUser.displayAvatarURL({ dynamic: true, size: 256 }) }); console.log(`✅ Message Palworld envoyé sur Discord (via webhook): ${displayName}: ${messageContent}`); return; } } catch (error) { console.error('Erreur lors de l\'envoi via webhook:', error); // Fallback vers message normal } } // Utilisateur non lié ou erreur webhook : envoyer un message normal await channel.send(`**${palworldUsername}**: ${messageContent}`); console.log(`✅ Message Palworld envoyé sur Discord: ${palworldUsername}: ${messageContent}`); } catch (error) { console.error('Erreur lors de l\'envoi du message Palworld vers Discord:', error); } }; // Fonction appelée par consoleMonitor pour traiter les messages de chat const handlePalworldChat = async (log) => { await parsePalworldChatAndSend(log); }; module.exports = { initPalworldBridge, handlePalworldChat };