fix: button always shows DEFAULT_BUTTON_TEXT when field is null/empty
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
process.chdir('/var/www/zeropost-engine');
|
||||
require('dotenv').config();
|
||||
|
||||
const { query } = require('./src/config/db');
|
||||
const ai = require('./src/services/ai');
|
||||
|
||||
const DELAY_MS = 3000;
|
||||
const TIMEOUT_MS = 120000; // 2 мин на статью
|
||||
const START_FROM_ID = parseInt(process.argv[2] || '0'); // можно передать start id
|
||||
|
||||
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
||||
|
||||
function withTimeout(promise, ms) {
|
||||
return Promise.race([
|
||||
promise,
|
||||
new Promise((_, reject) => setTimeout(() => reject(new Error('TIMEOUT')), ms))
|
||||
]);
|
||||
}
|
||||
|
||||
function parseContent(content, topic) {
|
||||
const lines = content.split('\n').filter(Boolean);
|
||||
let title = topic;
|
||||
const h1 = lines.find(l => l.startsWith('# '));
|
||||
if (h1) title = h1.replace(/^#\s+/, '').trim();
|
||||
const firstPara = lines.find(l => l.length > 80 && !l.startsWith('#'));
|
||||
const excerpt = firstPara ? firstPara.substring(0, 200) + (firstPara.length > 200 ? '...' : '') : '';
|
||||
const wordCount = content.replace(/<[^>]+>/g, '').split(/\s+/).length;
|
||||
const readingTime = Math.max(1, Math.round(wordCount / 200));
|
||||
return { title, excerpt, readingTime };
|
||||
}
|
||||
|
||||
async function regenArticle(article, blogChannel) {
|
||||
const topic = article.source_topic || article.title;
|
||||
try {
|
||||
const result = await withTimeout(
|
||||
ai.generateArticle(blogChannel, { topic }),
|
||||
TIMEOUT_MS
|
||||
);
|
||||
if (!result?.content) return false;
|
||||
|
||||
const { title, excerpt, readingTime } = parseContent(result.content, topic);
|
||||
await query(
|
||||
`UPDATE articles SET title=$1, content=$2, excerpt=$3, reading_time=$4,
|
||||
seo_title=$5, seo_descr=$6, updated_at=NOW() WHERE id=$7`,
|
||||
[title, result.content, excerpt, readingTime,
|
||||
title.substring(0,60), excerpt.substring(0,160), article.id]
|
||||
);
|
||||
console.log(`[Regen] OK id=${article.id} "${title.slice(0,60)}"`);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(`[Regen] ERROR id=${article.id}: ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { rows: articles } = await query(
|
||||
`SELECT id, title, source_topic, category FROM articles
|
||||
WHERE status='published' ${START_FROM_ID ? `AND id >= ${START_FROM_ID}` : ''}
|
||||
ORDER BY id ASC`
|
||||
);
|
||||
const { rows: channels } = await query(
|
||||
`SELECT * FROM channels WHERE is_system=true AND is_active=true LIMIT 1`
|
||||
);
|
||||
|
||||
console.log(`[Regen] ${articles.length} articles to process (from id=${START_FROM_ID || 'start'})`);
|
||||
|
||||
let ok = 0, fail = 0;
|
||||
for (let i = 0; i < articles.length; i++) {
|
||||
console.log(`[Regen] ${i+1}/${articles.length} id=${articles[i].id}`);
|
||||
const success = await regenArticle(articles[i], channels[0]);
|
||||
if (success) ok++; else fail++;
|
||||
if (i < articles.length - 1) await sleep(DELAY_MS);
|
||||
}
|
||||
|
||||
console.log(`[Regen] DONE: ${ok} OK, ${fail} FAILED`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
main().catch(e => { console.error(e); process.exit(1); });
|
||||
Reference in New Issue
Block a user