Добавить в корзинуПозвонить
Найти в Дзене

Как подключить бота MAX через Google Apps Script: подробное техническое руководство

Интеграция бота MAX с Google Apps Script — хороший вариант, когда нужен быстрый backend без отдельного сервера. Такой стек подходит для заявок, поддержки, FAQ, внутренних сервисов, уведомлений и простых workflow-сценариев. MAX предоставляет API для проверки бота, отправки сообщений и получения событий через webhook, а Google Apps Script удобно использовать как обработчик webhook, хранилище логики и связку с Google Таблицами и почтой. Рабочая схема выглядит так: MAX → webhook → Google Apps Script → Google Sheets / Mail / внешняя логика → ответ обратно в MAX MAX отправляет события на HTTPS webhook через POST /subscriptions, а Apps Script принимает их в doPost(e). Для production MAX рекомендует именно webhook, а не long polling. Для базового проекта обычно достаточно трёх методов. GET /me — проверка токена и получение информации о боте. Это правильный способ быстро понять, что токен действителен и бот отвечает. Токен передаётся в заголовке Authorization, а не через query-параметры. POST /
Оглавление

Практическое техническое руководство с учётом реальных проблем внедрения

Эта статья описывает не только базовую схему подключения MAX-бота к Google Apps Script, но и практические нюансы, которые проявляются уже после первого рабочего запуска: старые webhook-подписки, старые deployment-версии, дубли ответов, хранение настроек, переход от текстового меню к кнопкам и организация устойчивой логики бота. Текст написан техническим языком, но с расчётом на читателя без глубокого backend-опыта.

1. Что мы собираем

Рабочая схема проекта выглядит так:

MAX → Webhook → Google Apps Script → Google Sheets / Mail → ответ обратно в MAX

MAX отправляет события на HTTPS endpoint, опубликованный как Web App в Google Apps Script. Скрипт принимает эти события, определяет пользователя и контекст диалога, сохраняет состояние, пишет данные в таблицу, при необходимости отправляет уведомления и возвращает ответ в MAX.

2. Какие методы API MAX используются в реальном проекте

Базовая рабочая интеграция обычно опирается на несколько методов API.

· GET /me — проверка токена и получение информации о боте.

· POST /messages — отправка сообщения пользователю или в чат.

· POST /subscriptions — создание webhook-подписки.

· GET /subscriptions — просмотр существующих подписок.

· DELETE /subscriptions/{id} — удаление старых подписок, если они остались активными.

· POST /answers — ответ на callback, если используются callback-кнопки.

В боевом сценарии webhook предпочтительнее long polling. Для production-среды это самый устойчивый вариант, потому что бот не должен постоянно опрашивать API и зависеть от цикла фоновых запросов.

3. Почему Google Apps Script подходит для такого проекта

· Не требуется отдельный сервер или VPS.

· Есть нативный доступ к Google Sheets.

· Есть встроенная отправка почты через MailApp.

· Есть time-based triggers для периодических задач.

· Есть Web App deployment, который можно использовать как webhook endpoint.

Для небольших и средних проектов этого достаточно. Если логика не требует высокой параллельности, тяжёлых очередей, сложной аутентификации и собственной БД, Apps Script позволяет очень быстро собрать рабочую систему.

4. Ключевая архитектурная ошибка, которая встречается чаще всего

На практике самая частая проблема возникает не в самом коде API-вызовов, а в дублировании источников конфигурации.

· Токен хранится и в коде, и в свойствах проекта.

· WEB_APP_URL хранится и в константах, и в свойствах, и в таблице.

· После нового развертывания меняется только часть настроек.

· Бот начинает работать непредсказуемо, потому что непонятно, какой URL фактически используется.

Правильный подход: один источник правды. В рабочем варианте это Script Properties. Код должен только читать значения из свойств проекта, а не дублировать их в нескольких местах.

Что хранить в Script Properties

· MAX_BOT_TOKEN

· WEB_APP_URL

· MAX_WEBHOOK_SECRET

· Адрес для уведомлений

· BOT_NAME

5. Структура данных в Google Sheets

Минимальный проект удобно строить на нескольких листах.

Лист «Заявки»

· № заявки

· Дата и время

· MAX user_id

· MAX chat_id

· Раздел

· Тип обращения

· ФИО заявителя

