- Дата публикации
Как за вечер собрать бота обратной связи для Max.ru на Node.js: MVP без серверов и DevOps
Что появилось / что изменилось
Max запустил публичный Bot API и официальную JS-библиотеку @maxhub/max-bot-api. Для разработчиков это значит:
- Можно писать ботов на Node.js без собственного сервера и белого IP.
- Long Polling «из коробки» — бот сам опрашивает сервера Max, Webhook не обязателен.
- Для MVP хватает локального запуска:
npm start, без ngrok и Cloudflare Tunnel. - В качестве базы данных используется один файл SQLite (
database.sqlite) без отдельного процесса БД. - Реализован рабочий MVP бота обратной связи «клиент → админ → клиент» через Reply.
- Вся логика укладывается в связку: Node.js +
@maxhub/max-bot-api+sqlite/sqlite3+dotenv.
Цифры и артефакты из кода:
- Одна таблица
reply_mapдержит маппингowner_msg_mid -> client_user_id. - OWNER_ID (ID администратора) задаётся в
.envи берётся из логов первого запуска. - Токен бота берётся из интерфейса интеграций на
business.max.ru.
Как это работает
MVP решает одну задачу: превращает кнопку MAX на сайте в канал обратной связи. Клиент пишет в Max — администратор получает сообщение, отвечает Reply — бот отправляет ответ клиенту.
Технический скелет выглядит так:
-
Подключение к Max
Библиотека@maxhub/max-bot-apiподнимает long polling. Бот подписывается на событиеmessage_createdи получает все новые сообщения. -
ENV-конфиг
В.envдва ключа:BOT_TOKEN=ваш_токен_здесь OWNER_ID=12345678BOT_TOKEN— токен бота из Max Business.OWNER_ID— личный ID админа, который бот использует как «центральный инбокс». -
SQLite как хранилище связок
Подключение через:import { open } from 'sqlite'; import sqlite3 from 'sqlite3';Инициализация:
CREATE TABLE IF NOT EXISTS reply_map ( owner_msg_mid TEXT PRIMARY KEY, client_user_id INTEGER );Таблица хранит, какое сообщение у админа (
owner_msg_mid) относится к какому пользователю (client_user_id). -
Входящий поток: клиент → админ
В обработчикеbot.on('message_created', ...)бот:- читает
sender.user_idиbody.text; - если
senderId !== OWNER_ID, значит пишет клиент; - формирует текст для админа с именем и ID клиента;
- отправляет через
bot.api.sendMessageToUser(ownerId, text, { format: 'markdown' }); - берёт из ответа
sentMsg.body.midи сохраняет вreply_mapсвязкуmid → client_user_id.
- читает
-
Исходящий поток: админ → клиент
Когда пишет админ (senderId === OWNER_ID), бот анализирует полеlinkу сообщения:"link": { "type": "reply", "message": { "mid": "mid.исходного_сообщения..." } }- Если
link.type === 'reply', бот достаётmsg.link.message.mid. - Ищет в SQLite:
SELECT client_user_id FROM reply_map WHERE owner_msg_mid = ?. - Если запись найдена — отправляет ответ клиенту через
sendMessageToUserи подтверждает администратору:✅ Ответ отправлен пользователю ID: .... - Если записи нет — сообщает админу, что связка не найдена.
- Если
-
Fallback-сценарий
В заготовке логики предусмотрено поведение «по умолчанию»: если админ пишет не Reply, можно направить сообщение «последнему активному клиенту». В MVP это только набросок, но паттерн понятен: хранить очередность обращений и брать последнийclient_user_id.
Что это значит для вас
Если вы запускаете новый продукт, сервис или онлайн-магазин и уже тестируете Max как мессенджер для клиентов, этот MVP закрывает базовые потребности:
- собрать простой канал поддержки без сторонних SaaS-платформ;
- перенаправлять все входящие сообщения в Max одному администратору;
- отвечать клиентам привычным жестом Reply, без команд и кнопок;
- быстро проверить гипотезу: клиенты вообще будут писать в Max или нет.
Где MVP заходит хорошо:
- лендинги и промо-сайты, где нужна одна кнопка обратной связи MAX;
- маленькие команды и solo-проекты, которым не нужен отдельный backend-разработчик;
- быстрые пилоты и хакатоны:
node, один файл SQLite, один обработчик событий.
Где такой бот уже начинает упираться в ограничения:
- мультилайн-поддержка, когда вам нужно несколько операторов и маршрутизация по отделам;
- аналитика, SLA, очереди, статусы диалогов — этого в MVP нет, придётся дописывать;
- высокая нагрузка с параллельной записью в БД: SQLite подойдёт на старте, но при росте трафика придётся переезжать на PostgreSQL.
Юридические и инфраструктурные нюансы: бот завязан на экосистему Max.ru и бизнес-аккаунт business.max.ru. Для продакшн-развёртывания всё равно понадобится сервер с HTTPS и Webhook, но для разработки, теста и демо Long Polling на локалке экономит время.
Итоговая картинка для разработчика: вы за пару часов собираете работающий MVP без DevOps, а дальше можете нарастить сложную логику вокруг уже проверенного паттерна reply_map и простого event-лупа.
Место на рынке
В Telegram задачу обратной связи давно закрывают сервисы вроде Olgram. В экосистеме Max похожие решения пока только появляются, и описанный подход фактически выступает аналогом этого класса ботов, но на вашем собственном коде.
Ключевые отличия от привычного стекa в Telegram:
- Вместо webhook-ориентированного API Max даёт удобный Long Polling прямо из официальной библиотеки.
- Старт на локальной машине проще: не нужно поднимать HTTPS-туннели, VPN или временные домены.
- Вся бизнес-логика у вас в репозитории, без зависимости от внешней платформы-конструктора.
По сравнению с крупными SaaS-платформами для клиентской поддержки у этого подхода своя ниша:
- Меньше функции из коробки, но больше контроля над логикой.
- Ни подписок, ни тарифа за «оператора»: вы платите только за свою инфраструктуру, если уйдёте с локалки.
Для тех, кто уже строил ботов под Telegram или VK, порог входа в Max Bot API будет низким: события, sendMessageToUser, разбор JSON и reply-механика работают знакомым образом. Главное отличие — ставка на официальный JS-SDK и упор на простую, локально запускаемую разработку для быстрых MVP.