310 lines
11 KiB
JavaScript
310 lines
11 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder } = require('discord.js');
|
|
const { getConfig, updateConfig, getAllConfig } = require('../../database');
|
|
const { getMonitoringStatus } = require('../../ramMonitor');
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('panel')
|
|
.setDescription('Panneau de configuration du bot'),
|
|
|
|
async execute(interaction) {
|
|
// Vérifier les permissions
|
|
if (!interaction.member.roles.cache.has('1444684935632912394')) {
|
|
await interaction.reply({
|
|
content: '❌ Il faut avoir le rôle Rygainland pour accéder au panneau de configuration.',
|
|
flags: 64
|
|
});
|
|
return;
|
|
}
|
|
|
|
await showPanel(interaction);
|
|
}
|
|
};
|
|
|
|
function hasPanelRole(member) {
|
|
return Boolean(member?.roles?.cache?.has('1444684935632912394'));
|
|
}
|
|
|
|
async function buildPanelPayload() {
|
|
const config = await getAllConfig();
|
|
const monitoringStatus = getMonitoringStatus();
|
|
|
|
const autoRebootEnabled = config.auto_reboot_enabled === 'true';
|
|
const ramThreshold = Number.parseInt(config.ram_threshold_gb, 10);
|
|
const consoleMonitorEnabled = config.console_monitor_enabled === 'true';
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(0x0099FF)
|
|
.setTitle('⚙️ Panneau de Configuration')
|
|
.setDescription('Gérez les paramètres du bot et du serveur')
|
|
.addFields(
|
|
{
|
|
name: '🔄 Redémarrage Automatique',
|
|
value: `**État:** ${autoRebootEnabled ? '✅ Activé' : '❌ Désactivé'}\n**Seuil RAM:** ${ramThreshold} Go\n**Surveillance:** ${monitoringStatus.isMonitoring ? '🟢 Active' : '🔴 Inactive'}`,
|
|
inline: true
|
|
},
|
|
{
|
|
name: '📊 Surveillance Console',
|
|
value: `**État:** ${consoleMonitorEnabled ? '✅ Activée' : '❌ Désactivée'}`,
|
|
inline: true
|
|
},
|
|
{
|
|
name: '📈 Statistiques',
|
|
value: `**En redémarrage:** ${monitoringStatus.isRebooting ? 'Oui' : 'Non'}\n**Intervalle:** ${monitoringStatus.checkInterval / 1000}s`,
|
|
inline: false
|
|
}
|
|
)
|
|
.setTimestamp()
|
|
.setFooter({ text: 'Panneau de Configuration' });
|
|
|
|
const row1 = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('toggle_auto_reboot')
|
|
.setLabel(autoRebootEnabled ? 'Désactiver Auto-Reboot' : 'Activer Auto-Reboot')
|
|
.setStyle(autoRebootEnabled ? ButtonStyle.Danger : ButtonStyle.Success)
|
|
.setEmoji(autoRebootEnabled ? '⏹️' : '▶️'),
|
|
new ButtonBuilder()
|
|
.setCustomId('toggle_console_monitor')
|
|
.setLabel(consoleMonitorEnabled ? 'Désactiver Console' : 'Activer Console')
|
|
.setStyle(consoleMonitorEnabled ? ButtonStyle.Danger : ButtonStyle.Success)
|
|
.setEmoji(consoleMonitorEnabled ? '📵' : '📱')
|
|
);
|
|
|
|
const row2 = new ActionRowBuilder()
|
|
.addComponents(
|
|
new StringSelectMenuBuilder()
|
|
.setCustomId('change_ram_threshold')
|
|
.setPlaceholder(`Seuil RAM actuel: ${ramThreshold} Go`)
|
|
.addOptions([
|
|
{
|
|
label: '15 Go',
|
|
description: 'Redémarrage à 15 Go de RAM',
|
|
value: '15',
|
|
emoji: '🔵'
|
|
},
|
|
{
|
|
label: '17 Go',
|
|
description: 'Redémarrage à 17 Go de RAM',
|
|
value: '17',
|
|
emoji: '🟢'
|
|
},
|
|
{
|
|
label: '19 Go (défaut)',
|
|
description: 'Redémarrage à 19 Go de RAM',
|
|
value: '19',
|
|
emoji: '🟡',
|
|
default: ramThreshold === 19
|
|
},
|
|
{
|
|
label: '21 Go',
|
|
description: 'Redémarrage à 21 Go de RAM',
|
|
value: '21',
|
|
emoji: '🟠'
|
|
},
|
|
{
|
|
label: '23 Go',
|
|
description: 'Redémarrage à 23 Go de RAM',
|
|
value: '23',
|
|
emoji: '🔴'
|
|
},
|
|
{
|
|
label: '25 Go',
|
|
description: 'Redémarrage à 25 Go de RAM',
|
|
value: '25',
|
|
emoji: '🔴'
|
|
}
|
|
])
|
|
);
|
|
|
|
const row3 = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('refresh_panel')
|
|
.setLabel('Actualiser')
|
|
.setStyle(ButtonStyle.Secondary)
|
|
.setEmoji('🔄'),
|
|
new ButtonBuilder()
|
|
.setCustomId('view_stats')
|
|
.setLabel('Voir Stats Détaillées')
|
|
.setStyle(ButtonStyle.Primary)
|
|
.setEmoji('📊')
|
|
);
|
|
|
|
return { embeds: [embed], components: [row1, row2, row3], content: null };
|
|
}
|
|
|
|
async function buildStatsPayload() {
|
|
const config = await getAllConfig();
|
|
const monitoringStatus = getMonitoringStatus();
|
|
const { checkRAMUsage } = require('../../ramMonitor');
|
|
|
|
const ramData = await checkRAMUsage();
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(0x00FF00)
|
|
.setTitle('📊 Statistiques Détaillées du Monitoring')
|
|
.setDescription('Informations en temps réel sur le serveur')
|
|
.addFields(
|
|
{
|
|
name: '🎮 État du Serveur',
|
|
value: ramData ? `**État:** ${ramData.currentState}\n**RAM:** ${ramData.ramUsedGB} Go / ${config.ram_threshold_gb} Go` : 'Impossible de récupérer les données',
|
|
inline: true
|
|
},
|
|
{
|
|
name: '⚙️ Configuration',
|
|
value: `**Auto-Reboot:** ${config.auto_reboot_enabled === 'true' ? 'Oui' : 'Non'}\n**Seuil:** ${config.ram_threshold_gb} Go\n**Console:** ${config.console_monitor_enabled === 'true' ? 'Active' : 'Inactive'}`,
|
|
inline: true
|
|
},
|
|
{
|
|
name: '🔄 Surveillance',
|
|
value: `**Active:** ${monitoringStatus.isMonitoring ? 'Oui' : 'Non'}\n**En reboot:** ${monitoringStatus.isRebooting ? 'Oui' : 'Non'}\n**Intervalle:** ${monitoringStatus.checkInterval / 1000}s`,
|
|
inline: false
|
|
}
|
|
)
|
|
.setTimestamp()
|
|
.setFooter({ text: 'Statistiques en temps réel' });
|
|
|
|
const row = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('back_to_panel')
|
|
.setLabel('Retour au Panel')
|
|
.setStyle(ButtonStyle.Secondary)
|
|
.setEmoji('◀️')
|
|
);
|
|
|
|
return { embeds: [embed], components: [row], content: null };
|
|
}
|
|
|
|
function isIgnorableDiscordRestError(error) {
|
|
const code = error?.code ?? error?.rawError?.code;
|
|
return code === 10062 || code === 40060;
|
|
}
|
|
|
|
async function safeDeferUpdate(interaction) {
|
|
if (interaction?.deferred || interaction?.replied) return;
|
|
try {
|
|
await interaction.deferUpdate();
|
|
} catch (e) {
|
|
if (!isIgnorableDiscordRestError(e)) throw e;
|
|
}
|
|
}
|
|
|
|
async function renderPanel(interaction) {
|
|
const payload = await buildPanelPayload();
|
|
|
|
// Premier affichage via la commande slash
|
|
if (interaction.isChatInputCommand?.()) {
|
|
if (interaction.replied || interaction.deferred) {
|
|
await interaction.editReply(payload);
|
|
return interaction.fetchReply();
|
|
}
|
|
return interaction.reply({ ...payload, fetchReply: true });
|
|
}
|
|
|
|
// Refresh via composants: on édite directement le message
|
|
await safeDeferUpdate(interaction);
|
|
return interaction.message.edit(payload);
|
|
}
|
|
|
|
async function renderDetailedStats(interaction) {
|
|
// IMPORTANT: defer immédiatement pour éviter 10062 si les appels réseau sont lents
|
|
await safeDeferUpdate(interaction);
|
|
|
|
const payload = await buildStatsPayload();
|
|
|
|
if (interaction.isChatInputCommand?.()) {
|
|
if (interaction.replied || interaction.deferred) {
|
|
await interaction.editReply(payload);
|
|
return interaction.fetchReply();
|
|
}
|
|
return interaction.reply({ ...payload, fetchReply: true });
|
|
}
|
|
|
|
return interaction.message.edit(payload);
|
|
}
|
|
|
|
// Point d'entrée: affiche le panel et attache un collector AU message
|
|
async function showPanel(interaction) {
|
|
const message = await renderPanel(interaction);
|
|
|
|
const collector = message.createMessageComponentCollector({
|
|
time: 300000 // 5 minutes
|
|
});
|
|
|
|
collector.on('collect', async i => {
|
|
if (!hasPanelRole(i.member)) {
|
|
try {
|
|
await i.reply({
|
|
content: '❌ Vous n\'avez pas la permission d\'utiliser ce panneau.',
|
|
flags: 64
|
|
});
|
|
} catch {
|
|
// ignore
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
switch (i.customId) {
|
|
case 'toggle_auto_reboot': {
|
|
await safeDeferUpdate(i);
|
|
const currentState = (await getConfig('auto_reboot_enabled')) === 'true';
|
|
await updateConfig('auto_reboot_enabled', (!currentState).toString());
|
|
await renderPanel(i);
|
|
break;
|
|
}
|
|
case 'toggle_console_monitor': {
|
|
await safeDeferUpdate(i);
|
|
const currentState = (await getConfig('console_monitor_enabled')) === 'true';
|
|
await updateConfig('console_monitor_enabled', (!currentState).toString());
|
|
await renderPanel(i);
|
|
break;
|
|
}
|
|
case 'change_ram_threshold': {
|
|
await safeDeferUpdate(i);
|
|
const newThreshold = i.values?.[0];
|
|
if (newThreshold) {
|
|
await updateConfig('ram_threshold_gb', newThreshold);
|
|
}
|
|
await renderPanel(i);
|
|
break;
|
|
}
|
|
case 'refresh_panel': {
|
|
await safeDeferUpdate(i);
|
|
await renderPanel(i);
|
|
break;
|
|
}
|
|
case 'view_stats': {
|
|
await renderDetailedStats(i);
|
|
break;
|
|
}
|
|
case 'back_to_panel': {
|
|
await safeDeferUpdate(i);
|
|
await renderPanel(i);
|
|
break;
|
|
}
|
|
default: {
|
|
await safeDeferUpdate(i);
|
|
break;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors de l\'interaction avec le panel:', error);
|
|
if (isIgnorableDiscordRestError(error)) return;
|
|
|
|
// Ne pas crash le process si une réponse échoue
|
|
try {
|
|
await i.followUp?.({ content: '❌ Une erreur est survenue', flags: 64 });
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
});
|
|
|
|
collector.on('end', () => {
|
|
console.log('⏰ [Panel] Collector expiré');
|
|
});
|
|
}
|