Как написать телеграмм бота на java
Перейти к содержимому

Как написать телеграмм бота на java

  • автор:

Особенности создания телеграм-бота на Java

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

Ботами (bot) и чат ботами (chat bots) называют специальные аккаунты в Телеграмм, используемые для автоматической обработки и отправки сообщений. На практике пользователи взаимодействуют с ботами посредством сообщений, которые они отправляют как через обычные, так и через групповые чаты. Бот работает по определенной логике — она контролируется с помощью HTTPS-запросов к специальному API для ботов от Телеграм.

Особенности создания телеграм-бота на Java

Возможности ботов

Приведем несколько классических примеров применения ботов в Телеграмм:

  1. Утилиты и инструменты. Телеграм-бот может переводить тексты, отображать актуальную погоду, предупреждать о каких-либо предстоящих событиях, использоваться для проведения опросов.
  2. Интеграция с сервисами. Бота можно использовать для отправки комментариев либо уведомлений, управления «умным домом».
  3. Игры (как одно-, так и многопользовательские). Бот без проблем поиграет с вами в шахматы/шашки, проведет викторину и т. п.
  4. Социальные сервисы. При необходимости специальный бот найдет вам собеседника, взяв за основу для поиска ваши интересы и увлечения.
  5. Все остальное. Это «все остальное» ограничивается лишь вашей фантазией. На деле вы можете запрограммировать бота практически для чего угодно. Однако стоит понимать, что он все равно останется ботом, а значит, не сможет помыть посуду вместо вас.

Если резюмировать вышеперечисленное одним предложением, то бот в Телеграм умеет оставлять комментарии к записям и постам, переводить тексты, искать информацию и аудио/видеоданные, спрашивать и отвечать на вопросы, подключаться к сети, обходить блокировки роутеров и сервисов, создавать чаты для общения, транслировать презентации и т. д. — всего не перечислишь.

Как функционируют боты?

Боты — особые аккаунты, по сути, представляющие собой интерфейс к вашему сервису, работающему на удаленном сервере. Плюс в том, что для создания бота вам совершенно не обязательно изучать низкоуровневые технологии, так как все взаимодействие основано на обычном HTTPS-интерфейсе с упрощенными методами API — его называют Bot API .

В реальности вы можете создать бота в Телеграмм с помощью… бота. Для этого потребуется написать пользователю @BotFather , а потом следовать его инструкциям. После создания вы получите специальный ключ авторизации (токен). Выполнить необходимые настройки можно будет в разделе документации Bot API .

Особенности создания телеграм-бота на Java

Особенности создания бота с помощью Java

Если вы не ищете легких путей, хотите прокачаться в Java и привыкли все творить своими руками, вы можете написать бота, используя язык программирования Java («Джава», «Ява»). Ниже рассмотрим один из возможных алгоритмов действий.

Пишем бот на Java

На деле написать бота для Телеграмм, используя Java, не так уже сложно. Рассмотрим пример создания бота посредством Webhook.

Особенности создания телеграм-бота на Java

Общая последовательность действий будет следующей:

  1. Открываем «Эклипс», создаем новый Java-проект.
  2. Находим и загружаем базу, необходимую для создания Telegram-ботов.
  3. Импортируем загруженную библиотеку в проект.
  4. Создаем класс test.SimpleBot со следующим содержимым:

— открытие веб-браузера, переход по ссылке: https://telegram.me/botfather;

— нажатие кнопки «Send message»;

— выбор BotFather в Телеграме;

— ввод имени бота на Webhook.

Также надо будет придумать имя пользователя для вновь созданного бота. Тут главное, чтобы это имя было уникальным. После ввода имени надо будет нажать кнопку подтверждения, в результате чего появится сообщение об успешной конфигурации. Обратите внимание, что после «Use this token to access the HTTP API:» выведется ваш токен, который надо будет ввести в требуемом месте.

  1. Переходим в «Эклипс», запускаем бота.
  2. В адресной строке веб-браузера набираем https://telegram.me/имя_вашего_бота (это необходимо для тестирования работоспособности).
  3. Нажимаем «Send message».
  4. Возвращаемся в Телеграм, выбираем созданного бота.
  5. Кликаем «Старт».

