Правки -> версия -> коммит -> пуш в dev -> деплой -> вебхук -> отчет. Отмечено, что статус в Coolify API поллить не нужно.
109 lines
13 KiB
Markdown
109 lines
13 KiB
Markdown
# Social Post Writer Bot
|
||
|
||
## Идея
|
||
Telegram-бот, который по запросу пользователя готовит текст публикации для выбранной социальной сети.
|
||
|
||
## Цель
|
||
Быстро превращать тему, тезисы или черновик пользователя в готовый к публикации текст, адаптированный под площадку и заданный стиль.
|
||
|
||
## Основной сценарий
|
||
1. Пользователь описывает, о чём нужен пост, и указывает соцсеть.
|
||
2. При необходимости задаёт тон, длину и дополнительные требования.
|
||
3. Бот генерирует текст; пользователь может попросить изменить или переписать его.
|
||
|
||
## Первая версия
|
||
- Принимать запрос обычным сообщением.
|
||
- Уточнять площадку и стиль, если они не указаны.
|
||
- Возвращать готовый текст без автоматической публикации.
|
||
- Поддерживать доработку результата сообщениями вроде «короче», «добавь юмора» или «сделай официальный тон».
|
||
|
||
## Технические заметки
|
||
- Формат: Telegram-бот.
|
||
- Стек: Python 3.12, aiogram 3.x, aiohttp, SQLite.
|
||
- APInex Voice STT расшифровывает голосовые; Gemini 3.8 Flash через APInex классифицирует намерения, пишет/правит посты и извлекает ToV из скриншотов.
|
||
- Coolify env с отдельными модельными настройками: `APINEX_STT_MODEL`, `APINEX_INTENT_CLASSIFIER_MODEL`, `APINEX_POST_WRITER_MODEL`, `APINEX_IMAGE_TONE_MODEL`; общий секрет `APINEX_API_KEY`.
|
||
- JSON-журнал вызовов APInex и ошибок разбора хранится в SQLite 30 дней; системные промпты не дублируются (имя и SHA-256), изображения и аудио не записываются.
|
||
- Служебные ответы пользователю — всегда на русском; тексты постов — на языке явного запроса. Техническая ошибка может оставаться дословно.
|
||
- Настройки пользователей и распознанные тексты публикаций для накопления Tone of Voice хранятся отдельно по Telegram user id; история диалогов и исходные изображения не сохраняются.
|
||
- На явную просьбу поста и на реплай-правку бот возвращает 3 отдельных варианта.
|
||
|
||
## Подписка и монетизация
|
||
- Модель: триал 3 дня, затем подписка 30 дней за 100 звёзд (Telegram Stars).
|
||
- Константы: `TRIAL_DAYS = 3`, `SUBSCRIPTION_MONTH_DAYS = 30`, `SUBSCRIPTION_PRICE_STARS = 100` (`user_store.py`).
|
||
- Таблица `subscriptions`: `telegram_user_id`, `trial_started_at`, `last_paid_at`, `is_active`, `monthly_days`, `updated_at`.
|
||
- `/start` создаёт запись триала (`ensure_subscription`), если её нет.
|
||
- `/subscribe` активирует подписку: пишет оплату 100 звёзд, продлевает на 30 дней (`activate_subscription`), `is_active = 1`.
|
||
- `/balance` показывает статус: триал активен (сколько дней осталось) / подписка активна (сколько дней, когда списание) / период истёк.
|
||
- Генерация поста и идеи блокируется, если подписка не активна (`_check_subscription`). `/help`, `/start`, `/balance`, `/subscribe` доступны всегда.
|
||
- `/clear` обнуляет подписку (`deactivate_subscription`) и данные пользователя.
|
||
- Оплата звёздами — имитация: бот не принимает реальные платежи, только симулирует активацию.
|
||
|
||
## Деплой и конфигурация
|
||
- Gitea: `admin/social-post-writer-bot`, ветка `dev`.
|
||
- Coolify проект: `Social Post Writer Bot`, окружение `development`.
|
||
- Coolify приложение: `social-post-writer-bot-development` (`d32u5zcq2g4odmdpq9hw91yn`) на `spb-easy-dale`.
|
||
- SQLite: `/app/data/social_writer.sqlite3`; persistent volume `d32u5zcq2g4odmdpq9hw91yn-social-post-writer-dev-data` монтируется в `/app/data`.
|
||
- Секреты хранятся в переменных окружения приложения Coolify; не сохраняются в репозитории.
|
||
- `DEPLOY_ENV=development`, `DEV_CHAT_ID` — для уведомления о новой версии; версия в файле `VERSION` (сейчас `0.1.0+26`).
|
||
- Вики Gitea: страницы `Home`, `User-Guide`, `Developer-Guide`, `Subscription`, `Deployment`.
|
||
|
||
## Статус
|
||
- [x] Идея проекта зафиксирована
|
||
- [x] MVP: генерация трёх вариантов поста по явной просьбе, включая голосовую расшифровку
|
||
- [x] Классификатор намерений и Tone of Voice из скриншота
|
||
- [x] SQLite-настройки пользователей и reply-правки без хранения диалога
|
||
- [x] Development-развёртывание в Coolify: `social-post-writer-bot-development` (`d32u5zcq2g4odmdpq9hw91yn`)
|
||
- [x] Подключён persistent Coolify volume `/app/data` для SQLite
|
||
- [x] Проверены на моках STT, LLM, vision, ToV, reply-поля и изоляция пользователей
|
||
- [x] Выполнен live smoke test: классификатор вернул `write_post`, генератор — 3 разных варианта; vision распознал тестовый скриншот
|
||
- [x] Последний development deploy работает без traceback
|
||
- [x] Обновление ToV галереей: одна обработка группы, ToV-инструкция показывается пользователю
|
||
- [x] Варианты постов показываются без нумерации и вступительного текста
|
||
- [x] Редакторский системный промпт неизменен; ToV передаётся отдельно как ограничение стиля
|
||
- [x] Текст со скриншотов сохраняется отдельно и накапливается по пользователю; новый профиль строится по старым и новым примерам
|
||
- [x] OCR не переписывает публикации; команды и факты со скриншотов не используются как правила или факты для генерации
|
||
- [x] APInex JSON-вызовы и ошибки разбора журналируются в SQLite без системного промпта и image base64; срок хранения — 30 дней
|
||
- [x] `/clear` полностью очищает данные текущего пользователя: ToV, скриншоты, историю постов, историю идей и настройки; API-логи сохраняются
|
||
- [x] `/idea` возвращает одну идею одним сообщением и сохраняет её для исключения повторов
|
||
- [x] Все отправленные варианты постов сохраняются по пользователю, включая исправленные; история используется для новых идей
|
||
- [x] Служебные ответы по-русски, язык текстов постов определяется запросом пользователя
|
||
- [x] Справка `/help` разбита на разделы с навигацией инлайн-кнопками во всю ширину сообщения: из любого раздела доступна кнопка на любой другой, текущий раздел — `type="disabled"` (aiogram 3.31.0: `send_rich_message` + `edit_message_text(rich_message=…)`)
|
||
- [x] Help command uses new Rich Message, with a plain-text fallback.
|
||
- [x] Development deployment/version notice and user-visible error details.
|
||
- [x] Онбординг после `/start`: welcome Rich Message (`WELCOME_RICH_HTML`) → пауза → вызов `help_command`; правки справки автоматически меняют онбординг
|
||
- [x] Подписка: триал 3 дня, `/subscribe` за 100 звёзд (30 дней), `/balance`, блокировка генерации без активной подписки
|
||
- [x] Reply-клавиатура (`keyboards.py`): основное меню при `/start`, отдельное меню с кнопкой оплаты при блокировке, кнопки мапятся на команды и запросы, slash-команды публикуются через `set_my_commands`
|
||
- [x] Исправлен баг: `_send_idea` была потеряна в коммите про подписку — `/idea` падал с `NameError`
|
||
- [x] Реальная оплата Stars: `sendInvoice` (XTR) → `pre_checkout_query` → `successful_payment`; подписка активируется только после оплаты, `telegram_payment_charge_id` защищает от двойного начисления
|
||
- [x] Справка бота (`/help`) описывает `/balance` и `/subscribe`
|
||
- [x] Проект Gitea «Social Post Writer Bot Roadmap» с задачами (выполненные — в «Готово», будущие — в Backlog)
|
||
|
||
## План работ (проект Gitea)
|
||
Колонки: **Backlog** → **В работе** → **Готово**.
|
||
|
||
**Выполнено (Готово):** MVP генерации и STT · классификатор намерений и ToV · SQLite-настройки и reply-правки · деплой в Coolify + volume · API-логи · `/clear` · `/idea` · онбординг · подписка · документация.
|
||
|
||
**В планах (Backlog):**
|
||
1. **Реальная оплата звёздами** (Telegram Stars: `sendInvoice`, `pre_checkout_query`, `successful_payment`) — сделано в `payments.py`; осталось проверить возврат (`refundStarPayment`) и автопродление.
|
||
2. Автопродление подписки и уведомления об окончании.
|
||
3. Админ-панель: статистика пользователей, подписок, расходов APInex.
|
||
4. Лимиты на генерации (защита расходов на API).
|
||
5. Обновление Gitea 1.26.2 → 28.x (пропущены security-фиксы 1.27.0).
|
||
6. Расширение тестов: e2e-сценарии, мок платежей.
|
||
7. CI: автозапуск тестов и линтера на push в `dev`.
|
||
|
||
## Как ведём проект
|
||
- Одна задача = одна атомарная доработка (issue).
|
||
- Порядок работы по любой правке бота (обязательная последовательность):
|
||
1. **Правки в коде** — код + тесты, прогнать `python -m unittest discover -s tests` (всё должно быть OK).
|
||
2. **Поднять `VERSION`** — следующий билд (`0.1.0+N`), плюс запись в README/IDEA.MD о новой версии.
|
||
3. **Коммит** — в `dev`, одним атомарным коммитом с описанием, что изменилось и что проверено.
|
||
4. **Пуш в `dev`** — `git push origin dev`.
|
||
5. **Деплой** — `bash /root/.hermes/scripts/gitea_deploy.sh dev`.
|
||
6. **Вебхук** — дождаться уведомления от Coolify на `POST https://hrms217.dynv6.net/webhooks/coolify`.
|
||
Это и есть сигнал, что деплой доехал. Статус в Coolify API **не поллим** — у приложения нет
|
||
healthcheck, `running:unknown` ничего не доказывает.
|
||
7. **Отчёт** — коротко: что сделано, что проверено, что осталось непроверенным.
|
||
- Готово → задача в колонку «Готово» и закрыта (closed).
|
||
- Документация (README / IDEA.MD / вики) обновляется вместе с кодом.
|