JavaRush /Java блог /Random UA /Створюємо телеграм-бота з використанням Spring Boot
Whiskels
41 рівень
Москва

Створюємо телеграм-бота з використанням Spring Boot

Стаття з групи Random UA
Всім привіт! В якийсь момент навчання вам хочеться перейти від вирішення завдань до створення реальних проектів, які ляжуть в основу вашого портфоліо. Коли я починав навчатися на стажуванні (яке я всім дуже рекомендую), на фрілансі надійшла пропозиція написати телеграм-бота. Зважаючи на свої малі знання написав досить простого бота ( останній коміт до міграції на Spring ), який містив у собі три нитки:
  • нитка прийому повідомлень;
  • нитка відправлення повідомлень;
  • нитку планування подій (в ній перевірялася наявність запланованих повідомлень та оновлення кешованих даних з JSON).
При написанні цього функціоналу багато в чому спирався на цю статтю . Все цілком непогано працювало, але чим глибше я поринав у Spring, тим сильніше мені хотілося все відрефакторити з метою зменшення зв'язності програми та покращення якості коду. Ще SonarLint (плагін для автоматичної перевірки якості коду) весь час намагався мене переконати, що нескінченні цикли while мати не дуже добре. Якоїсь миті я зважився і все переписав, а тепер хочу поділитися отриманими в процесі рефакторингу знаннями з вами. Почнемо з основ, а конкретніше - з 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: CodeGymTelegramBot
  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 для створення обробників повідомлень та перевірки прав користувача;
  • підтримка створення графіка повідомлень.
Якщо щось із цього функціоналу вас зацікавило — пишіть у коментарі, і я спробую або відповісти, або написати розгорнуту статтю про те, як його відтворити. PS Це моя перша стаття на JavaRush, і мені хотілося б поринути в нетрі Spring JPA і анотації @ Scheduled, але для початку мені здалося, що варто написати цей посібник про те, як взагалі підняти бота з використанням Spring Boot. По ботах вже написано кілька статей, але пошук не видав подібного гайда, так що я вирішив заповнити цю нішу :) Також хотілося б відзначити Miroha - дякую за ідею UpdateHandler'ов, потяг її собі :)
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