feat: update image generation logic to use new Google GenAI API and enhance error handling

This commit is contained in:
2025-10-04 04:34:55 -05:00
parent 82c650addb
commit c348b5282f
2 changed files with 159 additions and 123 deletions

View File

@@ -1,61 +1,83 @@
import { CommandMessage } from "../../../core/types/commands";
import { aiService } from "../../../core/services/AIService";
import logger from "../../../core/lib/logger";
import { Message, AttachmentBuilder } from 'discord.js';
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 default {
name: 'image',
description: 'Genera una imagen usando IA',
cooldown: 10,
async execute(message: Message, args: string[]) {
// Verificar que hay un prompt
if (!args || args.length === 0) {
await message.reply('❌ **Error**: Debes proporcionar una descripción para generar la imagen.\n\n**Ejemplo**: `imagen un gato espacial flotando entre estrellas`');
return;
}
const prompt = args.join(' ').trim();
// Validar longitud del prompt
if (prompt.length < 3) {
await message.reply('❌ **Error**: La descripción debe tener al menos 3 caracteres.');
return;
}
if (prompt.length > 1000) {
await message.reply('❌ **Error**: La descripción es demasiado larga (máximo 1000 caracteres).');
return;
}
// Mostrar mensaje de "generando..."
const thinkingMessage = await message.reply('🎨 **Generando imagen**... Esto puede tomar unos momentos.');
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;
}
logger.info(`Generando imagen para usuario ${message.author.id}: ${prompt.slice(0, 100)}`);
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;
}
(message.channel as any)?.sendTyping?.().catch(() => {});
const result = await aiService.generateImage(prompt, { size });
await message.reply({
content: `✅ Imagen generada (${size}).`,
files: [{ attachment: result.data, name: result.fileName }]
// Generar la imagen usando el AIService actualizado
const result = await aiService.generateImage(prompt, {
size: 'square', // Por defecto usar formato cuadrado
mimeType: 'image/jpeg',
numberOfImages: 1,
personGeneration: true
});
} catch (error: any) {
logger.error(error, 'Error generando imagen');
await message.reply({ content: `❌ Error generando imagen: ${error?.message || 'Error desconocido'}` });
// Crear attachment para Discord
const attachment = new AttachmentBuilder(result.data, {
name: result.fileName,
description: `Imagen generada: ${prompt.slice(0, 100)}${prompt.length > 100 ? '...' : ''}`
});
// Responder con la imagen
await thinkingMessage.edit({
content: `✅ **Imagen generada** para: *${prompt.slice(0, 150)}${prompt.length > 150 ? '...' : ''}*`,
files: [attachment]
});
logger.info(`Imagen generada exitosamente para usuario ${message.author.id}, tamaño: ${result.data.length} bytes`);
} catch (error) {
logger.error(`Error generando imagen para usuario ${message.author.id}: ${error}`);
let errorMessage = '❌ **Error generando imagen**: ';
if (error instanceof Error) {
const errorText = error.message.toLowerCase();
if (errorText.includes('no está disponible') || errorText.includes('not found')) {
errorMessage += 'El servicio de generación de imágenes no está disponible en este momento.';
} else if (errorText.includes('límite') || errorText.includes('quota')) {
errorMessage += 'Se ha alcanzado el límite de generación de imágenes. Intenta más tarde.';
} else if (errorText.includes('bloqueado') || errorText.includes('safety')) {
errorMessage += 'Tu descripción fue bloqueada por las políticas de seguridad. Intenta con algo diferente.';
} else if (errorText.includes('inicializado') || errorText.includes('api')) {
errorMessage += 'El servicio no está configurado correctamente.';
} else {
errorMessage += error.message;
}
} else {
errorMessage += 'Error desconocido. Intenta de nuevo más tarde.';
}
await thinkingMessage.edit(errorMessage);
}
}
};