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
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
const { query } = require('../config/db');
|
||||
const axios = require('axios');
|
||||
const settings = require('../services/settings');
|
||||
|
||||
/**
|
||||
* Сохранить пост в базу (как черновик или сразу запланированный).
|
||||
*/
|
||||
async function savePost({ userId, channelId, content, imageUrl = null, topic = null, status = 'draft', scheduledAt = null }) {
|
||||
async function savePost({ userId, channelId, content, imageUrl = null, imageCredit = null, topic = null, status = 'draft', scheduledAt = null }) {
|
||||
const { rows } = await query(
|
||||
`INSERT INTO user_posts (user_id, channel_id, content, image_url, topic, status, scheduled_at)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING *`,
|
||||
[userId, channelId, content, imageUrl, topic, status, scheduledAt]
|
||||
`INSERT INTO user_posts (user_id, channel_id, content, image_url, image_credit, topic, status, scheduled_at)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING *`,
|
||||
[userId, channelId, content, imageUrl, imageCredit, topic, status, scheduledAt]
|
||||
);
|
||||
return rows[0];
|
||||
}
|
||||
@@ -30,7 +31,7 @@ async function getPost(userId, postId) {
|
||||
}
|
||||
|
||||
async function updatePost(userId, postId, data) {
|
||||
const allowed = ['content','image_url','status','scheduled_at','topic'];
|
||||
const allowed = ['content','image_url','image_credit','status','scheduled_at','topic'];
|
||||
const fields = []; const vals = []; let i = 1;
|
||||
for (const key of allowed) {
|
||||
if (data[key] !== undefined) { fields.push(`${key}=$${i++}`); vals.push(data[key]); }
|
||||
@@ -63,7 +64,7 @@ async function publishToTelegram(post, channel) {
|
||||
? post.image_url
|
||||
: `https://app.zeropost.ru${post.image_url}`;
|
||||
const res = await axios.post(
|
||||
`https://api.telegram.org/bot${channel.bot_token}/sendPhoto`,
|
||||
`${await settings.get('TELEGRAM_API_BASE', 'https://api.telegram.org')}/bot${channel.bot_token}/sendPhoto`,
|
||||
{
|
||||
chat_id: channel.tg_channel_id,
|
||||
photo: photoUrl,
|
||||
@@ -75,7 +76,7 @@ async function publishToTelegram(post, channel) {
|
||||
return { ok: true, message_id: res.data?.result?.message_id };
|
||||
} else {
|
||||
const res = await axios.post(
|
||||
`https://api.telegram.org/bot${channel.bot_token}/sendMessage`,
|
||||
`${await settings.get('TELEGRAM_API_BASE', 'https://api.telegram.org')}/bot${channel.bot_token}/sendMessage`,
|
||||
{
|
||||
chat_id: channel.tg_channel_id,
|
||||
text: post.content,
|
||||
|
||||
Reference in New Issue
Block a user