JavaRush /Java блог /Random /Создаем телеграм-бота с использованием Spring Boot
Whiskels
41 уровень
Москва

Создаем телеграм-бота с использованием Spring Boot

Статья из группы Random
Всем привет! В какой-то момент обучения вам хочется перейти от решения задач к созданию реальных проектов, которые лягут в основу вашего портфолио. Когда я начинал учиться на стажировке (которую я всем очень рекомендую), на фрилансе поступило предложение написать телеграм- бота. Ввиду своих малых познаний написал довольно простого бота (последний коммит до миграции на Spring), который содержал в себе три нити:
  • нить приема сообщений;
  • нить отправки сообщений;
  • нить планирования событий (в ней проверялось наличие запланированных сообщений и обновление кешированных данных из JSON).
При написании этого функционала во многом я опирался на эту статью. Все вполне неплохо работало, но чем глубже я погружался в Spring, тем сильнее мне хотелось все отрефакторить с целью уменьшения связности программы и улучшения качества кода. Еще SonarLint (плагин для автоматической проверки качества кода) все время пытался меня убедить, что бесконечные циклы while иметь не очень хорошо. В какой-то момент я решился и все переписал, а теперь хочу поделиться полученными в процессе рефакторинга знаниями с вами. Начнем с основ, а конкретнее — c TelegramBots-Spring-Boot-Starter Итак, поехали! Создадим бота, который будет здороваться в ответ на любое сообщение. Для начала нам необходимо создать новый Maven проект. Добавим необходимые зависимости в pom.xml. Добавляем в properties версии Java и TelegramBots-Spring-Boot-Starter. И прописываем dependencies — здесь у нас будет уже упомянутый выше TelegramBots-Spring-Boot-Starter и Telegram API:Создаем телеграм бота с использованием Spring Boot - 1Библиотека TelegramBots-Spring-Boot-Starter включает в себя Spring Boot и Telegram API. Ее использование позволяет нам довольно простым образом объявить бота в нашем коде, а Spring сам создаст Bean и активирует бота. Если вам интересно, что происходит под капотом в этот момент, то посмотрите исходники библиотеки (в среде разработки или на гитхабе). Также добавляем параметры компиляции:Создаем телеграм бота с использованием Spring Boot - 2 Не забудьте после заполнения pom обновить все зависимости! Создадим два класса — App и Bot, а также файл application.yaml в папке resources. Структура моего проекта выглядит так:Создаем телеграм бота с использованием Spring Boot - 3На данном этапе добавим в application.yaml credentials нашего бота:

bot:
  name: JavaRushTelegramBot
  token: 22313424:AAF4gck4D8gDhq68E7k0UH8vlyQADhxQhYo
Иерархическая запись позволяет нам избежать повторения (bot.name, bot.token) и повысить читаемость. Если у вас еще не создан бот, то завести его можно, следуя официальной инструкции. Если вы не хотите светить креденшлы к боту в application.yaml (что правильно) — используйте переменные окружения при деплое:

bot:
  name: ${BOT_NAME}
  token: ${BOT_TOKEN}
Заполняем класс Bot:

package com.whiskels.telegram.bot;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

// Аннотация @Component необходима, чтобы наш класс распознавался Spring, как полноправный Bean
@Component
// Наследуемся от TelegramLongPollingBot - абстрактного класса Telegram API
public class Bot extends TelegramLongPollingBot {
    // Аннотация @Value позволяет задавать значение полю путем считывания из application.yaml
    @Value("${bot.name}")
    private String botUsername;

    @Value("${bot.token}")
    private String botToken;

    /* Перегружаем метод интерфейса LongPollingBot
    Теперь при получении сообщения наш бот будет отвечать сообщением Hi!
     */
    @Override
    public void onUpdateReceived(Update update) {
        try {
            execute(new SendMessage().setChatId(update.getMessage().getChatId())
            .setText("Hi!"));
        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }

    // Геттеры, которые необходимы для наследования от TelegramLongPollingBot
    public String getBotUsername() {
        return botUsername;
    }

    public String getBotToken() {
        return botToken;
    }
}
Заполняем класс App:

package com.whiskels.telegram;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.telegram.telegrambots.ApiContextInitializer;

// Аннотация, которая объединяет в себя @Configuration, @EnableAutoConfiguration, @ComponentScan
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        // Здесь код написан по заветам 
        // https://github.com/rubenlagus/TelegramBots/tree/master/telegrambots-spring-boot-starter
        ApiContextInitializer.init();

