Skip to main content
От оператора требуется одно: группа в Telegram. Бот сам создаёт и привязывает каждый топик внутри неё, поддерживает привязку и заново создаёт удалённый топик. Поток сознательно сделан сигналом, а не хранилищем данных. Уведомление называет событие, класс суммы и идентификаторы, которые оператор может посмотреть через административный API, — и никогда текст клиента, ссылку на подписку, токен или полезную нагрузку платежа. Группа в Telegram — это место, откуда сообщения пересылают, откуда снимают скриншоты и где их хранят годами, поэтому вопрос при проектировании звучал не «что было бы здесь удобно», а «что безопасно оставить в чате навсегда».

Настройка

1

Создайте группу

Создайте группу в Telegram и включите в её настройках Топики. Топики — возможность супергруппы; обычная группа их не поддерживает.
2

Добавьте бота

Добавьте бота и выдайте ему права Управление топиками и Отправка сообщений.
3

Укажите боту группу

Идентификатор супергруппы отрицателен и начинается с -100. Обычный способ его узнать — переслать сообщение из группы боту вроде @userinfobot.
4

Перезапустите бота

При старте нотификатор привязывает все топики, а затем разбирает очередь каждые десять секунд. Стартовый лог говорит, что из двух произошло: operator notifications are disabled because no group is configured — или ничего вообще, если привязка удалась.
Доставляет уведомления только процесс bot. Процессы api и worker пишут их в очередь, поэтому установка без запущенного бота всё равно накапливает запись о происходившем — ей просто некому об этом сообщить.

Топики

Последние два несут то, чего остальные намеренно не несут, — готовое тело сообщения. Всё прочее здесь — набор разрешённых обезличенных полей, а предпросмотр по определению является самим текстом. Оба явно сообщают, что больше их никто не получил: предпросмотр, принятый за настоящую отправку, — это чья-то рука на кнопке паузы. См. Кампании и Тексты сообщений. Топик инцидентов сегодня несёт платёжные аномалии и ничего больше. Каждое уведомление называет заказ, провайдера, операцию, классификацию, валюту и сумму, а также состояние заказа на тот момент и дедуплицируется по платёжному намерению и классификации — повторно присланный вебхук ничего не добавляет. Что означает каждая классификация и как она разрешается, описано в Заказах и платежах. Режим обслуживания определяется в процессе api, у которого нет клиента Telegram, поэтому api записывает каждый переход в ту же очередь operator_notifications, которую разбирает бот; один переход — одно сообщение, с дедупликацией по направлению и минуте. Результаты резервного копирования и восстановления так же ставит в очередь процесс, который их выполнил, с ключом по копии и результату, поэтому повторённая задача сообщает один раз. Записью остаётся таблица backups: уведомление, которое не удалось поставить в очередь, попадает в лог и никогда не валит само копирование. См. Режим обслуживания и Резервные копии и восстановление.
Оценщик аномалий пишет уведомления под девятым видом, anomaly, который база данных принимает, но для которого у бота нет именованного топика. Эти уведомления до группы не доходят. Разбирайте аномалии на /admin/risk — см. Контроль рисков.

Конфигурация

Все три читаются один раз при старте. Раздел operator_group на /admin/settings/integrations хранит те же четыре числа и ничего не меняет — см. Настройки установки.

Когда привязка не удаётся

Топик, который не удалось создать, записывается в operator_topics со статусом failed и классифицированной причиной, а не молча остаётся без действия. Исходное сообщение Telegram отбрасывается, потому что оно может отражать содержимое запроса. Устраните причину и перезапустите бота или дождитесь следующего уведомления этого вида: доставка перед отправкой заново пытается выполнить привязку. Изменение APP_OPERATOR_CHAT_ID перепривязывает всё. У строк, чей сохранённый чат больше не совпадает, идентификатор топика очищается, а статус сбрасывается в pending, поэтому в новой группе создаются свежие топики, а не отправляются сообщения в группу, которую вы покинули. Топик, удалённый в Telegram, заново создаётся при следующем сообщении в него, один раз, после чего сообщение повторяется.

Доставка

