feat: mejorar la presentación de estadísticas y mensajes de error en los comandos de racha, estadísticas y tienda

This commit is contained in:
2025-10-08 22:51:15 -05:00
parent 32ede57d89
commit d842a4ebd5
3 changed files with 80 additions and 48 deletions

View File

@@ -29,13 +29,15 @@ export const command: CommandMessage = {
// Construir bloques de display (evitando type:9 sin accessory) // Construir bloques de display (evitando type:9 sin accessory)
const blocks: any[] = [ const blocks: any[] = [
textBlock(`# 🔥 Racha Diaria de ${message.author.username}`), textBlock(
`## <a:0fire:1425690572945100860> Racha diaria de ${message.author.username}`
),
dividerBlock(), dividerBlock(),
textBlock( textBlock(
`**📊 ESTADÍSTICAS**\n` + `**<:stats:1425689271788113991> ESTADÍSTICAS**\n` +
`🔥 Racha Actual: **${streak.currentStreak}** días\n` + `<a:0fire:1425690572945100860> Racha Actual: **${streak.currentStreak}** días\n` +
` Mejor Racha: **${streak.longestStreak}** días\n` + `<a:bluestargif:1425691124214927452> Mejor Racha: **${streak.longestStreak}** días\n` +
`📅 Días Activos: **${streak.totalDaysActive}** días` `<:events:1425691310194561106> Días Activos: **${streak.totalDaysActive}** días`
), ),
dividerBlock({ spacing: 1 }), dividerBlock({ spacing: 1 }),
]; ];
@@ -45,22 +47,23 @@ export const command: CommandMessage = {
if (daysIncreased) { if (daysIncreased) {
blocks.push( blocks.push(
textBlock( textBlock(
`** ¡RACHA INCREMENTADA!**\nHas mantenido tu racha por **${streak.currentStreak}** días seguidos.` `**<:Sup_res:1420535051162095747> ¡RACHA INCREMENTADA!**\nHas mantenido tu racha por **${streak.currentStreak}** días seguidos.`
) )
); );
} else { } else {
blocks.push( blocks.push(
textBlock( textBlock(
`**⚠️ RACHA REINICIADA**\nPasó más de un día sin actividad. Tu racha se ha reiniciado.` `**<:Sup_urg:1420535068056748042> RACHA REINICIADA**\nPasó más de un día sin actividad. Tu racha se ha reiniciado.`
) )
); );
} }
// Mostrar recompensas // Mostrar recompensas
if (rewards) { if (rewards) {
let rewardsText = "**🎁 RECOMPENSA DEL DÍA**\n"; let rewardsText =
"**<a:Chest:1425691840614764645> RECOMPENSA DEL DÍA**\n";
if (rewards.coins) if (rewards.coins)
rewardsText += `💰 **${rewards.coins.toLocaleString()}** monedas\n`; rewardsText += `<:coin:1425667511013081169> **${rewards.coins.toLocaleString()}** monedas\n`;
if (rewards.items && rewards.items.length) { if (rewards.items && rewards.items.length) {
const basics = await fetchItemBasics( const basics = await fetchItemBasics(
guildId, guildId,
@@ -83,7 +86,7 @@ export const command: CommandMessage = {
} else { } else {
blocks.push( blocks.push(
textBlock( textBlock(
`** YA RECLAMASTE HOY**\nYa has reclamado tu recompensa diaria. Vuelve mañana para continuar tu racha.` `**<:apin:1336533845541126174> YA RECLAMASTE HOY**\nYa has reclamado tu recompensa diaria. Vuelve mañana para continuar tu racha.`
) )
); );
} }
@@ -107,7 +110,9 @@ export const command: CommandMessage = {
await sendDisplayReply(message, display); await sendDisplayReply(message, display);
} catch (error) { } catch (error) {
console.error("Error en comando racha:", error); console.error("Error en comando racha:", error);
await message.reply("❌ Error al obtener tu racha diaria."); await message.reply(
"<:Cross:1420535096208920576> Error al obtener tu racha diaria."
);
} }
}, },
}; };

View File

@@ -1,15 +1,15 @@
import type { CommandMessage } from '../../../core/types/commands'; import type { CommandMessage } from "../../../core/types/commands";
import type Amayo from '../../../core/client'; import type Amayo from "../../../core/client";
import { getPlayerStatsFormatted } from '../../../game/stats/service'; import { getPlayerStatsFormatted } from "../../../game/stats/service";
import type { TextBasedChannel } from 'discord.js'; import type { TextBasedChannel } from "discord.js";
export const command: CommandMessage = { export const command: CommandMessage = {
name: 'stats', name: "stats",
type: 'message', type: "message",
aliases: ['estadisticas', 'est'], aliases: ["estadisticas", "est"],
cooldown: 5, cooldown: 5,
description: 'Ver estadísticas detalladas de un jugador', description: "Ver estadísticas detalladas de un jugador",
usage: 'stats [@usuario]', usage: "stats [@usuario]",
run: async (message, args, client: Amayo) => { run: async (message, args, client: Amayo) => {
try { try {
const guildId = message.guild!.id; const guildId = message.guild!.id;
@@ -20,52 +20,75 @@ export const command: CommandMessage = {
const stats = await getPlayerStatsFormatted(userId, guildId); const stats = await getPlayerStatsFormatted(userId, guildId);
const formatValue = (value: unknown): string => { const formatValue = (value: unknown): string => {
if (typeof value === 'number') return value.toLocaleString(); if (typeof value === "number") return value.toLocaleString();
if (typeof value === 'bigint') return value.toString(); if (typeof value === "bigint") return value.toString();
if (typeof value === 'string') return value.trim() || '0'; if (typeof value === "string") return value.trim() || "0";
return value == null ? '0' : String(value); return value == null ? "0" : String(value);
}; };
const components: any[] = [ const components: any[] = [
{ {
type: 10, type: 10,
content: `# 📊 Estadísticas de ${targetUser.username}` content: `## <:stats:1425689271788113991> Estadísticas de ${targetUser.username}`,
}, },
{ type: 14, divider: true } { type: 14, divider: false, spacing: 1 },
]; ];
const addSection = (title: string, data?: Record<string, unknown>) => { const addSection = (title: string, data?: Record<string, unknown>) => {
if (!data || typeof data !== 'object') return; if (!data || typeof data !== "object") return;
const entries = Object.entries(data); const entries = Object.entries(data);
const lines = entries.map(([key, value]) => `${key}: **${formatValue(value)}**`); const lines = entries.map(
const content = lines.length > 0 ? lines.join('\n') : 'Sin datos'; ([key, value]) => `${key}: **${formatValue(value)}**`
);
const content = lines.length > 0 ? lines.join("\n") : "Sin datos";
components.push({ components.push({
type: 10, type: 10,
content: `**${title}**\n${content}` content: `**${title}**\n${content}`,
}); });
components.push({ type: 14, divider: false, spacing: 1 }); components.push({ type: 14, divider: false, spacing: 1 });
}; };
addSection('🎮 ACTIVIDADES', stats.activities as Record<string, unknown> | undefined); addSection(
addSection('⚔️ COMBATE', stats.combat as Record<string, unknown> | undefined); "<:stats:1425689271788113991> ACTIVIDADES",
addSection('💰 ECONOMÍA', stats.economy as Record<string, unknown> | undefined); stats.activities as Record<string, unknown> | undefined
addSection('📦 ITEMS', stats.items as Record<string, unknown> | undefined); );
addSection('🏆 RÉCORDS', stats.records as Record<string, unknown> | undefined); addSection(
"<:damage:1425670476449189998> COMBATE",
stats.combat as Record<string, unknown> | undefined
);
addSection(
"<:coin:1425667511013081169> ECONOMÍA",
stats.economy as Record<string, unknown> | undefined
);
addSection(
"<:emptybox:1425678700753588305> ITEMS",
stats.items as Record<string, unknown> | undefined
);
addSection(
"<a:trophy:1425690252118462526> RÉCORDS",
stats.records as Record<string, unknown> | undefined
);
// Remove trailing separator if present // Remove trailing separator if present
if (components.length > 0 && components[components.length - 1]?.type === 14) { if (
components.length > 0 &&
components[components.length - 1]?.type === 14
) {
components.pop(); components.pop();
} }
if (components.length === 1) { if (components.length === 1) {
components.push({ type: 10, content: '*Sin estadísticas registradas.*' }); components.push({
type: 10,
content: "*Sin estadísticas registradas.*",
});
} }
// Crear DisplayComponent // Crear DisplayComponent
const display = { const display = {
type: 17, type: 17,
accent_color: 0x5865F2, accent_color: 0x5865f2,
components components,
}; };
// Enviar con flags // Enviar con flags
@@ -74,11 +97,13 @@ export const command: CommandMessage = {
content: null, content: null,
components: [display], components: [display],
flags: 32768, // MessageFlags.IS_COMPONENTS_V2 flags: 32768, // MessageFlags.IS_COMPONENTS_V2
reply: { messageReference: message.id } reply: { messageReference: message.id },
}); });
} catch (error) { } catch (error) {
console.error('Error en comando stats:', error); console.error("Error en comando stats:", error);
await message.reply('❌ Error al obtener las estadísticas.'); await message.reply(
"<:Cross:1420535096208920576> Error al obtener las estadísticas."
);
} }
} },
}; };

