feat: add descriptions, categories, and usage examples to commands for improved help functionality

This commit is contained in:
2025-09-26 06:38:09 -05:00
parent eb3f874628
commit 119ac89274
9 changed files with 193 additions and 388 deletions

View File

@@ -24,6 +24,9 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ['chat', 'gemini'], aliases: ['chat', 'gemini'],
cooldown: 5, cooldown: 5,
description: 'Chatea con la IA (Gemini) directamente desde Discord.',
category: 'IA',
usage: 'ai <mensaje>',
run: async (message, args) => { run: async (message, args) => {
// Verificar que se proporcione un prompt // Verificar que se proporcione un prompt
if (!args || args.length === 0) { if (!args || args.length === 0) {

View File

@@ -2,7 +2,6 @@ import { CommandMessage } from "../../../core/types/commands";
// @ts-ignore // @ts-ignore
import { import {
ComponentType, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, Message, MessageFlags, ComponentType, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, Message, MessageFlags,
AnyComponentBuilder
} from "discord.js"; } from "discord.js";
import { replaceVars, isValidUrlOrVariable, listVariables } from "../../../core/lib/vars"; import { replaceVars, isValidUrlOrVariable, listVariables } from "../../../core/lib/vars";
@@ -238,6 +237,9 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ["embed-crear", "nuevo-embed", "blockcreatev2"], aliases: ["embed-crear", "nuevo-embed", "blockcreatev2"],
cooldown: 20, cooldown: 20,
description: "Crea un nuevo bloque/embedded con editor interactivo (DisplayComponents).",
category: "Alianzas",
usage: "crear-embed <nombre>",
run: async (message, args, client) => { run: async (message, args, client) => {
if (!message.member?.permissions.has("Administrator")) { if (!message.member?.permissions.has("Administrator")) {
await message.reply("❌ No tienes permisos de Administrador."); await message.reply("❌ No tienes permisos de Administrador.");
@@ -383,7 +385,7 @@ export const command: CommandMessage = {
.setMaxLength(2000) .setMaxLength(2000)
.setRequired(true); .setRequired(true);
const firstActionRow: ActionRowBuilder<AnyComponentBuilder> = new ActionRowBuilder().addComponents(descInput); const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(descInput);
modal.addComponents(firstActionRow); modal.addComponents(firstActionRow);
//@ts-ignore //@ts-ignore
@@ -406,7 +408,7 @@ export const command: CommandMessage = {
.setMaxLength(7) .setMaxLength(7)
.setRequired(false); .setRequired(false);
const firstActionRow: ActionRowBuilder<TextInputBuilder> = new ActionRowBuilder().addComponents(colorInput); const firstActionRow: ActionRowBuilder<TextInputBuilder> = new ActionRowBuilder<TextInputBuilder>().addComponents(colorInput);
modal.addComponents(firstActionRow); modal.addComponents(firstActionRow);
//@ts-ignore //@ts-ignore
@@ -426,7 +428,7 @@ export const command: CommandMessage = {
.setMaxLength(2000) .setMaxLength(2000)
.setRequired(true); .setRequired(true);
const firstActionRow = new ActionRowBuilder().addComponents(contentInput); const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(contentInput);
modal.addComponents(firstActionRow); modal.addComponents(firstActionRow);
//@ts-ignore //@ts-ignore
@@ -446,7 +448,7 @@ export const command: CommandMessage = {
.setMaxLength(2000) .setMaxLength(2000)
.setRequired(true); .setRequired(true);
const firstActionRow = new ActionRowBuilder().addComponents(imageUrlInput); const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(imageUrlInput);
modal.addComponents(firstActionRow); modal.addComponents(firstActionRow);
//@ts-ignore //@ts-ignore
@@ -498,7 +500,7 @@ export const command: CommandMessage = {
.setMaxLength(2000) .setMaxLength(2000)
.setRequired(true); .setRequired(true);
const firstActionRow = new ActionRowBuilder().addComponents(coverInput); const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(coverInput);
modal.addComponents(firstActionRow); modal.addComponents(firstActionRow);
//@ts-ignore //@ts-ignore
@@ -527,7 +529,7 @@ export const command: CommandMessage = {
.setMaxLength(2000) .setMaxLength(2000)
.setRequired(true); .setRequired(true);
const firstActionRow = new ActionRowBuilder().addComponents(coverInput); const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(coverInput);
modal.addComponents(firstActionRow); modal.addComponents(firstActionRow);
//@ts-ignore //@ts-ignore
@@ -831,7 +833,7 @@ export const command: CommandMessage = {
.setMaxLength(4000) .setMaxLength(4000)
.setRequired(true); .setRequired(true);
const firstRow = new ActionRowBuilder().addComponents(jsonInput); const firstRow = new ActionRowBuilder<TextInputBuilder>().addComponents(jsonInput);
modal.addComponents(firstRow); modal.addComponents(firstRow);
//@ts-ignore //@ts-ignore
@@ -874,8 +876,8 @@ export const command: CommandMessage = {
.setMaxLength(1) .setMaxLength(1)
.setRequired(false); .setRequired(false);
const firstRow = new ActionRowBuilder().addComponents(visibleInput); const firstRow = new ActionRowBuilder<TextInputBuilder>().addComponents(visibleInput);
const secondRow = new ActionRowBuilder().addComponents(spacingInput); const secondRow = new ActionRowBuilder<TextInputBuilder>().addComponents(spacingInput);
modal.addComponents(firstRow, secondRow); modal.addComponents(firstRow, secondRow);
//@ts-ignore //@ts-ignore
@@ -936,7 +938,7 @@ export const command: CommandMessage = {
.setMaxLength(2000) .setMaxLength(2000)
.setRequired(false); .setRequired(false);
const firstRow = new ActionRowBuilder().addComponents(thumbnailInput); const firstRow = new ActionRowBuilder<TextInputBuilder>().addComponents(thumbnailInput);
modal.addComponents(firstRow); modal.addComponents(firstRow);
// Abrir modal directamente sin update previo // Abrir modal directamente sin update previo
@@ -1035,9 +1037,9 @@ export const command: CommandMessage = {
.setMaxLength(64) .setMaxLength(64)
.setRequired(false); .setRequired(false);
const r1 = new ActionRowBuilder().addComponents(urlInput); const r1 = new ActionRowBuilder<TextInputBuilder>().addComponents(urlInput);
const r2 = new ActionRowBuilder().addComponents(labelInput); const r2 = new ActionRowBuilder<TextInputBuilder>().addComponents(labelInput);
const r3 = new ActionRowBuilder().addComponents(emojiInput); const r3 = new ActionRowBuilder<TextInputBuilder>().addComponents(emojiInput);
modal.addComponents(r1, r2, r3); modal.addComponents(r1, r2, r3);
// Abrir modal directamente en la misma interacción del botón // Abrir modal directamente en la misma interacción del botón
@@ -1081,9 +1083,9 @@ export const command: CommandMessage = {
.setMaxLength(64) .setMaxLength(64)
.setRequired(false); .setRequired(false);
const r1 = new ActionRowBuilder().addComponents(urlInput); const r1 = new ActionRowBuilder<TextInputBuilder>().addComponents(urlInput);
const r2 = new ActionRowBuilder().addComponents(labelInput); const r2 = new ActionRowBuilder<TextInputBuilder>().addComponents(labelInput);
const r3 = new ActionRowBuilder().addComponents(emojiInput); const r3 = new ActionRowBuilder<TextInputBuilder>().addComponents(emojiInput);
modal.addComponents(r1, r2, r3); modal.addComponents(r1, r2, r3);
// Abrir modal directamente sin update previo // Abrir modal directamente sin update previo

View File

@@ -5,6 +5,9 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ["ddemo", "componentsdemo"], aliases: ["ddemo", "componentsdemo"],
cooldown: 10, cooldown: 10,
description: "Demostración de DisplayComponents con accesorios y acciones.",
category: "Alianzas",
usage: "displaydemo",
run: async (message, args, client) => { run: async (message, args, client) => {
if (!message.member?.permissions.has("Administrator")) { if (!message.member?.permissions.has("Administrator")) {
await message.reply("❌ No tienes permisos de Administrador."); await message.reply("❌ No tienes permisos de Administrador.");

View File

@@ -2,7 +2,6 @@ import { CommandMessage } from "../../../core/types/commands";
// @ts-ignore // @ts-ignore
import { ComponentType, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, MessageFlags } from "discord.js"; import { ComponentType, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, MessageFlags } from "discord.js";
import { replaceVars, isValidUrlOrVariable, listVariables } from "../../../core/lib/vars"; import { replaceVars, isValidUrlOrVariable, listVariables } from "../../../core/lib/vars";
import {Block} from "../../../core/types/block";
// Botones de edición (máx 5 por fila) // Botones de edición (máx 5 por fila)
const btns = (disabled = false) => ([ const btns = (disabled = false) => ([
@@ -122,6 +121,9 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ["embed-editar", "modificar-embed", "blockeditv2"], aliases: ["embed-editar", "modificar-embed", "blockeditv2"],
cooldown: 20, cooldown: 20,
description: "Edita un bloque/embed existente con herramientas interactivas.",
category: "Alianzas",
usage: "editar-embed <nombre>",
run: async (message, args, client) => { run: async (message, args, client) => {
if (!message.member?.permissions.has("Administrator")) { if (!message.member?.permissions.has("Administrator")) {
await message.reply("❌ No tienes permisos de Administrador."); await message.reply("❌ No tienes permisos de Administrador.");
@@ -142,7 +144,7 @@ export const command: CommandMessage = {
return; return;
} }
let blockState: Block = { let blockState: any = {
//@ts-ignore //@ts-ignore
title: existingBlock.config?.title ?? `## Block: ${blockName}`, title: existingBlock.config?.title ?? `## Block: ${blockName}`,
//@ts-ignore //@ts-ignore

View File

@@ -1,11 +1,15 @@
// @ts-ignore // @ts-ignore
import { CommandMessage } from "../../../core/types/commands"; import { CommandMessage } from "../../../core/types/commands";
import { commands as registry } from "../../core/loader";
export const command: CommandMessage = { export const command: CommandMessage = {
name: 'ayuda', name: 'ayuda',
type: "message", type: "message",
aliases: ['help', 'comandos', 'cmds'], aliases: ['help', 'comandos', 'cmds'],
cooldown: 5, 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) => { run: async (message: any, args: string[], client: any) => {
// Obtener información del servidor para mostrar el prefix actual // Obtener información del servidor para mostrar el prefix actual
const server = await client.prisma.guild.findFirst({ const server = await client.prisma.guild.findFirst({
@@ -13,432 +17,210 @@ export const command: CommandMessage = {
}); });
const prefix = server?.prefix || "!"; const prefix = server?.prefix || "!";
// Definir categorías de comandos con nombres modernos // Construir lista de comandos únicos (sin duplicar aliases)
const commandCategories = { const seen = new Set<string>();
"Alianzas": [ const allMsgCommands = [] as Array<{
{ name: string;
name: "crear-embed", aliases: string[];
aliases: ["embed-crear", "nuevo-embed"], description: string;
description: "Crear nuevos embeds con DisplayComponents modernos", category: string;
usage: `${prefix}crear-embed <nombre>` usage: string;
}, cooldown?: number;
{ }>;
name: "editar-embed",
aliases: ["embed-editar", "modificar-embed"], for (const [, cmd] of registry) {
description: "Editor avanzado de embeds con interfaz interactiva", if (!cmd || cmd.type !== 'message') continue;
usage: `${prefix}editar-embed <nombre>` const baseName: string | undefined = cmd.name ?? cmd.data?.name;
}, if (!baseName) continue;
{ if (seen.has(baseName)) continue; // evitar duplicados por alias
name: "lista-embeds", seen.add(baseName);
aliases: ["embeds", "ver-embeds"],
description: "Centro de gestión de embeds con paginación", const cdesc = (cmd.description ?? '').toString().trim();
usage: `${prefix}lista-embeds` const ccat = (cmd.category ?? 'Otros').toString();
}, const usage = (cmd.usage ? `${prefix}${cmd.usage}` : `${prefix}${baseName}`);
{
name: "eliminar-embed", allMsgCommands.push({
aliases: ["embed-eliminar", "borrar-embed"], name: baseName,
description: "Panel interactivo para eliminar embeds", aliases: Array.isArray(cmd.aliases) ? cmd.aliases : [],
usage: `${prefix}eliminar-embed [nombre]` description: cdesc || 'Sin descripción',
}, category: ccat,
{ usage,
name: "canal-alianza", cooldown: typeof cmd.cooldown === 'number' ? cmd.cooldown : undefined
aliases: ["configurar-canal", "setup-canal"], });
description: "Configurar canales para sistema de alianzas", }
usage: `${prefix}canal-alianza`
}, // Si no hay comandos
{ if (allMsgCommands.length === 0) {
name: "eliminar-canal-alianza", const emptyPanel = {
aliases: ["removechannel-alliance", "removealchannel", "delalchannel"], type: 17,
description: "Eliminar canales de la configuración de alianzas", accent_color: 0xf04747,
usage: `${prefix}eliminar-canal-alianza` components: [
}, {
{ type: 10,
name: "listar-canales-alianza", content: `### ❌ No hay comandos disponibles\n\nAún no se han cargado comandos de mensaje.`
aliases: ["listchannels-alliance", "listalchannel", "channelsally"], }
description: "Ver lista detallada de canales configurados para alianzas", ]
usage: `${prefix}listar-canales-alianza` };
}, await message.reply({ flags: 32768, components: [emptyPanel] });
{ return;
name: "demo-componentes", }
aliases: ["demo", "prueba-componentes"],
description: "Demostración de DisplayComponents con accesorios", // Index para búsqueda rápida por nombre/alias
usage: `${prefix}demo-componentes` const findByNameOrAlias = (q: string) => {
} const term = q.toLowerCase();
], return allMsgCommands.find(c => c.name === term || c.aliases.map(a => a.toLowerCase()).includes(term));
"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`
}
]
}; };
// Definir backRow una sola vez fuera de los casos // Agrupar por categoría
const backRow = { const byCategory = new Map<string, typeof allMsgCommands>();
type: 1, for (const c of allMsgCommands) {
components: [ const cat = c.category || 'Otros';
{ if (!byCategory.has(cat)) byCategory.set(cat, [] as any);
type: 2, // @ts-ignore
style: 2, byCategory.get(cat)!.push(c);
label: "↩️ Volver al Menú", }
custom_id: "back_to_main"
}
]
};
// 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) { if (args.length > 0) {
const searchCommand = args[0].toLowerCase(); const query = args.join(' ').trim();
let foundCommand = null; const found = findByNameOrAlias(query);
let foundCategory = null; if (found) {
const panel = {
// 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 = {
type: 17, type: 17,
accent_color: 0x5865f2, accent_color: 0x5865f2,
components: [ components: [
{ {
type: 10, 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 backRow = {
const detailActionsRow = {
type: 1, type: 1,
components: [ components: [
{ { type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' }
type: 2,
style: 2,
label: "📋 Ver Todos",
custom_id: "show_all_commands"
},
{
type: 2,
style: 2,
label: "🔍 Buscar Otro",
custom_id: "search_command"
}
] ]
}; };
await message.reply({ flags: 32768, components: [panel, backRow] });
await message.reply({
flags: 32768,
components: [commandDetailPanel, detailActionsRow]
});
return; return;
} else { }
// Comando no encontrado - SIMPLIFICADO // También permitir filtrar por categoría si coincide exacto (case-insensitive)
const notFoundPanel = { const matchCat = categories.find(c => c.toLowerCase() === query.toLowerCase());
if (matchCat) {
const cmds = byCategory.get(matchCat)!;
const catPanel = {
type: 17, type: 17,
accent_color: 0xf04747, accent_color: 0x00a8ff,
components: [ components: [
{ { type: 10, content: `### 📂 Categoría: **${matchCat}** (${cmds.length})` },
{ type: 14, spacing: 2, divider: true },
...cmds.map(cmd => ({
type: 10, 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 <categoría>\` para filtrar` content: `**${cmd.name}** — ${cmd.description}\n\`${cmd.usage}\``
} }))
] ]
}; };
const backRow = {
const notFoundRow = {
type: 1, type: 1,
components: [ components: [ { type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' } ]
{
type: 2,
style: 1,
label: "📋 Ver Todos",
custom_id: "show_all_commands"
}
]
}; };
await message.reply({ flags: 32768, components: [catPanel, backRow] });
await message.reply({
flags: 32768,
components: [notFoundPanel, notFoundRow]
});
return; return;
} }
} }
// Panel principal de ayuda - OPTIMIZADO para no exceder límite de componentes // Panel principal dinámico
const helpPanel = { const helpPanel: any = {
type: 17, type: 17,
accent_color: 0x5865f2, accent_color: 0x5865f2,
components: [ components: [
{ { type: 10, content: `### 📚 Centro de Ayuda — ${message.guild!.name}` },
type: 10, { type: 14, spacing: 1, divider: true },
content: `### 📚 **Centro de Ayuda - ${message.guild!.name}**` { 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 => {
type: 14, const list = byCategory.get(cat)!;
spacing: 1, const names = list.map(c => `\`${c.name}\``).join(', ');
divider: true return { type: 10, content: `🔹 **${cat}** (${list.length})\n${names}` };
}, })
{
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
}
] ]
}; };
// Agregar resumen de categorías de forma compacta // Select de categorías + botón exportar
for (const [categoryName, commands] of Object.entries(commandCategories)) { const categoryRow = {
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 = {
type: 1, type: 1,
components: [ components: [
{ {
type: 2, type: 3,
style: 1, custom_id: 'help_category_select',
label: "🤝 Alianzas", placeholder: '📂 Selecciona una categoría...',
custom_id: "category_alliances" options: categories.slice(0, 25).map(c => ({ label: c, value: `cat:${c}` }))
}, },
{ { type: 2, style: 3, label: '📋 Exportar', custom_id: 'export_commands' }
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"
}
] ]
}; };
const panelMessage = await message.reply({ const panelMessage = await message.reply({ flags: 32768, components: [helpPanel, categoryRow] });
flags: 32768,
components: [helpPanel, navigationRow]
});
const collector = panelMessage.createMessageComponentCollector({ const collector = panelMessage.createMessageComponentCollector({
time: 600000, time: 600000,
filter: (i: any) => i.user.id === message.author.id filter: (i: any) => i.user.id === message.author.id
}); });
collector.on("collect", async (interaction: any) => { collector.on('collect', async (interaction: any) => {
// Manejar información específica de comandos // Selección de categoría
if (interaction.customId.startsWith("cmd_info_")) { if (interaction.customId === 'help_category_select' && interaction.isStringSelectMenu()) {
const commandName = interaction.customId.replace("cmd_info_", ""); const val = interaction.values?.[0] ?? '';
let foundCommand = null; const cat = val.startsWith('cat:') ? val.slice(4) : val;
let foundCategory = null; const list = byCategory.get(cat) ?? [];
for (const [category, commands] of Object.entries(commandCategories)) { const catPanel = {
const command = commands.find(cmd => cmd.name === commandName); type: 17,
if (command) { accent_color: 0x00a8ff,
foundCommand = command; components: [
foundCategory = category; { type: 10, content: `### 📂 Categoría: **${cat}** (${list.length})` },
break; { type: 14, spacing: 2, divider: true },
} ...list.map(cmd => ({ type: 10, content: `**${cmd.name}** — ${cmd.description}\n\`${cmd.usage}\`` }))
} ]
};
if (foundCommand) { const backRow = { type: 1, components: [ { type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' } ] };
await interaction.reply({ await interaction.update({ components: [catPanel, backRow] });
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
});
}
return; return;
} }
// Manejar categorías específicas - VERSIÓN COMPACTA if (interaction.customId === 'back_to_main' || interaction.customId === 'show_all_commands') {
switch (interaction.customId) { await interaction.update({ components: [helpPanel, categoryRow] });
case "category_alliances": return;
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
}
]
};
// Agregar comandos de forma compacta if (interaction.customId === 'export_commands') {
commandCategories["Alianzas"].forEach(cmd => { let exportText = `Comandos — ${message.guild!.name}\n\nPrefix: ${prefix}\n\n`;
alliancePanel.components.push({ for (const cat of categories) {
type: 10, const list = byCategory.get(cat)!;
content: `**${cmd.name}**\n${cmd.description}\n\`${cmd.usage}\`` 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.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`;
} }
exportText += `\n`;
await interaction.reply({ }
content: `\`\`\`\n${exportText}\`\`\``, await interaction.reply({ content: `\`\`\`\n${exportText}\n\`\`\``, flags: 64 });
flags: 64 return;
});
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;
} }
}); });
collector.on("end", async (collected: any, reason: string) => { collector.on('end', async (collected: any, reason: string) => {
if (reason === "time") { 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.`
}
]
};
try { try {
await panelMessage.edit({ await panelMessage.edit({ components: [helpPanel] });
components: [timeoutPanel] } catch {}
});
} catch (error) {
// Mensaje eliminado o error de edición
}
} }
}); });
} }

View File

@@ -62,6 +62,9 @@ export const command: CommandMessage = {
type: 'message', type: 'message',
aliases: ['cmdadmin', 'synccommands', 'comandos-admin'], aliases: ['cmdadmin', 'synccommands', 'comandos-admin'],
cooldown: 5, 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) => { run: async (message, _args, _client) => {
if (message.author.id !== OWNER_ID) { if (message.author.id !== OWNER_ID) {
await message.reply({ content: '❌ No tienes permisos para usar este panel.' }); await message.reply({ content: '❌ No tienes permisos para usar este panel.' });

View File

@@ -5,6 +5,9 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ['latency', 'pong'], aliases: ['latency', 'pong'],
cooldown: 5, cooldown: 5,
description: 'Verifica la latencia y que el bot esté respondiendo.',
category: 'Red',
usage: 'ping',
run: async (message, args) => { run: async (message, args) => {
await message.reply('pong!') await message.reply('pong!')
} }

View File

@@ -5,6 +5,9 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ['config', 'ajustes', 'settings'], aliases: ['config', 'ajustes', 'settings'],
cooldown: 5, 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) => { run: async (message, args, client) => {
if (!message.member?.permissions.has("Administrator")) { if (!message.member?.permissions.has("Administrator")) {
await message.reply("❌ No tienes permisos de Administrador."); await message.reply("❌ No tienes permisos de Administrador.");

View File

@@ -6,6 +6,10 @@ export interface CommandMessage {
type: 'message'; type: 'message';
aliases?: string[]; aliases?: string[];
cooldown?: number; cooldown?: number;
// New optional metadata for auto-help
description?: string;
category?: string;
usage?: string;
run: (message: Message, args: string[], client: Amayo) => Promise<void>; run: (message: Message, args: string[], client: Amayo) => Promise<void>;
} }