feat: agregar categoría a varios comandos y mejorar la presentación de mensajes

This commit is contained in:
2025-10-08 23:06:16 -05:00
parent d842a4ebd5
commit de39e7e487
6 changed files with 112 additions and 75 deletions

View File

@@ -1,38 +1,45 @@
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 { getOrCreateWallet } from '../../../game/economy/service'; import { getOrCreateWallet } from "../../../game/economy/service";
import type { TextBasedChannel } from 'discord.js'; import type { TextBasedChannel } from "discord.js";
export const command: CommandMessage = { export const command: CommandMessage = {
name: 'monedas', name: "monedas",
type: 'message', type: "message",
aliases: ['coins','saldo'], aliases: ["coins", "saldo"],
cooldown: 2, cooldown: 2,
description: 'Muestra tu saldo de monedas en este servidor.', description: "Muestra tu saldo de monedas en este servidor.",
usage: 'monedas', category: "Economía",
usage: "monedas",
run: async (message, _args, _client: Amayo) => { run: async (message, _args, _client: Amayo) => {
const wallet = await getOrCreateWallet(message.author.id, message.guild!.id); const wallet = await getOrCreateWallet(
message.author.id,
message.guild!.id
);
const display = { const display = {
type: 17, type: 17,
accent_color: 0xFFD700, accent_color: 0xffd700,
components: [ components: [
{ {
type: 9, type: 9,
components: [{ components: [
type: 10, {
content: `**💰 Monedas de ${message.author.username}**\n\nSaldo: **${wallet.coins.toLocaleString()}** monedas` type: 10,
}] content: `**<:coin:1425667511013081169> Monedas de ${
} message.author.username
] }**\n\nSaldo: **${wallet.coins.toLocaleString()}** monedas`,
},
],
},
],
}; };
const channel = message.channel as TextBasedChannel & { send: Function }; const channel = message.channel as TextBasedChannel & { send: Function };
await (channel.send as any)({ await (channel.send as any)({
display, display,
flags: 32768, flags: 32768,
reply: { messageReference: message.id } reply: { messageReference: message.id },
}); });
} },
}; };

View File

@@ -28,6 +28,7 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ["fight", "arena"], aliases: ["fight", "arena"],
cooldown: 8, cooldown: 8,
category: "Minijuegos",
description: "Entra a la arena y pelea (usa espada si está disponible).", description: "Entra a la arena y pelea (usa espada si está disponible).",
usage: usage:
"pelear [nivel] [toolKey] [area:clave] (ej: pelear 1 weapon.sword.iron)", "pelear [nivel] [toolKey] [area:clave] (ej: pelear 1 weapon.sword.iron)",

View File

@@ -1,19 +1,24 @@
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 { prisma } from '../../../core/database/prisma'; import { prisma } from "../../../core/database/prisma";
import { getOrCreateWallet } from '../../../game/economy/service'; import { getOrCreateWallet } from "../../../game/economy/service";
import { getEquipment, getEffectiveStats } from '../../../game/combat/equipmentService'; import {
import { getPlayerStatsFormatted } from '../../../game/stats/service'; getEquipment,
import type { TextBasedChannel } from 'discord.js'; getEffectiveStats,
import { formatItemLabel } from './_helpers'; } from "../../../game/combat/equipmentService";
import { getPlayerStatsFormatted } from "../../../game/stats/service";
import type { TextBasedChannel } from "discord.js";
import { formatItemLabel } from "./_helpers";
export const command: CommandMessage = { export const command: CommandMessage = {
name: 'player', name: "player",
type: 'message', type: "message",
aliases: ['perfil', 'profile', 'yo', 'me'], aliases: ["perfil", "profile", "yo", "me"],
cooldown: 5, cooldown: 5,
description: 'Muestra toda tu información de jugador con vista visual mejorada', category: "Economía",
usage: 'player [@usuario]', description:
"Muestra toda tu información de jugador con vista visual mejorada",
usage: "player [@usuario]",
run: async (message, args, _client: Amayo) => { run: async (message, args, _client: Amayo) => {
const targetUser = message.mentions.users.first() || message.author; const targetUser = message.mentions.users.first() || message.author;
const userId = targetUser.id; const userId = targetUser.id;
@@ -29,7 +34,7 @@ export const command: CommandMessage = {
const progress = await prisma.playerProgress.findMany({ const progress = await prisma.playerProgress.findMany({
where: { userId, guildId }, where: { userId, guildId },
include: { area: true }, include: { area: true },
orderBy: { updatedAt: 'desc' }, orderBy: { updatedAt: "desc" },
take: 5, take: 5,
}); });
@@ -46,54 +51,67 @@ export const command: CommandMessage = {
// Cooldowns activos // Cooldowns activos
const activeCooldowns = await prisma.actionCooldown.findMany({ const activeCooldowns = await prisma.actionCooldown.findMany({
where: { userId, guildId, until: { gt: new Date() } }, where: { userId, guildId, until: { gt: new Date() } },
orderBy: { until: 'asc' }, orderBy: { until: "asc" },
take: 3, take: 3,
}); });
const weaponLine = weapon const weaponLine = weapon
? `⚔️ Arma: ${formatItemLabel(weapon, { fallbackIcon: '🗡️', bold: true })}` ? `⚔️ Arma: ${formatItemLabel(weapon, {
: '⚔️ Arma: *Ninguna*'; fallbackIcon: "🗡️",
bold: true,
})}`
: "⚔️ Arma: *Ninguna*";
const armorLine = armor const armorLine = armor
? `🛡️ Armadura: ${formatItemLabel(armor, { fallbackIcon: '🛡️', bold: true })}` ? `🛡️ Armadura: ${formatItemLabel(armor, {
: '🛡️ Armadura: *Ninguna*'; fallbackIcon: "🛡️",
bold: true,
})}`
: "🛡️ Armadura: *Ninguna*";
const capeLine = cape const capeLine = cape
? `🧥 Capa: ${formatItemLabel(cape, { fallbackIcon: '🧥', bold: true })}` ? `🧥 Capa: ${formatItemLabel(cape, { fallbackIcon: "🧥", bold: true })}`
: '🧥 Capa: *Ninguna*'; : "🧥 Capa: *Ninguna*";
// Crear DisplayComponent // Crear DisplayComponent
const display = { const display = {
type: 17, type: 17,
accent_color: 0x5865F2, accent_color: 0x5865f2,
components: [ components: [
{ {
type: 10, type: 10,
content: `👤 **${targetUser.username}**\n${targetUser.bot ? '🤖 Bot' : '👨 Usuario'}` content: `👤 **${targetUser.username}**\n${
targetUser.bot ? "🤖 Bot" : "👨 Usuario"
}`,
}, },
{ type: 14, divider: true }, { type: 14, divider: true },
{ {
type: 10, type: 10,
content: `**📊 ESTADÍSTICAS**\n` + content:
`❤️ HP: **${stats.hp}/${stats.maxHp}**\n` + `**<:stats:1425689271788113991> ESTADÍSTICAS**\n` +
`⚔️ ATK: **${stats.damage}**\n` + `<:healbonus:1425671499792121877> HP: **${stats.hp}/${stats.maxHp}**\n` +
`🛡️ DEF: **${stats.defense}**\n` + `<:damage:1425670476449189998> ATK: **${stats.damage}**\n` +
`💰 Monedas: **${wallet.coins.toLocaleString()}**` `<:defens:1425670433910427862> DEF: **${stats.defense}**\n` +
`<a:9470coin:1425694135607885906> Monedas: **${wallet.coins.toLocaleString()}**`,
}, },
{ type: 14, divider: true }, { type: 14, divider: true },
{ {
type: 10, type: 10,
content: `**⚔️ EQUIPO**\n` + content:
`${weaponLine}\n` + `**<:damage:1425670476449189998> EQUIPO**\n` +
`${armorLine}\n` + `${weaponLine}\n` +
`${capeLine}` `${armorLine}\n` +
`${capeLine}`,
}, },
{ type: 14, divider: true }, { type: 14, divider: true },
{ {
type: 10, type: 10,
content: `**🎒 INVENTARIO**\n` + content:
`📦 Items únicos: **${inventoryCount}**\n` + `**🎒 INVENTARIO**\n` +
`🔢 Total items: **${inventorySum._sum.quantity ?? 0}**` `<:emptybox:1425678700753588305> Items únicos: **${inventoryCount}**\n` +
} `<:table:1425673712312782879> Total items: **${
] inventorySum._sum.quantity ?? 0
}**`,
},
],
}; };
// Añadir stats de actividades si existen // Añadir stats de actividades si existen
@@ -101,13 +119,13 @@ export const command: CommandMessage = {
const activitiesText = Object.entries(playerStats.activities) const activitiesText = Object.entries(playerStats.activities)
.filter(([_, value]) => value > 0) .filter(([_, value]) => value > 0)
.map(([key, value]) => `${key}: **${value}**`) .map(([key, value]) => `${key}: **${value}**`)
.join('\n'); .join("\n");
if (activitiesText) { if (activitiesText) {
display.components.push({ type: 14, divider: true }); display.components.push({ type: 14, divider: true });
display.components.push({ display.components.push({
type: 10, type: 10,
content: `**🎮 ACTIVIDADES**\n${activitiesText}` content: `**🎮 ACTIVIDADES**\n${activitiesText}`,
}); });
} }
} }
@@ -117,25 +135,33 @@ export const command: CommandMessage = {
display.components.push({ type: 14, divider: true }); display.components.push({ type: 14, divider: true });
display.components.push({ display.components.push({
type: 10, type: 10,
content: `**🗺️ PROGRESO EN ÁREAS**\n` + content:
progress.map(p => `${p.area.name || p.area.key}: Nivel **${p.highestLevel}**`).join('\n') `**🗺️ PROGRESO EN ÁREAS**\n` +
progress
.map(
(p) =>
`${p.area.name || p.area.key}: Nivel **${p.highestLevel}**`
)
.join("\n"),
}); });
} }
// Añadir cooldowns activos // Añadir cooldowns activos
if (activeCooldowns.length > 0) { if (activeCooldowns.length > 0) {
const now = Date.now(); const now = Date.now();
const cooldownsText = activeCooldowns.map(cd => { const cooldownsText = activeCooldowns
const remaining = Math.ceil((cd.until.getTime() - now) / 1000); .map((cd) => {
const mins = Math.floor(remaining / 60); const remaining = Math.ceil((cd.until.getTime() - now) / 1000);
const secs = remaining % 60; const mins = Math.floor(remaining / 60);
return `${cd.key}: **${mins}m ${secs}s**`; const secs = remaining % 60;
}).join('\n'); return `${cd.key}: **${mins}m ${secs}s**`;
})
.join("\n");
display.components.push({ type: 14, divider: true }); display.components.push({ type: 14, divider: true });
display.components.push({ display.components.push({
type: 10, type: 10,
content: `** COOLDOWNS ACTIVOS**\n${cooldownsText}` content: `**<:swordcooldown:1425695375028912168> COOLDOWNS ACTIVOS**\n${cooldownsText}`,
}); });
} }
@@ -144,7 +170,7 @@ 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 },
}); });
} },
}; };