· Логин

· Текст вопроса / описание

· Статус

· Ответственный

· Комментарий

· Дата закрытия

· Уведомление отправлено

· Ответ в MAX отправлен

Лист «Пользователи»

· MAX user_id

· MAX chat_id

· Текущий шаг

· Черновик JSON

· Дата последнего сообщения

Лист «Логи»

· Дата и время

· Тип

· Сообщение

· JSON

Лист «Пароли»

Если бот умеет искать логины и выдавать автоматически сформированные пароли, нужен отдельный лист «Пароли» с колонками:

· Логин

· Пароль

· ФИО

· Комментарий

· Дата обновления

Важно: настройка проекта не должна затирать лист «Пароли». Это одна из практических проблем. Если функция инициализации каждый раз очищает все листы, вы теряете рабочую базу данных.

6. Как MAX присылает входящее событие

Одна из самых важных вещей — правильно понять структуру входящего update.

В личном диалоге:

· recipient — это бот.

· sender — это пользователь.

· recipient.chat_id — это диалог.

· recipient.user_id — это user_id самого бота.

· sender.user_id — это user_id человека.

Из-за этого очень легко допустить критическую ошибку: взять recipient.user_id как пользователя. Тогда бот будет пытаться отвечать не человеку, а самому себе или в невалидный контекст, что приводит к ошибкам вида chat.denied и Invalid chatId: 0.

Правильное правило

· userId берётся из sender.user_id;

· chatId берётся из recipient.chat_id;

· chatType берётся из recipient.chat_type.

7. Как правильно отправлять сообщение

Для отправки сообщения бот должен вызывать POST /messages.

Практическое правило:

· если это личный диалог и известен user_id — отправлять по user_id;

· если это групповой чат — отправлять по chat_id.

Текст сообщения, форматирование и клавиатура передаются в JSON body. Токен передаётся только в заголовке Authorization.

8. Главное практическое наблюдение: проблема часто не в коде, а в deployment и подписках

Во время внедрения чаще всего ломается не сам код, а инфраструктура вокруг него.

· В редакторе уже новый код, но Web App deployment всё ещё старый.

· Webhook подписан на старый URL.

· Остались две активные подписки, и событие приходит одновременно в два обработчика.

· После нескольких экспериментов начинают приходить задвоенные ответы.

Если один и тот же /start вызывает два разных сценария, это почти всегда значит, что одновременно работают две подписки или две активные версии развертывания.

Надёжная процедура обновления

1. Изменить код.

2. Сохранить проект.

3. Обновить Web App новой версией.

4. Проверить актуальный URL развертывания.

5. Обновить WEB_APP_URL в Script Properties.

6. Удалить старые webhook-подписки.

7. Создать одну новую подписку на актуальный URL.

9. Почему нужен лог-лист

Без системного логирования такой проект превращается в угадайку.

Минимум, который нужно логировать:

· входящий update целиком;

· разобранные user_id / chat_id / chat_type;

· URL исходящего запроса в MAX;

· payload исходящего сообщения;

· ответ MAX API;

· ошибки webhook;

· ошибки отправки почты;

· ошибки бизнес-логики.

Именно по логам можно понять, приходит ли событие в правильную версию deployment, какой идентификатор выбран для ответа и не дублируются ли подписки.

10. Эволюция меню: от текстовых цифр к кнопкам

Первый рабочий вариант почти всегда строится на текстовом меню: пользователь вводит цифры, бот анализирует текст и переводит его в состояние. Это удобно для отладки, потому что проще диагностировать каждую ветку диалога.

Когда логика уже стабильно работает, следующий шаг — перейти на кнопки.

Почему кнопки лучше

· Пользователь не ошибается в вводе цифр и формулировок.

· Навигация становится быстрее.

· Падает количество пустых и непонятных ответов.

· Интерфейс выглядит более профессионально.

Для MAX это реализуется через attachments с типом inline_keyboard и массивом payload.buttons. Кнопки типа message позволяют отправлять боту заранее определённый текст, а link — открывать ссылку.

Практический выбор для MVP

Самый простой и надёжный путь — использовать кнопки типа message. Тогда нажатие на кнопку эквивалентно отправке текста. Это не требует отдельной callback-логики и хорошо сочетается с уже существующим текстовым обработчиком.