Все, Telegram-bot Webhook, написанный на «Джава», готов. На данном этапе на любое обращение робот должен отвечать что-то в стиле «Я не знаю, что ответить на это», однако эту фразу можно поменять путем дополнения базы.

Каковы плюсы Telegram-бота на Java

Можно перечислить ряд преимуществ такой реализации:

  1. Простота.
  2. Минимум выполняемых операций.
  3. Минимум требуемых знаний и умений.

В сети вы можете найти целый спектр уже готовых решений в виде программного кода, поэтому написать бота на Java будет не сложно. Вот, к примеру, полезное обучающее видео , где подробно рассказывается о том, как создать погодного бота на «Джава». Преимущество именно этого решения — легкость, доступность, простота создания. Дерзайте!

  • https://stelegram.ru/faq/pravila-sozdaniya-telegramm-bota-na-java;
  • https://tlgrm.ru/docs/bots.

Разработка ботов в Telegram на Java с нуля

Telegram – одна из самых популярных платформ для разработки ботов, предоставляющая множество возможностей для автоматизации коммуникации и создания разнообразных сервисов.

На этом вебинаре вы узнаете, как начать работу с Telegram Bot API и как разрабатывать ботов с использованием Java. Вы получите практические навыки, которые позволят вам создать собственный бот и настроить его функционал в зависимости от ваших потребностей. Спикер с опытом разработки ботов поделится полезными советами и примерами кода.

  1. Введение
    • Приветствие и представление спикера.
    • Объяснение целей вебинара.
  2. Обзор Telegram Bot API
    • Обзор Telegram Bot API и его возможностей.
    • Регистрация и настройка бота в Telegram.
  3. Подготовка среды разработки
    • Установка и настройка Java Development Kit (JDK).
    • Выбор и настройка интегрированной среды разработки (IDE).
  4. Разработка основы бота
    • Создание проекта Java для бота.
    • Подключение и использование библиотеки Telegram Bot API для Java.
  5. Реализация основных функций бота
    • Обработка входящих сообщений и событий бота.
    • Отправка текстовых сообщений от бота.
    • Обработка команд и ответов на них.
    • Использование клавиатур и других элементов интерфейса бота.
  6. Расширенные возможности бота
    • Использование интерактивных элементов, таких как кнопки и ссылки.
    • Взаимодействие с базой данных для сохранения состояния и информации бота.
  7. Взаимодействие со сторонними сервисами и API
    • Пояснение, как интегрировать бота с посторонними сервисами и API для получения дополнительных функций.
    • Примеры кода для взаимодействия с API.
  8. Обеспечение безопасности и защиты бота
    • Защита доступа к боту с помощью токенов и других методов аутентификации.
  9. Настройка и развертывание бота
    • Развертывание бота на облачных платформах или на собственном сервере.
  10. Лучшие практики и советы
    • Разработка понятного и эффективного пользовательского интерфейса.
  11. Вопросы и ответы
    • Ответы на вопросы участников вебинара.
    • Предоставление дополнительных советов и рекомендаций.
  12. Заключительные слова
    • Итоги вебинара.

Целевая аудитория:

Этот вебинар будет полезен разработчикам, которые желают углубить свои знания в области разработки ботов и Telegram API, а также тем, кто имеет интерес к автоматизации коммуникации и созданию чат-ботов.

Условия участия: бесплатно. Для получения приглашения на онлайн-трансляцию заполните регистрационную форму.

При поддержке информационного партнера

Покупай подписку с доступом ко всем курсам и сервисам

Библиотека современных IT знаний в удобном формате

Выбирай свой вариант подписки в зависимости от задач, стоящих перед тобой. Но если нужно пройти полное обучение с нуля до уровня специалиста, то лучше выбирать Базовый или Премиум. А для того чтобы изучить 2-3 новые технологии, или повторить знания, готовясь к собеседованию, подойдет Пакет Стартовый.

  • Все видеокурсы на 3 месяца
  • Тестирование по 10 курсам
  • Проверка 5 домашних заданий
  • Консультация с тренером 30 мин

  • Все видеокурсы на 6 месяцев
  • Тестирование по 16 курсам
  • Проверка 10 домашних заданий
  • Консультация с тренером 60 мин

  • Все видеокурсы на 1 год
  • Тестирование по 24 курсам
  • Проверка 20 домашних заданий
  • Консультация с тренером 120 мин

