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);
|
if (reconnectTimeout) clearTimeout(reconnectTimeout);
|
||||||
const delay = reconnectDelayMs;
|
const delay = reconnectDelayMs;
|
||||||
reconnectDelayMs = Math.min(reconnectDelayMs * 2, RECONNECT_DELAY_MAX_MS);
|
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(() => {
|
reconnectTimeout = setTimeout(() => {
|
||||||
|
console.log('🔄 [WEBSOCKET] Tentative de reconnexion maintenant...');
|
||||||
checkAndManageWebSocket();
|
checkAndManageWebSocket();
|
||||||
}, delay);
|
}, delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
const connectWebSocket = async (pterodactylToken, serverId) => {
|
const connectWebSocket = async (pterodactylToken, serverId) => {
|
||||||
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (isConnecting) {
|
if (isConnecting) {
|
||||||
console.log('⚠️ Connexion WebSocket déjà en cours');
|
console.log('⚠️ [WEBSOCKET] Connexion déjà en cours, abandon de cette tentative');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
isConnecting = true;
|
isConnecting = true;
|
||||||
connectionTimestamp = Date.now();
|
connectionTimestamp = Date.now();
|
||||||
console.log(`📅 Timestamp de connexion: ${new Date(connectionTimestamp).toISOString()}`);
|
console.log(`📅 [WEBSOCKET] Timestamp de connexion: ${new Date(connectionTimestamp).toISOString()}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Toujours rafraîchir les credentials pour éviter les tokens expirés après redémarrage serveur
|
// 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);
|
const credentials = await getWebSocketCredentials(pterodactylToken, serverId);
|
||||||
|
console.log('✅ [WEBSOCKET] Credentials récupérés avec succès');
|
||||||
|
|
||||||
ws = new WebSocket(credentials.socket, {
|
ws = new WebSocket(credentials.socket, {
|
||||||
origin: process.env.PTERODACTYL_API_URL
|
origin: process.env.PTERODACTYL_API_URL
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('open', () => {
|
ws.on('open', () => {
|
||||||
console.log('✅ WebSocket Pterodactyl connecté');
|
console.log('✅ [WEBSOCKET] WebSocket Pterodactyl connecté avec succès');
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
resetReconnectBackoff();
|
resetReconnectBackoff();
|
||||||
|
|
||||||
|
console.log('🔐 [WEBSOCKET] Envoi de l\'authentification...');
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
event: 'auth',
|
event: 'auth',
|
||||||
args: [credentials.token]
|
args: [credentials.token]
|
||||||
@ -304,7 +308,8 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
|||||||
const message = JSON.parse(data.toString());
|
const message = JSON.parse(data.toString());
|
||||||
|
|
||||||
if (message.event === 'auth success') {
|
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({
|
ws.send(JSON.stringify({
|
||||||
event: 'send logs',
|
event: 'send logs',
|
||||||
@ -317,6 +322,7 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
|||||||
ws.send(JSON.stringify({ event: 'send heartbeat', args: [] }));
|
ws.send(JSON.stringify({ event: 'send heartbeat', args: [] }));
|
||||||
}
|
}
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
console.log('💓 [WEBSOCKET] Heartbeat configuré (30s)');
|
||||||
}
|
}
|
||||||
if (message.event === 'console output') {
|
if (message.event === 'console output') {
|
||||||
const log = message.args[0];
|
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
|
// Transférer le message de chat vers Discord via le bridge
|
||||||
console.log(`📋 [CONSOLE] Traitement du log pour le bridge...`);
|
console.log(`📋 [CONSOLE] Traitement du log pour le bridge...`);
|
||||||
try {
|
try {
|
||||||
@ -400,12 +411,15 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ws.on('error', (error) => {
|
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;
|
isConnecting = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('close', (code, reason) => {
|
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;
|
ws = null;
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
connectionTimestamp = null;
|
connectionTimestamp = null;
|
||||||
@ -413,18 +427,28 @@ const connectWebSocket = async (pterodactylToken, serverId) => {
|
|||||||
if (heartbeatInterval) {
|
if (heartbeatInterval) {
|
||||||
clearInterval(heartbeatInterval);
|
clearInterval(heartbeatInterval);
|
||||||
heartbeatInterval = null;
|
heartbeatInterval = null;
|
||||||
|
console.log('💔 [WEBSOCKET] Heartbeat arrêté');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Planifier une reconnexion avec backoff (utile lors des redémarrages quotidiens du serveur)
|
// 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) {
|
} 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;
|
isConnecting = false;
|
||||||
connectionTimestamp = null;
|
connectionTimestamp = null;
|
||||||
// Échec immédiat -> planifier reconnexion avec backoff
|
// É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();
|
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;
|
bridgeClient = client;
|
||||||
bridgeChannelId = channelId;
|
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
|
// Écouter les messages du salon Discord
|
||||||
client.on('messageCreate', async (message) => {
|
client.on('messageCreate', async (message) => {
|
||||||
@ -23,6 +23,7 @@ const initPalworldBridge = (client, channelId) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Récupérer le pseudo Palworld lié
|
// 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);
|
const userLink = await getUserLink(message.author.id);
|
||||||
console.log(`🔍 [BRIDGE] Liaison trouvée pour ${message.author.tag}:`, userLink);
|
console.log(`🔍 [BRIDGE] Liaison trouvée pour ${message.author.tag}:`, userLink);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user