refactor(economy): enhance type definitions and improve channel message handling

This commit is contained in:
2025-10-05 05:19:16 -05:00
parent 68f629d637
commit c868e3bf80
10 changed files with 32 additions and 22 deletions

View File

@@ -2,7 +2,7 @@ import type { CommandMessage } from '../../../core/types/commands';
import type Amayo from '../../../core/client'; import type Amayo from '../../../core/client';
import { hasManageGuildOrStaff } from '../../../core/lib/permissions'; import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
import { prisma } from '../../../core/database/prisma'; import { prisma } from '../../../core/database/prisma';
import { Message, MessageComponentInteraction, MessageFlags, ButtonInteraction } from 'discord.js'; import { Message, MessageComponentInteraction, MessageFlags, ButtonInteraction, TextBasedChannel } from 'discord.js';
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
interface AreaState { interface AreaState {
@@ -33,7 +33,8 @@ export const command: CommandMessage = {
const state: AreaState = { key, config: {}, metadata: {} }; const state: AreaState = { key, config: {}, metadata: {} };
const editorMsg = await message.channel.send({ const channel = message.channel as TextBasedChannel & { send: Function };
const editorMsg = await channel.send({
content: `🗺️ Editor de Área: \`${key}\``, content: `🗺️ Editor de Área: \`${key}\``,
components: [ { type: 1, components: [ components: [ { type: 1, components: [
{ type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'ga_base' }, { type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'ga_base' },

View File

@@ -2,7 +2,7 @@ import type { CommandMessage } from '../../../core/types/commands';
import type Amayo from '../../../core/client'; import type Amayo from '../../../core/client';
import { hasManageGuildOrStaff } from '../../../core/lib/permissions'; import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
import { prisma } from '../../../core/database/prisma'; import { prisma } from '../../../core/database/prisma';
import { Message, MessageComponentInteraction, MessageFlags, ButtonInteraction } from 'discord.js'; import { Message, MessageComponentInteraction, MessageFlags, ButtonInteraction, TextBasedChannel } from 'discord.js';
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
interface AreaState { interface AreaState {
@@ -33,7 +33,8 @@ export const command: CommandMessage = {
const state: AreaState = { key, name: area.name, type: area.type, config: area.config ?? {}, metadata: area.metadata ?? {} }; const state: AreaState = { key, name: area.name, type: area.type, config: area.config ?? {}, metadata: area.metadata ?? {} };
const editorMsg = await message.channel.send({ const channel = message.channel as TextBasedChannel & { send: Function };
const editorMsg = await channel.send({
content: `🗺️ Editor de Área (editar): \`${key}\``, content: `🗺️ Editor de Área (editar): \`${key}\``,
components: [ { type: 1, components: [ components: [ { type: 1, components: [
{ type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'ga_base' }, { type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'ga_base' },

View File

@@ -1,4 +1,4 @@
import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction } from 'discord.js'; import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction, TextBasedChannel } from 'discord.js';
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
import type { CommandMessage } from '../../../core/types/commands'; import type { CommandMessage } from '../../../core/types/commands';
import { hasManageGuildOrStaff } from '../../../core/lib/permissions'; import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
@@ -54,7 +54,8 @@ export const command: CommandMessage = {
props: {}, props: {},
}; };
const editorMsg = await message.channel.send({ const channel = message.channel as TextBasedChannel & { send: Function };
const editorMsg = await channel.send({
content: `🛠️ Editor de Item: \`${key}\`\nUsa los botones para configurar los campos y luego guarda.`, content: `🛠️ Editor de Item: \`${key}\`\nUsa los botones para configurar los campos y luego guarda.`,
components: [ components: [
{ type: 1, components: [ { type: 1, components: [

View File

@@ -1,4 +1,4 @@
import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction } from 'discord.js'; import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction, TextBasedChannel } from 'discord.js';
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
import type { CommandMessage } from '../../../core/types/commands'; import type { CommandMessage } from '../../../core/types/commands';
import { hasManageGuildOrStaff } from '../../../core/lib/permissions'; import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
@@ -47,7 +47,8 @@ export const command: CommandMessage = {
props: item.props ?? {}, props: item.props ?? {},
}; };
const editorMsg = await message.channel.send({ const channel = message.channel as TextBasedChannel & { send: Function };
const editorMsg = await channel.send({
content: `🛠️ Editor de Item (editar): \`${key}\``, content: `🛠️ Editor de Item (editar): \`${key}\``,
components: [ { type: 1, components: [ components: [ { type: 1, components: [
{ type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'it_base' }, { type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'it_base' },

View File

@@ -1,4 +1,4 @@
import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction } from 'discord.js'; import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction, TextBasedChannel } from 'discord.js';
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
import type { CommandMessage } from '../../../core/types/commands'; import type { CommandMessage } from '../../../core/types/commands';
import { hasManageGuildOrStaff } from '../../../core/lib/permissions'; import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
@@ -33,7 +33,8 @@ export const command: CommandMessage = {
const state: MobEditorState = { key, stats: { attack: 5 }, drops: {} }; const state: MobEditorState = { key, stats: { attack: 5 }, drops: {} };
const editorMsg = await message.channel.send({ const channel = message.channel as TextBasedChannel & { send: Function };
const editorMsg = await channel.send({
content: `👾 Editor de Mob: \`${key}\``, content: `👾 Editor de Mob: \`${key}\``,
components: [ { type: 1, components: [ components: [ { type: 1, components: [
{ type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'mb_base' }, { type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'mb_base' },

View File

@@ -1,4 +1,4 @@
import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction } from 'discord.js'; import { Message, MessageFlags, MessageComponentInteraction, ButtonInteraction, TextBasedChannel } from 'discord.js';
import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, TextInputStyle, ButtonStyle } from 'discord-api-types/v10';
import type { CommandMessage } from '../../../core/types/commands'; import type { CommandMessage } from '../../../core/types/commands';
import { hasManageGuildOrStaff } from '../../../core/lib/permissions'; import { hasManageGuildOrStaff } from '../../../core/lib/permissions';
@@ -39,7 +39,8 @@ export const command: CommandMessage = {
drops: mob.drops ?? {}, drops: mob.drops ?? {},
}; };
const editorMsg = await message.channel.send({ const channel = message.channel as TextBasedChannel & { send: Function };
const editorMsg = await channel.send({
content: `👾 Editor de Mob (editar): \`${key}\``, content: `👾 Editor de Mob (editar): \`${key}\``,
components: [ { type: 1, components: [ components: [ { type: 1, components: [
{ type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'mb_base' }, { type: 2, style: ButtonStyle.Primary, label: 'Base', custom_id: 'mb_base' },

View File

@@ -575,7 +575,7 @@ export class AIService {
* Procesar imágenes adjuntas para análisis con Gemini Vision * Procesar imágenes adjuntas para análisis con Gemini Vision
*/ */
private async processImageAttachments(attachments: any[]): Promise<any[]> { private async processImageAttachments(attachments: any[]): Promise<any[]> {
const imageAttachments = []; const imageAttachments: Array<{ inlineData: { data: string; mimeType: string } }> = [];
for (const attachment of attachments) { for (const attachment of attachments) {
if (this.hasImageAttachments([attachment])) { if (this.hasImageAttachments([attachment])) {
@@ -1121,7 +1121,7 @@ Responde de forma directa y útil:`;
.filter((role: any) => role.id !== guild.id) // Excluir @everyone .filter((role: any) => role.id !== guild.id) // Excluir @everyone
.sort((a: any, b: any) => b.position - a.position) .sort((a: any, b: any) => b.position - a.position)
.map((role: any) => { .map((role: any) => {
const permissions = []; const permissions: string[] = [];
if (role.permissions.has('Administrator')) permissions.push('Admin'); if (role.permissions.has('Administrator')) permissions.push('Admin');
if (role.permissions.has('ManageGuild')) permissions.push('Manage Server'); if (role.permissions.has('ManageGuild')) permissions.push('Manage Server');
if (role.permissions.has('ManageChannels')) permissions.push('Manage Channels'); if (role.permissions.has('ManageChannels')) permissions.push('Manage Channels');

View File

@@ -136,7 +136,7 @@ async function handleAIReply(message: any) {
// Enviar respuesta (dividir si es muy larga) // Enviar respuesta (dividir si es muy larga)
const MAX_CONTENT = 2000; const MAX_CONTENT = 2000;
if (finalResponse.length > MAX_CONTENT) { if (finalResponse.length > MAX_CONTENT) {
const chunks = []; const chunks: string[] = [];
let currentChunk = ''; let currentChunk = '';
const lines = finalResponse.split('\n'); const lines = finalResponse.split('\n');
@@ -158,13 +158,17 @@ async function handleAIReply(message: any) {
if (i === 0) { if (i === 0) {
await message.reply({ content: chunks[i] }); await message.reply({ content: chunks[i] });
} else { } else {
await message.channel.send({ content: chunks[i] }); if ('send' in message.channel) {
await new Promise(resolve => setTimeout(resolve, 500)); await message.channel.send({ content: chunks[i] });
await new Promise(resolve => setTimeout(resolve, 500));
}
} }
} }
if (chunks.length > 3) { if (chunks.length > 3) {
await message.channel.send({ content: "⚠️ Respuesta truncada por longitud." }); if ('send' in message.channel) {
await message.channel.send({ content: "⚠️ Respuesta truncada por longitud." });
}
} }
} else { } else {
await message.reply({ content: finalResponse }); await message.reply({ content: finalResponse });

View File

@@ -1,7 +1,7 @@
import { prisma } from '../../core/database/prisma'; import { prisma } from '../../core/database/prisma';
import { Prisma } from '@prisma/client'; import { Prisma } from '@prisma/client';
async function upsertEconomyItem(guildId: string | null, key: string, data: Omit<Parameters<typeof prisma.economyItem.create>[0]['data'], 'key' | 'guildId'>) { async function upsertEconomyItem(guildId: string | null, key: string, data: Omit<Prisma.EconomyItemUncheckedCreateInput, 'key' | 'guildId'>) {
if (guildId) { if (guildId) {
return prisma.economyItem.upsert({ where: { guildId_key: { guildId, key } }, update: {}, create: { ...data, key, guildId } }); return prisma.economyItem.upsert({ where: { guildId_key: { guildId, key } }, update: {}, create: { ...data, key, guildId } });
} }
@@ -10,7 +10,7 @@ async function upsertEconomyItem(guildId: string | null, key: string, data: Omit
return prisma.economyItem.create({ data: { ...data, key, guildId: null } }); return prisma.economyItem.create({ data: { ...data, key, guildId: null } });
} }
async function upsertGameArea(guildId: string | null, key: string, data: Omit<Parameters<typeof prisma.gameArea.create>[0]['data'], 'key' | 'guildId'>) { async function upsertGameArea(guildId: string | null, key: string, data: Omit<Prisma.GameAreaUncheckedCreateInput, 'key' | 'guildId'>) {
if (guildId) { if (guildId) {
return prisma.gameArea.upsert({ where: { guildId_key: { guildId, key } }, update: {}, create: { ...data, key, guildId } }); return prisma.gameArea.upsert({ where: { guildId_key: { guildId, key } }, update: {}, create: { ...data, key, guildId } });
} }
@@ -19,7 +19,7 @@ async function upsertGameArea(guildId: string | null, key: string, data: Omit<Pa
return prisma.gameArea.create({ data: { ...data, key, guildId: null } }); return prisma.gameArea.create({ data: { ...data, key, guildId: null } });
} }
async function upsertMob(guildId: string | null, key: string, data: Omit<Parameters<typeof prisma.mob.create>[0]['data'], 'key' | 'guildId'>) { async function upsertMob(guildId: string | null, key: string, data: Omit<Prisma.MobUncheckedCreateInput, 'key' | 'guildId'>) {
if (guildId) { if (guildId) {
return prisma.mob.upsert({ where: { guildId_key: { guildId, key } }, update: { stats: (data as any).stats, drops: (data as any).drops, name: (data as any).name }, create: { ...data, key, guildId } }); return prisma.mob.upsert({ where: { guildId_key: { guildId, key } }, update: { stats: (data as any).stats, drops: (data as any).drops, name: (data as any).name }, create: { ...data, key, guildId } });
} }

View File

@@ -64,7 +64,7 @@ async function validateRequirements(userId: string, guildId: string, req?: Level
// Auto-select tool when required and not provided // Auto-select tool when required and not provided
if (!toolKeyUsed && toolReq.required && toolReq.toolType) { if (!toolKeyUsed && toolReq.required && toolReq.toolType) {
toolKeyUsed = await findBestToolKey(userId, guildId, toolReq.toolType, { minTier: toolReq.minTier, allowedKeys: toolReq.allowedKeys }); toolKeyUsed = await findBestToolKey(userId, guildId, toolReq.toolType, { minTier: toolReq.minTier, allowedKeys: toolReq.allowedKeys }) ?? undefined;
} }
// herramienta requerida // herramienta requerida