Всем привет! Да-да тема не очень актуальна и на просторах habr-a есть очень много статей про то, как написать простейшего telegram bota, но я все-таки рискну написать еще одну. Может кому-то она будет интересна и полезна.
Для написания бота нужен аккаунт в telegram.
И так начнем: наш бот будет "ходить" на официальную страницу национального банка и выдавать текущий официальный курс к запрашиваемой валюте.
Создадим проект, я это сделаю с помощью https://start.spring.io/

Генерируем и открываем в среде разработки.
Сейчас нужно зайти в telegram и найти там @BotFather.

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

После этого BotFather сгенерирует нам уникальный токен с помощью которого мы получим доступ к нему. Данный токен лучше держать в секрете и никому не показывать, потому что узнав его можно получить доступ к этому боту. Конечно после написания данной статьи я его поменяю.
Далее идем в наш проект и добавляем зависимости для telegram, lombok и json. Библиотеку json будем использовать для пар��инга jsona, который будем получать через официальный API банка.
<dependency> <groupId>org.telegram</groupId> <artifactId>telegrambots</artifactId> <version>6.5.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20220924</version> </dependency>
В application.properties прописываем наши данные для доступу к боту.
bot.name=OfficialRateOfBYNBot bot.token=5888893679:AAGQWAbS0zCMtnQrTeWrVYz9KHj2nUlyVIw
Создадим папку config, и там создадим класс BotConfig. Он нужен для использования имени и токена нашего бота для подключения к нему.
@Configuration @Data @PropertySource("application.properties") public class BotConfig { @Value("${bot.name}") String botName; @Value("${bot.token}") String token; }
Сейчас поговорим про API через которую мы будем получать данные о курсах валют. Я нашел такой https://www.nbrb.by/apihelp/exrates на официальном сайте национального банка.

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

Чтобы легче обрабатывать json создадим класс CurrencyModel в папке model
@Data public class CurrencyModel { Integer cur_ID; Date date; String cur_Abbreviation; Integer cur_Scale; String cur_Name; Double cur_OfficialRate; }
Далее создадим класс 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({ContextRefreshedEvent.class}) public void init()throws TelegramApiException{ TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class); try{ telegramBotsApi.registerBot(telegramBot); } catch (TelegramApiException e){ } } }
В данном классе создаем сессию и регистрируем нашего telegram бота.
Наш бот готов! Будем тестировать!
Находим нашего бота в telegram.

Запускаем проект.

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

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

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