Короткий пост, полный полезных лайфхаков тривиальных советов о том, как сделать хостинг Telegram бота с помощью Google Apps Script.
В сети есть миллионы статей, плохих и хороших, о том, как создать бота в Telegram и как развернуть приложение на Google Script. Поэтому подробных описаний как всё это делать, не будет. Зачем тогда этот пост? Затем, что даже выбрав самую лучшую статью и скопировав оттуда код, ничего не взлетит (скорее всего). И только прочтение нескольких хороших статей, комментариев на stackoverflow и документации API телеграма и гугла, дадут результат. Чтобы сэкономить время на более интересные задачи, здесь я соберу несколько деталей, которые позволят быстро понять, почему не взлетают copy-paste примеры.
Разработчики меняют API, чтобыподставить новый костыль сделать мир лучше, поэтому следует учитывать, что описываемые в посте особенности актуальны на февраль 2020.
Разработчики меняют API, чтобы
Итак, базовая последовательность действий, хорошо описанная в интернетах:
- зарегистрировать бота в Telegram, получить токен.
- создать скрипт Google Apps Script (нужно иметь аккаунт Google), реализующий вашу логику (ну, пускай это будет записывание значения в ячейку Google Spreadsheet и отправка пользователю в Telegram сообщения)
Короткое отступление для тех, кто собирается запилить своего первого бота в Телеграм. Важно разложить по полкам два способа получения обновлений от Телеграм - Long polling mode vs. setWebhook. В режиме long polling для получения обновлений ваш код должен вызывать метод getUpdates из API телеграма. В режиме setWebhook, как только появится апдейт, Телеграм сам отправит его на указанный url.
Например, если вы хотите создать чат-бота, который бы отвечал что-то на вопросы пользователя, то, наверно, вы хотите чтобы пользователь получал эти ответы от бота мгновенно, а не через минуту. В таком случае, при использовании long polling, ваш код должен вызывать метод getUpdates очень часто (раз в секунду, например) и более уместен режим webhook. Однако, у режима webhook есть свои сложности - вам нужен веб-хостинг и нужно будет получить ssl сертификат или сгенерировать самоподписанный сертификат. В то время как бота в режиме long polling можно запустить хоть на локальном компьютере.
Разворачивание веб-приложения в Google Apps Script как раз позволяет использовать режим webhook и при этом еще и не настраивать ничего с ssl сертификатами.
Теперь советы.
- если вы сделали изменение в коде Google Script (даже если изменения в коде были в духе добавить комментарий), нужно заново разворачивать приложение! Просто клик "Сохранить" не применит обновления.
- нужно всегда выбирать Project version как "Новый". Иначе обновления тоже не применятся:
- Функции в Google Apps Script для обработки POST и GET запросов должны называться doPost(e) и doGet(e) соответственно.
- Эти функции должны возвращать результат. Даже если он вам не нужен. Примеры кода без return работать не будут.
- Если, с точки зрения логики приложения, вам не важно, что возвращать, то вы все равно должны уделить внимание этой части кода.
Это проще объяснить на примере. Представим, что пользователь с именем User (вот это поворот!) посылает сообщение с текстом test вашему боту. Вы, например, хотите, чтобы приложение записало имя и сообщение пользователя в ячейки Google Spreadsheet и чтобы бот отправил вам уведомление. Если setWebhook установлен, то сервер Телеграма выполнит POST запрос по указанному URL. Произойдет вызов функции doPost, данные запишутся в ячейки и бот отправит вам уведомление. И вот здесь вступит в игру то, что возвращает doPost. Для вашей логики приложения это, вроде бы не важно. В интернете можно найти примеры с использованием сервиса ContentService для возвращения 'raw textual content'. Например, такой код с объяснением "давайте вернем пустой текстовый контент, так как нам это не очень-то и важно, главное иметь return в коде:
return ContentService.createTextOutput();
С таким кодом функция doPost будет вызвана корректно и вернет Телеграму HTTP код 200 OK. Вроде здорово, но вы заметите, что ваш бот начнет посылать вам одно и тоже оповещение бесконечно. В спецификации API Telegram написано: "In case of an unsuccessful request, we will give up after a reasonable amount of attempts." Но возможно, ваши представления о reasonable amount разойдутся :) Дело в том, что ваше приложение должно дать ответ на POST запрос, что он успешно обработан. Для этого нужно вернуть html c телом ответа, пустым. Сделать это можно так:
return HtmlService.createHtmlOutput();
Теперь Telegram поймет, что ваше веб-приложение получило апдейт из POST запроса корректно и не нужно его повторять.
- Если все же завести код не получается, при дебаге тестируйте всё отдельно со стороны Телеграма и со стороны Гугла. Для тестирования правильных действий бота, можно временно удалить вебхук (deleteWebhook) и проверять обновления с помощью метода getUpdates() (хоть просто в адресной строке браузера). Для тестирования Google Apps Script выполняйте POST/GET запросы с помощью какого-нибудь инструмента (например). Учитывайте, что запросы из Postman не работают из-за каких-то проблем с аутентификацией.
В репозитории можно посмотреть код простого примера, в котором веб-приложение, развернутое в Google Apps Script обрабатывает получение апдейтов из Телеграм, записывает в первые три колонки spreadsheet время, автора и текст сообщения боту, и, наконец, уведомляет админа о полученном апдейте:
Комментарии
Отправить комментарий