Pull to refresh

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

Reading time5 min
Views52K

Всем привет! Да-да тема не очень актуальна и на просторах 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 и получаем

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

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

Tags:
Hubs:
Total votes 2: ↑1 and ↓1+1
Comments8

Articles