Files
postcast-engine/src/routes/channelStats.js
T
Nik (Claude) a370b8f7d8 feat: Зеро-персонаж, auto-publish, auto-series, channel-stats, fallback covers
- Персонаж Зеро: 23 позы (zeroCharacter.js), скрипты генерации
- Auto-publish статей в TG: multipart upload, кнопки, режим alternating Zero/cover
- Fallback цепочка обложек: aiprimetech gpt-5.5 → Pollinations → local SVG (6 палитр)
- Auto-series: Claude haiku определяет серию для каждой статьи автоматически
- Channel stats: подписчики, история, delta 24h/7d
- Photo-search: Yandex API, профили доменов, Redis лимиты
- Scheduled posts runner: backfill, preview, queue, cancel
- promptBuilder: author_persona Зеро, голос от первого лица
- Fixes: dollar-placeholder bugs в PATCH channels/autogen, listArticles фильтры
- AI model: gpt-5.5 для image generation
2026-06-07 14:03:56 +03:00

32 lines
1.2 KiB
JavaScript

const express = require('express');
const router = express.Router();
const stats = require('../services/channelStats');
const { query } = require('../config/db');
// POST /api/channel-stats/collect — собрать статистику (cron, раз в час)
router.post('/collect', async (req, res) => {
try {
const results = await stats.collectAll();
res.json({ ok: true, results });
} catch (err) { res.status(500).json({ error: err.message }); }
});
// GET /api/channel-stats/:channelId/summary — сводка по каналу
router.get('/:channelId/summary', async (req, res) => {
try {
const summary = await stats.getChannelSummary(parseInt(req.params.channelId));
res.json(summary);
} catch (err) { res.status(500).json({ error: err.message }); }
});
// GET /api/channel-stats/:channelId/history?days=30 — история подписчиков
router.get('/:channelId/history', async (req, res) => {
try {
const days = Math.min(parseInt(req.query.days) || 30, 365);
const history = await stats.getMembersHistory(parseInt(req.params.channelId), days);
res.json(history);
} catch (err) { res.status(500).json({ error: err.message }); }
});
module.exports = router;