
MAX в России постепенно превращается не просто в «ещё один мессенджер», а в канал, который всё чаще рассматривают как рабочую точку контакта с пользователем: для уведомлений, сервисных сообщений, внутренних ботов и групповых сценариев. И как только компания доходит до реальной интеграции, почти всегда начинается знакомая история: сначала один скрипт на отправку уведомлений, потом второй на обработку входящих сообщений, потом отдельная логика для групп, потом ещё пара «временных» костылей. Через месяц это уже не интеграция, а набор хрупких связок, которые страшно трогать.
Именно эту проблему и решает max.botservice: один сервис, который закрывает сразу несколько задач. Он принимает события из MAX, умеет работать как бот в личных сообщениях и группах, хранит контакты, отдает HTTP API для внешних систем и позволяет использовать MAX как полноценный канал уведомлений без необходимости плодить десяток вспомогательных утилит.
Исходный код:https://github.com/DmitryBoyko/max-bot/tree/main
Что это такое
Если коротко, max.botservice — это HTTP-сервис на Go, который стоит между API MAX и вашими внутренними системами.
С одной стороны, он принимает события от MAX: сообщения пользователей, действия в чатах, обновления по группам. С другой — отдает наружу собственные HTTP-эндпоинты, через которые ваши backend-сервисы, CRM, ERP, мониторинг или внутренние панели могут отправлять сообщения пользователям и в групповые чаты.
То есть это не просто «бот», который отвечает на команды. Это скорее инфраструктурный слой для интеграции с MAX: один процесс, один конфиг, одна точка входа.
Как это выглядит для пользователя
В личке бот работает как понятный сервисный интерфейс. Пользователь пишет ему и получает меню с кнопками: можно посмотреть ID чата, открыть список групп, настроить уведомления, привязать телефон или отвязать его.
Это важно в прикладных сценариях: если вы хотите слать уведомления не просто в абстрактный чат, а конкретному человеку из корпоративной или клиентской системы, привязка номера телефона дает нормальный мост между вашим учетом пользователей и аккаунтом в MAX.
В группах логика аккуратнее. Бот не шумит там, где он просто присутствует «для галочки». Он показывает меню и кнопку «ID этого чата» только в том случае, если у него есть права администратора. Такой подход особенно полезен для рабочих чатов, где лишние сервисные сообщения быстро начинают раздражать.
Как сервис получает события из MAX
Здесь поддерживаются оба базовых сценария, и это удобно, потому что у команд на разных стадиях внедрения обычно разные условия.
Первый вариант — webhook. MAX сам отправляет события на ваш внешний URL, например на POST /webhook. Это хороший продакшн-режим: события приходят сразу, без постоянного опроса. Но для него нужен доступный снаружи HTTPS-адрес, а значит, придется подумать о публикации сервиса и базовой защите входящей точки.
Второй вариант — long polling. Если WEBHOOK_URL в конфиге не задан, сервис сам ходит в MAX за обновлениями через GET /updates. Такой режим особенно хорош на старте проекта, в тестовой среде или там, где пока не хочется поднимать внешний HTTPS-контур. При этом сервис сам снимает старые webhook-подписки, чтобы не получить дубли событий.
Практически это означает простую вещь: один и тот же код можно использовать и для локальной разработки, и для полноценного продакшна. Меняется только конфигурация.
Где хранятся данные
Чтобы не усложнять внедрение, сервис использует SQLite. В базе лежат две основные сущности:
контакты — привязка номера телефона к пользователю MAX;
групповые чаты — идентификаторы, названия и служебные признаки вроде отметки, что приветственное меню уже отправлялось.
Для многих команд это сильный плюс: не нужно ради запуска поднимать отдельный PostgreSQL или тащить еще один инфраструктурный компонент. Достаточно каталога ./data, а в Docker — обычного volume.
Отдельно полезно, что список групп сервис обновляет сам: при старте и затем периодически по таймеру. Если бота добавили в новый чат, изменили его роль или выдали админские права, сервис это подхватит без ручного вмешательства. При этом приветствие и кнопка с ID отправляются один раз, без навязчивого повторения.
Что можно делать через внешнее API
Для интеграции с остальными системами сервис отдает обычный HTTP API, без экзотики и сложных SDK.
Основные сценарии такие:
POST /send-message— отправка сообщения в личный чат или по chat ID; при необходимости можно использовать режимprivate: true, чтобы искать получателя по контакту.POST /send-by-phone— отправка сообщения по номеру телефона; сервис находит пользователя в локальной таблице контактов и доставляет текст в MAX.POST /send-to-group-by-chatid— отправка сообщения в конкретную группу по еёchat_id.
Плюс есть служебные методы:
POST /refresh-group-chats— принудительно обновить кеш групп;GET /group-chats— получить список известных групп;GET /metrics— забрать простой JSON со счетчиками запросов, ошибок и срабатываний rate limit;GET /— редирект на страницу бота в MAX.
На практике это позволяет быстро подключить MAX к существующему ландшафту. Например, backend системы заказов может слать пользователю уведомление о статусе заявки, а система мониторинга — писать в рабочую группу о сбоях или инцидентах.
Безопасность без перегруза
У таких сервисов всегда есть риск впасть в две крайности: либо оставить всё «как есть» и получить дыру, либо обвесить интеграцию сложной защитой так, что поддерживать её станет тяжелее, чем сам бот. В max.botservice сделан разумный баланс.
Если задан WEBHOOK_SECRET, то POST /webhook ожидает заголовок X-Webhook-Secret. Если значение не совпадает, сервис возвращает 401. Это простой и рабочий способ отсечь лишние входящие запросы.
Если задан API_KEY, то административные методы вроде /refresh-group-chats и /group-chats принимают запросы только с заголовком X-API-Key. Это позволяет не выносить служебное API в отдельный контур, но и не оставлять его полностью открытым.
Для методов отправки сообщений предусмотрен rate limit: по умолчанию задан лимит запросов в минуту, который можно настроить или отключить. Если лимит превышен, сервис вернет 429. Это защита не только от злоумышленников, но и от обычных внутренних ошибок — например, когда сбойный скрипт начинает слать сообщения по кругу.
Весь этот набор включается переменными окружения, без переписывания приложения.
Развертывание
Запуск предельно прямолинейный. Нужен Go версии 1.251.25 и выше. Дальше:
Клонируете репозиторий.
Копируете
.env.exampleв.env.Заполняете минимум
BOT_TOKEN.Запускаете через
go run ./cmdили собираете Docker-образ.При необходимости поднимаете через
docker-compose.
Порт по умолчанию — 8080, но его можно изменить через PORT.
Логи можно переключить в JSON через LOG_FORMAT=json, а детализацию — через LOG_LEVEL. Внутри используется стандартный slog, так что стек остается легким и предсказуемым, без лишних зависимостей.
Почему это особенно актуально сейчас
На фоне курса на расширение использования MAX в России выигрывают решения, которые можно встроить быстро и без тяжелой инфраструктурной реформы. Бизнесу и внутренним IT-командам редко нужен «идеальный платформенный комбайн» на первом этапе. Обычно нужен понятный, поднимаемый за вечер сервис, который уже завтра сможет:
принимать входящие сообщения от пользователей;
отправлять уведомления из внутренних систем;
работать с групповыми чатами;
давать минимальную управляемость и наблюдаемость;
не требовать отдельной команды на сопровождение.
Именно в таком сценарии max.botservice выглядит особенно уместно. Он не пытается стать всем сразу. Он решает конкретную задачу: превращает MAX из просто мессенджера в рабочий транспорт для сервисных коммуникаций.
Кому это подойдет
В первую очередь — командам, которые уже смотрят в сторону MAX как канала взаимодействия с пользователями или сотрудниками и не хотят строить интеграцию из разрозненных кусков.
Это хороший вариант, если вам нужен:
бот с внятным пользовательским меню;
канал уведомлений из backend-сервисов;
отправка сообщений в личные и групповые чаты;
простое локальное хранение контактов и чатов;
минимальный порог входа для запуска и сопровождения.
Итог здесь довольно практичный: один бинарник, одна база, один конфиг и предсказуемое поведение в работе. А это в интеграционных историях обычно ценится куда выше, чем «гибкость на будущее», которая потом превращается в бесконечный зоопарк скриптов.
