feat(economy): migrate commands to DisplayComponents V2 and enhance user interaction
This commit is contained in:
@@ -59,7 +59,7 @@ export const command: CommandMessage = {
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
const editorMsg = await channel.send({
|
||||
...displayMessage,
|
||||
flags: MessageFlags.IsComponentsV2,
|
||||
flags: 32768, // MessageFlags.IsComponentsV2
|
||||
components: [
|
||||
{
|
||||
type: ComponentType.ActionRow,
|
||||
@@ -87,8 +87,7 @@ export const command: CommandMessage = {
|
||||
case 'ach_cancel':
|
||||
await i.deferUpdate();
|
||||
await editorMsg.edit({
|
||||
flags: 32768,
|
||||
components: [{
|
||||
display: {
|
||||
type: 17,
|
||||
accent_color: 0xFF0000,
|
||||
components: [{
|
||||
@@ -98,7 +97,9 @@ export const command: CommandMessage = {
|
||||
content: '**❌ Creación de logro cancelada.**'
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
},
|
||||
flags: 32768,
|
||||
components: []
|
||||
});
|
||||
collector.stop('cancel');
|
||||
return;
|
||||
@@ -138,8 +139,7 @@ export const command: CommandMessage = {
|
||||
|
||||
await i.reply({ content: '✅ Logro creado exitosamente!', flags: 64 });
|
||||
await editorMsg.edit({
|
||||
flags: 32768,
|
||||
components: [{
|
||||
display: {
|
||||
type: 17,
|
||||
accent_color: 0x00FF00,
|
||||
components: [{
|
||||
@@ -149,7 +149,9 @@ export const command: CommandMessage = {
|
||||
content: `**✅ Logro \`${state.key}\` creado exitosamente.**`
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
},
|
||||
flags: 32768,
|
||||
components: []
|
||||
});
|
||||
collector.stop('saved');
|
||||
return;
|
||||
@@ -166,8 +168,7 @@ export const command: CommandMessage = {
|
||||
if (r === 'time') {
|
||||
try {
|
||||
await editorMsg.edit({
|
||||
flags: 32768,
|
||||
components: [{
|
||||
display: {
|
||||
type: 17,
|
||||
accent_color: 0xFFA500,
|
||||
components: [{
|
||||
@@ -177,7 +178,9 @@ export const command: CommandMessage = {
|
||||
content: '**⏰ Editor expirado.**'
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
},
|
||||
flags: 32768,
|
||||
components: []
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ export const command: CommandMessage = {
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
const editorMsg = await channel.send({
|
||||
...displayMessage,
|
||||
flags: 32768,
|
||||
components: [
|
||||
{
|
||||
type: ComponentType.ActionRow,
|
||||
@@ -85,8 +86,7 @@ export const command: CommandMessage = {
|
||||
case 'quest_cancel':
|
||||
await i.deferUpdate();
|
||||
await editorMsg.edit({
|
||||
flags: 32768,
|
||||
components: [{
|
||||
display: {
|
||||
type: 17,
|
||||
accent_color: 0xFF0000,
|
||||
components: [{
|
||||
@@ -96,7 +96,9 @@ export const command: CommandMessage = {
|
||||
content: '**❌ Creación de misión cancelada.**'
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
},
|
||||
flags: 32768,
|
||||
components: []
|
||||
});
|
||||
collector.stop('cancel');
|
||||
return;
|
||||
@@ -137,9 +139,19 @@ export const command: CommandMessage = {
|
||||
|
||||
await i.reply({ content: '✅ Misión creada exitosamente.', flags: 64 });
|
||||
await editorMsg.edit({
|
||||
content: `✅ Misión \`${state.key}\` creada.`,
|
||||
components: [],
|
||||
display: undefined
|
||||
display: {
|
||||
type: 17,
|
||||
accent_color: 0x00FF00,
|
||||
components: [{
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**✅ Misión \`${state.key}\` creada exitosamente.**`
|
||||
}]
|
||||
}]
|
||||
},
|
||||
flags: 32768,
|
||||
components: []
|
||||
});
|
||||
collector.stop('saved');
|
||||
return;
|
||||
@@ -156,8 +168,7 @@ export const command: CommandMessage = {
|
||||
if (r === 'time') {
|
||||
try {
|
||||
await editorMsg.edit({
|
||||
flags: 32768,
|
||||
components: [{
|
||||
display: {
|
||||
type: 17,
|
||||
accent_color: 0xFFA500,
|
||||
components: [{
|
||||
@@ -167,7 +178,9 @@ export const command: CommandMessage = {
|
||||
content: '**⏰ Editor expirado.**'
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
},
|
||||
flags: 32768,
|
||||
components: []
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CommandMessage } from '../../../core/types/commands';
|
||||
import type Amayo from '../../../core/client';
|
||||
import { prisma } from '../../../core/database/prisma';
|
||||
import { EmbedBuilder } from 'discord.js';
|
||||
import type { TextBasedChannel } from 'discord.js';
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'cooldowns',
|
||||
@@ -30,12 +30,6 @@ export const command: CommandMessage = {
|
||||
return;
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(0xFF6B6B)
|
||||
.setTitle('⏰ Cooldowns Activos')
|
||||
.setDescription(`${message.author.username}, estos son tus cooldowns:`)
|
||||
.setThumbnail(message.author.displayAvatarURL({ size: 128 }));
|
||||
|
||||
// Emojis por tipo de acción
|
||||
const actionEmojis: Record<string, string> = {
|
||||
'mine': '⛏️',
|
||||
@@ -91,16 +85,38 @@ export const command: CommandMessage = {
|
||||
cooldownText += `${emoji} **${actionName}**: ${timeStr}\n`;
|
||||
}
|
||||
|
||||
embed.addFields({
|
||||
name: `📋 Cooldowns (${cooldowns.length})`,
|
||||
value: cooldownText,
|
||||
inline: false
|
||||
// Crear DisplayComponent
|
||||
const display = {
|
||||
type: 17,
|
||||
accent_color: 0xFF6B6B,
|
||||
components: [
|
||||
{
|
||||
type: 10,
|
||||
content: `# ⏰ Cooldowns Activos\n${message.author.username}, estos son tus cooldowns:`
|
||||
},
|
||||
{ type: 14, divider: true },
|
||||
{
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**📋 Cooldowns (${cooldowns.length})**\n${cooldownText}`
|
||||
}]
|
||||
},
|
||||
{ type: 14, spacing: 1 },
|
||||
{
|
||||
type: 10,
|
||||
content: `*Los cooldowns se actualizan en tiempo real*`
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Enviar con flags
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
await (channel.send as any)({
|
||||
display,
|
||||
flags: 32768, // MessageFlags.IS_COMPONENTS_V2
|
||||
reply: { messageReference: message.id }
|
||||
});
|
||||
|
||||
embed.setFooter({ text: 'Los cooldowns se actualizan en tiempo real' });
|
||||
embed.setTimestamp();
|
||||
|
||||
await message.reply({ embeds: [embed] });
|
||||
} catch (error) {
|
||||
console.error('Error en comando cooldowns:', error);
|
||||
await message.reply('❌ Error al obtener los cooldowns.');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { CommandMessage } from '../../../core/types/commands';
|
||||
import type Amayo from '../../../core/client';
|
||||
import { getOrCreateWallet } from '../../../game/economy/service';
|
||||
import type { TextBasedChannel } from 'discord.js';
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'monedas',
|
||||
@@ -11,7 +12,27 @@ export const command: CommandMessage = {
|
||||
usage: 'monedas',
|
||||
run: async (message, _args, _client: Amayo) => {
|
||||
const wallet = await getOrCreateWallet(message.author.id, message.guild!.id);
|
||||
await message.reply(`💰 Monedas: ${wallet.coins}`);
|
||||
|
||||
const display = {
|
||||
type: 17,
|
||||
accent_color: 0xFFD700,
|
||||
components: [
|
||||
{
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**💰 Monedas de ${message.author.username}**\n\nSaldo: **${wallet.coins.toLocaleString()}** monedas`
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
await (channel.send as any)({
|
||||
display,
|
||||
flags: 32768,
|
||||
reply: { messageReference: message.id }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -170,6 +170,7 @@ export const command: CommandMessage = {
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
await (channel.send as any)({
|
||||
display,
|
||||
flags: 32768, // MessageFlags.IS_COMPONENTS_V2
|
||||
reply: { messageReference: message.id }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CommandMessage } from '../../../core/types/commands';
|
||||
import type Amayo from '../../../core/client';
|
||||
import { getStreakInfo, updateStreak } from '../../../game/streaks/service';
|
||||
import { EmbedBuilder } from 'discord.js';
|
||||
import type { TextBasedChannel } from 'discord.js';
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'racha',
|
||||
@@ -18,50 +18,49 @@ export const command: CommandMessage = {
|
||||
// Actualizar racha
|
||||
const { streak, newDay, rewards, daysIncreased } = await updateStreak(userId, guildId);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(daysIncreased ? 0x00FF00 : 0xFFA500)
|
||||
.setTitle('🔥 Racha Diaria')
|
||||
.setDescription(`${message.author.username}, aquí está tu racha:`)
|
||||
.setThumbnail(message.author.displayAvatarURL({ size: 128 }));
|
||||
|
||||
// Racha actual
|
||||
embed.addFields(
|
||||
{
|
||||
name: '🔥 Racha Actual',
|
||||
value: `**${streak.currentStreak}** días consecutivos`,
|
||||
inline: true
|
||||
// Construir componentes
|
||||
const components: any[] = [
|
||||
{
|
||||
type: 10,
|
||||
content: `# 🔥 Racha Diaria de ${message.author.username}`
|
||||
},
|
||||
{
|
||||
name: '⭐ Mejor Racha',
|
||||
value: `**${streak.longestStreak}** días`,
|
||||
inline: true
|
||||
{ type: 14, divider: true },
|
||||
{
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**📊 ESTADÍSTICAS**\n` +
|
||||
`🔥 Racha Actual: **${streak.currentStreak}** días\n` +
|
||||
`⭐ Mejor Racha: **${streak.longestStreak}** días\n` +
|
||||
`📅 Días Activos: **${streak.totalDaysActive}** días`
|
||||
}]
|
||||
},
|
||||
{
|
||||
name: '📅 Días Activos',
|
||||
value: `**${streak.totalDaysActive}** días totales`,
|
||||
inline: true
|
||||
}
|
||||
);
|
||||
{ type: 14, spacing: 1 }
|
||||
];
|
||||
|
||||
// Mensaje de estado
|
||||
if (newDay) {
|
||||
if (daysIncreased) {
|
||||
embed.addFields({
|
||||
name: '✅ ¡Racha Incrementada!',
|
||||
value: `Has mantenido tu racha por **${streak.currentStreak}** días seguidos.`,
|
||||
inline: false
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**✅ ¡RACHA INCREMENTADA!**\nHas mantenido tu racha por **${streak.currentStreak}** días seguidos.`
|
||||
}]
|
||||
});
|
||||
} else {
|
||||
embed.addFields({
|
||||
name: '⚠️ Racha Reiniciada',
|
||||
value: 'Pasó más de un día sin actividad. Tu racha se ha reiniciado.',
|
||||
inline: false
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**⚠️ RACHA REINICIADA**\nPasó más de un día sin actividad. Tu racha se ha reiniciado.`
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
// Mostrar recompensas
|
||||
if (rewards) {
|
||||
let rewardsText = '';
|
||||
let rewardsText = '**🎁 RECOMPENSA DEL DÍA**\n';
|
||||
if (rewards.coins) rewardsText += `💰 **${rewards.coins.toLocaleString()}** monedas\n`;
|
||||
if (rewards.items) {
|
||||
rewards.items.forEach(item => {
|
||||
@@ -69,19 +68,22 @@ export const command: CommandMessage = {
|
||||
});
|
||||
}
|
||||
|
||||
if (rewardsText) {
|
||||
embed.addFields({
|
||||
name: '🎁 Recompensa del Día',
|
||||
value: rewardsText,
|
||||
inline: false
|
||||
});
|
||||
}
|
||||
components.push({ type: 14, spacing: 1 });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: rewardsText
|
||||
}]
|
||||
});
|
||||
}
|
||||
} else {
|
||||
embed.addFields({
|
||||
name: 'ℹ️ Ya Reclamaste Hoy',
|
||||
value: 'Ya has reclamado tu recompensa diaria. Vuelve mañana para continuar tu racha.',
|
||||
inline: false
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**ℹ️ YA RECLAMASTE HOY**\nYa has reclamado tu recompensa diaria. Vuelve mañana para continuar tu racha.`
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,17 +93,28 @@ export const command: CommandMessage = {
|
||||
|
||||
if (nextMilestone) {
|
||||
const remaining = nextMilestone - streak.currentStreak;
|
||||
embed.addFields({
|
||||
name: '🎯 Próximo Hito',
|
||||
value: `Faltan **${remaining}** días para alcanzar el día **${nextMilestone}**`,
|
||||
inline: false
|
||||
components.push({ type: 14, spacing: 1 });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**🎯 PRÓXIMO HITO**\nFaltan **${remaining}** días para alcanzar el día **${nextMilestone}**`
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
embed.setFooter({ text: 'Juega todos los días para mantener tu racha activa' });
|
||||
embed.setTimestamp();
|
||||
const display = {
|
||||
type: 17,
|
||||
accent_color: daysIncreased ? 0x00FF00 : 0xFFA500,
|
||||
components
|
||||
};
|
||||
|
||||
await message.reply({ embeds: [embed] });
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
await (channel.send as any)({
|
||||
display,
|
||||
flags: 32768,
|
||||
reply: { messageReference: message.id }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error en comando racha:', error);
|
||||
await message.reply('❌ Error al obtener tu racha diaria.');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CommandMessage } from '../../../core/types/commands';
|
||||
import type Amayo from '../../../core/client';
|
||||
import { getPlayerStatsFormatted } from '../../../game/stats/service';
|
||||
import { EmbedBuilder } from 'discord.js';
|
||||
import type { TextBasedChannel } from 'discord.js';
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'stats',
|
||||
@@ -19,19 +19,29 @@ export const command: CommandMessage = {
|
||||
// Obtener estadísticas formateadas
|
||||
const stats = await getPlayerStatsFormatted(userId, guildId);
|
||||
|
||||
// Crear embed
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(0x5865F2)
|
||||
.setTitle(`📊 Estadísticas de ${targetUser.username}`)
|
||||
.setThumbnail(targetUser.displayAvatarURL({ size: 128 }))
|
||||
.setTimestamp();
|
||||
// Construir componentes de DisplayComponent
|
||||
const components: any[] = [
|
||||
// Header
|
||||
{
|
||||
type: 10,
|
||||
content: `# 📊 Estadísticas de ${targetUser.username}`
|
||||
},
|
||||
{ type: 14, divider: true }
|
||||
];
|
||||
|
||||
// Actividades
|
||||
if (stats.activities) {
|
||||
const activitiesText = Object.entries(stats.activities)
|
||||
.map(([key, value]) => `${key}: **${value.toLocaleString()}**`)
|
||||
.join('\n');
|
||||
embed.addFields({ name: '🎮 Actividades', value: activitiesText || 'Sin datos', inline: true });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**🎮 ACTIVIDADES**\n${activitiesText || 'Sin datos'}`
|
||||
}]
|
||||
});
|
||||
components.push({ type: 14, spacing: 1 });
|
||||
}
|
||||
|
||||
// Combate
|
||||
@@ -39,7 +49,14 @@ export const command: CommandMessage = {
|
||||
const combatText = Object.entries(stats.combat)
|
||||
.map(([key, value]) => `${key}: **${value.toLocaleString()}**`)
|
||||
.join('\n');
|
||||
embed.addFields({ name: '⚔️ Combate', value: combatText || 'Sin datos', inline: true });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**⚔️ COMBATE**\n${combatText || 'Sin datos'}`
|
||||
}]
|
||||
});
|
||||
components.push({ type: 14, spacing: 1 });
|
||||
}
|
||||
|
||||
// Economía
|
||||
@@ -47,7 +64,14 @@ export const command: CommandMessage = {
|
||||
const economyText = Object.entries(stats.economy)
|
||||
.map(([key, value]) => `${key}: **${value.toLocaleString()}**`)
|
||||
.join('\n');
|
||||
embed.addFields({ name: '💰 Economía', value: economyText || 'Sin datos', inline: false });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**💰 ECONOMÍA**\n${economyText || 'Sin datos'}`
|
||||
}]
|
||||
});
|
||||
components.push({ type: 14, spacing: 1 });
|
||||
}
|
||||
|
||||
// Items
|
||||
@@ -55,7 +79,14 @@ export const command: CommandMessage = {
|
||||
const itemsText = Object.entries(stats.items)
|
||||
.map(([key, value]) => `${key}: **${value.toLocaleString()}**`)
|
||||
.join('\n');
|
||||
embed.addFields({ name: '📦 Items', value: itemsText || 'Sin datos', inline: true });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**📦 ITEMS**\n${itemsText || 'Sin datos'}`
|
||||
}]
|
||||
});
|
||||
components.push({ type: 14, spacing: 1 });
|
||||
}
|
||||
|
||||
// Récords
|
||||
@@ -63,12 +94,29 @@ export const command: CommandMessage = {
|
||||
const recordsText = Object.entries(stats.records)
|
||||
.map(([key, value]) => `${key}: **${value.toLocaleString()}**`)
|
||||
.join('\n');
|
||||
embed.addFields({ name: '🏆 Récords', value: recordsText || 'Sin datos', inline: true });
|
||||
components.push({
|
||||
type: 9,
|
||||
components: [{
|
||||
type: 10,
|
||||
content: `**🏆 RÉCORDS**\n${recordsText || 'Sin datos'}`
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
embed.setFooter({ text: 'Usa !ranking-stats para ver el ranking global' });
|
||||
// Crear DisplayComponent
|
||||
const display = {
|
||||
type: 17,
|
||||
accent_color: 0x5865F2,
|
||||
components
|
||||
};
|
||||
|
||||
await message.reply({ embeds: [embed] });
|
||||
// Enviar con flags
|
||||
const channel = message.channel as TextBasedChannel & { send: Function };
|
||||
await (channel.send as any)({
|
||||
display,
|
||||
flags: 32768, // MessageFlags.IS_COMPONENTS_V2
|
||||
reply: { messageReference: message.id }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error en comando stats:', error);
|
||||
await message.reply('❌ Error al obtener las estadísticas.');
|
||||
|
||||
Reference in New Issue
Block a user