diff --git a/consoleMonitor.js b/consoleMonitor.js index 603e91b..dc07fb4 100644 --- a/consoleMonitor.js +++ b/consoleMonitor.js @@ -15,6 +15,9 @@ let connectionTimestamp = null; let reconnectDelayMs = 5000; const RECONNECT_DELAY_MAX_MS = 5 * 60 * 1000; // 5 min +// Suivi des joueurs connectés (fallback si la console n’affiche pas les déconnexions) +const connectedPlayers = new Map(); // steamId -> { name, playerId, lastSeen } + const parseLogMessage = (log) => { // Format réel de log Palworld: // [2025-12-09 13:28:23] [CHAT] !link X2NMAY @@ -135,12 +138,87 @@ const getWebSocketCredentials = async (pterodactylToken, serverId) => { } }; +// Helper: récupérer la liste actuelle des joueurs via l’API Palworld +const fetchCurrentPlayers = async () => { + try { + const response = await axios({ + method: 'get', + maxBodyLength: Infinity, + url: 'http://play.louismazin.ovh:8212/v1/api/players', + headers: { + 'Accept': 'application/json', + 'Authorization': `Basic ${process.env.PALWORLD_API_TOKEN}` + } + }); + const players = response.data.players || {}; + const list = []; + for (const [, player] of Object.entries(players)) { + list.push({ + steamId: player.userId, + playerId: player.playerId, + name: player.name + }); + } + return list; + } catch (error) { + // API inaccessible quand le serveur est down + return null; + } +}; + +// Mettre à jour le set des joueurs et détecter les départs silencieux +const pollPlayersAndDetectDisconnects = async (serverState = null) => { + const list = await fetchCurrentPlayers(); + + const now = Date.now(); + + if (list && list.length > 0) { + // Marquer présents + for (const p of list) { + connectedPlayers.set(p.steamId, { name: p.name, playerId: p.playerId, lastSeen: now }); + } + // Détecter ceux qui ont disparu depuis le dernier poll + for (const [steamId, info] of connectedPlayers) { + const stillHere = list.find(x => x.steamId === steamId); + if (!stillHere) { + try { + const result = await updateLastConnection(steamId); + if (result.changes > 0) { + console.log(`✅ Départ silencieux détecté: ${info.name} (${steamId}) -> lastConnection mis à jour`); + } + } catch (e) { + console.error(`❌ Erreur update lastConnection pour ${steamId}:`, e.message); + } + connectedPlayers.delete(steamId); + } + } + } else { + // Pas de liste (serveur inaccessible) ou vide: + // Si le serveur est arrêté/stopping/offline, considérer tous comme déconnectés + if (serverState && ['offline', 'stopping', 'stopped'].includes(serverState)) { + for (const [steamId, info] of connectedPlayers) { + try { + const result = await updateLastConnection(steamId); + if (result.changes > 0) { + console.log(`✅ Serveur ${serverState}: déconnexion implicite de ${info.name} (${steamId})`); + } + } catch (e) { + console.error(`❌ Erreur update lastConnection pour ${steamId}:`, e.message); + } + } + connectedPlayers.clear(); + } + } +}; + const checkAndManageWebSocket = async () => { - const { hasActiveLinkCodes, cleanExpiredCodes } = require('./database.js'); - + const { cleanExpiredCodes } = require('./database.js'); try { await cleanExpiredCodes(); - + + // Fallback polling toutes les 20s + await pollPlayersAndDetectDisconnects(); + // Le WebSocket doit toujours être connecté maintenant (pour les déconnexions) if (!ws && !isConnecting) { console.log('🔌 Connexion au WebSocket pour surveillance...'); @@ -263,7 +341,13 @@ const connectWebSocket = async (pterodactylToken, serverId) => { } if (message.event === 'status') { - console.log('📊 Statut du serveur:', message.args[0]); + const state = message.args[0]; + console.log('📊 Statut du serveur:', state); + + // Si le serveur s’arrête/offline, forcer la mise à jour des joueurs connectés (déconnexions implicites) + if (['offline', 'stopping', 'stopped'].includes(state)) { + await pollPlayersAndDetectDisconnects(state); + } } } catch (error) { @@ -335,9 +419,9 @@ const startConsoleMonitoring = (discordClient, pterodactylToken) => { // Vérifier immédiatement checkAndManageWebSocket(); - // Vérifier toutes les 30 secondes (nettoyage codes et reconnect si besoin) + // Vérifier toutes les 20 secondes (nettoyage codes et reconnect si besoin) if (checkInterval) clearInterval(checkInterval); - checkInterval = setInterval(checkAndManageWebSocket, 30000); + checkInterval = setInterval(checkAndManageWebSocket, 20000); // 20s pour détecter vite les départs silencieux }; const stopConsoleMonitoring = () => {