· Главное меню — три message-кнопки.

· Меню инструкций — набор message-кнопок.

· После выдачи пароля — кнопки «Написать обращение» и «В начало».

· Кнопка «В начало» — во всех ветках, где пользователь может потеряться.

Когда переходить на callback

Callback-кнопки нужны, когда вы хотите редактировать текущее сообщение, обновлять меню без новых сообщений в чате или строить более сложный интерфейс. В MAX это делается через POST /answers после получения события message_callback. Для первой стабильной версии бота это необязательно. Кнопки типа message обычно проще и надёжнее.

11. Рекомендуемая структура диалога

Главное меню

· Инструкция по привязке ЕСИА к СГО и MAX

· Заявка на смену пароля

· Вопросы по оценкам в ЭЖ

Ветка инструкций

· Инструкция по привязке ЕСИА

· Инструкция по работе с MAX

· Что делать, если не получается

· В начало

В инструкции можно включать и прямые ссылки: на Госуслуги, на баннер-инструкцию по входу через ЕСИА, на Сферум и другие внешние ресурсы.

Ветка смены пароля

8. Запросить ФИО.

9. Запросить логин.

10. Проверить логин в листе «Пароли».

11. Если логин найден — показать пароль и предупредить, что он мог быть изменён пользователем.

12. Предложить кнопку «Написать обращение на смену пароля».

13. Предложить кнопку «В начало».

Ветка вопросов

14. Попросить пользователя написать вопрос одним сообщением.

15. Создать заявку.

16. Отправить подтверждение с номером обращения.

17. Вернуть кнопку «В начало».

12. Важный вопрос безопасности

Если бот показывает пароль прямо в диалоге, это удобно, но рискованно. Такой подход допустим только как внутренний проект или временный MVP.

· Выдачу пароля лучше логировать.

· Лучше требовать минимум два идентификатора: ФИО и логин.

· В перспективе лучше перейти на временный пароль или отдельный сценарий обновления пароля.

· Токен бота нельзя держать в коде, скриншотах и публикациях.

13. Чек-лист первого стабильного запуска

18. Создать или обновить листы проекта.

19. Заполнить Script Properties.

20. Проверить токен через GET /me.

21. Опубликовать актуальное Web App развертывание.

22. Проверить, что WEB_APP_URL в свойствах совпадает с URL deployment.

23. Удалить старые webhook-подписки.

24. Создать одну новую подписку.

25. Проверить /start.

26. Проверить создание заявки.

27. Проверить исходящее письмо.

28. Проверить отправку результата обратно в MAX.

14. Что оказалось самым ценным в реальной настройке

После практического внедрения можно сделать несколько очень важных выводов.

· Один источник правды для настроек важнее, чем десятки мелких правок в коде.

· Старые webhook-подписки — один из самых частых источников магических проблем.

· Старые deployment-версии могут создавать впечатление, что код не меняется.

· Логи должны быть максимально подробными уже с первой версии проекта.

· Сначала нужно добиться стабильного текстового сценария, а потом переводить его на кнопки.

· Если бот отвечает дважды, сначала нужно искать вторую подписку или старое развертывание, а не переписывать бизнес-логику.

15. Итог

MAX-бот на Google Apps Script — это вполне рабочая схема для реального проекта. При правильной архитектуре она закрывает полный цикл: меню, пошаговый диалог, работу с таблицей, поиск по базе, уведомления, обработку обращений и возврат ответа пользователю.

Ключ к стабильности здесь не только в API-вызовах, а в сопровождении среды: один источник конфигурации, контроль deployment-версий, очистка старых webhook-подписок и подробное логирование. Когда эти части настроены правильно, связка MAX + Apps Script работает предсказуемо и удобно даже для пользователя без глубокого технического опыта.

Приложение. Практические рекомендации по сопровождению

· Перед каждым крупным обновлением отмечайте версию в doGet() или в тексте меню.

· После обновления deployment всегда проверяйте WEB_APP_URL в Script Properties.

· Не запускайте инициализацию листов так, чтобы она очищала рабочие данные.

· Не храните боевой токен в коде.

· Если меню обновилось, а ответы остались старыми, почти всегда виноват старый webhook или старое deployment-развертывание.

· Если после /start приходят два разных ответа, почти всегда существует две активные подписки.