View File

@@ -13,6 +13,7 @@ export const command: CommandMessage = {
name: "racha", name: "racha",
type: "message", type: "message",
aliases: ["streak", "daily"], aliases: ["streak", "daily"],
category: "Economía",
cooldown: 10, cooldown: 10,
description: "Ver tu racha diaria y reclamar recompensa", description: "Ver tu racha diaria y reclamar recompensa",
usage: "racha", usage: "racha",
@@ -80,7 +81,7 @@ export const command: CommandMessage = {
}); });
} }
blocks.push(dividerBlock({ spacing: 1 })); blocks.push(dividerBlock({ spacing: 1, divider: false }));
blocks.push(textBlock(rewardsText)); blocks.push(textBlock(rewardsText));
} }
} else { } else {
@@ -97,7 +98,7 @@ export const command: CommandMessage = {
if (nextMilestone) { if (nextMilestone) {
const remaining = nextMilestone - streak.currentStreak; const remaining = nextMilestone - streak.currentStreak;
blocks.push(dividerBlock({ spacing: 1 })); blocks.push(dividerBlock({ spacing: 1, divider: false }));
blocks.push( blocks.push(
textBlock( textBlock(
`**🎯 PRÓXIMO HITO**\nFaltan **${remaining}** días para alcanzar el día **${nextMilestone}**` `**🎯 PRÓXIMO HITO**\nFaltan **${remaining}** días para alcanzar el día **${nextMilestone}**`

View File

@@ -8,6 +8,7 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ["estadisticas", "est"], aliases: ["estadisticas", "est"],
cooldown: 5, cooldown: 5,
category: "Economía",
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) => {

View File

@@ -78,6 +78,7 @@ export const command: CommandMessage = {
type: "message", type: "message",
aliases: ["shop", "store"], aliases: ["shop", "store"],
cooldown: 5, cooldown: 5,
category: "Economía",
description: description:
"Abre la tienda y navega por las ofertas disponibles con un panel interactivo.", "Abre la tienda y navega por las ofertas disponibles con un panel interactivo.",
usage: "tienda [categoria]", usage: "tienda [categoria]",
@@ -279,7 +280,7 @@ async function buildShopPanel(
container.components.push({ container.components.push({
type: 10, type: 10,
content: `${label}\n\n${ content: `${label}\n\n${
item.description || null item.description || ""
}${statsInfo}\n\nPrecio: ${price}${stockInfo}`, }${statsInfo}\n\nPrecio: ${price}${stockInfo}`,
}); });