From 119ac89274a001d26fe0a71c01de52261abe80d4 Mon Sep 17 00:00:00 2001 From: shni Date: Fri, 26 Sep 2025 06:38:09 -0500 Subject: [PATCH] feat: add descriptions, categories, and usage examples to commands for improved help functionality --- src/commands/messages/AI/chat.ts | 3 + .../messages/alliaces/createEmbedv2.ts | 36 +- .../alliaces/displayComponentsDemo.ts | 3 + src/commands/messages/alliaces/editEmbedv2.ts | 6 +- src/commands/messages/help.ts | 520 +++++------------- src/commands/messages/net/commandsAdmin.ts | 3 + src/commands/messages/net/ping.ts | 3 + .../messages/settings-server/settings.ts | 3 + src/core/types/commands.ts | 4 + 9 files changed, 193 insertions(+), 388 deletions(-) diff --git a/src/commands/messages/AI/chat.ts b/src/commands/messages/AI/chat.ts index 6d58940..8651f75 100644 --- a/src/commands/messages/AI/chat.ts +++ b/src/commands/messages/AI/chat.ts @@ -24,6 +24,9 @@ export const command: CommandMessage = { type: "message", aliases: ['chat', 'gemini'], cooldown: 5, + description: 'Chatea con la IA (Gemini) directamente desde Discord.', + category: 'IA', + usage: 'ai ', run: async (message, args) => { // Verificar que se proporcione un prompt if (!args || args.length === 0) { diff --git a/src/commands/messages/alliaces/createEmbedv2.ts b/src/commands/messages/alliaces/createEmbedv2.ts index 354167e..6d0b80a 100644 --- a/src/commands/messages/alliaces/createEmbedv2.ts +++ b/src/commands/messages/alliaces/createEmbedv2.ts @@ -2,7 +2,6 @@ import { CommandMessage } from "../../../core/types/commands"; // @ts-ignore import { ComponentType, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, Message, MessageFlags, - AnyComponentBuilder } from "discord.js"; import { replaceVars, isValidUrlOrVariable, listVariables } from "../../../core/lib/vars"; @@ -238,6 +237,9 @@ export const command: CommandMessage = { type: "message", aliases: ["embed-crear", "nuevo-embed", "blockcreatev2"], cooldown: 20, + description: "Crea un nuevo bloque/embedded con editor interactivo (DisplayComponents).", + category: "Alianzas", + usage: "crear-embed ", run: async (message, args, client) => { if (!message.member?.permissions.has("Administrator")) { await message.reply("❌ No tienes permisos de Administrador."); @@ -383,7 +385,7 @@ export const command: CommandMessage = { .setMaxLength(2000) .setRequired(true); - const firstActionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(descInput); + const firstActionRow = new ActionRowBuilder().addComponents(descInput); modal.addComponents(firstActionRow); //@ts-ignore @@ -406,7 +408,7 @@ export const command: CommandMessage = { .setMaxLength(7) .setRequired(false); - const firstActionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(colorInput); + const firstActionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(colorInput); modal.addComponents(firstActionRow); //@ts-ignore @@ -426,7 +428,7 @@ export const command: CommandMessage = { .setMaxLength(2000) .setRequired(true); - const firstActionRow = new ActionRowBuilder().addComponents(contentInput); + const firstActionRow = new ActionRowBuilder().addComponents(contentInput); modal.addComponents(firstActionRow); //@ts-ignore @@ -446,7 +448,7 @@ export const command: CommandMessage = { .setMaxLength(2000) .setRequired(true); - const firstActionRow = new ActionRowBuilder().addComponents(imageUrlInput); + const firstActionRow = new ActionRowBuilder().addComponents(imageUrlInput); modal.addComponents(firstActionRow); //@ts-ignore @@ -498,7 +500,7 @@ export const command: CommandMessage = { .setMaxLength(2000) .setRequired(true); - const firstActionRow = new ActionRowBuilder().addComponents(coverInput); + const firstActionRow = new ActionRowBuilder().addComponents(coverInput); modal.addComponents(firstActionRow); //@ts-ignore @@ -527,7 +529,7 @@ export const command: CommandMessage = { .setMaxLength(2000) .setRequired(true); - const firstActionRow = new ActionRowBuilder().addComponents(coverInput); + const firstActionRow = new ActionRowBuilder().addComponents(coverInput); modal.addComponents(firstActionRow); //@ts-ignore @@ -831,7 +833,7 @@ export const command: CommandMessage = { .setMaxLength(4000) .setRequired(true); - const firstRow = new ActionRowBuilder().addComponents(jsonInput); + const firstRow = new ActionRowBuilder().addComponents(jsonInput); modal.addComponents(firstRow); //@ts-ignore @@ -874,8 +876,8 @@ export const command: CommandMessage = { .setMaxLength(1) .setRequired(false); - const firstRow = new ActionRowBuilder().addComponents(visibleInput); - const secondRow = new ActionRowBuilder().addComponents(spacingInput); + const firstRow = new ActionRowBuilder().addComponents(visibleInput); + const secondRow = new ActionRowBuilder().addComponents(spacingInput); modal.addComponents(firstRow, secondRow); //@ts-ignore @@ -936,7 +938,7 @@ export const command: CommandMessage = { .setMaxLength(2000) .setRequired(false); - const firstRow = new ActionRowBuilder().addComponents(thumbnailInput); + const firstRow = new ActionRowBuilder().addComponents(thumbnailInput); modal.addComponents(firstRow); // Abrir modal directamente sin update previo @@ -1035,9 +1037,9 @@ export const command: CommandMessage = { .setMaxLength(64) .setRequired(false); - const r1 = new ActionRowBuilder().addComponents(urlInput); - const r2 = new ActionRowBuilder().addComponents(labelInput); - const r3 = new ActionRowBuilder().addComponents(emojiInput); + const r1 = new ActionRowBuilder().addComponents(urlInput); + const r2 = new ActionRowBuilder().addComponents(labelInput); + const r3 = new ActionRowBuilder().addComponents(emojiInput); modal.addComponents(r1, r2, r3); // Abrir modal directamente en la misma interacción del botón @@ -1081,9 +1083,9 @@ export const command: CommandMessage = { .setMaxLength(64) .setRequired(false); - const r1 = new ActionRowBuilder().addComponents(urlInput); - const r2 = new ActionRowBuilder().addComponents(labelInput); - const r3 = new ActionRowBuilder().addComponents(emojiInput); + const r1 = new ActionRowBuilder().addComponents(urlInput); + const r2 = new ActionRowBuilder().addComponents(labelInput); + const r3 = new ActionRowBuilder().addComponents(emojiInput); modal.addComponents(r1, r2, r3); // Abrir modal directamente sin update previo diff --git a/src/commands/messages/alliaces/displayComponentsDemo.ts b/src/commands/messages/alliaces/displayComponentsDemo.ts index e63bdff..2706eed 100644 --- a/src/commands/messages/alliaces/displayComponentsDemo.ts +++ b/src/commands/messages/alliaces/displayComponentsDemo.ts @@ -5,6 +5,9 @@ export const command: CommandMessage = { type: "message", aliases: ["ddemo", "componentsdemo"], cooldown: 10, + description: "Demostración de DisplayComponents con accesorios y acciones.", + category: "Alianzas", + usage: "displaydemo", run: async (message, args, client) => { if (!message.member?.permissions.has("Administrator")) { await message.reply("❌ No tienes permisos de Administrador."); diff --git a/src/commands/messages/alliaces/editEmbedv2.ts b/src/commands/messages/alliaces/editEmbedv2.ts index a22a6b4..a11d1f4 100644 --- a/src/commands/messages/alliaces/editEmbedv2.ts +++ b/src/commands/messages/alliaces/editEmbedv2.ts @@ -2,7 +2,6 @@ import { CommandMessage } from "../../../core/types/commands"; // @ts-ignore import { ComponentType, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, MessageFlags } from "discord.js"; import { replaceVars, isValidUrlOrVariable, listVariables } from "../../../core/lib/vars"; -import {Block} from "../../../core/types/block"; // Botones de edición (máx 5 por fila) const btns = (disabled = false) => ([ @@ -122,6 +121,9 @@ export const command: CommandMessage = { type: "message", aliases: ["embed-editar", "modificar-embed", "blockeditv2"], cooldown: 20, + description: "Edita un bloque/embed existente con herramientas interactivas.", + category: "Alianzas", + usage: "editar-embed ", run: async (message, args, client) => { if (!message.member?.permissions.has("Administrator")) { await message.reply("❌ No tienes permisos de Administrador."); @@ -142,7 +144,7 @@ export const command: CommandMessage = { return; } - let blockState: Block = { + let blockState: any = { //@ts-ignore title: existingBlock.config?.title ?? `## Block: ${blockName}`, //@ts-ignore diff --git a/src/commands/messages/help.ts b/src/commands/messages/help.ts index ed06c89..610d6a1 100644 --- a/src/commands/messages/help.ts +++ b/src/commands/messages/help.ts @@ -1,11 +1,15 @@ // @ts-ignore import { CommandMessage } from "../../../core/types/commands"; +import { commands as registry } from "../../core/loader"; export const command: CommandMessage = { name: 'ayuda', type: "message", aliases: ['help', 'comandos', 'cmds'], cooldown: 5, + description: 'Muestra la lista de comandos y detalles por categoría.', + category: 'Utilidad', + usage: 'ayuda [comando] | [categoría] | vacío', run: async (message: any, args: string[], client: any) => { // Obtener información del servidor para mostrar el prefix actual const server = await client.prisma.guild.findFirst({ @@ -13,432 +17,210 @@ export const command: CommandMessage = { }); const prefix = server?.prefix || "!"; - // Definir categorías de comandos con nombres modernos - const commandCategories = { - "Alianzas": [ - { - name: "crear-embed", - aliases: ["embed-crear", "nuevo-embed"], - description: "Crear nuevos embeds con DisplayComponents modernos", - usage: `${prefix}crear-embed ` - }, - { - name: "editar-embed", - aliases: ["embed-editar", "modificar-embed"], - description: "Editor avanzado de embeds con interfaz interactiva", - usage: `${prefix}editar-embed ` - }, - { - name: "lista-embeds", - aliases: ["embeds", "ver-embeds"], - description: "Centro de gestión de embeds con paginación", - usage: `${prefix}lista-embeds` - }, - { - name: "eliminar-embed", - aliases: ["embed-eliminar", "borrar-embed"], - description: "Panel interactivo para eliminar embeds", - usage: `${prefix}eliminar-embed [nombre]` - }, - { - name: "canal-alianza", - aliases: ["configurar-canal", "setup-canal"], - description: "Configurar canales para sistema de alianzas", - usage: `${prefix}canal-alianza` - }, - { - name: "eliminar-canal-alianza", - aliases: ["removechannel-alliance", "removealchannel", "delalchannel"], - description: "Eliminar canales de la configuración de alianzas", - usage: `${prefix}eliminar-canal-alianza` - }, - { - name: "listar-canales-alianza", - aliases: ["listchannels-alliance", "listalchannel", "channelsally"], - description: "Ver lista detallada de canales configurados para alianzas", - usage: `${prefix}listar-canales-alianza` - }, - { - name: "demo-componentes", - aliases: ["demo", "prueba-componentes"], - description: "Demostración de DisplayComponents con accesorios", - usage: `${prefix}demo-componentes` - } - ], - "Red": [ - { - name: "ping", - aliases: ["latencia", "pong"], - description: "Verificar latencia y estado del bot", - usage: `${prefix}ping` - } - ], - "Configuracion": [ - { - name: "configuracion", - aliases: ["config", "ajustes", "settings"], - description: "Panel de configuración del servidor", - usage: `${prefix}configuracion` - } - ] + // Construir lista de comandos únicos (sin duplicar aliases) + const seen = new Set(); + const allMsgCommands = [] as Array<{ + name: string; + aliases: string[]; + description: string; + category: string; + usage: string; + cooldown?: number; + }>; + + for (const [, cmd] of registry) { + if (!cmd || cmd.type !== 'message') continue; + const baseName: string | undefined = cmd.name ?? cmd.data?.name; + if (!baseName) continue; + if (seen.has(baseName)) continue; // evitar duplicados por alias + seen.add(baseName); + + const cdesc = (cmd.description ?? '').toString().trim(); + const ccat = (cmd.category ?? 'Otros').toString(); + const usage = (cmd.usage ? `${prefix}${cmd.usage}` : `${prefix}${baseName}`); + + allMsgCommands.push({ + name: baseName, + aliases: Array.isArray(cmd.aliases) ? cmd.aliases : [], + description: cdesc || 'Sin descripción', + category: ccat, + usage, + cooldown: typeof cmd.cooldown === 'number' ? cmd.cooldown : undefined + }); + } + + // Si no hay comandos + if (allMsgCommands.length === 0) { + const emptyPanel = { + type: 17, + accent_color: 0xf04747, + components: [ + { + type: 10, + content: `### ❌ No hay comandos disponibles\n\nAún no se han cargado comandos de mensaje.` + } + ] + }; + await message.reply({ flags: 32768, components: [emptyPanel] }); + return; + } + + // Index para búsqueda rápida por nombre/alias + const findByNameOrAlias = (q: string) => { + const term = q.toLowerCase(); + return allMsgCommands.find(c => c.name === term || c.aliases.map(a => a.toLowerCase()).includes(term)); }; - // Definir backRow una sola vez fuera de los casos - const backRow = { - type: 1, - components: [ - { - type: 2, - style: 2, - label: "↩️ Volver al Menú", - custom_id: "back_to_main" - } - ] - }; + // Agrupar por categoría + const byCategory = new Map(); + for (const c of allMsgCommands) { + const cat = c.category || 'Otros'; + if (!byCategory.has(cat)) byCategory.set(cat, [] as any); + // @ts-ignore + byCategory.get(cat)!.push(c); + } - // Si se especifica un comando específico + // Ordenar categorías por nombre + const categories = Array.from(byCategory.keys()).sort((a, b) => a.localeCompare(b, 'es')); + + // Si se solicita un comando concreto if (args.length > 0) { - const searchCommand = args[0].toLowerCase(); - let foundCommand = null; - let foundCategory = null; - - // Buscar el comando en todas las categorías - for (const [category, commands] of Object.entries(commandCategories)) { - const command = commands.find(cmd => - cmd.name === searchCommand || cmd.aliases.includes(searchCommand) - ); - if (command) { - foundCommand = command; - foundCategory = category; - break; - } - } - - if (foundCommand) { - // Panel detallado del comando específico - SIMPLIFICADO - const commandDetailPanel = { + const query = args.join(' ').trim(); + const found = findByNameOrAlias(query); + if (found) { + const panel = { type: 17, accent_color: 0x5865f2, components: [ { type: 10, - content: `### 📖 **Ayuda: \`${foundCommand.name}\`**\n\n**Categoría:** ${foundCategory}\n**Descripción:** ${foundCommand.description}\n**Uso:** ${foundCommand.usage}\n\n**Aliases disponibles:**\n${foundCommand.aliases.map(alias => `\`${prefix}${alias}\``).join(", ")}` + content: `### 📖 Ayuda: \`${found.name}\`\n\n` + + `• Categoría: **${found.category}**\n` + + `• Descripción: ${found.description}\n` + + `• Uso: \`${found.usage}\`\n` + + (found.aliases.length ? `• Aliases: ${found.aliases.map(a => `\`${prefix}${a}\``).join(', ')}` : '') } ] }; - - const detailActionsRow = { + const backRow = { type: 1, components: [ - { - type: 2, - style: 2, - label: "📋 Ver Todos", - custom_id: "show_all_commands" - }, - { - type: 2, - style: 2, - label: "🔍 Buscar Otro", - custom_id: "search_command" - } + { type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' } ] }; - - await message.reply({ - flags: 32768, - components: [commandDetailPanel, detailActionsRow] - }); + await message.reply({ flags: 32768, components: [panel, backRow] }); return; - } else { - // Comando no encontrado - SIMPLIFICADO - const notFoundPanel = { + } + // También permitir filtrar por categoría si coincide exacto (case-insensitive) + const matchCat = categories.find(c => c.toLowerCase() === query.toLowerCase()); + if (matchCat) { + const cmds = byCategory.get(matchCat)!; + const catPanel = { type: 17, - accent_color: 0xf04747, + accent_color: 0x00a8ff, components: [ - { + { type: 10, content: `### 📂 Categoría: **${matchCat}** (${cmds.length})` }, + { type: 14, spacing: 2, divider: true }, + ...cmds.map(cmd => ({ type: 10, - content: `### ❌ **Comando no encontrado: \`${searchCommand}\`**\n\nNo se encontró ningún comando con el nombre o alias \`${searchCommand}\`.\n\n🔍 **Sugerencias:**\n• Verifica la ortografía\n• Usa \`${prefix}ayuda\` para ver todos los comandos\n• Usa \`${prefix}ayuda \` para filtrar` - } + content: `**${cmd.name}** — ${cmd.description}\n\`${cmd.usage}\`` + })) ] }; - - const notFoundRow = { + const backRow = { type: 1, - components: [ - { - type: 2, - style: 1, - label: "📋 Ver Todos", - custom_id: "show_all_commands" - } - ] + components: [ { type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' } ] }; - - await message.reply({ - flags: 32768, - components: [notFoundPanel, notFoundRow] - }); + await message.reply({ flags: 32768, components: [catPanel, backRow] }); return; } } - // Panel principal de ayuda - OPTIMIZADO para no exceder límite de componentes - const helpPanel = { + // Panel principal dinámico + const helpPanel: any = { type: 17, accent_color: 0x5865f2, components: [ - { - type: 10, - content: `### 📚 **Centro de Ayuda - ${message.guild!.name}**` - }, - { - type: 14, - spacing: 1, - divider: true - }, - { - type: 10, - content: `**Prefix actual:** \`${prefix}\`\n**Total de comandos:** ${Object.values(commandCategories).flat().length}\n**Categorías disponibles:** ${Object.keys(commandCategories).length}` - }, - { - type: 14, - spacing: 2, - divider: false - } + { type: 10, content: `### 📚 Centro de Ayuda — ${message.guild!.name}` }, + { type: 14, spacing: 1, divider: true }, + { type: 10, content: `**Prefix actual:** \`${prefix}\`\n**Total de comandos:** ${allMsgCommands.length}\n**Categorías disponibles:** ${categories.length}` }, + { type: 14, spacing: 2, divider: false }, + ...categories.map(cat => { + const list = byCategory.get(cat)!; + const names = list.map(c => `\`${c.name}\``).join(', '); + return { type: 10, content: `🔹 **${cat}** (${list.length})\n${names}` }; + }) ] }; - // Agregar resumen de categorías de forma compacta - for (const [categoryName, commands] of Object.entries(commandCategories)) { - const commandsList = commands.map(cmd => `\`${cmd.name}\``).join(", "); - helpPanel.components.push({ - type: 10, - content: `🔹 **${categoryName}** (${commands.length})\n${commandsList}` - }); - } - - // Botones de navegación - const navigationRow = { + // Select de categorías + botón exportar + const categoryRow = { type: 1, components: [ { - type: 2, - style: 1, - label: "🤝 Alianzas", - custom_id: "category_alliances" + type: 3, + custom_id: 'help_category_select', + placeholder: '📂 Selecciona una categoría...', + options: categories.slice(0, 25).map(c => ({ label: c, value: `cat:${c}` })) }, - { - type: 2, - style: 2, - label: "🌐 Red", - custom_id: "category_network" - }, - { - type: 2, - style: 2, - label: "⚙️ Config", - custom_id: "category_settings" - }, - { - type: 2, - style: 3, - label: "📋 Exportar", - custom_id: "export_commands" - } + { type: 2, style: 3, label: '📋 Exportar', custom_id: 'export_commands' } ] }; - const panelMessage = await message.reply({ - flags: 32768, - components: [helpPanel, navigationRow] - }); + const panelMessage = await message.reply({ flags: 32768, components: [helpPanel, categoryRow] }); const collector = panelMessage.createMessageComponentCollector({ time: 600000, filter: (i: any) => i.user.id === message.author.id }); - collector.on("collect", async (interaction: any) => { - // Manejar información específica de comandos - if (interaction.customId.startsWith("cmd_info_")) { - const commandName = interaction.customId.replace("cmd_info_", ""); - let foundCommand = null; - let foundCategory = null; + collector.on('collect', async (interaction: any) => { + // Selección de categoría + if (interaction.customId === 'help_category_select' && interaction.isStringSelectMenu()) { + const val = interaction.values?.[0] ?? ''; + const cat = val.startsWith('cat:') ? val.slice(4) : val; + const list = byCategory.get(cat) ?? []; - for (const [category, commands] of Object.entries(commandCategories)) { - const command = commands.find(cmd => cmd.name === commandName); - if (command) { - foundCommand = command; - foundCategory = category; - break; - } - } - - if (foundCommand) { - await interaction.reply({ - content: `📖 **${foundCommand.name}**\n\n**Categoría:** ${foundCategory}\n**Descripción:** ${foundCommand.description}\n**Uso:** ${foundCommand.usage}\n**Aliases:** ${foundCommand.aliases.join(", ")}\n\n💡 **Tip:** Usa \`${foundCommand.usage}\` para ejecutar este comando.`, - flags: 64 - }); - } + const catPanel = { + type: 17, + accent_color: 0x00a8ff, + components: [ + { type: 10, content: `### 📂 Categoría: **${cat}** (${list.length})` }, + { type: 14, spacing: 2, divider: true }, + ...list.map(cmd => ({ type: 10, content: `**${cmd.name}** — ${cmd.description}\n\`${cmd.usage}\`` })) + ] + }; + const backRow = { type: 1, components: [ { type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' } ] }; + await interaction.update({ components: [catPanel, backRow] }); return; } - // Manejar categorías específicas - VERSIÓN COMPACTA - switch (interaction.customId) { - case "category_alliances": - const alliancePanel = { - type: 17, - accent_color: 0x00ff88, - components: [ - { - type: 10, - content: "### 🤝 **Comandos de Alianzas**\n\nSistema completo para gestionar alianzas entre servidores:" - }, - { - type: 14, - spacing: 2, - divider: true - } - ] - }; + if (interaction.customId === 'back_to_main' || interaction.customId === 'show_all_commands') { + await interaction.update({ components: [helpPanel, categoryRow] }); + return; + } - // Agregar comandos de forma compacta - commandCategories["Alianzas"].forEach(cmd => { - alliancePanel.components.push({ - type: 10, - content: `**${cmd.name}**\n${cmd.description}\n\`${cmd.usage}\`` - }); - }); - - await interaction.update({ - components: [alliancePanel, backRow] - }); - break; - - case "category_network": - const networkPanel = { - type: 17, - accent_color: 0x0099ff, - components: [ - { - type: 10, - content: "### 🌐 **Comandos de Red**" - }, - { - type: 14, - spacing: 2, - divider: true - } - ] - }; - - commandCategories["Red"].forEach(cmd => { - networkPanel.components.push({ - type: 10, - content: `**${cmd.name}**\n${cmd.description}\n\`${cmd.usage}\`` - }); - }); - - await interaction.update({ - components: [networkPanel, backRow] - }); - break; - - case "category_settings": - const settingsPanel = { - type: 17, - accent_color: 0xff9500, - components: [ - { - type: 10, - content: "### ⚙️ **Comandos de Configuración**" - }, - { - type: 14, - spacing: 2, - divider: true - } - ] - }; - - commandCategories["Configuracion"].forEach(cmd => { - settingsPanel.components.push({ - type: 10, - content: `**${cmd.name}**\n${cmd.description}\n\`${cmd.usage}\`` - }); - }); - - await interaction.update({ - components: [settingsPanel, backRow] - }); - break; - - case "back_to_main": - await interaction.update({ - components: [helpPanel, navigationRow] - }); - break; - - case "export_commands": - let exportText = `📋 **Lista Completa de Comandos - ${message.guild!.name}**\n\n`; - exportText += `**Prefix:** ${prefix}\n\n`; - - for (const [category, commands] of Object.entries(commandCategories)) { - exportText += `**${category}**\n`; - commands.forEach(cmd => { - exportText += `• ${cmd.name} - ${cmd.description}\n`; - exportText += ` Uso: ${cmd.usage}\n`; - if (cmd.aliases.length > 0) { - exportText += ` Aliases: ${cmd.aliases.join(", ")}\n`; - } - exportText += `\n`; - }); - exportText += `\n`; + if (interaction.customId === 'export_commands') { + let exportText = `Comandos — ${message.guild!.name}\n\nPrefix: ${prefix}\n\n`; + for (const cat of categories) { + const list = byCategory.get(cat)!; + exportText += `${cat}\n`; + for (const cmd of list) { + exportText += `• ${cmd.name} — ${cmd.description}\n Uso: ${cmd.usage}\n`; + if (cmd.aliases.length) exportText += ` Aliases: ${cmd.aliases.join(', ')}\n`; } - - await interaction.reply({ - content: `\`\`\`\n${exportText}\`\`\``, - flags: 64 - }); - break; - - default: - if (interaction.customId.startsWith("use_")) { - const commandName = interaction.customId.replace("use_", ""); - const foundCmd = Object.values(commandCategories).flat().find(cmd => cmd.name === commandName); - - if (foundCmd) { - await interaction.reply({ - content: `🚀 **Ejecutar: \`${foundCmd.name}\`**\n\nUsa: \`${foundCmd.usage}\`\n\n💡 **Tip:** Copia y pega el comando en el chat para usarlo.`, - flags: 64 - }); - } - } - break; + exportText += `\n`; + } + await interaction.reply({ content: `\`\`\`\n${exportText}\n\`\`\``, flags: 64 }); + return; } }); - collector.on("end", async (collected: any, reason: string) => { - if (reason === "time") { - const timeoutPanel = { - type: 17, - accent_color: 0x36393f, - components: [ - { - type: 10, - content: `### ⏰ **Panel de Ayuda Expirado**\n\nEl panel de ayuda ha expirado por inactividad.\n\nUsa \`${prefix}ayuda\` para abrir un nuevo panel.` - } - ] - }; - + collector.on('end', async (collected: any, reason: string) => { + if (reason === 'time') { try { - await panelMessage.edit({ - components: [timeoutPanel] - }); - } catch (error) { - // Mensaje eliminado o error de edición - } + await panelMessage.edit({ components: [helpPanel] }); + } catch {} } }); } diff --git a/src/commands/messages/net/commandsAdmin.ts b/src/commands/messages/net/commandsAdmin.ts index db3fac5..6ffbb7e 100644 --- a/src/commands/messages/net/commandsAdmin.ts +++ b/src/commands/messages/net/commandsAdmin.ts @@ -62,6 +62,9 @@ export const command: CommandMessage = { type: 'message', aliases: ['cmdadmin', 'synccommands', 'comandos-admin'], cooldown: 5, + description: 'Panel del dueño para registrar/limpiar comandos slash y revisar memoria.', + category: 'Administración', + usage: 'admin-comandos', run: async (message, _args, _client) => { if (message.author.id !== OWNER_ID) { await message.reply({ content: '❌ No tienes permisos para usar este panel.' }); diff --git a/src/commands/messages/net/ping.ts b/src/commands/messages/net/ping.ts index d27315f..9690c0a 100644 --- a/src/commands/messages/net/ping.ts +++ b/src/commands/messages/net/ping.ts @@ -5,6 +5,9 @@ export const command: CommandMessage = { type: "message", aliases: ['latency', 'pong'], cooldown: 5, + description: 'Verifica la latencia y que el bot esté respondiendo.', + category: 'Red', + usage: 'ping', run: async (message, args) => { await message.reply('pong!') } diff --git a/src/commands/messages/settings-server/settings.ts b/src/commands/messages/settings-server/settings.ts index 7dfa09a..5a74acb 100644 --- a/src/commands/messages/settings-server/settings.ts +++ b/src/commands/messages/settings-server/settings.ts @@ -5,6 +5,9 @@ export const command: CommandMessage = { type: "message", aliases: ['config', 'ajustes', 'settings'], cooldown: 5, + description: 'Abre el panel de configuración del servidor (prefix y más).', + category: 'Configuración', + usage: 'configuracion', run: async (message, args, client) => { if (!message.member?.permissions.has("Administrator")) { await message.reply("❌ No tienes permisos de Administrador."); diff --git a/src/core/types/commands.ts b/src/core/types/commands.ts index ceb62c0..a4a1ffc 100644 --- a/src/core/types/commands.ts +++ b/src/core/types/commands.ts @@ -6,6 +6,10 @@ export interface CommandMessage { type: 'message'; aliases?: string[]; cooldown?: number; + // New optional metadata for auto-help + description?: string; + category?: string; + usage?: string; run: (message: Message, args: string[], client: Amayo) => Promise; }