Пишем простой Telegram bot на java, который показывает официальный курс по отношению к иностранным валютам

Всем привет! Да-да тема не очень актуальна и на просторах habr-a есть очень много статей про то, как написать простейшего telegram bota, но я все-таки рискну написать еще одну. Может кому-то она будет интересна и полезна.

Для написания бота нужен аккаунт в telegram.

И так начнем: наш бот будет «ходить» на официальную страницу национального банка и выдавать текущий официальный курс к запрашиваемой валюте.

Создадим проект, я это сделаю с помощью https://start.spring.io/

Генерируем и открываем в среде разработки.

Сейчас нужно зайти в telegram и найти там @BotFather.

Пишем команду /newbot и вводим имя для нашего нового бота. Имя должно быть уникальным и заканчиваться на bot. По данному имени нас будут искать в telegram.

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

Далее идем в наш проект и добавляем зависимости для telegram, lombok и json. Библиотеку json будем использовать для парсинга jsona, который будем получать через официальный API банка.

  org.telegram telegrambots 6.5.0  org.projectlombok lombok 1.18.26 provided  org.json json 20220924 

В application.properties прописываем наши данные для доступу к боту.

bot.name=OfficialRateOfBYNBot bot.token=5888893679:AAGQWAbS0zCMtnQrTeWrVYz9KHj2nUlyVIw

Создадим папку config, и там создадим класс BotConfig. Он нужен для использования имени и токена нашего бота для подключения к нему.

@Configuration @Data @PropertySource("application.properties") public class BotConfig < @Value("$") String botName; @Value("$") String token; >

Сейчас поговорим про API через которую мы будем получать данные о курсах валют. Я нашел такой https://www.nbrb.by/apihelp/exrates на официальном сайте национального банка.

Отправив get запрос на данный API через postman мы получим вот такой json.

Чтобы легче обрабатывать json создадим класс CurrencyModel в папке model

@Data public class CurrencyModel

Далее создадим класс CurrencyService в папке service.

public class CurrencyService < public static String getCurrencyRate(String message, CurrencyModel model) throws IOException, ParseException < URL url = new URL("https://www.nbrb.by/api/exrates/rates/" + message + "?parammode=2"); Scanner scanner = new Scanner((InputStream) url.getContent()); String result = ""; while (scanner.hasNext())< result +=scanner.nextLine(); >JSONObject object = new JSONObject(result); model.setCur_ID(object.getInt("Cur_ID")); model.setDate(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(object.getString("Date"))); model.setCur_Abbreviation(object.getString("Cur_Abbreviation")); model.setCur_Scale(object.getInt("Cur_Scale")); model.setCur_Name(object.getString("Cur_Name")); model.setCur_OfficialRate(object.getDouble("Cur_OfficialRate")); return "Official rate of BYN to " + model.getCur_Abbreviation() + "\n" + "on the date: " + getFormatDate(model) + "\n" + "is: " + model.getCur_OfficialRate() + " BYN per " + model.getCur_Scale() + " " + model.getCur_Abbreviation(); > private static String getFormatDate(CurrencyModel model) < return new SimpleDateFormat("dd MMM yyyy").format(model.getDate()); >>

В данном классе мы напишем статический метод getCurrencyRate, делаем его статическим чтобы обращаться к нему без создания объекта данного класса. В данном методе мы «идем» на сайт НБ и там по запрашиваемой валюте находим её курс и сохраняем полученную информацию в нашу модель CurrencyModel. На выходе выдаем данные, из этой модели уже в таком виде, в котором их будут видеть наши пользователи.

Далее создаем класс TelegramBot и наследуемся от TelegramLongPollingBot.