        SpringApplication.run(App.class, args);
    }
}
Если мы все сделали правильно, то можно запустить main и поздороваться с нашим ботом.Создаем телеграм бота с использованием Spring Boot - 4Готово! Мы успешно написали и запустили телеграм бота, который на каждое входящее сообщение здоровается. Если вам была полезна эта статья, то лучшей благодарностью будет, если вы загляните в мой репозиторий и поставите звездочку. Там же вы найдете мою версию телеграм-бота, который имеет много интересных особенностей:
  • хранение пользователей в базе Postgres;
  • авторизацию доступа к командам на основе ролей пользователя;
  • использование кастомных аннотаций @BotCommand и @RequiredRoles для создания обработчиков сообщений и проверки прав пользователя;
  • поддержка создания графика уведомлений.
Если что-то из этого функционала вас заинтересовало — пишите в комментарии, и я постараюсь либо ответить, либо написать развернутую статью о том, как его воссоздать. P. S. Это моя первая статья на JavaRush, и мне хотелось бы погрузиться в дебри Spring JPA и аннотации @Scheduled, но для начала мне показалось, что стоит написать это руководство о том, как вообще поднять бота с использованием Spring Boot. По ботам уже написано несколько статей, но поиск не выдал подобного гайда, так что я решил заполнить эту нишу :) Также хотелось бы отметить Miroha — спасибо за идею UpdateHandler'ов, утащил ее себе :) ЧАСТЬ 2 ЧАСТЬ 3
Комментарии (39)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anonymous #3144751 Уровень 1
8 марта 2024
Почему я не могу написать бота без использования spring? Я написал бота для своего школьного проекта с помощью библиотеки телеграмботс Могу ли я залить бота на удаленную машину чтобы он работал 24/7?
Алексей Уровень 53 Expert
13 ноября 2023
метод getBotToken в последних версия API deprecated, но при этом в самой документации на него все время ссылаются))))
SlesarADmi93 Уровень 51
3 июля 2023
Ребят. Никак не могу понять, почему IIDEA ругается. Голову сломал уже. Не пойму в чём ошибка.
SlesarADmi93 Уровень 51
3 июля 2023
hidden #2592309 Уровень 2
3 апреля 2023
Как создать переменные окружения? Нигде нет нормальной информации об этом для java, один python
Максим Уровень 19
25 ноября 2022
Подскажите, а можно ли принять сообщение из чата, спарсить его и данные раскидать в БД?! Как ни будь по простому, без 10000 строк кода! Спасибо!
Konstantin Уровень 29
10 января 2022
не могу сформировать запрос что бы понять аде по читать про этот англицизм Если вы не хотите светить креденшлы к боту в application.yaml (что правильно) — используйте переменные окружения при деплое: - киньте стать. пжл
Vladislav Ryzhov Уровень 1
1 декабря 2021
При попытке запустить проект (поменял только токен и имя бота) получаю такую ошибку org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bot' defined in file "путь".Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.vladynush.telegram.bot.Bot]: Constructor threw exception; nested exception is com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: Unable to load cache item Из-за чего такое может происходить?
Armoredsword Уровень 20
10 марта 2021
как прикреплять кнопки к сообщениям ? у меня есть билдер кнопок - как ее отправить пользователю вместе с сообщением, можно пример кода как это делать в onUpdateReceived ? public static InlineKeyboardButton createInlineKeyboardButton(String text, String command) { InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); inlineKeyboardButton.setText(text); inlineKeyboardButton.setCallbackData(command); return inlineKeyboardButton; }
Михаил Уровень 27
14 февраля 2021
Добрый день! Прошу прощения, может вопрос глупый, только начинаю изучать Spring.Не подскажете в чем может быть проблема?