Compare commits

...
6 Commits
+4 -7
View File
@@ -35,7 +35,6 @@ Telegram-бот, который по запросу пользователя г
## Технические заметки
- Формат: Telegram-бот.
- Стек: Python 3.12, aiogram 3.x, aiohttp, SQLite.
- Аналитика: отдельная SQLite `/app/data/analytics.sqlite3`, события на пользователя; команда `/stats` в админском топике выводит таблицы по периодам «Сегодня», «7 дней», «30 дней», «Всё время».
- APInex Voice STT расшифровывает голосовые; Gemini 3.8 Flash через APInex классифицирует намерения, пишет/правит посты и извлекает ToV из скриншотов.
- Coolify env с отдельными модельными настройками: `APINEX_STT_MODEL`, `APINEX_INTENT_CLASSIFIER_MODEL`, `APINEX_INJECTION_CLASSIFIER_MODEL`, `APINEX_POST_WRITER_MODEL`, `APINEX_IMAGE_TONE_MODEL`, `APINEX_RESPONSE_REPAIR_MODEL`; общий секрет `APINEX_API_KEY`. При невалидном JSON допускается одна попытка исправления форматирования до валидации схемы. Обрезанный на середине строки ответ не требует доотправки: `_extract_complete_post_strings` достаёт целые строки и возвращает три полных варианта. Лимит `max_tokens` у вызовов LLM снят.
- В режиме «Обучение» текстовые заметки, голосовые/аудио и примеры постов дополняют единый накопительный профиль аккаунта; сброс обучения удаляет и заметки, и образцы. Флаг `users.is_trained` включает самостоятельную генерацию поста.
@@ -66,14 +65,14 @@ Telegram-бот, который по запросу пользователя г
- 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`; analytics: `/app/data/analytics.sqlite3` на том же persistent volume `d32u5zcq2g4odmdpq9hw91yn-social-post-writer-dev-data` монтируется в `/app/data`.
- SQLite: `/app/data/social_writer.sqlite3`; persistent volume `d32u5zcq2g4odmdpq9hw91yn-social-post-writer-dev-data` монтируется в `/app/data`.
- Важно при поиске логов: приложение запущено на сервере `spb-easy-dale` (`31.129.103.242`), который может отличаться от хоста управления Coolify. Ориентируйся на поле Server у приложения; `docker ps` и `docker logs --since 24h <container>` выполняй на сервере приложения, имя контейнера начинается с `d32u5zcq2g4odmdpq9hw91yn-`. Не делай вывод об отсутствии контейнера по проверке только хоста Coolify.
- После деплоя файл приложения `/app/data/bot.log` и его ротационные копии хранятся на persistent volume выше и переживают пересоздание контейнера. Пока logging-изменение не задеплоено, используй `docker logs` и API-журнал `api_call_logs` в SQLite. API-логи сохраняются в `/app/data/social_writer.sqlite3` на том же volume.
- Raw update log (все окружения, включая production): отдельная SQLite `/app/data/bot_updates.sqlite3`, таблица `raw_updates`; поиск по Telegram `update_id` (`SELECT payload FROM raw_updates WHERE update_id = ?`). Middleware подключается всегда — в проде это единственный способ увидеть события из групп администрирования и поддержки; записи старше 30 дней удаляются при запуске и записи новых событий. Секретные поля/токены маскируются. JSON включает приватный текст и metadata апдейта.
- Секреты хранятся в переменных окружения приложения Coolify; не сохраняются в репозитории.
- Админская группа «Писатель постов: Админка»: `chat_id = -1004459624166` (supergroup, forum). Топики: `4` — Статистика, `5` — Расходы, `6` — Рассылка, `7` — Ошибки. В production эти значения заданы env (`ADMIN_GROUP_ID`, `ANALYTICS_CHAT_ID`, `ANALYTICS_TOPIC_ID`, `TOPIC_STATS_ID`, `TOPIC_EXPENSES_ID`, `TOPIC_BROADCAST_ID`, `TOPIC_ERRORS_ID`); в коде оставлены дефолты для dev. Реализован только топик «Статистика» (`/stats`), остальные зарезервированы.
- Поддержка: `SUPPORT_GROUP_ID` — id группы операторов (`-1003957663233`, «Писатель постов: Поддержка», forum; production), `SUPPORT_NOTE_PREFIX` (по умолчанию `//`), `SUPPORT_GREETINGS` (пул приветствий, разделитель `|`), `SUPPORT_OPERATOR_SIGNATURE` (по умолчанию `Оператор поддержки`), `SUPPORT_TOPIC_EMOJI_ID` (опционально). Без `SUPPORT_GROUP_ID` поддержка выключена. **Требование к правам:** бот в этой группе должен быть админом с включённым «Manage Topics» (`can_manage_topics=true`) — иначе создание топика падает с `not enough rights to create a topic`, а пользователь видит «Поддержка временно недоступна». Проверка: `get_chat_member(SUPPORT_GROUP_ID, bot_id)`.
- `DEPLOY_ENV` включает dev-поведение только при точном значении `development`; production, пустое и неизвестное значение отключают его. `BOT_ENV` отдельно выбирает Telegram Bot API. `DEV_CHAT_ID` используется для уведомления о версии; версия в файле `VERSION` (сейчас `0.1.0+67`). Ротационный файл лога — `BOT_LOG_PATH` (по умолчанию `/app/data/bot.log`) на том же volume; сырые апдейты — `RAW_UPDATES_DB_PATH` (по умолчанию `/app/data/bot_updates.sqlite3`).
- Поддержка: `SUPPORT_GROUP_ID` — id группы операторов (`-1003957663233`, «Писатель постов: Поддержка», forum; production), `SUPPORT_NOTE_PREFIX` (по умолчанию `//`), `SUPPORT_GREETINGS` (пул приветствий, разделитель `|`), `SUPPORT_OPERATOR_SIGNATURE` (по умолчанию «Оператор поддержки»), `SUPPORT_TOPIC_EMOJI_ID` (опционально). Без `SUPPORT_GROUP_ID` поддержка выключена. **Требование к правам:** бот в этой группе должен быть админом с включённым «Manage Topics» (`can_manage_topics=true`) — иначе создание топика падает с `not enough rights to create a topic`, а пользователь видит «Поддержка временно недоступна». Проверка: `get_chat_member(SUPPORT_GROUP_ID, bot_id)`.
- `DEPLOY_ENV` включает dev-поведение только при точном значении `development`; production, пустое и неизвестное значение отключают его. `BOT_ENV` отдельно выбирает Telegram Bot API. `DEV_CHAT_ID` используется для уведомления о версии; версия в файле `VERSION` (сейчас `0.1.0+78`). Ротационный файл лога — `BOT_LOG_PATH` (по умолчанию `/app/data/bot.log`) на том же volume; сырые апдейты — `RAW_UPDATES_DB_PATH` (по умолчанию `/app/data/bot_updates.sqlite3`).
- Вики Gitea: страницы `Home`, `User-Guide`, `Developer-Guide`, `Subscription`, `Deployment`.
## Статус
@@ -82,7 +81,6 @@ Telegram-бот, который по запросу пользователя г
- [x] Классификатор намерений и Tone of Voice из скриншота
- [x] SQLite-настройки пользователей и reply-правки без хранения диалога
- [x] Development-развёртывание в Coolify: `social-post-writer-bot-development` (`d32u5zcq2g4odmdpq9hw91yn`)
- [x] Аналитика пользователей: отдельная SQLite, отчёт `/stats` с таблицами и периодами
- [x] Подключён persistent Coolify volume `/app/data` для SQLite
- [x] Проверены на моках STT, LLM, vision, ToV, reply-поля и изоляция пользователей
- [x] Выполнен live smoke test: классификатор вернул `write_post`, генератор — 3 разных варианта; vision распознал тестовый скриншот
@@ -107,8 +105,7 @@ Telegram-бот, который по запросу пользователя г
- [x] Исправлен баг: `_send_idea` была потеряна в коммите про подписку — `/idea` падал с `NameError`
- [x] Реальная оплата Stars: `sendInvoice` (XTR) → `pre_checkout_query` → `successful_payment`; подписка активируется только после оплаты, `telegram_payment_charge_id` защищает от двойного начисления
- [x] В `DEPLOY_ENV=development` после обычного сообщения об инвойсе отдельным сообщением доступна кнопка «🧪 Оплатил (dev)»; callback ограничен пользователем инвойса, а все dev-ветви fail-closed выключены вне development
- [x] Статистика активности по пользователям хранится в отдельной SQLite `/app/data/analytics.sqlite3`; `/stats` в админском топике показывает таблицы с колонками за сегодня, 7 дней, 30 дней и всё время. Генерация считает посты, идеи, правки и типы сообщений; обучение — только типы сообщений.
- Версия разработки: `0.1.0+67`
- Версия разработки: `0.1.0+64`
- [x] Статус долгой операции стримится живым драфтом `sendMessageDraft` в приватном чате и каждые 3–8 сек меняет случайную фразу из пула операции (`activity_phrases.py`); в группах и топиках работает прежний `edit_text`
- [x] Справка `/help` отправляется как Rich Message с обычной inline-клавиатурой; каждый callback `help:<section>` открывает раздел, кнопки доступны на всех страницах.
- [x] Проект Gitea «Social Post Writer Bot Roadmap» с задачами (выполненные — в «Готово», будущие — в Backlog)