forked from admin/zeropost-engine
feat: autogen blog admin API
routes/admin.js: GET /autogen — настройки+статистика+очередь+размеры банков тем PATCH /autogen/:category — enabled/per_day/run_hour/run_minute POST /autogen/:category/run — ручной запуск генерации POST /autogen/queue — добавить тему с приоритетом DELETE /autogen/queue/:id — удалить тему
This commit is contained in:
@@ -405,3 +405,88 @@ router.get('/logs', async (req, res) => {
|
|||||||
res.json({ errors: all, total: all.length, topErrors });
|
res.json({ errors: all, total: all.length, topErrors });
|
||||||
} catch (err) { res.status(500).json({ error: err.message }); }
|
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── AUTOGEN BLOG ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
// GET /api/admin/autogen — статус автогенерации блога
|
||||||
|
router.get('/autogen', async (req, res) => {
|
||||||
|
if (!await requireAdmin(req, res)) return;
|
||||||
|
try {
|
||||||
|
const { getAutogenStatus, TOPIC_BANK } = require('../services/autogen');
|
||||||
|
const status = await getAutogenStatus();
|
||||||
|
|
||||||
|
// Статистика статей по категориям за последние 7 дней
|
||||||
|
const { rows: recentStats } = await query(`
|
||||||
|
SELECT category, count(*)::int as cnt_7d,
|
||||||
|
max(created_at) as last_article_at
|
||||||
|
FROM articles
|
||||||
|
WHERE status='published' AND created_at > NOW() - INTERVAL '7 days'
|
||||||
|
GROUP BY category
|
||||||
|
`);
|
||||||
|
const byCategory = Object.fromEntries(recentStats.map(r => [r.category, r]));
|
||||||
|
|
||||||
|
// Очередь тем
|
||||||
|
const { rows: queueItems } = await query(
|
||||||
|
`SELECT * FROM content_queue ORDER BY priority DESC, created_at ASC LIMIT 20`
|
||||||
|
);
|
||||||
|
|
||||||
|
const topicBankSizes = Object.fromEntries(
|
||||||
|
Object.entries(TOPIC_BANK).map(([k, v]) => [k, v.length])
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({ settings: status, byCategory, queue: queueItems, topicBankSizes });
|
||||||
|
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// PATCH /api/admin/autogen/:category — обновить настройки категории
|
||||||
|
router.patch('/autogen/:category', async (req, res) => {
|
||||||
|
if (!await requireAdmin(req, res)) return;
|
||||||
|
try {
|
||||||
|
const { enabled, per_day, run_hour, run_minute } = req.body;
|
||||||
|
const fields = []; const vals = []; let i = 1;
|
||||||
|
if (enabled !== undefined) { fields.push(`enabled=$${i++}`); vals.push(enabled); }
|
||||||
|
if (per_day !== undefined) { fields.push(`per_day=$${i++}`); vals.push(per_day); }
|
||||||
|
if (run_hour !== undefined) { fields.push(`run_hour=$${i++}`); vals.push(run_hour); }
|
||||||
|
if (run_minute !== undefined) { fields.push(`run_minute=$${i++}`); vals.push(run_minute); }
|
||||||
|
if (!fields.length) return res.status(400).json({ error: 'Nothing to update' });
|
||||||
|
vals.push(req.params.category);
|
||||||
|
await query(`UPDATE autogen_settings SET ${fields.join(',')} WHERE category=$${i}`, vals);
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST /api/admin/autogen/:category/run — запустить генерацию вручную
|
||||||
|
router.post('/autogen/:category/run', async (req, res) => {
|
||||||
|
if (!await requireAdmin(req, res)) return;
|
||||||
|
try {
|
||||||
|
res.json({ ok: true, message: `Генерация категории ${req.params.category} запущена` });
|
||||||
|
const { runAutogenForCategory } = require('../services/autogen');
|
||||||
|
runAutogenForCategory(req.params.category).catch(e =>
|
||||||
|
console.error(`[Autogen manual] ${req.params.category}: ${e.message}`)
|
||||||
|
);
|
||||||
|
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST /api/admin/autogen/queue — добавить тему в очередь
|
||||||
|
router.post('/autogen/queue', async (req, res) => {
|
||||||
|
if (!await requireAdmin(req, res)) return;
|
||||||
|
const { category, topic, tags = [], keywords = [], priority = 5 } = req.body;
|
||||||
|
if (!category || !topic) return res.status(400).json({ error: 'category и topic обязательны' });
|
||||||
|
try {
|
||||||
|
const { rows: [item] } = await query(
|
||||||
|
`INSERT INTO content_queue (category, topic, tags, keywords, priority)
|
||||||
|
VALUES ($1,$2,$3,$4,$5) RETURNING *`,
|
||||||
|
[category, topic, JSON.stringify(tags), JSON.stringify(keywords), priority]
|
||||||
|
);
|
||||||
|
res.json(item);
|
||||||
|
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// DELETE /api/admin/autogen/queue/:id
|
||||||
|
router.delete('/autogen/queue/:id', async (req, res) => {
|
||||||
|
if (!await requireAdmin(req, res)) return;
|
||||||
|
try {
|
||||||
|
await query('DELETE FROM content_queue WHERE id=$1', [req.params.id]);
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch (err) { res.status(500).json({ error: err.message }); }
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user