5 октября 2020
Тэги: Spring Boot Spring Kotlin gradle
В настоящее время чат-боты в Telegram не делал только ленивый. Они плотно вошли в нашу жизнь и почти у каждой компании есть бот, решающий какие-то бизнесовые задачи, тем самым разгружая «живых» сотрудников. После прочтения этой статьи вы сможете создать и запустить свой чат-бот в Telegram. Также пример готового приложения доступен по ссылке на github.
Сперва нам нужно выбрать подходящее имя для бота и зарегистрировать его в Telegram. Регистрация нового бота происходит через бота по имени BotFather. Просто найдите его через поиск контактов Telegram. В чате вы всегда можете понять, что общаетесь с ботом, т.к. рядом с его именем есть подпись «bot». BotFather позволяет управлять вашими ботами в диалоговом режиме. Команды боту представляют собой текст, начинающийся со слеша.
Для создания нового бота отправьте команду /newbot. Вам будет предложено ввести имя бота. На данном шаге постарайтесь не использовать слово «bot» в названии. Если выбранное вами имя не занято, то далее вам будет предложено ввести логин для этого бота. Причём он должен заканчиваться на «bot». Если логин не занят, то вам будет сгенерирован access token для работы с Telegram API по http. Сохраните этот токен - он нам понадобится далее.
За основу нашего чат-бота возьмём Spring Boot. Код будем писать на Kotlin. Воспользуемся сайтом start.spring.io для создания заготовки нашего приложения. В настройках выберем Gradle Project и Kotlin, в качестве зависимости нам здесь будет достаточно только Web. Скачаем заготовку проекта и откроем файл build.gradle.kts. Проверьте, что в секции dependencies присутствует org.springframework.boot:spring-boot-starter-web. Также добавим туда библиотеку для работы с Telegram org.telegram:telegrambots-spring-boot-starter:4.1.
Теперь давайте найдём главный класс нашего приложения, в котором находится метод main() и аннотация @SpringBootApplication. В него нужно добавить инициализацию контекста Telegram API:
Если этого не сделать, то ошибок при запуске не будет, но и бот также работать не будет.
Теперь создадим новый сервис. В telegram боты можно подключать двумя способами: long polling и web-hook. В случае с long polling наше приложение кидает запрос и ждёт ответа от сервера telegram. Сервер ответит не сразу, а только тогда, когда произойдёт какое-либо событие (например, сообщение от пользователя). А в случае с webhook сервер telegram сам будет дёргать заранее зарегистрированные эндпоинты нашего приложения. В подключенной нами библиотеке поддерживаются оба варианта, но webhook чуть сложнее в настройке. Поэтому рассмотрим long polling.
Унаследуем наш сервис от класса TelegramLongPollingBot. Этот абстрактный класс потребует от нас реализации методов getBotUsername(), getBotToken() и onUpdateReceived().
Первые два метода должны возвращать те самые данные, которые мы получили при регистрации. Однако нельзя их хардкодить в виде констант. Они должны подгружаться из параметров приложения.
Благодаря аннотации @Value Spring сам подставит параметры из файла application.properties. Пропишем их в этом файле, а лучше сразу его переименуем в application.yml, чтобы писать в yaml-формате:
Здесь мы указываем имя бота (telegram.botName) в явном виде, а вот токен (telegram.token) подгружаем из переменной окружения, т.к. этот токен должен сохраняться в секрете. Переменную окружения можно указывать при запуске приложения из командной строки через опцию -D или непосредственно в Idea.
Теперь вернёмся к нашему сервису и реализуем метод onUpdateReceived().
В начале мы проверяем объект типа Update на наличие сообщения с помощью метода hasMessage(). Далее, извлекаем chatId (уникальный идентификатор пользователя в telegram). Затем проверяем, что входящее сообщение содержит текст (а не стикер, к примеру). Если сообщение от пользователя равно строке «/start», то мы приветствуем пользователя. Дело в том, что именно такое сообщение отправляется, когда вы впервые подключаетесь к боту и жмёте кнопку «Start». Для любого другого текста мы просто дублируем его в ответе. Если же текста нет, бот ответит, что понимает только текст.
Отправка сообщения происходит во вспомогательном методе sendNotification().
В нём мы создаём объект ответа, заполняя chatId и текст ответа. Затем с помощью метода setParseMode() включаем режим разметки Markdown. Этот режим позволяет делать простое форматирование текста. Например, текст, обрамлённый с двух сторон символами звёздочки будет отображаться жирным. Затем для отправки сообщения вызываем метод execute() из родительского класса.
Указанный выше способ взаимодействия между пользователем и ботом довольно универсален. Однако чтобы пользователю не набирать каждый раз одни и те же команды, а также чтобы исключить вероятность опечатки, мы можем предоставить ему несколько заранее заготовленных команд в виде кнопок. При нажатии на кнопку бот получит ровно тот текст, который на ней написан. В этом смысле нет разницы между нажатием на кнопку и набором этого текста вручную.
Давайте сделаем так, чтобы пользователю отображалось 4 кнопки, по 2 в ряд. Для этого модифицируем наш метод отправки сообщения пользователю:
Тут мы просто указываем свойство replyMarkup, для чего вызываем метод getReplyMarkup(), передавая ему на вход список списков строк. Сам метод выглядит примерно так:
Создаём объект ReplyKeyboardMarkup. Как нетрудно догадаться по названию, он отвечает за разметку кнопок. Затем проходимся по каждой строке, создавая KeyboardRow и заполняем её кнопками. Для создания кнопки требуется указать только текст.
Наконец, немного модифицируем наш обработчик запросов:
Как только пользователь отправит сообщение, начинающееся со строки «Кнопка », мы определим, что пользователь нажал именно кнопку.
Как видите, Spring Boot позволяет запустить чат-бот с минимальным количеством усилий. Вам же остаётся только реализовать саму обработку сообщения согласно вашей бизнес-логике.
Подавляющее большинство чат-ботов работает именно с текстовой информацией. Помимо применения в бизнесе также известно немало успешных примеров реализации текстовых игр и даже MMORPG. Именно поэтому чат-боты Telegram сейчас используются повсеместно.
Kotlin, Java, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Hibernate, Collections, Stream API, многопоточность, Apache, maven, gradle, JUnit, ООП, алгоритмы, головоломки, rest