diff --git a/Developer-Guide.md b/Developer-Guide.md index d3ee62a..4faec4f 100644 --- a/Developer-Guide.md +++ b/Developer-Guide.md @@ -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` | Доставляет ответ оператора пользователю, пропуская заметки | diff --git a/Support.md b/Support.md index 01e9392..252f5e4 100644 --- a/Support.md +++ b/Support.md @@ -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`; топик **не удаляется и не закрывается** — оператор