View File

@@ -178,7 +178,9 @@ export const command: CommandMessage = {
console.error("Error handling shop interaction:", error); console.error("Error handling shop interaction:", error);
if (!interaction.replied && !interaction.deferred) { if (!interaction.replied && !interaction.deferred) {
await interaction.reply({ await interaction.reply({
content: `❌ Error: ${error?.message ?? error}`, content: `<:Cross:1420535096208920576> Error: ${
error?.message ?? error
}`,
flags: MessageFlags.Ephemeral, flags: MessageFlags.Ephemeral,
}); });
} }
@@ -229,7 +231,7 @@ async function buildShopPanel(
}, },
{ {
type: 14, type: 14,
divider: true, divider: false,
spacing: 2, spacing: 2,
}, },
], ],
@@ -277,13 +279,13 @@ async function buildShopPanel(
container.components.push({ container.components.push({
type: 10, type: 10,
content: `${label}\n\n${ content: `${label}\n\n${
item.description || undefined item.description || null
}${statsInfo}\n\nPrecio: ${price}${stockInfo}`, }${statsInfo}\n\nPrecio: ${price}${stockInfo}`,
}); });
container.components.push({ container.components.push({
type: 14, type: 14,
divider: true, divider: false,
spacing: 1, spacing: 1,
}); });
} }
@@ -308,7 +310,7 @@ async function buildShopPanel(
const stockText = const stockText =
offer.stock != null ? ` (${offer.stock} disponibles)` : ""; offer.stock != null ? ` (${offer.stock} disponibles)` : "";
const selectedMark = isSelected ? " " : ""; const selectedMark = isSelected ? " <a:Sparkles:1321196183133098056>" : "";
container.components.push({ container.components.push({
type: 9, type: 9,