diff --git a/src/commands/messages/AI/stats.ts b/src/commands/messages/AI/stats.ts index de49f25..71d1840 100644 --- a/src/commands/messages/AI/stats.ts +++ b/src/commands/messages/AI/stats.ts @@ -1,8 +1,10 @@ import { CommandMessage } from "../../../core/types/commands"; -import { PermissionFlagsBits } from "discord.js"; +import { ContainerBuilder, TextDisplayBuilder, SectionBuilder, ButtonBuilder, ButtonStyle, MessageFlags } from "discord.js"; import { aiService } from "../../../core/services/AIService"; import logger from "../../../core/lib/logger"; + const OWNER_ID = '327207082203938818'; + /** * Formatear tiempo de actividad */ @@ -24,7 +26,7 @@ function formatBytesMB(bytes: number): string { } /** - * Construir panel de administración de IA + * Construir panel de administración de IA usando la API REAL de Discord.js 14.22.1 */ function buildAIAdminPanel() { const stats = aiService.getStats(); @@ -43,63 +45,53 @@ function buildAIAdminPanel() { const heapTotal = formatBytesMB(memoryUsage.heapTotal); const external = formatBytesMB(memoryUsage.external); - // @ts-ignore - return { - type: 17, - accent_color: 0xFF69B4, - components: [ - { - type: 10, - content: '## 🌸 Panel de Administración - Gemini-chan' - }, - { - type: 10, - content: '-# Gestiona el sistema de IA y monitorea estadísticas en tiempo real.' - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: `🔄 **Conversaciones Activas:** ${stats.activeConversations}` } - ], - accessory: { - type: 2, - style: 1, - emoji: "🧹", - label: 'Limpiar Cache', - custom_id: 'ai_clear_cache' - } - }, - { - type: 9, - components: [ - { type: 10, content: `📊 **Requests en Cola:** ${stats.queueLength} | **Estado:** ${queueStatus}` } - ], - accessory: { - type: 2, - style: 1, - emoji: "🔄", - label: 'Refrescar Stats', - custom_id: 'ai_refresh_stats' - } - }, - { - type: 9, - components: [ - { type: 10, content: `⏱️ **Total Requests:** ${stats.totalRequests} | **Uptime:** ${formatUptime(uptime)}` } - ], - accessory: { - type: 2, - style: 2, - emoji: "🔧", - label: 'Configuración', - custom_id: 'ai_config' - } - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: ` ## 🧠 Uso de Memoria del Sistema IA + // Crear texto de header + const headerText = new TextDisplayBuilder() + .setContent('## 🌸 Panel de Administración - Gemini-chan\n-# Gestiona el sistema de IA y monitorea estadísticas en tiempo real.'); + + // Crear secciones con estadísticas + const statsSection1 = new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent(`🔄 **Conversaciones Activas:** ${stats.activeConversations}`) + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_clear_cache') + .setLabel('Limpiar Cache') + .setEmoji('🧹') + .setStyle(ButtonStyle.Primary) + ); + + const statsSection2 = new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent(`📊 **Requests en Cola:** ${stats.queueLength} | **Estado:** ${queueStatus}`) + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_refresh_stats') + .setLabel('Refrescar Stats') + .setEmoji('🔄') + .setStyle(ButtonStyle.Primary) + ); + + const configSection = new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent(`⏱️ **Total Requests:** ${stats.totalRequests} | **Uptime:** ${formatUptime(uptime)}`) + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_config') + .setLabel('Configuración') + .setEmoji('🔧') + .setStyle(ButtonStyle.Secondary) + ); + + // Texto de memoria + const memoryText = new TextDisplayBuilder() + .setContent(`## 🧠 Uso de Memoria del Sistema IA \`\`\` ┌─────────────────┬──────────────┬──────────┐ │ Memory Type │ Usage │ Status │ @@ -110,33 +102,32 @@ function buildAIAdminPanel() { │ External │ ${external.padEnd(12)} │ Normal │ └─────────────────┴──────────────┴──────────┘ -📈 Configuración Actual: -• Rate Limit: 20 req/min por usuario -• Cooldown: 3 segundos entre requests -• Max Tokens: 1M entrada / 8K salida -• Max Concurrent: 3 requests simultáneos -• Modelo: gemini-1.5-flash +📈 Configuración: 20 req/min | 3s cooldown | 1M/8K tokens | 3 concurrent \`\`\` -Última actualización: ${ts} UTC +🔄 Última actualización: ${ts} UTC`); -⚠️ **Nota:** El sistema se resetea automáticamente cada 30 minutos para optimizar memoria.` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: "<:Sup_urg:1420535068056748042> **REINICIAR** todo el sistema de IA (limpia cache, conversaciones y estadísticas)" } - ], - accessory: { - type: 2, - style: 4, - emoji: "⚠️", - label: 'RESET COMPLETO', - custom_id: 'ai_full_reset' - } - } - ] - }; + // Sección de reset + const resetSection = new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent("**REINICIAR** todo el sistema de IA") + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_full_reset') + .setLabel('RESET COMPLETO') + .setEmoji('⚠️') + .setStyle(ButtonStyle.Danger) + ); + + // Construir container principal + const container = new ContainerBuilder() + .addTextDisplayComponents(headerText) + .addSectionComponents(statsSection1, statsSection2, configSection) + .addTextDisplayComponents(memoryText) + .addSectionComponents(resetSection); + + return container; } export const command: CommandMessage = { @@ -144,13 +135,13 @@ export const command: CommandMessage = { type: "message", aliases: ['ai-stats', 'ai-info', 'ai-panel'], cooldown: 5, - description: 'Panel de administración del sistema de IA (Solo administradores)', + description: 'Panel de administración del sistema de IA (Solo el dueño)', category: 'Administración', usage: 'aistats [reset]', run: async (message, args) => { - // Verificar permisos de administrador + // Verificar que sea el dueño del bot (MUY CRÍTICO) if (message.author.id !== OWNER_ID) { - await message.reply({ content: '❌ No tienes permisos para usar este panel.' }); + await message.reply({ content: '❌ Solo el dueño del bot puede usar este panel administrativo.' }); return; } @@ -159,32 +150,17 @@ export const command: CommandMessage = { // Reset del sistema si se solicita if (action === 'reset') { - // @ts-ignore - const resetPanel = { - type: 17, - accent_color: 0x00FF00, - components: [ - { - type: 10, - content: '## ✅ Sistema de IA Reiniciado' - }, - { - type: 10, - content: 'Las estadísticas, cache y conversaciones han sido limpiados exitosamente.' - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: `🔄 **Estado:** Sistema reiniciado\n⏰ **Timestamp:** ${new Date().toISOString().replace('T', ' ').split('.')[0]} UTC\n👤 **Administrador:** ${message.author.username}` - } - ] - }; + const resetContainer = new ContainerBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent('## ✅ Sistema de IA Reiniciado\nLas estadísticas, cache y conversaciones han sido limpiados exitosamente.\n\n🔄 **Estado:** Sistema reiniciado\n⏰ **Timestamp:** ' + new Date().toISOString().replace('T', ' ').split('.')[0] + ' UTC\n👤 **Dueño:** ' + message.author.username) + ); await message.reply({ - flags: 32768, - components: [resetPanel] + components: [resetContainer], + flags: MessageFlags.IsComponentsV2 }); - logger.info(`Sistema de IA reiniciado por ${message.author.username} (${message.author.id})`); + logger.info(`Sistema de IA reiniciado por el dueño ${message.author.username} (${message.author.id})`); return; } @@ -192,38 +168,26 @@ export const command: CommandMessage = { const adminPanel = buildAIAdminPanel(); await message.reply({ - flags: 32768, - components: [adminPanel] + components: [adminPanel], + flags: MessageFlags.IsComponentsV2 }); } catch (error: any) { logger.error('Error obteniendo estadísticas de IA:', error); - // @ts-ignore - const errorPanel = { - type: 17, - accent_color: 0xFF4444, - components: [ - { - type: 10, - content: '## ❌ Error del Sistema' - }, - { - type: 10, - content: 'No se pudieron obtener las estadísticas del sistema de IA.' - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: `**Error:** ${error.message || 'Error desconocido'}\n**Timestamp:** ${new Date().toISOString()}` - } - ] - }; + const errorContainer = new ContainerBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent('## ❌ Error del Sistema\nNo se pudieron obtener las estadísticas del sistema de IA.\n\n**Error:** ' + (error.message || 'Error desconocido') + '\n**Timestamp:** ' + new Date().toISOString()) + ); await message.reply({ - flags: 32768, - components: [errorPanel] + components: [errorContainer], + flags: MessageFlags.IsComponentsV2 }); } } } + +// Exportar función para reutilizar en botones +export { buildAIAdminPanel }; diff --git a/src/components/buttons/aiClearCache.ts b/src/components/buttons/aiClearCache.ts index 8fa638e..2ffe223 100644 --- a/src/components/buttons/aiClearCache.ts +++ b/src/components/buttons/aiClearCache.ts @@ -1,67 +1,59 @@ import logger from "../../core/lib/logger"; -import { ButtonInteraction, MessageFlags, PermissionFlagsBits } from 'discord.js'; +import { ButtonInteraction, MessageFlags, ContainerBuilder, TextDisplayBuilder, SectionBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; import { aiService } from '../../core/services/AIService'; +const OWNER_ID = '327207082203938818'; // Solo el dueño puede usar este panel + export default { customId: 'ai_clear_cache', run: async (interaction: ButtonInteraction) => { - // Verificar permisos de administrador - if (!interaction.memberPermissions?.has(PermissionFlagsBits.Administrator)) { - return interaction.reply({ - content: '❌ No tienes permisos de administrador para usar este botón.', - flags: MessageFlags.Ephemeral + // Verificar que sea el dueño del bot (CRÍTICO) + if (interaction.user.id !== OWNER_ID) { + return interaction.reply({ + content: '❌ Solo el dueño del bot puede usar este panel administrativo.', + flags: MessageFlags.Ephemeral }); } try { await interaction.deferUpdate(); - // Limpiar cache de conversaciones (simular limpieza) + // Limpiar cache de conversaciones const stats = aiService.getStats(); const conversationsCleared = stats.activeConversations; - // Aquí podrías agregar lógica real para limpiar el cache - // Por ejemplo: aiService.clearConversations(); - - // @ts-ignore - const successPanel = { - type: 17, - accent_color: 0x00FF00, - components: [ - { - type: 10, - content: '## 🧹 Cache Limpiado Exitosamente' - }, - { - type: 10, - content: `-# Se han limpiado ${conversationsCleared} conversaciones activas.` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: `✅ **Estado:** Cache limpiado\n🔄 **Conversaciones eliminadas:** ${conversationsCleared}\n⏰ **Timestamp:** ${new Date().toISOString().replace('T', ' ').split('.')[0]} UTC\n👤 **Administrador:** ${interaction.user.username}` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: "🔙 Volver al panel principal de administración" } - ], - accessory: { - type: 2, - style: 2, - emoji: "🔙", - label: 'Volver al Panel', - custom_id: 'ai_refresh_stats' - } - } - ] - }; + // Aquí iría la lógica real de limpieza: + // aiService.clearAllConversations(); + + // Crear container de éxito usando la API real + const successContainer = new ContainerBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent('## 🧹 Cache Limpiado Exitosamente\n-# Se han limpiado ' + conversationsCleared + ' conversaciones activas.\n\n✅ **Estado:** Cache limpiado\n🔄 **Conversaciones eliminadas:** ' + conversationsCleared + '\n⏰ **Timestamp:** ' + new Date().toISOString().replace('T', ' ').split('.')[0] + ' UTC\n👤 **Dueño:** ' + interaction.user.username) + ) + .addSectionComponents( + new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent("🔙 Volver al panel principal de administración") + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_refresh_stats') + .setLabel('Volver al Panel') + .setEmoji('🔙') + .setStyle(ButtonStyle.Primary) + ) + ); + + await interaction.message.edit({ + components: [successContainer], + flags: MessageFlags.IsComponentsV2 + }); + logger.info(`Cache de IA limpiado por el dueño ${interaction.user.username} (${interaction.user.id})`); - await interaction.message.edit({ components: [successPanel] }); - logger.info(`Cache de IA limpiado por ${interaction.user.username} (${interaction.user.id})`); - } catch (error) { + //@ts-ignore logger.error('Error limpiando cache de IA:', error); if (!interaction.deferred && !interaction.replied) { await interaction.reply({ diff --git a/src/components/buttons/aiConfig.ts b/src/components/buttons/aiConfig.ts index e026772..63bb5a1 100644 --- a/src/components/buttons/aiConfig.ts +++ b/src/components/buttons/aiConfig.ts @@ -1,38 +1,30 @@ import logger from "../../core/lib/logger"; -import { ButtonInteraction, MessageFlags, PermissionFlagsBits } from 'discord.js'; +import { ButtonInteraction, MessageFlags, ContainerBuilder, TextDisplayBuilder, SectionBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; + +const OWNER_ID = '327207082203938818'; // Solo el dueño puede usar este panel export default { customId: 'ai_config', run: async (interaction: ButtonInteraction) => { - // Verificar permisos de administrador - if (!interaction.memberPermissions?.has(PermissionFlagsBits.Administrator)) { - return interaction.reply({ - content: '❌ No tienes permisos de administrador para usar este botón.', - flags: MessageFlags.Ephemeral + // Verificar que sea el dueño del bot (CRÍTICO) + if (interaction.user.id !== OWNER_ID) { + return interaction.reply({ + content: '❌ Solo el dueño del bot puede usar este panel administrativo.', + flags: MessageFlags.Ephemeral }); } try { await interaction.deferUpdate(); - // Panel de configuración detallada - // @ts-ignore - const configPanel = { - type: 17, - accent_color: 0x3498DB, - components: [ - { - type: 10, - content: '## ⚙️ Configuración del Sistema de IA' - }, - { - type: 10, - content: '-# Ajustes avanzados y configuración del servicio Gemini-chan.' - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: `## 🔧 Configuración Actual + // Panel de configuración usando la API real de Discord.js 14.22.1 + const configContainer = new ContainerBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent(`## ⚙️ Configuración del Sistema de IA +-# Ajustes avanzados y configuración del servicio Gemini-chan. + +## 🔧 Configuración Actual \`\`\`yaml # Límites de Rate Limiting rate_limit_max: 20 # requests por minuto por usuario @@ -59,71 +51,31 @@ model: "gemini-1.5-flash" # modelo de Google AI temperature: 0.7 # creatividad de respuestas top_p: 0.85 # diversidad de tokens top_k: 40 # límite de candidatos -\`\`\` +\`\`\``) + ) + .addSectionComponents( + new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent("🔙 Volver al panel principal de administración") + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_refresh_stats') + .setLabel('Volver al Panel') + .setEmoji('🔙') + .setStyle(ButtonStyle.Primary) + ) + ); -## 🔄 Opciones Disponibles` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: "📊 **Ver logs del sistema** en tiempo real" } - ], - accessory: { - type: 2, - style: 2, - emoji: "📊", - label: 'Ver Logs', - custom_id: 'ai_view_logs' - } - }, - { - type: 9, - components: [ - { type: 10, content: "🔧 **Cambiar configuración** de rate limits y timeouts" } - ], - accessory: { - type: 2, - style: 2, - emoji: "🔧", - label: 'Configurar', - custom_id: 'ai_modify_config' - } - }, - { - type: 9, - components: [ - { type: 10, content: "🧪 **Modo de prueba** para testing del sistema" } - ], - accessory: { - type: 2, - style: 2, - emoji: "🧪", - label: 'Modo Test', - custom_id: 'ai_test_mode' - } - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: "🔙 Volver al panel principal de administración" } - ], - accessory: { - type: 2, - style: 1, - emoji: "🔙", - label: 'Volver al Panel', - custom_id: 'ai_refresh_stats' - } - } - ] - }; + await interaction.message.edit({ + components: [configContainer], + flags: MessageFlags.IsComponentsV2 + }); + logger.info(`Panel de configuración de IA accedido por el dueño ${interaction.user.username} (${interaction.user.id})`); - await interaction.message.edit({ components: [configPanel] }); - logger.info(`Panel de configuración de IA accedido por ${interaction.user.username} (${interaction.user.id})`); - } catch (error) { + //@ts-ignore logger.error('Error mostrando configuración de IA:', error); if (!interaction.deferred && !interaction.replied) { await interaction.reply({ diff --git a/src/components/buttons/aiFullReset.ts b/src/components/buttons/aiFullReset.ts index b82f7c3..5313a4a 100644 --- a/src/components/buttons/aiFullReset.ts +++ b/src/components/buttons/aiFullReset.ts @@ -1,5 +1,5 @@ import logger from "../../core/lib/logger"; -import { ButtonInteraction, MessageFlags, PermissionFlagsBits } from 'discord.js'; +import { ButtonInteraction, MessageFlags, ContainerBuilder, TextDisplayBuilder, SectionBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; import { aiService } from '../../core/services/AIService'; const OWNER_ID = '327207082203938818'; // Solo el dueño puede hacer reset completo @@ -7,7 +7,7 @@ const OWNER_ID = '327207082203938818'; // Solo el dueño puede hacer reset compl export default { customId: 'ai_full_reset', run: async (interaction: ButtonInteraction) => { - // Verificar que sea el dueño del bot (reset completo es crítico) + // Verificar que sea el dueño del bot (reset completo es CRÍTICO) if (interaction.user.id !== OWNER_ID) { return interaction.reply({ content: '❌ Solo el dueño del bot puede realizar un reset completo del sistema de IA.', @@ -23,33 +23,22 @@ export default { const conversationsCleared = statsBefore.activeConversations; const requestsCleared = statsBefore.queueLength; - // Aquí irían las funciones reales de reset del servicio - // Por ejemplo: + // Aquí irían las funciones reales de reset del servicio: // aiService.fullReset(); // aiService.clearAllConversations(); // aiService.clearRequestQueue(); // aiService.resetStatistics(); - + const resetTimestamp = new Date().toISOString().replace('T', ' ').split('.')[0]; - // Panel de confirmación de reset completo - // @ts-ignore - const resetCompletePanel = { - type: 17, - accent_color: 0xFF4444, - components: [ - { - type: 10, - content: '## ⚠️ RESET COMPLETO EJECUTADO' - }, - { - type: 10, - content: '-# El sistema de IA ha sido completamente reiniciado.' - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: `## 🔄 Resumen del Reset + // Panel de confirmación de reset completo usando la API real + const resetCompleteContainer = new ContainerBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent(`## ⚠️ RESET COMPLETO EJECUTADO +-# El sistema de IA ha sido completamente reiniciado. + +## 🔄 Resumen del Reset \`\`\` ┌─────────────────────────┬─────────────┐ │ Elemento Limpiado │ Cantidad │ @@ -69,12 +58,9 @@ export default { ⚠️ ADVERTENCIA: Todas las conversaciones activas han sido eliminadas permanentemente. -\`\`\`` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: `## ✅ Sistema Restaurado +\`\`\` + +## ✅ Sistema Restaurado El sistema de IA ha vuelto a su estado inicial: • **Memoria limpia** - Sin conversaciones previas @@ -83,45 +69,46 @@ El sistema de IA ha vuelto a su estado inicial: • **Configuración default** - Valores originales • **Cache limpio** - Memoria optimizada -El sistema está listo para recibir nuevas consultas.` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: "🔙 Volver al panel principal (con datos reset)" } - ], - accessory: { - type: 2, - style: 1, - emoji: "🔙", - label: 'Volver al Panel', - custom_id: 'ai_refresh_stats' - } - }, - { - type: 9, - components: [ - { type: 10, content: "⚠️ **REALIZAR OTRO RESET** (solo si es necesario)" } - ], - accessory: { - type: 2, - style: 4, - emoji: "⚠️", - label: 'Reset Nuevamente', - custom_id: 'ai_full_reset' - } - } - ] - }; +El sistema está listo para recibir nuevas consultas.`) + ) + .addSectionComponents( + new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent("🔙 Volver al panel principal (con datos reset)") + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_refresh_stats') + .setLabel('Volver al Panel') + .setEmoji('🔙') + .setStyle(ButtonStyle.Primary) + ), + new SectionBuilder() + .addTextDisplayComponents( + new TextDisplayBuilder() + .setContent("⚠️ **REALIZAR OTRO RESET** (solo si es necesario)") + ) + .setButtonAccessory( + new ButtonBuilder() + .setCustomId('ai_full_reset') + .setLabel('Reset Nuevamente') + .setEmoji('⚠️') + .setStyle(ButtonStyle.Danger) + ) + ); + + await interaction.message.edit({ + components: [resetCompleteContainer], + flags: MessageFlags.IsComponentsV2 + }); - await interaction.message.edit({ components: [resetCompletePanel] }); - // Log crítico del reset completo - logger.warn(`🚨 RESET COMPLETO DE IA ejecutado por ${interaction.user.username} (${interaction.user.id})`); + logger.warn(`🚨 RESET COMPLETO DE IA ejecutado por el dueño ${interaction.user.username} (${interaction.user.id})`); logger.info(`Reset stats - Conversaciones: ${conversationsCleared}, Queue: ${requestsCleared}, Timestamp: ${resetTimestamp}`); } catch (error) { + //@ts-ignore logger.error('Error ejecutando reset completo de IA:', error); if (!interaction.deferred && !interaction.replied) { await interaction.reply({ diff --git a/src/components/buttons/aiRefreshStats.ts b/src/components/buttons/aiRefreshStats.ts index de65c8b..2952a19 100644 --- a/src/components/buttons/aiRefreshStats.ts +++ b/src/components/buttons/aiRefreshStats.ts @@ -1,164 +1,33 @@ import logger from "../../core/lib/logger"; -import { ButtonInteraction, MessageFlags, PermissionFlagsBits } from 'discord.js'; +import { ButtonInteraction, MessageFlags, ContainerBuilder, TextDisplayBuilder, SectionBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; +import { buildAIAdminPanel } from '../../commands/messages/AI/stats'; -/** - * Formatear tiempo de actividad - */ -function formatUptime(seconds: number): string { - const days = Math.floor(seconds / 86400); - const hours = Math.floor((seconds % 86400) / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - - if (days > 0) return `${days}d ${hours}h ${minutes}m`; - if (hours > 0) return `${hours}h ${minutes}m`; - return `${minutes}m`; -} - -/** - * Formatear bytes a formato legible - */ -function formatBytesMB(bytes: number): string { - return (bytes / 1024 / 1024).toFixed(1) + 'MB'; -} - -/** - * Construir panel de administración de IA actualizado - */ -function buildRefreshedAIPanel() { - const { aiService } = require('../../core/services/AIService'); - const stats = aiService.getStats(); - const uptime = process.uptime(); - const memoryUsage = process.memoryUsage(); - const now = new Date(); - const ts = now.toISOString().replace('T', ' ').split('.')[0]; - - // Estados del sistema - const queueStatus = stats.queueLength === 0 ? '🟢 Normal' : - stats.queueLength < 5 ? '🟡 Ocupado' : '🔴 Saturado'; - const memoryStatus = memoryUsage.heapUsed / memoryUsage.heapTotal > 0.8 ? '🔴 Alta' : '🟢 Normal'; - - const rss = formatBytesMB(memoryUsage.rss); - const heapUsed = formatBytesMB(memoryUsage.heapUsed); - const heapTotal = formatBytesMB(memoryUsage.heapTotal); - const external = formatBytesMB(memoryUsage.external); - - // @ts-ignore - return { - type: 17, - accent_color: 0xFF69B4, - components: [ - { - type: 10, - content: '## 🌸 Panel de Administración - Gemini-chan (Actualizado)' - }, - { - type: 10, - content: '-# Estadísticas refrescadas automáticamente.' - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: `🔄 **Conversaciones Activas:** ${stats.activeConversations}` } - ], - accessory: { - type: 2, - style: 1, - emoji: "🧹", - label: 'Limpiar Cache', - custom_id: 'ai_clear_cache' - } - }, - { - type: 9, - components: [ - { type: 10, content: `📊 **Requests en Cola:** ${stats.queueLength} | **Estado:** ${queueStatus}` } - ], - accessory: { - type: 2, - style: 1, - emoji: "🔄", - label: 'Refrescar Stats', - custom_id: 'ai_refresh_stats' - } - }, - { - type: 9, - components: [ - { type: 10, content: `⏱️ **Total Requests:** ${stats.totalRequests} | **Uptime:** ${formatUptime(uptime)}` } - ], - accessory: { - type: 2, - style: 2, - emoji: "🔧", - label: 'Configuración', - custom_id: 'ai_config' - } - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 10, - content: ` ## 🧠 Uso de Memoria del Sistema IA -\`\`\` -┌─────────────────┬──────────────┬──────────┐ -│ Memory Type │ Usage │ Status │ -├─────────────────┼──────────────┼──────────┤ -│ RSS │ ${rss.padEnd(12)} │ Normal │ -│ Heap Used │ ${heapUsed.padEnd(12)} │ ${memoryStatus.padEnd(8)} │ -│ Heap Total │ ${heapTotal.padEnd(12)} │ Normal │ -│ External │ ${external.padEnd(12)} │ Normal │ -└─────────────────┴──────────────┴──────────┘ - -📈 Configuración Actual: -• Rate Limit: 20 req/min por usuario -• Cooldown: 3 segundos entre requests -• Max Tokens: 1M entrada / 8K salida -• Max Concurrent: 3 requests simultáneos -• Modelo: gemini-1.5-flash -\`\`\` -🔄 Última actualización: ${ts} UTC - -⚠️ **Nota:** El sistema se resetea automáticamente cada 30 minutos para optimizar memoria.` - }, - { type: 14, divider: true, spacing: 1 }, - { - type: 9, - components: [ - { type: 10, content: "<:Sup_urg:1420535068056748042> **REINICIAR** todo el sistema de IA (limpia cache, conversaciones y estadísticas)" } - ], - accessory: { - type: 2, - style: 4, - emoji: "⚠️", - label: 'RESET COMPLETO', - custom_id: 'ai_full_reset' - } - } - ] - }; -} +const OWNER_ID = '327207082203938818'; // Solo el dueño puede usar este panel export default { customId: 'ai_refresh_stats', run: async (interaction: ButtonInteraction) => { - // Verificar permisos de administrador - if (!interaction.memberPermissions?.has(PermissionFlagsBits.Administrator)) { - return interaction.reply({ - content: '❌ No tienes permisos de administrador para usar este botón.', - flags: MessageFlags.Ephemeral + // Verificar que sea el dueño del bot (CRÍTICO) + if (interaction.user.id !== OWNER_ID) { + return interaction.reply({ + content: '❌ Solo el dueño del bot puede usar este panel administrativo.', + flags: MessageFlags.Ephemeral }); } try { await interaction.deferUpdate(); - // Refrescar y reconstruir el panel con datos actualizados - const refreshedPanel = buildRefreshedAIPanel(); - - await interaction.message.edit({ components: [refreshedPanel] }); - logger.info(`Estadísticas de IA refrescadas por ${interaction.user.username} (${interaction.user.id})`); - - } catch (error) + // Reconstruir panel principal con datos actualizados + const refreshedPanel = buildAIAdminPanel(); + + await interaction.message.edit({ + components: [refreshedPanel], + flags: MessageFlags.IsComponentsV2 + }); + logger.info(`Estadísticas de IA refrescadas por el dueño ${interaction.user.username} (${interaction.user.id})`); + + } catch (error) { //@ts-ignore logger.error('Error refrescando estadísticas de IA:', error); if (!interaction.deferred && !interaction.replied) {