Поддержка/тикеты
В проекте есть два канала поддержки:
- внешняя ссылка
SUPPORT_LINK, которая ведет пользователя в Telegram-чат, канал, форму или любой другой публичный URL; - встроенные тикеты Web App / Mini App, если включен
SUPPORT_TICKETS_ENABLED.
Внешняя ссылка остается простым резервным каналом. Тикеты дают полноценный диалог внутри личного кабинета: пользователь создает обращение, видит историю ответов, получает счетчик непрочитанных сообщений, а администратор отвечает из админ-панели.
Пользовательский сценарий
Заголовок раздела «Пользовательский сценарий»Раздел Поддержка появляется в Web App, когда SUPPORT_TICKETS_ENABLED=True. Пользователь может:
- создать тикет с темой, категорией, приоритетом, текстом и/или изображением;
- выбрать категорию
billing,technical,accountилиother; - выбрать приоритет
normalилиhigh; - открыть список своих тикетов с фильтром по активным и всем обращениям;
- отвечать в открытом тикете текстом и/или изображением и видеть ответы поддержки;
- перейти по
SUPPORT_LINK, если нужна внешняя поддержка.
Заблокированные пользователи не могут создавать тикеты и отвечать в них. Для пользователей показываются только обычные сообщения: внутренние заметки администраторов скрыты.
Сообщение пишется в том же визуальном редакторе, что и рассылки: жирный, курсив, подчёркнутый, зачёркнутый, моноширинный, блок кода, цитата и ссылка. Пользователю доступно только форматирование - без исходного HTML, шорткодов и кнопок. Ссылки, набранные обычным текстом, становятся кликабельными и в редакторе, и в чате, включая сообщения, написанные до появления редактора. Счётчик длины и лимит SUPPORT_TICKET_MAX_BODY_LENGTH считают видимый текст, а не разметку вокруг него.
Админский сценарий
Заголовок раздела «Админский сценарий»В админ-панели тикеты доступны в разделе Коммуникации -> Поддержка. Доступ проверяется так же, как и для остальных /api/admin/*: нужна Web App-сессия пользователя, чей Telegram ID указан в ADMIN_IDS.
Администратор может:
- видеть сводку по открытым, ожидающим ответа, закрытым и непрочитанным тикетам;
- фильтровать обращения по статусу, приоритету, категории и назначенному администратору;
- искать по теме, username, имени и email пользователя;
- сортировать по обновлению, созданию или важности;
- отвечать пользователю, менять статус, категорию, приоритет и исполнителя;
- оставлять внутренние заметки, которые видны только администраторам;
- открыть карточку пользователя и видеть контекст подписки: тариф, статус, остаток времени, обычный и premium-трафик.
Ответ пишется в том же редакторе, что и рассылка, и дополнительно даёт:
- переключатель исходного HTML;
- шорткоды персонализации - те же, что в рассылках. Они подставляются один раз, в момент отправки, и в тикете хранится уже готовый текст, поэтому админ и пользователь видят одно и то же сообщение;
- меню Вставить с быстрыми ссылками для этого пользователя:
{config_link}(ссылка на подписку для импорта в приложение),{miniapp_link}(личный кабинет в Mini App) и{install_link}(персональная инструкция по установке); - до четырёх кнопок под сообщением - ссылка, промокод в боте, промокод в Mini App или экран Mini App. Кнопки показываются в чате и добавляются в Telegram-уведомление об ответе. Внутренняя заметка кнопок не несёт: она не доходит до пользователя.
- вложение одного изображения, выбранного через диалог или перетащенного из проводника. Изображения доступны и во внутренних заметках, но никогда не показываются пользователю вместе с ними.
Сообщения хранятся в подмножестве HTML, которое понимает Telegram (b i u s code a pre blockquote); всё остальное при сохранении превращается в обычный текст, а ссылки допускают только схемы http, https, tg и mailto.
Статусы тикета: open, awaiting_user, awaiting_admin, resolved, closed. При создании тикет сразу получает статус awaiting_admin; ответ пользователя переводит незакрытый тикет в awaiting_admin, ответ администратора - в awaiting_user. Закрытые статусы считаются resolved и closed.
Уведомления
Заголовок раздела «Уведомления»Новые тикеты и ответы пользователя могут отправляться в Telegram-уведомления администраторам и в лог-чат. Для отдельного топика поддержки используйте LOG_SUPPORT_THREAD_ID; если он пустой, сообщения идут в общий LOG_THREAD_ID/чат по настройкам логирования.
Повторные уведомления по одному непрочитанному тикету ограничиваются cooldown-настройками, чтобы не заспамить админов:
SUPPORT_ADMIN_NOTIFICATION_COOLDOWN_SECONDS- пауза для Telegram/log уведомлений;SUPPORT_ADMIN_EMAIL_COOLDOWN_SECONDS- пауза для email-уведомлений.
Telegram-уведомления администраторам и в лог-чат по умолчанию включены и управляются через SUPPORT_ADMIN_TELEGRAM_NOTIFICATIONS_ENABLED. Email-уведомления по умолчанию выключены и включаются через SUPPORT_ADMIN_EMAIL_NOTIFICATIONS_ENABLED=True. Письма отправляются только администраторам из ADMIN_IDS, у которых в базе есть email. Для отправки нужен рабочий SMTP-конфиг из раздела «Способы входа».
Ответ администратора и закрытие тикета дополнительно отправляются пользователю в Telegram, если у него есть Telegram-аккаунт, и на email, если он привязан.
Изображение отправляется отдельным фото в Telegram и встраивается в HTML-письмо. Текст остаётся отдельным сообщением, поэтому сохраняются полный лимит Telegram на текст и кнопки под ним. Сообщение может состоять только из изображения.
Настройки
Заголовок раздела «Настройки»| Переменная | Назначение |
|---|---|
SUPPORT_LINK |
Внешняя HTTP(S)-ссылка поддержки. Для Telegram можно указать @username, t.me/username или полную https://t.me/username; сокращённые варианты автоматически приводятся к полной HTTPS-ссылке. Показывается в боте и Web App как быстрый способ связаться с командой. |
SUPPORT_TICKETS_ENABLED |
Включает раздел тикетов в Mini App и разрешает создание обращений. |
SUPPORT_TICKET_MAX_BODY_LENGTH |
Максимальная длина сообщения тикета. |
SUPPORT_TICKET_MAX_SUBJECT_LENGTH |
Максимальная длина темы тикета. |
SUPPORT_TICKET_RATE_LIMIT_PER_HOUR |
Сколько новых тикетов пользователь может создать за час; 0 отключает лимит. |
SUPPORT_MESSAGE_RATE_LIMIT_PER_MINUTE |
Сколько сообщений в тикетах пользователь может отправить за минуту; 0 отключает лимит. По умолчанию 10. |
SUPPORT_IMAGE_RATE_LIMIT_PER_DAY |
Сколько изображений в тикетах пользователь может отправить за сутки; 0 отключает лимит. По умолчанию 20. |
LOG_SUPPORT |
Включает Telegram/log уведомления по тикетам поддержки. |
LOG_SUPPORT_THREAD_ID |
Необязательный ID топика в лог-чате для сообщений поддержки. |
SUPPORT_ADMIN_TELEGRAM_NOTIFICATIONS_ENABLED |
Включает Telegram/log уведомления администраторам о новых тикетах и ответах пользователей. По умолчанию true. |
SUPPORT_ADMIN_EMAIL_NOTIFICATIONS_ENABLED |
Включает email-уведомления администраторам о новых тикетах и ответах пользователей. |
SUPPORT_ADMIN_NOTIFICATION_COOLDOWN_SECONDS |
Минимальная пауза между повторными Telegram/log уведомлениями по одному непрочитанному тикету. |
SUPPORT_ADMIN_EMAIL_COOLDOWN_SECONDS |
Минимальная пауза между повторными email-уведомлениями по одному непрочитанному тикету. |
Все эти параметры описаны в env-vars.md. Основной рекомендуемый способ менять их - админка Система -> Настройки -> Поддержка; значения применяются как override поверх .env.
API и хранение
Заголовок раздела «API и хранение»Пользовательские маршруты:
GET /api/support/tickets- список тикетов пользователя;POST /api/support/tickets- создать тикет;GET /api/support/tickets/{id}- открыть тикет;POST /api/support/tickets/{id}/messages- отправить ответ;GET /api/support/images/{image_id}- получить изображение из доступного пользователю невнутреннего сообщения;POST /api/support/tickets/{id}/read- отметить сообщения прочитанными;GET /api/support/unread- счетчик непрочитанных ответов поддержки.
Админские маршруты находятся под /api/admin/support/*: список, карточка тикета, ответ, изменение статуса/приоритета/категории/исполнителя, отметка прочитанного и статистика.
Данные хранятся в таблицах support_tickets, support_ticket_messages и message_images; миграция применяется автоматически сервисом migrate при docker compose up -d --build.
Принимается одно изображение JPEG, PNG или WebP до 8 МБ и 16 мегапикселей. Сервер не доверяет имени файла и MIME-типу: файл полностью декодируется Pillow, анимация и повреждённые/неподдерживаемые форматы отклоняются, EXIF и другие метаданные удаляются, разрешение ограничивается 2560 px, после чего создаётся новая статичная WebP-копия. На диске копии лежат в data/message-images по SHA-256 и физически дедуплицируются; в БД каждое вложение получает отдельный случайный ID. Пользовательский маршрут проверяет принадлежность изображения тикету и скрывает вложения внутренних заметок. Ответы запрещают MIME-sniffing и публичное кеширование.
У сообщения есть body_format (text или html) и buttons - готовые кнопки в виде JSON. Сообщения, написанные до появления редактора, остаются text и читаются буквально: разметка в них не «оживает» задним числом.