diff --git a/src/services/covers.js b/src/services/covers.js index 4f786ce..850c1ff 100644 --- a/src/services/covers.js +++ b/src/services/covers.js @@ -559,28 +559,25 @@ async function generateCover({ articleId, title, tags = [], channelId = null }) const prompt = buildCoverPrompt({ title, tags, articleId, channelStyle, rubric: selectedRubric }); - let img; + let img = null; let usedPath = 'routerai'; - // Единственный провайдер картинок: routerai /responses + gpt-5-image-mini - // Цена: ~₽2.72/картинка (4175 image tokens, high quality, quality param не работает) - try { - img = await generateCoverViaRouterAI({ prompt }); - } catch (err) { - const status = err.response?.status; - // Ретрай при 5xx - if (!status || (status >= 500 && status < 600)) { - console.warn(`[Cover] routerai attempt 1 failed (${status||'timeout'}), retry in 10s...`); - await new Promise(r => setTimeout(r, 10_000)); - try { - img = await generateCoverViaRouterAI({ prompt }); - } catch (err2) { - console.warn(`[Cover] routerai attempt 2 failed: ${(err2.response?.data?.error?.message || err2.message).slice(0, 150)}`); - img = null; - } - } else { - console.warn(`[Cover] routerai failed (${status}): ${(err.response?.data?.error?.message || err.message).slice(0, 150)}`); - img = null; + // Единственный провайдер картинок — routerai /responses + gpt-5-image-mini + // (самый надёжный). Бывает медленным/таймаутит, поэтому до 4 попыток с + // нарастающей паузой; local SVG — только если все попытки провалились, + // чтобы обложка не осталась пустой. + const ROUTERAI_ATTEMPTS = 4; + for (let attempt = 1; attempt <= ROUTERAI_ATTEMPTS; attempt++) { + try { + img = await generateCoverViaRouterAI({ prompt }); + if (img) break; + } catch (err) { + const status = err.response?.status; + const retriable = !status || (status >= 500 && status < 600) || status === 429; + const msg = (err.response?.data?.error?.message || err.message || '').slice(0, 150); + console.warn(`[Cover] article=${articleId} routerai attempt ${attempt}/${ROUTERAI_ATTEMPTS} failed (${status || 'timeout'}): ${msg}`); + if (!retriable || attempt === ROUTERAI_ATTEMPTS) break; + await new Promise(r => setTimeout(r, attempt * 8000)); // 8s → 16s → 24s } } if (!img) {