Реализация простого телеграм-бота

Работа с проектом

Работа с проектом будет выстроена аналогично остальным нашим курсам: проект в Git репозитории, патчи для изменения проекта, ветка с готовым кодом и группа поддержки в Telegram.
  • По мере прохождения материала нужно будет последовательно применять в ветке master пронумерованные патчи (Apply patch) из архива патчей (патчи сделаны в JetBrains IDEA, лучше всего применять их в этой IDE или аналогах).
  • После применения каждого патча следует делать коммит, чтобы было легче отслеживать изменения в git. Ветку patched можно использовать для разрешения конфликтов.
ИЛИ
  • Переключиться в проекте на ветку patched c уже примененными патчами:
    https://github.com/JavaOPs/ai-bot/tree/patched
  • По мере прохождения материала откатывать проект (Checkout Revision) на нужное место
Также можете настроить push проекта в свой Git репозиторий
Проходя занятие вы смотрите проект - добавленный в него код, объяснения добавленного кода в занятии, запускаете и дебажите бота. Таким образом вы быстро на практике усваиваете Telegram API и Java классы для удобной организации работы с ними в реальных проектах.


На проекте мы будем использовать последнюю LTS JDK 25 (скачать OpenJDK 25)

Создаем телеграм-бота

Создайте бота в @BotFather по инструкции (займет одну-две минуты).
Сохраните HTTP API Token созданного бота, он нам понадобится в приложении.

Getting Started c telegrambots

Создадим простейшего телеграм бота на основе Java библиотеки TelegramBots (библиотеки, которая имплементирует Telegram APIs) по "getting-started" руководству.
Инициализация проекта: Getting Started with TelegramBots
  • В pom.xml к проекту подключены зависимости логирования logback-classic и утилитная библиотека для сокращения кода Lombok (используем аннотацию @Slf4j)
  • Класс проекта AIBot реализует получение данных из бота (getUpdates API), используя Long polling.
    После получения Update, если он содержит сообщение с текстом, мы логируем текст в консоль.

    В Telegram APIs есть еще второй метод получения данных - WebHook. Из обсуждения статьи сравнения этих методов на Хабр:

    "Long polling подразумевает, что сервер не разрывает запрос в течение длительного времени (обычно это минута или 30 секунд), если нет новых событий для вас, но вернет их моментально, как только они появятся. Таким образом, вы выполняете очень мало запросов и получаете запросы моментально. Long polling, в отличие от webhook, не может быть бутылочным горлышком для вашего бота, потому что вы сами отправляете запрос на обновления к Telegram, когда готовы их обработать, и работает это максимально эффективно. В случае с webhook Telegram сам шлет вам запросы, что на пике может положить ваш сервер или заставить его обрабатывать запросы значительно медленнее, потому что у веб-серверов есть ограничения на максимальное количество открытых запросов одновременно.

    Более того, в случае с webhook 1 обновление = 1 запрос, то есть запросов будет гораздо больше, чем при использовании long polling, и на больших ботах это будет вызывать проблемы с производительностью.

    Если к этому добавить то, что для работы webhook нужно возиться с сертификатами и получить белый IP, я считаю использование long polling выигрышным в 100% случаев."
  • В классе AIBotMain замените "BOT_HTTP_API_Token" на токен вашего созданного бота
  • Запустите AIBotMain.
    Перейдите в вашего созданного бота. Проверьте, что команда /start и любое ваше сообщение появляется в логе приложения

Отправка сообщений

На основе примера Simple echo bot сделаем отправку эха сообщения с учетом того, что наш проект будет развиваться.
В ветке master примените патч 1_1_sendMessage из архива патчей
  • TelegramBots имеет 2 реализации отправки сообщений: на основе библиотек OkHttp и Jetty. С учетом того, что в дальнейшем мы подключим Spring Boot, а он умеет работать с Jetty, сразу подключим зависимость Jetty HTTP client.
  • Добавим свои классы исключений: общий AppException и TelegramException. Впоследствии мы будем их дополнять.
  • Добавим утилитные классы-обертки для работы с telegrambots:
  • Добавим конфигурацию логирования /src/main/resources/logback.xml.
    Классы проекта логируются с уровнем debug, все остальное с уровнем info.
  • В классе AIBot мы отправляем принятое сообщение с помощью ClientHandler.
    При общении пользователя с ботом message.chatId совпадает с message.from.id.
    Т.к. User нам впоследствии пригодится, telegram_id получаем из него.
  • Токен бота нельзя хранить в репозитории (точно так же, как и другие креденшелы). Вынесем его в переменную окружения BOT_HTTP_API_TOKEN. При запуске следует или выставить его в системе (перезапустив IDEA) или задать в конфигурации запуска:

Форматирование сообщений

В Telegram API можно посылать сообщения в обычном текстовом, HTML и Markdown форматах.
Попробуйте послать нашему боту сообщение с форматированием, например такое (в формате Markdown):
Приглашаем *Java-разработчиков на открытый курс* [Java AI Bot](https://javaops.ru/view/ai-bot)
*Разработка ИИ телеграм-бота с использованием TelegramBots + Spring AI*

_Мы создадим с нуля телеграм-бот, который_:
🔥 Сохраняет состояние и работает с форматированными сообщениями
🔥 Интегрирован с Spring AI и ИИ чатом

_ВЫ ПОЛУЧИТЕ_:
⚡️ Понимание принципов и опыт работы с [TelegramBots](https://github.com/rubenlagus/TelegramBots) + [Spring AI](https://spring.io/projects/spring-ai)
⚡️ Готовое полноценное приложение как основу для большого проекта
⚡️ Поддержку и живое общение в телеграм-группе с темами на каждое занятие

*Ждем на нашем курсе!*
Ответ придет "as is", без форматирования. Научим наш бот отсылать форматированные сообщения.
В ветке master примените патч 1_2_sendMd из архива патчей
Добавим в ClientHandler 3 разных метода отправки для всех форматов и используем в AIBot метод clientHandler.sendMd.
Проверьте, что теперь отправляется сообщение с форматированием.
Теперь скопируйте-вставьте сообщение бота, пришедшее как эхо (или создаете новое средствами форматирования Telegram, выделив фрагмент):
service discovery
Ответ придет снова без форматирования - в принимаемом сообщении Message с форматированием используются MessageEntity. Научим наш бот конвертировать принимаемое сообщения в формат Markdown.
В ветке master примените патч 1_3_getFormatting из архива патчей

ИИ-чат сгенерировал мне метод UpdateHandler.recoverMarkdown, который переводит Message + MessageEntity в формат Markdown. Подключим этот метод в AIBot. Теперь, когда бот принимает форматированное средствами Telegram сообщение, он преобразует его в формат Markdown и мы снова получим от него форматированный ответ-эхо.

PS: преобразованный Markdown не будет работать, если оно форматирование накладывается, например Bold + Link или Bold + Italic).
Телеграм-бот «Java ассистент»