@Component @AllArgsConstructor public class TelegramBot extends TelegramLongPollingBot < private final BotConfig botConfig; @Override public String getBotUsername() < return botConfig.getBotName(); >@Override public String getBotToken() < return botConfig.getToken(); >@Override public void onUpdateReceived(Update update) < CurrencyModel currencyModel = new CurrencyModel(); String currency = ""; if(update.hasMessage() && update.getMessage().hasText())< String messageText = update.getMessage().getText(); long chatId = update.getMessage().getChatId(); switch (messageText)< case "/start": startCommandReceived(chatId, update.getMessage().getChat().getFirstName()); break; default: try < currency = CurrencyService.getCurrencyRate(messageText, currencyModel); >catch (IOException e) < sendMessage(chatId, "We have not found such a currency." + "\n" + "Enter the currency whose official exchange rate" + "\n" + "you want to know in relation to BYN." + "\n" + "For example: USD"); >catch (ParseException e) < throw new RuntimeException("Unable to parse date"); >sendMessage(chatId, currency); > > > private void startCommandReceived(Long chatId, String name) < String answer = "Hi, " + name + ", nice to meet you!" + "\n" + "Enter the currency whose official exchange rate" + "\n" + "you want to know in relation to BYN." + "\n" + "For example: USD"; sendMessage(chatId, answer); >private void sendMessage(Long chatId, String textToSend) < SendMessage sendMessage = new SendMessage(); sendMessage.setChatId(String.valueOf(chatId)); sendMessage.setText(textToSend); try < execute(sendMessage); >catch (TelegramApiException e) < >> >

В данном классе внедряем класс BotConfig с нашими настройками для подключения к боту. Переопределяем три метода класса TelegramLongPollingBot:

getBotUsername() — возвращаем имя нашего бота.

getBotToken() — возвращаем токен нашего бота.

onUpdateReceived(Update update) — данный метод вызывается каждый раз при отправке сообщения пользователем. Он вызывается с параметром update, с помощью которого мы можем получить текст сообщения, id чата для отправки ответного сообщения и другую информацию.

Также я написал дополнительно два метода:

startCommandReceived(Long chatId, String name) — данный метод отправляет приветствие после набора команды /start в telegram.

sendMessage(Long chatId, String textToSend) — данный метод через id чата отправляет пользователю сообщение в telegram.

И последний класс, который мы создадим BotInitializer в папке config.

@Component public class BotInitializer < private final TelegramBot telegramBot; @Autowired public BotInitializer(TelegramBot telegramBot) < this.telegramBot = telegramBot; >@EventListener() public void init()throws TelegramApiException < TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class); try< telegramBotsApi.registerBot(telegramBot); >catch (TelegramApiException e) < >> >

В данном классе создаем сессию и регистрируем нашего telegram бота.

Наш бот готов! Будем тестировать!

Находим нашего бота в telegram.

Переходим в telegram и нажимаем start или набираем /start и получаем

Можем тестировать дальше. Наш функционал работает.

Спасибо Всем кто читал данную статью. Пока.

Telegram-бот на Java для самых маленьких — от старта до бесплатного размещения на heroku

Если вы ни разу не писали Telegram-ботов на Java и только начинаете разбираться — эта статья для вас. В ней подробно и с пояснениями описано создание реального бота, автоматизирующего одну конкретную функцию. Можно использовать статью как мануал для создания скелета своего бота, а потом подключить его к своей бизнес-логике.

Предыстория

Когда моя дочь начала изучать арифметику, я между делом накидал алгоритм генерации простых примеров на сложение и вычитание вида «5 + 7 =», чтобы не придумывать и не гуглить для неё задания.

И тут на глаза попалась новость, что Telegram выпустил новую версию Bot API 5.0. Ботов я раньше не писал, и потому решил попробовать поднять бота как интерфейс для своей поделки. Все примеры, которые мне удалось найти, показались либо совсем простыми (нужные мне функции не были представлены), либо очень сложными для новичка. Также мне не хватало объяснений, почему выбран тот или иной путь. В общем, написано было сразу для умных, а не для меня. Потому я решил описать свой опыт создания простого бота — надеюсь, кому-нибудь это поможет быстрее въехать в тему.

Что в статье есть, чего нет

