Refactor el comando 'items-lista' para mejorar la gestión de paginación y la estructura del mensaje, añadiendo botones de navegación y optimizando la construcción del payload.

This commit is contained in:
Shni
2025-10-14 15:04:23 -05:00
parent 852b1d02a2
commit b49447e2bd

View File

@@ -1,39 +1,37 @@
import type { CommandMessage } from '../../../core/types/commands';
import type Amayo from '../../../core/client';
import { prisma } from '../../../core/database/prisma';
import { ComponentType, ButtonStyle } from 'discord-api-types/v10';
import type { MessageComponentInteraction, TextBasedChannel } from 'discord.js';
import { buildDisplay, dividerBlock, textBlock } from '../../../core/lib/componentsV2';
import type { CommandMessage } from "../../../core/types/commands";
import type Amayo from "../../../core/client";
import { prisma } from "../../../core/database/prisma";
import { ComponentType, ButtonStyle } from "discord-api-types/v10";
import type { MessageComponentInteraction, TextBasedChannel } from "discord.js";
import {
buildDisplay,
dividerBlock,
textBlock,
} from "../../../core/lib/componentsV2";
export const command: CommandMessage = {
name: 'items-lista',
type: 'message',
aliases: ['lista-items', 'items-list'],
name: "items-lista",
type: "message",
aliases: ["lista-items", "items-list"],
cooldown: 5,
description: 'Ver lista de todos los items del servidor',
usage: 'items-lista [pagina]',
description: "Ver lista de todos los items del servidor",
usage: "items-lista [pagina]",
run: async (message, args, client: Amayo) => {
const guildId = message.guild!.id;
const page = parseInt(args[0]) || 1;
const perPage = 8;
async function buildPayload(page: number) {
const total = await prisma.economyItem.count({
where: { OR: [{ guildId }, { guildId: null }] }
where: { OR: [{ guildId }, { guildId: null }] },
});
const items = await prisma.economyItem.findMany({
where: { OR: [{ guildId }, { guildId: null }] },
orderBy: [{ category: 'asc' }, { name: 'asc' }],
orderBy: [{ category: "asc" }, { name: "asc" }],
skip: (page - 1) * perPage,
take: perPage
take: perPage,
});
if (items.length === 0) {
await message.reply('No hay items configurados en este servidor.');
return;
}
const totalPages = Math.ceil(total / perPage);
const totalPages = Math.max(1, Math.ceil(total / perPage));
const displayBlocks = [
textBlock(`# 🛠️ Lista de Items`),
@@ -44,87 +42,105 @@ export const command: CommandMessage = {
const lines = [
`**${item.name || item.key}**`,
`└ Key: \`${item.key}\``,
`└ Categoría: ${item.category || '*Sin categoría*'}`,
`${item.stackable ? '📚 Apilable' : '🔒 No apilable'}${item.maxPerInventory ? ` (Máx: ${item.maxPerInventory})` : ''}${item.guildId === guildId ? ' • 📍 Local' : ' • 🌐 Global'}`,
].join('\n');
`└ Categoría: ${item.category || "*Sin categoría*"}`,
`${item.stackable ? "📚 Apilable" : "🔒 No apilable"}${
item.maxPerInventory ? ` (Máx: ${item.maxPerInventory})` : ""
}${item.guildId === guildId ? " • 📍 Local" : " • 🌐 Global"}`,
].join("\n");
const blocks = [textBlock(lines)];
if (index < items.length - 1) {
blocks.push(dividerBlock({ divider: false, spacing: 1 }));
}
return blocks;
})
}),
];
const display = buildDisplay(0x00D9FF, displayBlocks);
const display = buildDisplay(0x00d9ff, displayBlocks);
const buttons: any[] = [];
if (page > 1) {
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Secondary,
label: '◀ Anterior',
custom_id: `items_prev_${page}`
label: "◀ Anterior",
custom_id: `items_prev_${page}`,
});
}
if (page < totalPages) {
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Secondary,
label: 'Siguiente ▶',
custom_id: `items_next_${page}`
label: "Siguiente ▶",
custom_id: `items_next_${page}`,
});
}
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Primary,
label: 'Ver Detalle',
custom_id: 'items_detail'
label: "Ver Detalle",
custom_id: "items_detail",
});
const components: any[] = [display];
if (buttons.length > 0)
components.push({ type: ComponentType.ActionRow, components: buttons });
return { components, total, totalPages };
}
const page = parseInt(args[0]) || 1;
const channel = message.channel as TextBasedChannel & { send: Function };
const initial = await buildPayload(page);
if (initial.total === 0) {
await message.reply("No hay items configurados en este servidor.");
return;
}
const msg = await (channel.send as any)({
content: null,
flags: 32768,
reply: { messageReference: message.id },
components: [
display,
...(buttons.length > 0 ? [{
type: ComponentType.ActionRow,
components: buttons
}] : [])
]
components: initial.components,
});
const collector = msg.createMessageComponentCollector({
let collector = msg.createMessageComponentCollector({
time: 5 * 60_000,
filter: (i) => i.user.id === message.author.id
filter: (i) => i.user.id === message.author.id,
});
collector.on('collect', async (i: MessageComponentInteraction) => {
collector.on("collect", async (i: MessageComponentInteraction) => {
if (!i.isButton()) return;
if (i.customId.startsWith('items_prev_')) {
const currentPage = parseInt(i.customId.split('_')[2]);
if (
i.customId.startsWith("items_prev_") ||
i.customId.startsWith("items_next_")
) {
const parts = i.customId.split("_");
const currentPage = parseInt(parts[2]);
const newPage = i.customId.startsWith("items_prev_")
? currentPage - 1
: currentPage + 1;
await i.deferUpdate();
args[0] = String(currentPage - 1);
await command.run!(message, args, client);
collector.stop();
} else if (i.customId.startsWith('items_next_')) {
const currentPage = parseInt(i.customId.split('_')[2]);
await i.deferUpdate();
args[0] = String(currentPage + 1);
await command.run!(message, args, client);
collector.stop();
} else if (i.customId === 'items_detail') {
// rebuild payload and edit message
try {
const p = await buildPayload(newPage);
await msg.edit({ content: null, components: p.components });
} catch (e) {
await i.followUp({
content: `❌ Error actualizando página: ${(e as any).message || e}`,
flags: 64,
});
}
return;
}
if (i.customId === "items_detail") {
await i.reply({
content: '💡 Usa `!item-ver <key>` para ver detalles de un item específico.',
flags: 64
content:
"💡 Usa `!item-ver <key>` para ver detalles de un item específico.",
flags: 64,
});
}
});
}
},
};