test
This commit is contained in:
parent
8e0dfb33b3
commit
c5b95a2698
88
commands/utility/diagnostique-ws.js
Normal file
88
commands/utility/diagnostique-ws.js
Normal file
@ -0,0 +1,88 @@
|
||||
const { SlashCommandBuilder, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const { getWebSocketStatus, forceWebSocketReconnect } = require('../../consoleMonitor.js');
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('diagnostique-ws')
|
||||
.setDescription('Vérifier l\'état du WebSocket et forcer une reconnexion si nécessaire')
|
||||
.addBooleanOption(option =>
|
||||
option.setName('reconnect')
|
||||
.setDescription('Forcer une reconnexion du WebSocket')
|
||||
.setRequired(false)
|
||||
),
|
||||
|
||||
async execute(interaction) {
|
||||
try {
|
||||
const forceReconnect = interaction.options.getBoolean('reconnect') || false;
|
||||
|
||||
if (forceReconnect) {
|
||||
await interaction.reply({
|
||||
content: '🔄 Reconnexion forcée du WebSocket en cours...',
|
||||
flags: MessageFlags.Ephemeral
|
||||
});
|
||||
|
||||
await forceWebSocketReconnect();
|
||||
|
||||
// Attendre un peu pour laisser le temps de se reconnecter
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}
|
||||
|
||||
const status = getWebSocketStatus();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(status.hasWebSocket && status.wsState === 'OPEN' ? 0x00FF00 : 0xFF0000)
|
||||
.setTitle('🔌 Diagnostic WebSocket')
|
||||
.addFields(
|
||||
{ name: '📊 Monitoring Actif', value: status.isMonitoring ? '✅ Oui' : '❌ Non', inline: true },
|
||||
{ name: '🔗 WebSocket Présent', value: status.hasWebSocket ? '✅ Oui' : '❌ Non', inline: true },
|
||||
{ name: '📡 État Connexion', value: status.wsState || 'N/A', inline: true },
|
||||
{ name: '🔄 En cours de connexion', value: status.isConnecting ? '⏳ Oui' : '✅ Non', inline: true },
|
||||
{ name: '💓 Heartbeat Actif', value: status.hasHeartbeat ? '✅ Oui' : '❌ Non', inline: true },
|
||||
{ name: '🔍 Vérification Auto', value: status.hasCheckInterval ? '✅ Oui' : '❌ Non', inline: true },
|
||||
{ name: '⏱️ Reconnexion Planifiée', value: status.hasPendingReconnect ? '⏳ Oui' : '❌ Non', inline: true },
|
||||
{ name: '🔁 Délai Reconnexion', value: `${Math.round(status.reconnectDelayMs / 1000)}s`, inline: true },
|
||||
{ name: '🔄 Refresh Credentials', value: status.hasRefreshInterval ? '✅ Oui' : '❌ Non', inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
if (status.connectionTimestamp) {
|
||||
embed.addFields({ name: '🕐 Dernière Connexion', value: status.connectionTimestamp, inline: false });
|
||||
}
|
||||
|
||||
if (status.monitoringStartTimestamp) {
|
||||
embed.addFields({ name: '🚀 Démarrage Monitoring', value: status.monitoringStartTimestamp, inline: false });
|
||||
}
|
||||
|
||||
// Recommandations
|
||||
let recommendations = '';
|
||||
if (!status.isMonitoring) {
|
||||
recommendations += '⚠️ Le monitoring n\'est pas actif. Redémarrer le bot.\n';
|
||||
}
|
||||
if (!status.hasWebSocket || status.wsState !== 'OPEN') {
|
||||
recommendations += '⚠️ Le WebSocket n\'est pas connecté. Utilisez `/diagnostique-ws reconnect:True` pour forcer une reconnexion.\n';
|
||||
}
|
||||
if (status.hasPendingReconnect) {
|
||||
recommendations += `ℹ️ Une reconnexion est prévue dans ${Math.round(status.reconnectDelayMs / 1000)}s.\n`;
|
||||
}
|
||||
|
||||
if (recommendations) {
|
||||
embed.addFields({ name: '💡 Recommandations', value: recommendations, inline: false });
|
||||
} else {
|
||||
embed.addFields({ name: '✅ Statut', value: 'Tout fonctionne normalement !', inline: false });
|
||||
}
|
||||
|
||||
if (forceReconnect) {
|
||||
await interaction.editReply({ content: null, embeds: [embed], flags: MessageFlags.Ephemeral });
|
||||
} else {
|
||||
await interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral });
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('[DIAGNOSTIQUE-WS] Erreur:', error);
|
||||
await interaction.reply({
|
||||
content: '❌ Erreur lors du diagnostic',
|
||||
flags: MessageFlags.Ephemeral
|
||||
}).catch(() => {});
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -260,39 +260,43 @@ const scheduleReconnect = () => {
|
||||
if (reconnectTimeout) clearTimeout(reconnectTimeout);
|
||||
const delay = reconnectDelayMs;
|
||||
reconnectDelayMs = Math.min(reconnectDelayMs * 2, RECONNECT_DELAY_MAX_MS);
|
||||
console.log(`🔄 Reconnexion WebSocket dans ${Math.round(delay / 1000)}s...`);
|
||||
console.log(`🔄 [WEBSOCKET] Reconnexion WebSocket programmée dans ${Math.round(delay / 1000)}s... (Monitoring actif: ${isMonitoring})`);
|
||||
reconnectTimeout = setTimeout(() => {
|
||||
console.log('🔄 [WEBSOCKET] Tentative de reconnexion maintenant...');
|
||||
checkAndManageWebSocket();
|
||||
}, delay);
|
||||
};
|
||||
|
||||
const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
|
||||
console.log('⚠️ WebSocket déjà connecté ou en cours de connexion');
|
||||
console.log('⚠️ [WEBSOCKET] Déjà connecté ou en cours de connexion (état:', ws.readyState, ')');
|
||||
return;
|
||||
}
|
||||
if (isConnecting) {
|
||||
console.log('⚠️ Connexion WebSocket déjà en cours');
|
||||
console.log('⚠️ [WEBSOCKET] Connexion déjà en cours, abandon de cette tentative');
|
||||
return;
|
||||
}
|
||||
|
||||
isConnecting = true;
|
||||
connectionTimestamp = Date.now();
|
||||
console.log(`📅 Timestamp de connexion: ${new Date(connectionTimestamp).toISOString()}`);
|
||||
console.log(`📅 [WEBSOCKET] Timestamp de connexion: ${new Date(connectionTimestamp).toISOString()}`);
|
||||
|
||||
try {
|
||||
// Toujours rafraîchir les credentials pour éviter les tokens expirés après redémarrage serveur
|
||||
console.log('🔑 [WEBSOCKET] Récupération de nouveaux credentials...');
|
||||
const credentials = await getWebSocketCredentials(pterodactylToken, serverId);
|
||||
console.log('✅ [WEBSOCKET] Credentials récupérés avec succès');
|
||||
|
||||
ws = new WebSocket(credentials.socket, {
|
||||
origin: process.env.PTERODACTYL_API_URL
|
||||
});
|
||||
|
||||
ws.on('open', () => {
|
||||
console.log('✅ WebSocket Pterodactyl connecté');
|
||||
console.log('✅ [WEBSOCKET] WebSocket Pterodactyl connecté avec succès');
|
||||
isConnecting = false;
|
||||
resetReconnectBackoff();
|
||||
|
||||
console.log('🔐 [WEBSOCKET] Envoi de l\'authentification...');
|
||||
ws.send(JSON.stringify({
|
||||
event: 'auth',
|
||||
args: [credentials.token]
|
||||
@ -304,7 +308,8 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||
const message = JSON.parse(data.toString());
|
||||
|
||||
if (message.event === 'auth success') {
|
||||
console.log('✅ Authentification WebSocket réussie');
|
||||
console.log('✅ [WEBSOCKET] Authentification WebSocket réussie');
|
||||
console.log('📡 [WEBSOCKET] Demande de réception des logs console...');
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
event: 'send logs',
|
||||
@ -317,6 +322,7 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||
ws.send(JSON.stringify({ event: 'send heartbeat', args: [] }));
|
||||
}
|
||||
}, 30000);
|
||||
console.log('💓 [WEBSOCKET] Heartbeat configuré (30s)');
|
||||
}
|
||||
if (message.event === 'console output') {
|
||||
const log = message.args[0];
|
||||
@ -340,6 +346,11 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Détecter si c'est un message de chat
|
||||
if (log.includes('[CHAT]')) {
|
||||
console.log(`💬 [CONSOLE] Message de chat détecté: ${log.substring(0, 100)}`);
|
||||
}
|
||||
|
||||
// Transférer le message de chat vers Discord via le bridge
|
||||
console.log(`📋 [CONSOLE] Traitement du log pour le bridge...`);
|
||||
try {
|
||||
@ -400,12 +411,15 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||
});
|
||||
|
||||
ws.on('error', (error) => {
|
||||
console.error('❌ Erreur WebSocket:', error.message);
|
||||
console.error('❌ [WEBSOCKET] Erreur WebSocket:', error.message);
|
||||
console.error('❌ [WEBSOCKET] Code erreur:', error.code || 'N/A');
|
||||
isConnecting = false;
|
||||
});
|
||||
|
||||
ws.on('close', (code, reason) => {
|
||||
console.log(`⚠️ WebSocket Pterodactyl déconnecté (Code: ${code})`);
|
||||
const reasonStr = reason ? reason.toString() : 'Aucune raison fournie';
|
||||
console.log(`⚠️ [WEBSOCKET] WebSocket Pterodactyl déconnecté (Code: ${code}, Raison: ${reasonStr})`);
|
||||
console.log(`🔍 [WEBSOCKET] État actuel: isMonitoring=${isMonitoring}, isConnecting=${isConnecting}`);
|
||||
ws = null;
|
||||
isConnecting = false;
|
||||
connectionTimestamp = null;
|
||||
@ -413,18 +427,28 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||
if (heartbeatInterval) {
|
||||
clearInterval(heartbeatInterval);
|
||||
heartbeatInterval = null;
|
||||
console.log('💔 [WEBSOCKET] Heartbeat arrêté');
|
||||
}
|
||||
|
||||
// Planifier une reconnexion avec backoff (utile lors des redémarrages quotidiens du serveur)
|
||||
scheduleReconnect();
|
||||
if (isMonitoring) {
|
||||
scheduleReconnect();
|
||||
} else {
|
||||
console.log('⚠️ [WEBSOCKET] Monitoring désactivé, pas de reconnexion');
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la connexion WebSocket:', error);
|
||||
console.error('❌ [WEBSOCKET] Erreur lors de la connexion WebSocket:', error.message);
|
||||
console.error('❌ [WEBSOCKET] Stack:', error.stack);
|
||||
isConnecting = false;
|
||||
connectionTimestamp = null;
|
||||
// Échec immédiat -> planifier reconnexion avec backoff
|
||||
scheduleReconnect();
|
||||
if (isMonitoring) {
|
||||
scheduleReconnect();
|
||||
} else {
|
||||
console.log('⚠️ [WEBSOCKET] Monitoring désactivé, pas de reconnexion');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -528,4 +552,29 @@ const forceWebSocketReconnect = async () => {
|
||||
await forceReconnectToRefreshCredentials();
|
||||
};
|
||||
|
||||
module.exports = { startConsoleMonitoring, stopConsoleMonitoring, forceWebSocketReconnect };
|
||||
// Fonction pour obtenir l'état du WebSocket (pour diagnostic)
|
||||
const getWebSocketStatus = () => {
|
||||
const wsStates = {
|
||||
[WebSocket.CONNECTING]: 'CONNECTING',
|
||||
[WebSocket.OPEN]: 'OPEN',
|
||||
[WebSocket.CLOSING]: 'CLOSING',
|
||||
[WebSocket.CLOSED]: 'CLOSED'
|
||||
};
|
||||
|
||||
return {
|
||||
isMonitoring,
|
||||
isConnecting,
|
||||
hasWebSocket: !!ws,
|
||||
wsState: ws ? wsStates[ws.readyState] : 'N/A',
|
||||
wsStateRaw: ws ? ws.readyState : null,
|
||||
connectionTimestamp: connectionTimestamp ? new Date(connectionTimestamp).toISOString() : null,
|
||||
monitoringStartTimestamp: monitoringStartTimestamp ? new Date(monitoringStartTimestamp).toISOString() : null,
|
||||
reconnectDelayMs,
|
||||
hasHeartbeat: !!heartbeatInterval,
|
||||
hasCheckInterval: !!checkInterval,
|
||||
hasRefreshInterval: !!refreshCredentialsInterval,
|
||||
hasPendingReconnect: !!reconnectTimeout
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = { startConsoleMonitoring, stopConsoleMonitoring, forceWebSocketReconnect, getWebSocketStatus };
|
||||
|
||||
@ -9,7 +9,7 @@ const initPalworldBridge = (client, channelId) => {
|
||||
bridgeClient = client;
|
||||
bridgeChannelId = channelId;
|
||||
|
||||
console.log(`🌉 Pont Palworld-Discord initialisé (Salon: ${channelId})`);
|
||||
console.log(`🌉 [BRIDGE] Pont Palworld-Discord initialisé (Salon: ${channelId})`);
|
||||
|
||||
// Écouter les messages du salon Discord
|
||||
client.on('messageCreate', async (message) => {
|
||||
@ -23,6 +23,7 @@ const initPalworldBridge = (client, channelId) => {
|
||||
|
||||
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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user