docs: сводка профиля в карточке обращения поддержки

hermes committed 2026-10-11 15:33:31 +02:00
1 parent c6d91a1dce
commit 70275a3e16
2 files changed
+26 -2

No files matched your search

+3 -1
@@ -113,6 +113,7 @@ update_tone_from_image → _handle_image_message
| `deactivate_subscription` | `is_active = 0` |
| `is_subscribed` | Запись есть, `is_active = 1`, срок не истёк |
| `subscription_row` | Строка подписки |
| `support_profile_summary` | Сводка для карточки поддержки: дни использования, продления, остаток, обученность |
| `is_user_trained` | Флаг `users.is_trained` — гейт «Придумать пост» |
| `add_training_notes` / `get_training_notes` | Текстовые сведения об аккаунте |
| `add_post_samples` / `get_post_samples` | Образцы постов со скриншотов |
@@ -151,6 +152,7 @@ update_tone_from_image → _handle_image_message
| `generated_ideas` | История идей (для исключения повторов) |
| `api_call_logs` | JSON-логи вызовов APInex + ошибки (30 дней) |
| `support_topics` | `telegram_user_id` → `thread_id` топика поддержки, `is_active` |
| `payments` | Платежи Stars; `COUNT(*)` по пользователю — число продлений подписки |
| `subscriptions` | Подписки и триалы |
| `payments` | `telegram_payment_charge_id` — защита от двойного начисления |
@@ -187,7 +189,7 @@ update_tone_from_image → _handle_image_message
| `set_active` / `is_support_active` | Флаг открытого обращения |
| `get_user_by_thread` | Обратный поиск пользователя по `thread_id` |
| `topic_title` | «Имя · @username» (без username — «Имя · id»), лимит 128 |
| `send_profile_card` | Аватарка (`get_user_profile_photos`) как первое сообщение топика |
| `send_profile_card` | Аватарка (`get_user_profile_photos`) + сводка профиля как первое сообщение топика (один раз) |
| `ensure_topic` | Создаёт топик при первом обращении, переиспользует существующий |
| `relay_user_message` | `copy_message` в топик; при «thread not found» пересоздаёт топик |
| `handle_support_group_message` | Доставляет ответ оператора пользователю, пропуская заметки |
+23 -1
@@ -40,8 +40,30 @@
- **Название топика** — «Имя · @username». Если username нет — «Имя · id».
- **Аватарка**: Telegram Bot API не умеет ставить на топик произвольную картинку, только custom emoji.
Поэтому аватарка профиля уходит **первым сообщением-карточкой** в топик: фото + имя, `@username`,
`user_id` и подсказка про префикс заметки. Custom emoji на самом топике — опционально,
`user_id`, сводка профиля и подсказка про префикс заметки. Custom emoji на самом топике — опционально,
через `SUPPORT_TOPIC_EMOJI_ID`.
- **Топик создаётся сразу при первом нажатии «🆘 Поддержка»**, а не при первом сообщении.
Карточка уходит **один раз** — при создании топика. Повторные обращения пишут в тот же топик
и ничего не дублируют; если топик удалили вручную, при следующем сообщении он создаётся заново
и сводка уйдёт снова.
---
## Данные профиля в карточке
Собирает `user_store.support_profile_summary()`:
| Поле | Источник |
|---|---|
| ID пользователя | `users.telegram_user_id` |
| Пользуется ботом | полных дней с `users.created_at`; если записи нет — с `subscriptions.trial_started_at` |
| Продлений подписки | `COUNT(*)` по `payments` пользователя |
| Осталось дней | `user_store._days_until` по строке подписки; при истёкшем или отсутствующем периоде — «нет активного периода» |
| Бот обучен | флаг `users.is_trained` — «да» / «нет» |
Сводка считается в отдельном потоке и не роняет обращение: при любой ошибке карточка уходит
без блока полей, топик всё равно создаётся. Таблица `payments` может отсутствовать — тогда
число продлений считается как 0.
- **Все типы контента**: текст, фото, документы, голосовые — пересылаются как есть (`copy_message`),
без пометки «forwarded from».
- **Завершение** снимает флаг `is_active`; топик **не удаляется и не закрывается** — оператор