Corrige ReferenceError safeExtractError e adiciona retries resilientes multi-engine no gerador de imagens
This commit is contained in:
@@ -11,6 +11,26 @@ function escapeHtml(text) {
|
|||||||
.replace(/'/g, "'");
|
.replace(/'/g, "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper global para extração segura de erros de resposta HTTP no frontend
|
||||||
|
async function safeExtractError(resp, defaultMsg = 'Erro na operação') {
|
||||||
|
if (!resp) return defaultMsg;
|
||||||
|
try {
|
||||||
|
const text = await resp.text();
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(text);
|
||||||
|
return json.error || defaultMsg;
|
||||||
|
} catch (e) {
|
||||||
|
if (resp.status === 502 || text.includes('Bad Gateway')) {
|
||||||
|
return 'O servidor está temporariamente ocupado processando a requisição. Por favor, tente novamente em instantes.';
|
||||||
|
}
|
||||||
|
return text.slice(0, 160) || defaultMsg;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return defaultMsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Função global para exibir notificações elegantes estilo Toast
|
// Função global para exibir notificações elegantes estilo Toast
|
||||||
function showToast(message, type = 'info') {
|
function showToast(message, type = 'info') {
|
||||||
let container = document.getElementById('toast-container');
|
let container = document.getElementById('toast-container');
|
||||||
|
|||||||
@@ -586,30 +586,44 @@ app.post('/api/comics/generate-frame', requireAuth, async (req, res) => {
|
|||||||
console.warn('[Comics Image] Falha/Timeout no MiniMax image-01 (' + minimaxErr.message + '), acionando gerador fallback...');
|
console.warn('[Comics Image] Falha/Timeout no MiniMax image-01 (' + minimaxErr.message + '), acionando gerador fallback...');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tentativa 2 (Fallback): Pollinations FLUX de alta resolução estilizado 3D Pixar
|
// Tentativa 2 (Fallback Resiliente Multi-Engine com Retries):
|
||||||
if (!imageBuffer) {
|
if (!imageBuffer) {
|
||||||
providerUsed = 'pollinations-flux';
|
const is169 = proporcao === '16:9' || (prompt && prompt.includes('16:9'));
|
||||||
try {
|
const width = is169 ? 1280 : 1024;
|
||||||
const is169 = proporcao === '16:9' || prompt.includes('16:9');
|
const height = is169 ? 720 : 768;
|
||||||
const width = is169 ? 1280 : 1024;
|
const cleanPrompt = (prompt || 'cute children book illustration').replace(/[^\w\s,.-]/gi, '');
|
||||||
const height = is169 ? 720 : 768;
|
const enhancedPrompt = encodeURIComponent(`${cleanPrompt}, 3d pixar disney style, digital children book illustration, vibrant colors, masterpiece, cinematic lighting`);
|
||||||
const enhancedPrompt = encodeURIComponent(`${prompt}, 3d pixar disney style, digital children book illustration, vibrant colors, masterpiece, cinematic lighting`);
|
|
||||||
const fallbackUrl = `https://image.pollinations.ai/prompt/${enhancedPrompt}?width=${width}&height=${height}&nologo=true&seed=${Math.floor(Math.random() * 100000)}`;
|
const engines = ['flux', 'turbo'];
|
||||||
|
|
||||||
const controller = new AbortController();
|
for (const engine of engines) {
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
if (imageBuffer) break;
|
||||||
|
for (let attempt = 1; attempt <= 2; attempt++) {
|
||||||
|
try {
|
||||||
|
providerUsed = `pollinations-${engine}`;
|
||||||
|
const seed = Math.floor(Math.random() * 1000000);
|
||||||
|
const fallbackUrl = `https://image.pollinations.ai/prompt/${enhancedPrompt}?width=${width}&height=${height}&model=${engine}&nologo=true&seed=${seed}`;
|
||||||
|
|
||||||
const fbResp = await fetch(fallbackUrl, { signal: controller.signal });
|
const controller = new AbortController();
|
||||||
clearTimeout(timeoutId);
|
const timeoutId = setTimeout(() => controller.abort(), 25000);
|
||||||
|
|
||||||
if (fbResp.ok) {
|
const fbResp = await fetch(fallbackUrl, { signal: controller.signal });
|
||||||
imageBuffer = Buffer.from(await fbResp.arrayBuffer());
|
clearTimeout(timeoutId);
|
||||||
console.log('[Comics Image] Imagem gerada com sucesso via Fallback Inteligente (Pollinations Flux).');
|
|
||||||
} else {
|
if (fbResp.ok) {
|
||||||
throw new Error(`Fallback HTTP ${fbResp.status}`);
|
imageBuffer = Buffer.from(await fbResp.arrayBuffer());
|
||||||
|
console.log(`[Comics Image] Imagem gerada com sucesso via Fallback (${providerUsed}, tentativa ${attempt}).`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
console.warn(`[Comics Image] Fallback ${providerUsed} tentativa ${attempt} respondeu ${fbResp.status}`);
|
||||||
|
if (fbResp.status === 429) {
|
||||||
|
await new Promise(r => setTimeout(r, 700 * attempt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (fbErr) {
|
||||||
|
console.warn(`[Comics Image] Erro no fallback ${engine} tentativa ${attempt}:`, fbErr.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (fbErr) {
|
|
||||||
console.error('[Comics Image] Erro também no provedor Fallback:', fbErr.message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user