В статье есть про:

  • создание бекенда не-инлайн бота на Java 11 с использованием Telegram Bot Api 5.0;
  • обработка команд вида /dosomething ;
  • обработка текстовых сообщений, не являющихся командами (т.е. не начинающихся с «/»);
  • отправку пользователю текстовых сообщений и файлов;
  • деплой и запуск бота на heroku.
  • использование функций ботов, не перечисленных выше (например, создание клавиатур — я их сначала добавил, но в итоге они мне просто не пригодились);
  • создание списка заданий;
  • работу с Word-документом;
  • обеспечивающие функции — логирование, тесты и т.п.;
  • общение с BotFather (создание бота, получение его токена и формирование списка команд подробно и понятно описано во многих источниках, вот первый попавшийся мануал).

Бизнес-функции бота

  • выдавать пользователю справочную текстовую информацию в ответ на команды /start , /help и /settings ;
  • обрабатывать и запоминать пользовательские настройки, направленные текстовым сообщением заданного формата. Настроек три — минимальное + максимальное число, используемые в заданиях, и количество страниц выгружаемого файла;
  • оповещать пользователя о несоблюдении им формата сообщения;
  • формировать Word-файл с заданиями на сложение, вычитание или вперемешку в ответ на команды /plus , /minus и /plusminus с использованием дефолтных или установленных пользователем настроек.

Порядок разработки

  • разобраться с зависимостями;
  • создать класс бота и реализовать обработку текстовых сообщений пользователя, не являющихся командами;
  • создать классы команд;
  • прописать запуск приложения;
  • задеплоить на heroku.

Зависимости

Для управления зависимостями использовался Apache Maven. Нужные зависимости — собственно Telegram Bots и Lombok, использовавшийся для упрощения кода (заменяет стандартные java-методы аннотациями).

Вот что вышло в

pom.xml

 *** *** 1.0-SNAPSHOT *** *** jar 11 $ $ UTF-8 1.18.16 4.1.2 5.0.1    org.telegram telegrambots $ org.telegram telegrambotsextensions $  org.projectlombok lombok $ compile   $  org.apache.maven.plugins maven-compiler-plugin 3.8.1 $  org.projectlombok lombok $    org.apache.maven.plugins maven-dependency-plugin 3.1.2  copy-dependencies package copy-dependencies     org.apache.maven.plugins maven-surefire-plugin 3.0.0-M5    

Класс бота и обработка текстовых сообщений

Мой класс Bot унаследован от TelegramLongPollingCommandBot , который, в свою очередь, наследуется от более распространённого в примерах TelegramLongPollingBot . Он хорош тем, что в нём уже реализованы приём и обработка команд — то есть сообщений, начинающихся с «/». Можно создавать отдельные классы команд (подробнее о них ниже), инициализировать их в конструкторе бота и уже в них писать логику их обработки.

В классе Bot таким образом остаётся только логика обработки текстовых сообщений, не являющихся командами. В моём случае это пользовательские настройки или мусорные сообщения, не соответствующие формату. Для лаконичности логику их обработки тоже стоит вынести в отдельный вспомогательный класс, вызывая его метод из переопределенного метода processNonCommandUpdate(Update update) класса Bot .

В качестве параметров для инициализации бота используются его имя и токен, полученные от BotFather. В ходе разработки удобно создать тестового бота и прописать его параметры прямо в коде, чтобы проще было запускать бекенд локально и отлаживать прямо в Telegram, однако перед релизом стоит пересоздать бота и вынести эти настройки из кода — например, в переменные окружения (об этом ниже).

Получился вот такой

Bot.java

