Всем привет! Меня зовут Шалико, я Java-разработчик и часто создаю Telegram-ботов в своих pet-проектах.
Сегодня хочу рассказать вам про фреймворк, который я разработал, чтобы сильно упростить этот процесс.

Не спешите пролистывать статью - вам действительно может быть интересно, даже если вы не пишете Telegram-ботов каждый день.

Исходники проекта на GitHub
А ниже я расскажу, как это работает и почему вообще возникла идея фреймворка.

Зачем? Какие боли решаем?

У меня за плечами уже с десяток Telegram-ботов, но разработка каждого нового превращается в копипасту конфигурации, property-классов и жизненного цикла приложения из сервиса в сервис - эта рутина утомляет.

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

Кто-то спросит:

Наверняка есть уже готовые решения, зачем городить свой велосипед?

Я тоже так думал.
Но поиск Plug-and-Play фреймворков по GitHub не дал ничего, кроме проектов трёхлетней давности, которые уже не поддерживаются ни разработчиками, ни сообществом.

Поэтому я разработал Telegram Bot Spring Boot Starter - фреймворк, который:

  • минимизирует усилия для запуска простого бота;

  • имеет прозрачную архитектуру и легко расширяется;

  • управляет жизненным циклом за вас;

  • содержит готовые механизмы маршрутизации и обработки ошибок;

  • имеет единый и понятный пайплайн обработки апдейтов;

  • отлично интегрируется в Spring Boot-экосистему.

Описание фреймворка и его архитектура

Верхнеуровневая архитектура

В действительности сущностей немного больше чем здесь представлено, однако я не хочу вдаваться сильно в детали, чтобы не перегружать статью.

Общее описание

  • Ingress - абстракция, которая отвечает за получение Telegram-апдейтов;

  • Delivery - передает их дальше и может работать асинхронно, при любых ошибках происходит fallback на ExceptionHandler;

  • Interceptor - позволяет встроиться в цепочку обработки (фильтр, метрики и т.д.);

  • Dispatcher - определяет Router для использования;

  • Router - выбирает Handler на основе типа апдейта и его содержания;

  • Handler - содержит непосредственную бизнес-логику для конкретного апдейта;

  • NoMatchStrategy - fallback, если не смогли найти подходящий Router или Handler;

По умолчанию все реализации уже есть из коробки, но вы можете переопределить любой из этапов.

А что насчет API? Yet Another Telegram Bot API?

На самом деле нет никакой необходимости в ручной реализации Telegram Bot API.
Поэтому фреймворк я построил вокруг java-telegram-bot-api - надежная и популярная библиотека, которую многие используют в проде.
Однако я постарался максимально изолировать использование сущностей из этой библиотеки, чтобы потенциальный переезд на другие реализации Bot API был прост.

Небольшой пример

Ниже хочу привести простой пример, как мо��но быстро запустить бота, который умеет отвечать на /start и /help.

application.properties

telegram.bot.token=<ваш-токен>

Java-код

@SpringBootApplication  
public class LongPollingSampleApplication {  
    public static void main(String[] args) {  
        SpringApplication.run(LongPollingSampleApplication.class, args);  
    }  
}

@Component  
public class StartCommandHandler implements CommandUpdateHandler {  
    private final TelegramBotExecutor telegramBotExecutor;  
  
    @Override  
    public void handle(Update update) {  
        SendMessage sendMessage = new SendMessage(update.message().from().id(), "Simple Hello!");  
        telegramBotExecutor.execute(sendMessage);  
    }  
  
    @Override  
    public Set<String> commands() {  
        return Set.of("/start", "/help");  
    }  
}

Для маршрутизации plain-text сообщений и InlineQuery предусмотрены специальные правила, при помощи которых фреймворк может определить какой именно handler необходимо использовать.

Например, так может выглядеть обработка сообщения, которое содержит подстроку test:

@Component  
public class TestMessageUpdateRule implements MessageUpdateRule {  
    private final TestMessageUpdateHandler updateHandler;  
  
    @Override  
    public Matcher<Message> matcher() {  
        return (m) -> m.text().toLowerCase().contains("test");  
    }  
  
    @Override  
    public UpdateHandler handler() {  
        return updateHandler;  
    }  
}

@Component  
public class TestMessageUpdateHandler implements MessageUpdateHandler {  
    private final TelegramBotExecutor telegramBotExecutor;  
  
    @Override  
    public void handle(Update update) {  
        SendMessage sendMessage = new SendMessage(update.message().chat().id(),  
                "Your 'test' message was successfully handled");  
        telegramBotExecutor.execute(sendMessage);  
    }  
}

Более подробный пример вы можете увидеть здесь: telegram-bot-advanced-sample-long-polling

А что дальше?

Сейчас фреймворк полностью готов к использованию, а часть своих проектов я уже перевел на него.

Однако есть множество "хотелок", которые я еще не успел покрыть, вот самые первые на очереди:

  • модуль для работы с Apache Kafka;

  • модуль для observability;

  • модуль с машиной состояний + интеграция с БД;

  • маршрутизация других типов апдейтов;

Итог

В этом проекте я ставил себе цель - разработать фреймворк, который:

  • удобен для быстрого старта и простых ботов;

  • но при этом достаточно гибкий для серьезных проектов;

Послесловие

Проект открытый и развивается - приглашаю посмотреть

Спасибо, что уделили время статье!
Если вы попробуете фреймворк в работе — буду рад любой обратной связи:
issues, идеи, вопросы, предложения.