Greetings, my dear friends. Yes, yes, exactly friends. I have already become so familiar with this series of articles that those people who regularly write their gratitude in the comments and/or show that they have read and understood the material have already become close. You and I are moving from both sides towards the same goal. You want to understand, but I want to explain. And we have the same final goal - a written application that is understandable to you from start to finish. You may have already heard about much of what I will describe in this article. I don’t think that I will tell you anything new and extraordinary (but within the framework of the project it is necessary to know/repeat this). In the spring I wrote a bot for myself, so we will rely on its “patterns”.
We write JRTB-2
We will do the same as we did in the article with task JRTB-0 :- We update the main branch in the local project using the ctrl + t combination .
- Based on the main branch, we create:
- Add a bot.
- We create a new commit with a description of what has been done and push it to GitHub.
- Create a pull request for the main branch and check it again. We are waiting for the build to go through (github actions), merge it into the main branch.
- Close the corresponding task.
What is a telegram bot
We, developers, can imagine working with a telegram bot like this: we use their client to work with them. We have a ready-made library for work. There is a set of actions after which the telegram bot will know that it is associated with our program. And already inside the program we will learn how to receive letters, commands and somehow process them. There is such a thing as a command in telegram bots : it begins with a slash “/”. After it, we immediately write the word together, and this will be considered a command. For example, there are two commands that everyone should know:- /start — start working with the bot;
- /stop - end work with the bot.
Create a bot with BotFather
To connect a bot, you first need to create it. Telegram has an approach - creating a bot with its own unique name. It will also be accompanied by a token (a large string that works like a password). I have already created a bot for JavaRush - @javarush_community_bot . This bot is still empty and can’t do anything. The main thing is that there should be _bot at the end of the name . To show how to do this, I will create a bot on which we will test our functionality. In terms of real projects, this would be a test environment. And our main one will be the prod environment (prod - production, that is, the real environment on which the project will be executed). Of course, it would be possible to add another environment - a sandbox environment: a common sandbox, more changeable and accessible to all development participants. But this will only complicate the situation at the project creation stage. For now, let's create two more bots for test and for sandbox environment. The first step is to create (register) a bot in Telegram itself. We need to find the bot: @BotFather and write the command to it: /newbot Next, we are asked to give a name to this bot. Since this is a bot for testing tasks, its name will be appropriate: [TEST] JavarushBot Now it’s time to give a unique name by which it can always be found - its username: test_javarush_community As I said above, you need to add the _bot suffix for username, so we write again: test_javarush_community_bot And that’s it! The bot has been created. Now, using username and token, it can be connected to our project. Of course, for the smooth operation of the test server, I will not display the token (essentially a password to access the bot) of this bot for public viewing.We connect the bot to the project
We will not include the library as usual, but will immediately take advantage of our skeleton - SpringBoot. He has such a thing as Starter. By including the library, we can use it to let SpringBoot know that we want to configure the project correctly. If we were to go the usual route, which is described in many places, we would need to create a configuration somewhere that would have something like this:ApiContextInitializer.init();
TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
try {
telegramBotsApi.registerBot(Bot.getBot());
} catch (TelegramApiRequestException e) {
e.printStackTrace();
}
Here an object is created with which you can establish a connection with the bot. In our case, the starter that we want to connect will do everything for us somewhere “under the hood” (this is also a translation of a frequently used phrase in IT - under the hood). Here is a link to this starter . You can immediately see from the README.md file what it is, why and how to use it. To connect it, you just need to add this dependency to the memory. That's all :) Here is the required dependency:
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-spring-boot-starter</artifactId>
<version>5.0.1</version>
</dependency>
We add it to our memory. We install the version as expected and update the Maven project. Based on the description, we just need to create a new class, inherit from TelegramLongPollingBot and add this class to the Application Context of our SpringBoot. Application Context is the place where the created objects for running the project are stored. To add a class, you need to use one of the annotations: @Component, @Service, @Repository, @Controller. Or the @Bean annotation if created through a method in a configuration class (that is, in a class that is marked with the Configuration annotation). I understand that all this may still seem incomprehensible. But when you start to figure it out, you will see that there is nothing complicated there. To quickly understand Spring Boot, I recommend a cool book - Spring In Action 5th edition. If there is a desire, I can write a series of articles based on this book. Let's go back. In the package that contains JavarushTelegramBotApplication, we create the bot package , which will contain our telegram bot. Its name will be JavaRushTelegramBot :
package com.github.javarushcommunity.jrtb.bot;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;
/**
* Telegrambot for Javarush Community from Javarush community.
*/
@Component
public class JavarushTelegramBot extends TelegramLongPollingBot {
@Override
public void onUpdateReceived(Update update) {
}
@Override
public String getBotUsername() {
return null;
}
@Override
public String getBotToken() {
return null;
}
}
This class was abstract and three methods had to be implemented. Let's talk about them in more detail:
- onUpdateReceived(Update update) - this is the entry point where messages from users will arrive. All new logic will come from here;
- getBotUsername() - here you need to add the username of our bot to which we will connect;
- getBotToken() - and this, accordingly, is the bot token.
- bot.username ;
- bot.token .
package com.github.javarushcommunity.jrtb.bot;
import org.springframework.beans.factory.annotation.Value;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;
/**
* Telegram bot for Javarush Community from Javarush community.
*/
@Component
public class JavarushTelegramBot extends TelegramLongPollingBot {
@Value("${bot.username}")
private String username;
@Value("${bot.token}")
private String token;
@Override
public void onUpdateReceived(Update update) {
}
@Override
public String getBotUsername() {
return username;
}
@Override
public String getBotToken() {
return token;
}
}
It can be seen that we passed the value of the variable to the annotation. And when SpringBoot creates our bot object, the values will be taken from the properties (again, tracing paper from English - properties). We're almost there. You need to make the bot answer something. Therefore, let's update the onUpdateReceived method . We need to retrieve the message that came to the bot and pass it back. This way we will know that the bot is working. To do this, we will roughly and quickly write what is needed:
@Override
public void onUpdateReceived(Update update) {
if(update.hasMessage() && update.getMessage().hasText()) {
String message = update.getMessage().getText().trim();
String chatId = update.getMessage().getChatId().toString();
SendMessage sm = new SendMessage();
sm.setChatId(chatId);
sm.setText(message);
try {
execute(sm);
} catch (TelegramApiException e) {
//todo add logging to the project.
e.printStackTrace();
}
}
}
Everything here is extremely simple: we check that the message really exists, so we extract the message itself ( message ) and the chat ID ( chatId ) in which the correspondence is taking place. Next, we create an object for sending a message SendMessage , pass the message itself and the chat ID to it - that is, what to send to the bot and where. We already have enough of this. Next, we run the main method in the JavarushTelegramBotApplication class and look for our bot in Telegram: From the logs we see that the bot has started. So, it’s time to go to Telegram and write to the bot: We click start and we immediately receive an answer: Let’s write some more crap to check: And that’s it, at this point we can say that our JRTB-2 task is completed. You can’t really write any tests here yet, so we’ll leave everything as it is. Next you need to create a new commit: Pay attention to the name of the commit: again I draw your attention to this. A commit first contains the name of the task, and then a more detailed description of what has been done. Click Commit and Push... and confirm by clicking Push again : Go to our project . As before, GitHub has already seen the new branch and offers to create a pull request for main. We don’t resist and create it: As usual, we have already chosen a label, a project and assigned it to me. Finally, click Create Pull Request. Let's wait a little while the build goes through - and that's it, the pull request is ready for merging:
Versioning
I somehow missed the point that we need to do versioning. To do this, we will make a few more changes in our branch. We go back to IDEA and look at the project version in the memory: The version is 0.0.1-SNAPSHOT . This is the duty version. And we will start by updating the version of the project with each new solved problem. Until we reach MVP, the version will come with the suffix -SNAPSHOT. What will be the versioning scheme? XYZ-SNAPSHOT Where:- X - major version update, often contains problems with backward compatibility with the previous version;
- Y - not very big changes, fully compatible with the previous version;
- Z is a counter of defects that we found and repaired.
GO TO FULL VERSION