import lombok.Getter; import org.telegram.telegrambots.extensions.bots.commandbot.TelegramLongPollingCommandBot; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import ru.taksebe.telegram.mentalCalculation.telegram.commands.operations.MinusCommand; import ru.taksebe.telegram.mentalCalculation.telegram.commands.operations.PlusCommand; import ru.taksebe.telegram.mentalCalculation.telegram.commands.operations.PlusMinusCommand; import ru.taksebe.telegram.mentalCalculation.telegram.commands.service.HelpCommand; import ru.taksebe.telegram.mentalCalculation.telegram.commands.service.SettingsCommand; import ru.taksebe.telegram.mentalCalculation.telegram.commands.service.StartCommand; import ru.taksebe.telegram.mentalCalculation.telegram.nonCommand.NonCommand; import ru.taksebe.telegram.mentalCalculation.telegram.nonCommand.Settings; import java.util.HashMap; import java.util.Map; public final class Bot extends TelegramLongPollingCommandBot < private final String BOT_NAME; private final String BOT_TOKEN; //Настройки по умолчанию @Getter private static final Settings defaultSettings = new Settings(1, 15, 1); //Класс для обработки сообщений, не являющихся командой private final NonCommand nonCommand; /** * Настройки файла для разных пользователей. Ключ - уникальный id чата */ @Getter private static MapuserSettings; public Bot(String botName, String botToken) < super(); this.BOT_NAME = botName; this.BOT_TOKEN = botToken; //создаём вспомогательный класс для работы с сообщениями, не являющимися командами this.nonCommand = new NonCommand(); //регистрируем команды register(new StartCommand("start", "Старт")); register(new PlusCommand("plus", "Сложение")); register(new MinusCommand("minus", "Вычитание")); register(new PlusMinusCommand("plusminus", "Сложение и вычитание")); register(new HelpCommand("help","Помощь")); register(new SettingsCommand("settings", "Мои настройки")); userSettings = new HashMap<>(); > @Override public String getBotToken() < return BOT_TOKEN; >@Override public String getBotUsername() < return BOT_NAME; >/** * Ответ на запрос, не являющийся командой */ @Override public void processNonCommandUpdate(Update update) < Message msg = update.getMessage(); Long chatId = msg.getChatId(); String userName = getUserName(msg); String answer = nonCommand.nonCommandExecute(chatId, userName, msg.getText()); setAnswer(chatId, userName, answer); >/** * Получение настроек по id чата. Если ранее для этого чата в ходе сеанса работы бота настройки не были установлены, используются настройки по умолчанию */ public static Settings getUserSettings(Long chatId) < MapuserSettings = Bot.getUserSettings(); Settings settings = userSettings.get(chatId); if (settings == null) < return defaultSettings; >return settings; > /** * Формирование имени пользователя * @param msg сообщение */ private String getUserName(Message msg) < User user = msg.getFrom(); String userName = user.getUserName(); return (userName != null) ? userName : String.format("%s %s", user.getLastName(), user.getFirstName()); >/** * Отправка ответа * @param chatId id чата * @param userName имя пользователя * @param text текст ответа */ private void setAnswer(Long chatId, String userName, String text) < SendMessage answer = new SendMessage(); answer.setText(text); answer.setChatId(chatId.toString()); try < execute(answer); >catch (TelegramApiException e) < //логируем сбой Telegram Bot API, используя userName >> > 

Класс обработки текстовых сообщений
NonCommand.java

import ru.taksebe.telegram.mentalCalculation.exceptions.IllegalSettingsException; import ru.taksebe.telegram.mentalCalculation.telegram.Bot; /** * Обработка сообщения, не являющегося командой (т.е. обычного текста не начинающегося с "/") */ public class NonCommand < public String nonCommandExecute(Long chatId, String userName, String text) < Settings settings; String answer; try < //создаём настройки из сообщения пользователя settings = createSettings(text); //добавляем настройки в мапу, чтобы потом их использовать для этого пользователя при генерации файла saveUserSettings(chatId, settings); answer = "Настройки обновлены. Вы всегда можете их посмотреть с помощью /settings"; //логируем событие, используя userName >catch (IllegalSettingsException e) < answer = e.getMessage() + "\n\n Настройки не были изменены. Вы всегда можете их посмотреть с помощью /settings"; //логируем событие, используя userName >catch (Exception e) < answer = "Простите, я не понимаю Вас. Возможно, Вам поможет /help"; //логируем событие, используя userName >return answer; > /** * Создание настроек из полученного пользователем сообщения * @param text текст сообщения * @throws IllegalArgumentException пробрасывается, если сообщение пользователя не соответствует формату */ private Settings createSettings(String text) throws IllegalArgumentException < //отсекаем файлы, стикеры, гифки и прочий мусор if (text == null) < throw new IllegalArgumentException("Сообщение не является текстом"); >//создаём из сообщения пользователя 3 числа-настройки (min, max, listCount) либо пробрасываем исключение о несоответствии сообщения требуемому формату return new Settings(min, max, listCount); > /** * Добавление настроек пользователя в мапу, чтобы потом их использовать для этого пользователя при генерации файла * Если настройки совпадают с дефолтными, они не сохраняются, чтобы впустую не раздувать мапу * @param chatId id чата * @param settings настройки */ private void saveUserSettings(Long chatId, Settings settings) < if (!settings.equals(Settings.getDefaultSettings())) < Bot.getUserSettings().put(chatId, settings); >else < Bot.getUserSettings().remove(chatId); >> > 

