feat: add descriptions, categories, and usage examples to commands for improved help functionality
This commit is contained in:
@@ -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 <mensaje>',
|
||||
run: async (message, args) => {
|
||||
// Verificar que se proporcione un prompt
|
||||
if (!args || args.length === 0) {
|
||||
|
||||
@@ -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 <nombre>",
|
||||
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<AnyComponentBuilder> = new ActionRowBuilder().addComponents(descInput);
|
||||
const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(descInput);
|
||||
modal.addComponents(firstActionRow);
|
||||
|
||||
//@ts-ignore
|
||||
@@ -406,7 +408,7 @@ export const command: CommandMessage = {
|
||||
.setMaxLength(7)
|
||||
.setRequired(false);
|
||||
|
||||
const firstActionRow: ActionRowBuilder<TextInputBuilder> = new ActionRowBuilder().addComponents(colorInput);
|
||||
const firstActionRow: ActionRowBuilder<TextInputBuilder> = new ActionRowBuilder<TextInputBuilder>().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<TextInputBuilder>().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<TextInputBuilder>().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<TextInputBuilder>().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<TextInputBuilder>().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<TextInputBuilder>().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<TextInputBuilder>().addComponents(visibleInput);
|
||||
const secondRow = new ActionRowBuilder<TextInputBuilder>().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<TextInputBuilder>().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<TextInputBuilder>().addComponents(urlInput);
|
||||
const r2 = new ActionRowBuilder<TextInputBuilder>().addComponents(labelInput);
|
||||
const r3 = new ActionRowBuilder<TextInputBuilder>().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<TextInputBuilder>().addComponents(urlInput);
|
||||
const r2 = new ActionRowBuilder<TextInputBuilder>().addComponents(labelInput);
|
||||
const r3 = new ActionRowBuilder<TextInputBuilder>().addComponents(emojiInput);
|
||||
modal.addComponents(r1, r2, r3);
|
||||
|
||||
// Abrir modal directamente sin update previo
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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 <nombre>",
|
||||
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
|
||||
|
||||
@@ -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 <nombre>`
|
||||
},
|
||||
{
|
||||
name: "editar-embed",
|
||||
aliases: ["embed-editar", "modificar-embed"],
|
||||
description: "Editor avanzado de embeds con interfaz interactiva",
|
||||
usage: `${prefix}editar-embed <nombre>`
|
||||
},
|
||||
{
|
||||
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<string>();
|
||||
const allMsgCommands = [] as Array<{
|
||||
name: string;
|
||||
aliases: string[];
|
||||
description: string;
|
||||
category: string;
|
||||
usage: string;
|
||||
cooldown?: number;
|
||||
}>;
|
||||
|
||||
// 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"
|
||||
}
|
||||
]
|
||||
};
|
||||
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);
|
||||
|
||||
// Si se especifica un comando específico
|
||||
if (args.length > 0) {
|
||||
const searchCommand = args[0].toLowerCase();
|
||||
let foundCommand = null;
|
||||
let foundCategory = null;
|
||||
const cdesc = (cmd.description ?? '').toString().trim();
|
||||
const ccat = (cmd.category ?? 'Otros').toString();
|
||||
const usage = (cmd.usage ? `${prefix}${cmd.usage}` : `${prefix}${baseName}`);
|
||||
|
||||
// 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,
|
||||
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(", ")}`
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const detailActionsRow = {
|
||||
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"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await message.reply({
|
||||
flags: 32768,
|
||||
components: [commandDetailPanel, detailActionsRow]
|
||||
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
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// Comando no encontrado - SIMPLIFICADO
|
||||
const notFoundPanel = {
|
||||
}
|
||||
|
||||
// Si no hay comandos
|
||||
if (allMsgCommands.length === 0) {
|
||||
const emptyPanel = {
|
||||
type: 17,
|
||||
accent_color: 0xf04747,
|
||||
components: [
|
||||
{
|
||||
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: `### ❌ No hay comandos disponibles\n\nAún no se han cargado comandos de mensaje.`
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const notFoundRow = {
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
type: 2,
|
||||
style: 1,
|
||||
label: "📋 Ver Todos",
|
||||
custom_id: "show_all_commands"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await message.reply({
|
||||
flags: 32768,
|
||||
components: [notFoundPanel, notFoundRow]
|
||||
});
|
||||
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));
|
||||
};
|
||||
|
||||
// Agrupar por categoría
|
||||
const byCategory = new Map<string, typeof allMsgCommands>();
|
||||
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);
|
||||
}
|
||||
|
||||
// Panel principal de ayuda - OPTIMIZADO para no exceder límite de componentes
|
||||
const helpPanel = {
|
||||
// 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 query = args.join(' ').trim();
|
||||
const found = findByNameOrAlias(query);
|
||||
if (found) {
|
||||
const panel = {
|
||||
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
|
||||
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(', ')}` : '')
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 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({
|
||||
const backRow = {
|
||||
type: 1,
|
||||
components: [
|
||||
{ type: 2, style: 2, label: '↩️ Volver', custom_id: 'back_to_main' }
|
||||
]
|
||||
};
|
||||
await message.reply({ flags: 32768, components: [panel, backRow] });
|
||||
return;
|
||||
}
|
||||
// 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: 0x00a8ff,
|
||||
components: [
|
||||
{ type: 10, content: `### 📂 Categoría: **${matchCat}** (${cmds.length})` },
|
||||
{ type: 14, spacing: 2, divider: true },
|
||||
...cmds.map(cmd => ({
|
||||
type: 10,
|
||||
content: `🔹 **${categoryName}** (${commands.length})\n${commandsList}`
|
||||
});
|
||||
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 message.reply({ flags: 32768, components: [catPanel, backRow] });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Botones de navegación
|
||||
const navigationRow = {
|
||||
// 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:** ${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}` };
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
// 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`;
|
||||
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`;
|
||||
}
|
||||
exportText += `\n`;
|
||||
});
|
||||
exportText += `\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;
|
||||
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 {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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.' });
|
||||
|
||||
@@ -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!')
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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<void>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user