Нотификатор разбирает до 50 ожидающих уведомлений каждые десять секунд в порядке создания, в одной транзакции с FOR UPDATE SKIP LOCKED, поэтому два бота не могут доставить одну и ту же строку. Каждое уведомление заканчивается ровно в одном терминальном состоянии: Уведомление в статусе failed не повторяется. Строка и её полезная нагрузка остаются в базе данных, поэтому запись о событии сохраняется даже тогда, когда сообщение не дошло, но лекарство от устойчивого сбоя — исправить группу и пропустить следующее событие, а не ждать повторного проигрывания.

Контроль объёма

Перед каждой отправкой нотификатор считает, сколько уведомлений этого вида было отправлено внутри окна. На лимите или выше уведомление завершается как suppressed с причиной volume_cap, и в лог пишется предупреждение с видом и числом подавленных за этот проход. Лимит действует на каждый вид отдельно, поэтому сбой Remnawave, порождающий тысячи неудач выдачи доступа, не может похоронить поток покупок, а подавленные уведомления сами в лимит не засчитываются. Ничего не теряется: строки остаются в базе данных вместе со своими полезными нагрузками. Установите лимит в 0, чтобы отправлялось всё.
Группа, настроенная впервые после долгой работы, разбирает накопленную очередь. Очередь хранит каждое уведомление, записанное, пока группы не было, а разбор ограничен 50 штуками каждые десять секунд, и поверх этого действует лимит объёма, — поэтому бо́льшая часть крупного накопления будет доставлена как suppressed, а не как сообщения. Это ожидаемый исход; читайте историю в панели, а не рассчитывайте увидеть её в чате.

Дедупликация

Каждое уведомление несёт ключ дедупликации: заказ — для покупки, возврат — для возврата, операция выдачи доступа — для сбоя, событие и аккаунт — для уведомления о безопасности. Пара operator_notifications (kind, dedupe_key) уникальна, а вставка выполняется как ON CONFLICT DO NOTHING, поэтому повторённый вебхук, второй проход сверки и раз за разом падающее задание дают одно сообщение. Уведомление ставится в очередь в той же транзакции, что и событие, которое оно описывает. Поэтому уведомление существует ровно тогда, когда то, о чём оно сообщает, зафиксировано, — никогда для откаченного события и никогда не отсутствует для зафиксированного. Сбой постановки в очередь логируется и никогда не роняет вызвавшую его транзакцию, потому что состоявшийся платёж не должен отменяться сообщением в чат.

Что содержит уведомление

Рендерер печатает имя топика, затем только поля из фиксированного списка разрешённых, затем отметку времени. Всё прочее, что случайно оказалось в полезной нагрузке, отбрасывается, а не фильтруется, поэтому поле, добавленное в полезную нагрузку в будущем, не может утечь по недосмотру:
Поэтому уведомление о покупке выглядит так:
Здесь нет ни имени клиента, ни аккаунта Telegram, ни ссылки на подписку, ни токена провайдера, ни полезной нагрузки платежа. Идентификаторы включены именно потому, что сами по себе они бесполезны: оператор смотрит их через панель или административный API, где действуют авторизация и аудит. Уведомление о безопасности называет событие, аккаунт оператора и метод, и больше ничего. Адрес оператора, токен сессии и IP клиента остаются вне группового чата; эти детали живут в журнале аудита, за правами доступа, которые им управляют. См. Панель администратора.

Уведомления о сбоях выдачи доступа

Падающий прогон выдачи доступа не уведомляет сразу. Ожидается, что обычная экспоненциальная пауза позволит восстановиться, поэтому оператору сообщают только после трёх неудачных попыток или сразу при постоянной ошибке. Ключом дедупликации служит операция, поэтому одно проблемное право на услугу порождает одно сообщение, сколько бы раз оно ни повторялось. Уведомление несёт право на услугу, операцию, текущий статус и классифицированный код ошибки вроде remnawave_http_502 или remnawave_unavailable. Тело ответа панели оно не несёт никогда. В тот же топик попадают два родственных случая:
  • Доставка цифрового товара, которую провайдер не смог завершить.
  • Дополнение, оплаченное при отсутствии действующего права на услугу, — заказ сохраняет статус оплаченного, поэтому деньги никогда не теряются молча, а уведомление вместе с событием аудита addon.no_active_entitlement говорит оператору ровно то, что нужно вернуть или применить заново.

Связанные страницы

Telegram

BotFather, вебхук против длинного опроса и группа операторов.

Диагностика неисправностей

Что проверить, когда группа замолчала.