Классы команд

Все классы команд наследуются от BotCommand .

Команды в моём боте делятся на 2 группы:

  • Сервисные — возвращают справочную информацию;
  • Основные — формируют файл с заданиями.

Начнём с более простых Сервисных команд. В абстрактный суперкласс вынесен метод отправки пользователю ответа, а в классах команд формируется текст ответа.

Абстрактный суперкласс Сервисных команд

ServiceCommand.java

import org.telegram.telegrambots.extensions.bots.commandbot.commands.BotCommand; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.bots.AbsSender; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; /** * Суперкласс для сервисных команд */ abstract class ServiceCommand extends BotCommand < ServiceCommand(String identifier, String description) < super(identifier, description); >/** * Отправка ответа пользователю */ void sendAnswer(AbsSender absSender, Long chatId, String commandName, String userName, String text) < SendMessage message = new SendMessage(); //включаем поддержку режима разметки, чтобы управлять отображением текста и добавлять эмодзи message.enableMarkdown(true); message.setChatId(chatId.toString()); message.setText(text); try < absSender.execute(message); >catch (TelegramApiException e) < //логируем сбой Telegram Bot API, используя commandName и userName >> > 

Класс Сервисной команды на примере
StartCommand.java

import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; /** * Команда "Старт" */ public class StartCommand extends ServiceCommand < public StartCommand(String identifier, String description) < super(identifier, description); >@Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) < //формируем имя пользователя - поскольку userName может быть не заполнено, для этого случая используем имя и фамилию пользователя String userName = (user.getUserName() != null) ? user.getUserName() : String.format("%s %s", user.getLastName(), user.getFirstName()); //обращаемся к методу суперкласса для отправки пользователю ответа sendAnswer(absSender, chat.getId(), this.getCommandIdentifier(), userName, "Давайте начнём! Если Вам нужна помощь, нажмите /help"); >> 

В суперклассе Основных команд, помимо аналогичного метода отправки ответов, содержится формирование Word-документа.

OperationCommand.java

import org.telegram.telegrambots.extensions.bots.commandbot.commands.BotCommand; import org.telegram.telegrambots.meta.api.methods.send.SendDocument; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.InputFile; import org.telegram.telegrambots.meta.bots.AbsSender; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import ru.taksebe.telegram.mentalCalculation.calculation.Calculator; import ru.taksebe.telegram.mentalCalculation.calculation.PlusMinusService; import ru.taksebe.telegram.mentalCalculation.enums.OperationEnum; import ru.taksebe.telegram.mentalCalculation.fileProcessor.WordFileProcessorImpl; import ru.taksebe.telegram.mentalCalculation.telegram.Settings; import java.io.FileInputStream; import java.io.IOException; import java.util.List; /** * Суперкласс для команд создания заданий с различными операциями */ abstract class OperationCommand extends BotCommand < private PlusMinusService service; OperationCommand(String identifier, String description) < super(identifier, description); this.service = new PlusMinusService(new WordFileProcessorImpl(), new Calculator()); >/** * Отправка ответа пользователю */ void sendAnswer(AbsSender absSender, Long chatId, List operations, String description, String commandName, String userName) < try < absSender.execute(createDocument(chatId, operations, description)); >catch (IOException | IllegalArgumentException e) < sendError(absSender, chatId, commandName, userName); e.printStackTrace(); >catch (TelegramApiException e) < //логируем сбой Telegram Bot API, используя commandName и userName >> /** * Создание документа для отправки пользователю * @param chatId id чата * @param operations список типов операций (сложение и/или вычитание) * @param fileName имя, которое нужно присвоить файлу */ private SendDocument createDocument(Long chatId, List operations, String fileName) throws IOException < FileInputStream stream = service.getPlusMinusFile(operations, Bot.getUserSettings(chatId)); SendDocument document = new SendDocument(); document.setChatId(chatId.toString()); document.setDocument(new InputFile(stream, String.format("%s.docx", fileName))); return document; >/** * Отправка пользователю сообщения об ошибке */ private void sendError(AbsSender absSender, Long chatId, String commandName, String userName) < try < absSender.execute(new SendMessage(chatId.toString(), "Похоже, я сломался. Попробуйте позже")); >catch (TelegramApiException e) < //логируем сбой Telegram Bot API, используя commandName и userName >> > 

