2025-10-05 05:19:16 -05:00
|
|
|
|
import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction, TextBasedChannel } from 'discord.js';
|
2025-10-05 01:20:52 -05:00
|
|
|
|
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
|
|
|
|
|
|
import type { CommandMessage } from '../../../core/types/commands';
|
|
|
|
|
|
import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
|
|
|
|
|
|
import logger from '../../../core/lib/logger';
|
|
|
|
|
|
import type Amayo from '../../../core/client';
|
|
|
|
|
|
|
|
|
|
|
|
interface ItemEditorState {
|
|
|
|
|
|
key: string;
|
|
|
|
|
|
name?: string;
|
|
|
|
|
|
description?: string;
|
|
|
|
|
|
category?: string;
|
|
|
|
|
|
icon?: string;
|
|
|
|
|
|
stackable?: boolean;
|
|
|
|
|
|
maxPerInventory?: number | null;
|
|
|
|
|
|
tags: string[];
|
|
|
|
|
|
props?: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const command: CommandMessage = {
|
|
|
|
|
|
name: 'item-editar',
|
|
|
|
|
|
type: 'message',
|
2025-10-05 06:42:10 -05:00
|
|
|
|
aliases: ['editar-item','itemedit'],
|
2025-10-05 01:20:52 -05:00
|
|
|
|
cooldown: 10,
|
2025-10-05 06:42:10 -05:00
|
|
|
|
description: 'Edita un EconomyItem existente del servidor con un pequeño editor interactivo.',
|
2025-10-05 01:20:52 -05:00
|
|
|
|
category: 'Economía',
|
|
|
|
|
|
usage: 'item-editar <key-única>',
|
|
|
|
|
|
run: async (message: Message, args: string[], client: Amayo) => {
|
2025-10-05 06:42:10 -05:00
|
|
|
|
const channel = message.channel as TextBasedChannel & { send: Function };
|
2025-10-05 01:20:52 -05:00
|
|
|
|
const allowed = await hasManageGuildOrStaff(message.member, message.guild!.id, client.prisma);
|
2025-10-05 06:09:53 -05:00
|
|
|
|
if (!allowed) {
|
2025-10-05 06:42:10 -05:00
|
|
|
|
await (channel.send as any)({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0xFF0000,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: '❌ **Error de Permisos**\n└ No tienes permisos de ManageGuild ni rol de staff.'
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}],
|
|
|
|
|
|
message_reference: {
|
|
|
|
|
|
message_id: message.id,
|
|
|
|
|
|
channel_id: message.channel.id,
|
|
|
|
|
|
guild_id: message.guild!.id,
|
|
|
|
|
|
fail_if_not_exists: false
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-05 06:09:53 -05:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-05 01:20:52 -05:00
|
|
|
|
const key = args[0]?.trim();
|
2025-10-05 06:09:53 -05:00
|
|
|
|
if (!key) {
|
2025-10-05 06:42:10 -05:00
|
|
|
|
await (channel.send as any)({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0xFFA500,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: '⚠️ **Uso Incorrecto**\n└ Uso: `!item-editar <key-única>`'
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}],
|
|
|
|
|
|
message_reference: {
|
|
|
|
|
|
message_id: message.id,
|
|
|
|
|
|
channel_id: message.channel.id,
|
|
|
|
|
|
guild_id: message.guild!.id,
|
|
|
|
|
|
fail_if_not_exists: false
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-05 06:09:53 -05:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-05 01:20:52 -05:00
|
|
|
|
const guildId = message.guild!.id;
|
|
|
|
|
|
|
2025-10-05 06:42:10 -05:00
|
|
|
|
const existing = await client.prisma.economyItem.findFirst({ where: { key, guildId } });
|
|
|
|
|
|
if (!existing) {
|
|
|
|
|
|
await (channel.send as any)({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0xFF0000,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: '❌ **Item No Encontrado**\n└ No existe un item con esa key en este servidor.'
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}],
|
|
|
|
|
|
message_reference: {
|
|
|
|
|
|
message_id: message.id,
|
|
|
|
|
|
channel_id: message.channel.id,
|
|
|
|
|
|
guild_id: message.guild!.id,
|
|
|
|
|
|
fail_if_not_exists: false
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-05 06:09:53 -05:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-05 01:20:52 -05:00
|
|
|
|
|
|
|
|
|
|
const state: ItemEditorState = {
|
|
|
|
|
|
key,
|
2025-10-05 06:42:10 -05:00
|
|
|
|
name: existing.name,
|
|
|
|
|
|
description: existing.description || undefined,
|
|
|
|
|
|
category: existing.category || undefined,
|
|
|
|
|
|
icon: existing.icon || undefined,
|
|
|
|
|
|
stackable: existing.stackable ?? true,
|
|
|
|
|
|
maxPerInventory: existing.maxPerInventory || null,
|
|
|
|
|
|
tags: existing.tags || [],
|
|
|
|
|
|
props: existing.props || {},
|
2025-10-05 01:20:52 -05:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-05 06:09:53 -05:00
|
|
|
|
// Función para crear display
|
|
|
|
|
|
const createDisplay = () => ({
|
|
|
|
|
|
display: {
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0x00D9FF,
|
|
|
|
|
|
components: [
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: `**🛠️ Editando Item: \`${key}\`**`
|
|
|
|
|
|
}]
|
|
|
|
|
|
},
|
|
|
|
|
|
{ type: 14, divider: true },
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: `**Nombre:** ${state.name || '*Sin definir*'}\n` +
|
|
|
|
|
|
`**Descripción:** ${state.description || '*Sin definir*'}\n` +
|
|
|
|
|
|
`**Categoría:** ${state.category || '*Sin definir*'}\n` +
|
|
|
|
|
|
`**Icon URL:** ${state.icon || '*Sin definir*'}\n` +
|
|
|
|
|
|
`**Stackable:** ${state.stackable ? 'Sí' : 'No'}\n` +
|
|
|
|
|
|
`**Máx. Inventario:** ${state.maxPerInventory || 'Ilimitado'}`
|
|
|
|
|
|
}]
|
|
|
|
|
|
},
|
|
|
|
|
|
{ type: 14, divider: true },
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: `**Tags:** ${state.tags.length > 0 ? state.tags.join(', ') : '*Ninguno*'}`
|
|
|
|
|
|
}]
|
|
|
|
|
|
},
|
|
|
|
|
|
{ type: 14, divider: true },
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: `**Props (JSON):**\n\`\`\`json\n${JSON.stringify(state.props, null, 2)}\n\`\`\``
|
|
|
|
|
|
}]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-10-05 06:42:10 -05:00
|
|
|
|
const editorMsg = await (channel.send as any)({
|
|
|
|
|
|
flags: 32768,
|
2025-10-05 06:09:53 -05:00
|
|
|
|
components: [
|
2025-10-05 06:42:10 -05:00
|
|
|
|
createDisplay().display,
|
2025-10-05 06:09:53 -05:00
|
|
|
|
{ type: 1, components: [
|
|
|
|
|
|
{ type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'it_base' },
|
|
|
|
|
|
{ type: 2, style: ButtonStyle.Secondary, label: 'Tags', custom_id: 'it_tags' },
|
|
|
|
|
|
{ type: 2, style: ButtonStyle.Secondary, label: 'Props (JSON)', custom_id: 'it_props' },
|
|
|
|
|
|
{ type: 2, style: ButtonStyle.Success, label: 'Guardar', custom_id: 'it_save' },
|
|
|
|
|
|
{ type: 2, style: ButtonStyle.Danger, label: 'Cancelar', custom_id: 'it_cancel' },
|
|
|
|
|
|
]},
|
|
|
|
|
|
],
|
2025-10-05 01:20:52 -05:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const collector = editorMsg.createMessageComponentCollector({ time: 30 * 60_000, filter: (i) => i.user.id === message.author.id });
|
|
|
|
|
|
|
|
|
|
|
|
collector.on('collect', async (i: MessageComponentInteraction) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (!i.isButton()) return;
|
2025-10-05 06:09:53 -05:00
|
|
|
|
if (i.customId === 'it_cancel') {
|
|
|
|
|
|
await i.deferUpdate();
|
2025-10-05 06:28:42 -05:00
|
|
|
|
await editorMsg.edit({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0xFF0000,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: '**❌ Editor cancelado.**'
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
2025-10-05 06:09:53 -05:00
|
|
|
|
collector.stop('cancel');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (i.customId === 'it_base') {
|
|
|
|
|
|
await showBaseModal(i as ButtonInteraction, state, editorMsg, createDisplay);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (i.customId === 'it_tags') {
|
|
|
|
|
|
await showTagsModal(i as ButtonInteraction, state, editorMsg, createDisplay);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (i.customId === 'it_props') {
|
|
|
|
|
|
await showPropsModal(i as ButtonInteraction, state, editorMsg, createDisplay);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-05 01:20:52 -05:00
|
|
|
|
if (i.customId === 'it_save') {
|
2025-10-05 06:09:53 -05:00
|
|
|
|
// Validar
|
|
|
|
|
|
if (!state.name) {
|
|
|
|
|
|
await i.reply({ content: '❌ Falta el nombre del item (configura en Base).', flags: MessageFlags.Ephemeral });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-05 06:42:10 -05:00
|
|
|
|
// Actualizar
|
|
|
|
|
|
await client.prisma.economyItem.update({
|
|
|
|
|
|
where: { id: existing.id },
|
2025-10-05 01:20:52 -05:00
|
|
|
|
data: {
|
|
|
|
|
|
name: state.name!,
|
|
|
|
|
|
description: state.description,
|
|
|
|
|
|
category: state.category,
|
|
|
|
|
|
icon: state.icon,
|
|
|
|
|
|
stackable: state.stackable ?? true,
|
|
|
|
|
|
maxPerInventory: state.maxPerInventory ?? undefined,
|
|
|
|
|
|
tags: state.tags,
|
|
|
|
|
|
props: state.props ?? {},
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
2025-10-05 06:42:10 -05:00
|
|
|
|
await i.reply({ content: '✅ Item actualizado!', flags: MessageFlags.Ephemeral });
|
|
|
|
|
|
await editorMsg.edit({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0x00FF00,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: `✅ **Item Actualizado**\n└ Item \`${state.key}\` actualizado exitosamente.`
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
2025-10-05 01:20:52 -05:00
|
|
|
|
collector.stop('saved');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
logger.error({ err }, 'item-editar interaction error');
|
|
|
|
|
|
if (!i.deferred && !i.replied) await i.reply({ content: '❌ Error procesando la acción.', flags: MessageFlags.Ephemeral });
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-10-05 06:09:53 -05:00
|
|
|
|
collector.on('end', async (_c, r) => {
|
|
|
|
|
|
if (r === 'time') {
|
2025-10-05 06:28:42 -05:00
|
|
|
|
try { await editorMsg.edit({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 17,
|
|
|
|
|
|
accent_color: 0xFFA500,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 9,
|
|
|
|
|
|
components: [{
|
|
|
|
|
|
type: 10,
|
|
|
|
|
|
content: '**⏰ Editor expirado.**'
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}]
|
|
|
|
|
|
}); } catch {}
|
2025-10-05 06:09:53 -05:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-05 01:20:52 -05:00
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-05 06:09:53 -05:00
|
|
|
|
async function showBaseModal(i: ButtonInteraction, state: ItemEditorState, editorMsg: any, createDisplay: Function) {
|
2025-10-05 01:20:52 -05:00
|
|
|
|
const modal = {
|
2025-10-05 06:09:53 -05:00
|
|
|
|
title: 'Configuración base del Item',
|
|
|
|
|
|
customId: 'it_base_modal',
|
|
|
|
|
|
components: [
|
2025-10-05 01:20:52 -05:00
|
|
|
|
{ type: ComponentType.Label, label: 'Nombre', component: { type: ComponentType.TextInput, customId: 'name', style: TextInputStyle.Short, required: true, value: state.name ?? '' } },
|
|
|
|
|
|
{ type: ComponentType.Label, label: 'Descripción', component: { type: ComponentType.TextInput, customId: 'desc', style: TextInputStyle.Paragraph, required: false, value: state.description ?? '' } },
|
|
|
|
|
|
{ type: ComponentType.Label, label: 'Categoría', component: { type: ComponentType.TextInput, customId: 'cat', style: TextInputStyle.Short, required: false, value: state.category ?? '' } },
|
|
|
|
|
|
{ type: ComponentType.Label, label: 'Icon URL', component: { type: ComponentType.TextInput, customId: 'icon', style: TextInputStyle.Short, required: false, value: state.icon ?? '' } },
|
2025-10-05 01:35:55 -05:00
|
|
|
|
{ type: ComponentType.Label, label: 'Stackable y Máx inventario', component: { type: ComponentType.TextInput, customId: 'stack_max', style: TextInputStyle.Short, required: false, placeholder: 'true,10', value: state.stackable !== undefined ? `${state.stackable},${state.maxPerInventory ?? ''}` : '' } },
|
2025-10-05 06:09:53 -05:00
|
|
|
|
],
|
|
|
|
|
|
} as const;
|
|
|
|
|
|
|
2025-10-05 01:20:52 -05:00
|
|
|
|
await i.showModal(modal);
|
|
|
|
|
|
try {
|
|
|
|
|
|
const sub = await i.awaitModalSubmit({ time: 300_000 });
|
2025-10-05 06:09:53 -05:00
|
|
|
|
const name = sub.components.getTextInputValue('name').trim();
|
|
|
|
|
|
const desc = sub.components.getTextInputValue('desc').trim();
|
|
|
|
|
|
const cat = sub.components.getTextInputValue('cat').trim();
|
|
|
|
|
|
const icon = sub.components.getTextInputValue('icon').trim();
|
2025-10-05 01:20:52 -05:00
|
|
|
|
const stackMax = sub.components.getTextInputValue('stack_max').trim();
|
2025-10-05 06:09:53 -05:00
|
|
|
|
|
|
|
|
|
|
state.name = name;
|
|
|
|
|
|
state.description = desc || undefined;
|
|
|
|
|
|
state.category = cat || undefined;
|
|
|
|
|
|
state.icon = icon || undefined;
|
|
|
|
|
|
|
|
|
|
|
|
if (stackMax) {
|
|
|
|
|
|
const [s, m] = stackMax.split(',');
|
|
|
|
|
|
state.stackable = String(s).toLowerCase() !== 'false';
|
|
|
|
|
|
const mv = m?.trim();
|
|
|
|
|
|
state.maxPerInventory = mv ? Math.max(0, parseInt(mv, 10) || 0) : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await sub.deferUpdate();
|
2025-10-05 06:42:10 -05:00
|
|
|
|
await editorMsg.edit({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [createDisplay().display]
|
|
|
|
|
|
});
|
2025-10-05 01:20:52 -05:00
|
|
|
|
} catch {}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-05 06:09:53 -05:00
|
|
|
|
async function showTagsModal(i: ButtonInteraction, state: ItemEditorState, editorMsg: any, createDisplay: Function) {
|
|
|
|
|
|
const modal = {
|
|
|
|
|
|
title: 'Tags del Item (separados por coma)',
|
|
|
|
|
|
customId: 'it_tags_modal',
|
|
|
|
|
|
components: [
|
|
|
|
|
|
{ type: ComponentType.Label, label: 'Tags', component: { type: ComponentType.TextInput, customId: 'tags', style: TextInputStyle.Paragraph, required: false, value: state.tags.join(', ') } },
|
|
|
|
|
|
],
|
|
|
|
|
|
} as const;
|
2025-10-05 01:20:52 -05:00
|
|
|
|
await i.showModal(modal);
|
2025-10-05 06:09:53 -05:00
|
|
|
|
try {
|
|
|
|
|
|
const sub = await i.awaitModalSubmit({ time: 300_000 });
|
|
|
|
|
|
const tags = sub.components.getTextInputValue('tags');
|
|
|
|
|
|
state.tags = tags ? tags.split(',').map((t) => t.trim()).filter(Boolean) : [];
|
|
|
|
|
|
await sub.deferUpdate();
|
2025-10-05 06:42:10 -05:00
|
|
|
|
await editorMsg.edit({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [createDisplay().display]
|
|
|
|
|
|
});
|
2025-10-05 06:09:53 -05:00
|
|
|
|
} catch {}
|
2025-10-05 01:20:52 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-05 06:09:53 -05:00
|
|
|
|
async function showPropsModal(i: ButtonInteraction, state: ItemEditorState, editorMsg: any, createDisplay: Function) {
|
|
|
|
|
|
const template = state.props && Object.keys(state.props).length ? JSON.stringify(state.props) : JSON.stringify({
|
|
|
|
|
|
tool: undefined,
|
|
|
|
|
|
breakable: undefined,
|
|
|
|
|
|
chest: undefined,
|
|
|
|
|
|
eventCurrency: undefined,
|
|
|
|
|
|
passiveEffects: [],
|
|
|
|
|
|
mutationPolicy: undefined,
|
|
|
|
|
|
craftingOnly: false,
|
|
|
|
|
|
food: undefined,
|
|
|
|
|
|
damage: undefined,
|
|
|
|
|
|
defense: undefined,
|
|
|
|
|
|
maxHpBonus: undefined,
|
|
|
|
|
|
});
|
|
|
|
|
|
const modal = {
|
|
|
|
|
|
title: 'Props (JSON) del Item',
|
|
|
|
|
|
customId: 'it_props_modal',
|
|
|
|
|
|
components: [
|
|
|
|
|
|
{ type: ComponentType.Label, label: 'JSON', component: { type: ComponentType.TextInput, customId: 'props', style: TextInputStyle.Paragraph, required: false, value: template.slice(0,4000) } },
|
|
|
|
|
|
],
|
|
|
|
|
|
} as const;
|
2025-10-05 01:20:52 -05:00
|
|
|
|
await i.showModal(modal);
|
|
|
|
|
|
try {
|
|
|
|
|
|
const sub = await i.awaitModalSubmit({ time: 300_000 });
|
|
|
|
|
|
const raw = sub.components.getTextInputValue('props');
|
2025-10-05 06:09:53 -05:00
|
|
|
|
if (raw) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const parsed = JSON.parse(raw);
|
|
|
|
|
|
state.props = parsed;
|
2025-10-05 06:42:10 -05:00
|
|
|
|
await sub.deferUpdate();
|
|
|
|
|
|
await editorMsg.edit({
|
|
|
|
|
|
flags: 32768,
|
|
|
|
|
|
components: [createDisplay().display]
|
|
|
|
|
|
});
|
2025-10-05 06:09:53 -05:00
|
|
|
|
} catch (e) {
|
|
|
|
|
|
await sub.reply({ content: '❌ JSON inválido.', flags: MessageFlags.Ephemeral });
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
state.props = {};
|
|
|
|
|
|
await sub.reply({ content: 'ℹ️ Props limpiados.', flags: MessageFlags.Ephemeral });
|
|
|
|
|
|
}
|
2025-10-05 01:20:52 -05:00
|
|
|
|
} catch {}
|
|
|
|
|
|
}
|