feat: integrate modern GenAI SDK for image generation and enhance image handling in AI requests

This commit is contained in:
2025-10-04 03:10:04 -05:00
parent e2770f70dc
commit a6c47cca5e
5 changed files with 295 additions and 66 deletions

View File

@@ -227,56 +227,23 @@ export const command: CommandMessage = {
// Verificar si hay imágenes adjuntas
const attachments = Array.from(message.attachments.values());
const hasImages = attachments.length > 0 && aiService.hasImageAttachments?.(attachments);
const hasImages = attachments.length > 0 && aiService.hasImageAttachments(attachments);
// Usar el nuevo método con memoria persistente y soporte para imágenes
if (hasImages) {
// Agregar información sobre las imágenes a los metadatos
const imageInfo = attachments
.filter(att => att.contentType?.startsWith('image/') ||
['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'].some(ext =>
att.name?.toLowerCase().endsWith(ext)))
.map(att => `${att.name} (${att.contentType || 'imagen'})`)
.join(', ');
const enhancedMeta = messageMeta + (imageInfo ? ` | Imágenes adjuntas: ${imageInfo}` : '');
// Usar método específico para imágenes
const request = {
userId,
guildId,
channelId: message.channel.id,
prompt: prompt.trim(),
priority: 'normal' as const,
timestamp: Date.now(),
aiRolePrompt: undefined,
meta: enhancedMeta,
messageId: message.id,
referencedMessageId,
attachments: attachments,
client: message.client
};
// Procesar con imágenes
aiResponse = await new Promise((resolve, reject) => {
request.resolve = resolve;
request.reject = reject;
aiService.requestQueue.push(request as any);
});
} else {
// Método normal sin imágenes
aiResponse = await aiService.processAIRequestWithMemory(
userId,
prompt,
guildId,
message.channel.id,
message.id,
referencedMessageId,
message.client,
'normal',
{ meta: messageMeta }
);
}
// Usar el método unificado con memoria persistente y soporte para imágenes
aiResponse = await aiService.processAIRequestWithMemory(
userId,
prompt,
guildId,
message.channel.id,
message.id,
referencedMessageId,
message.client,
'normal',
{
meta: messageMeta + (hasImages ? ` | Tiene ${attachments.length} imagen(es) adjunta(s)` : ''),
attachments: hasImages ? attachments : undefined
}
);
// Reemplazar :nombre: por el tag real del emoji, evitando bloques de código
if (emojiNames.length > 0) {

View File

@@ -0,0 +1,62 @@
import { CommandMessage } from "../../../core/types/commands";
import { aiService } from "../../../core/services/AIService";
import logger from "../../../core/lib/logger";
function parseSizeArg(arg?: string): 'square' | 'portrait' | 'landscape' {
if (!arg) return 'square';
const v = arg.toLowerCase();
if (v === 'square' || v === 'cuadrado' || v === '1:1') return 'square';
if (v === 'portrait' || v === 'vertical' || v === '9:16') return 'portrait';
if (v === 'landscape' || v === 'horizontal' || v === '16:9') return 'landscape';
return 'square';
}
export const command: CommandMessage = {
name: 'aiimg',
type: 'message',
aliases: ['img', 'imagen'],
cooldown: 5,
description: 'Genera una imagen con Gemini (gemini-2.5-flash-image).',
category: 'IA',
usage: 'aiimg [square|portrait|landscape] <prompt>',
run: async (message, args) => {
try {
if (!args || args.length === 0) {
await message.reply({
content: 'Uso: aiimg [square|portrait|landscape] <prompt>\nEjemplo: aiimg portrait un gato astronauta'
});
return;
}
let size: 'square' | 'portrait' | 'landscape' = 'square';
let prompt = args.join(' ').trim();
// Si el primer arg es un tamaño válido, usarlo y quitarlo del prompt
const maybeSize = parseSizeArg(args[0]);
if (maybeSize !== 'square' || ['square', 'cuadrado', '1:1'].includes(args[0]?.toLowerCase?.() ?? '')) {
// Detect explicit size keyword; if first arg matches any known size token, shift it
if (['square','cuadrado','1:1','portrait','vertical','9:16','landscape','horizontal','16:9'].includes(args[0].toLowerCase())) {
size = maybeSize;
prompt = args.slice(1).join(' ').trim();
}
}
if (!prompt) {
await message.reply({ content: 'El prompt no puede estar vacío.' });
return;
}
//@ts-ignore
await message.channel.sendTyping().catch(() => {});
const result = await aiService.generateImage(prompt, { size });
await message.reply({
content: `✅ Imagen generada (${size}).`,
files: [{ attachment: result.data, name: result.fileName }]
});
} catch (error: any) {
logger.error('Error generando imagen:', error);
await message.reply({ content: `❌ Error generando imagen: ${error?.message || 'Error desconocido'}` });
}
}
};

View File

@@ -172,7 +172,7 @@ export const command: CommandMessage = {
]
};
const panelMessage = await message.reply({ flags: 32768, components: [helpPanel, categorySelectRow, exportRow] });
const panelMessage = await message.reply({ flags: 32768, components: [helpPanel, categorySelectRow] });
const collector = panelMessage.createMessageComponentCollector({
time: 600000,