Класс Основной команды на примере
PlusMinusCommand.java

import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; import ru.taksebe.telegram.mentalCalculation.enums.OperationEnum; /** * Команда получение файла с заданиями на сложение и вычитание */ public class PlusMinusCommand extends OperationCommand < public PlusMinusCommand(String identifier, String description) < super(identifier, description); >@Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) < //формируем имя пользователя - поскольку userName может быть не заполнено, для этого случая используем имя и фамилию пользователя String userName = (user.getUserName() != null) ? user.getUserName() : String.format("%s %s", user.getLastName(), user.getFirstName()); //обращаемся к методу суперкласса для формирования файла на сложение и вычитание (за это отвечает метод getPlusMinus() перечисления OperationEnum) и отправки его пользователю sendAnswer(absSender, chat.getId(), OperationEnum.getPlusMinus(), this.getDescription(), this.getCommandIdentifier(), userName); >> 

Приложение

В методе main инициализируется TelegramBotsApi , в котором и регистрируется Bot.

TelegramBotsApi в качестве параметра принимает Class . Если нет никаких заморочек с прокси, можно использовать DefaultBotSession.class .

Чтобы получать имя и токен бота как переменные окружения, необходимо использовать System.getenv() .

Получаем вот такой

MentalCalculationApplication.java

import org.telegram.telegrambots.meta.TelegramBotsApi; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; import ru.taksebe.telegram.mentalCalculation.telegram.Bot; import java.util.Map; public class MentalCalculationApplication < private static final Mapgetenv = System.getenv(); public static void main(String[] args) < try < TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); botsApi.registerBot(new Bot(getenv.get("BOT_NAME"), getenv.get("BOT_TOKEN"))); >catch (TelegramApiException e) < e.printStackTrace(); >> > 

Деплой на heroku

Для начала нужно создать в корне проекта файл Procfile и написать в него одну строку:
worker: java -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -cp ./target/classes:./target/dependency/*
, где worker — это тип процесса.

Если в проекте используется версия Java, отличная от 8, также необходимо создать в корне проекта файл system.properties и прописать в нём одну строку:
java.runtime.version=

Далее порядок такой:

  1. Регистрируемся на heroku и идём в консоль;
  2. mvn clean install ;
  3. heroku login — после выполнения потребуется нажать любую клавишу и залогиниться в открывшемся окне браузера;
  4. heroku create — создаём приложение на heroku;
  5. git push heroku master — пушим в репозиторий heroku;
  6. heroku config:set BOT_NAME= — добавляем имя бота в переменные окружения;
  7. heroku config:set BOT_TOKEN= — добавляем токен бота в переменные окружения;
  8. heroku config:get BOT_NAME (аналогично BOT_TOKEN) — убеждаемся, что переменные окружения установлены верно;
  9. heroku ps:scale worker=1 — устанавливаем количество контейнеров (dynos) для типа процесса worker (ранее мы выбрали этот тип в Procfile), при этом происходит рестарт приложения;
  10. В интерфейсе управления приложением в личном кабинете на heroku переходим к логам (прячутся под кнопкой «More» в правом верхнем углу) и убеждаемся, что приложение запущено;
  11. Тестируем бота через Telegram.

Что можно доделать

Heroku периодически перезапускает приложение, и тогда введённые пользователем настройки удаляются. Можно добавить к проекту БД (например, Heroku Redis, как в другом моём боте), чтобы этого избежать.

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

Вместо заключения

Как выяснилось, не только лишь все видели чудесный советский мультик про козлёнка, который учился считать до 10.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *