📜 ⬆️ ⬇️

An example of using Java-library to create Telegram-bot

Every developer (and not only) who uses Telegram in everyday life, at least once thought about what it is - to create your own bot, how difficult it is and what programming language is better to use.


I can give the simplest (and, probably, the most correct) answer to all these questions: everything depends on you, your knowledge and intentions.


... But in this small article, I will show how you can create your bot in the Java language and that it is quite interesting and easy.


We will use the library to work with the Telegram Bots API and its extension , which allows you to create your teams (' /custom_cmd ') and process them in a simple way.


The task of the bot will be to register the user and send a message on behalf of his name to other bot users.


Creating a new project and preparing


1. Adding dependencies to the project


Create a new maven project and edit pom.xml , adding the necessary dependencies to it:


pom.xml
  <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>io.example</groupId> <artifactId>anonymizerbot</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> ```8</source> <target>8</target> </configuration> </plugin> </plugins> </build> <dependencies> <!-- Telegram API --> <dependency> <groupId>org.telegram</groupId> <artifactId>telegrambots</artifactId> <version>LATEST</version> </dependency> <dependency> <groupId>org.telegram</groupId> <artifactId>telegrambotsextensions</artifactId> <version>LATEST</version> </dependency> ... </dependencies> </project> 

Telegram API - a library for working with the Telegram Bots API , contains classes and methods for interacting with Telegram services and some extensions of these classes.


2. Creating an account for the bot


To do this, we need to contact BotFather bot for help:



After executing these commands, we get the token we need to use the Bot API. (7xxxxxxx2: Axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0)






Implementation


1. Model anonymous sender of messages


The data we need from each user:



Anonymous.java
 package io.example.anonymizerbot.model; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; public final class Anonymous { private static final Logger LOG = LogManager.getLogger(Anonymous.class); private static final String USER_CHAT_CANNOT_BE_NULL = "User or chat cannot be null!"; private final User mUser; private final Chat mChat; private String mDisplayedName; public Anonymous(User user, Chat chat) { if (user == null || chat == null) { LOG.error(USER_CHAT_CANNOT_BE_NULL); throw new IllegalStateException(USER_CHAT_CANNOT_BE_NULL); } mUser = user; mChat = chat; } @Override public int hashCode() { return mUser.hashCode(); } @Override public boolean equals(Object obj) { return obj instanceof Anonymous && ((Anonymous) obj).getUser().equals(mUser); } public User getUser() { return mUser; } public Chat getChat() { return mChat; } public String getDisplayedName() { return mDisplayedName; } public void setDisplayedName(String displayedName) { mDisplayedName = displayedName; } } 

Add a service containing commonly used methods to manipulate a variety of anonymous users.


AnonymousService.java
 package io.example.anonymizerbot.service; import io.example.anonymizerbot.model.Anonymous; import org.telegram.telegrambots.meta.api.objects.User; import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.stream.Stream; public final class AnonymousService { private final Set<Anonymous> mAnonymouses; public AnonymousService() { mAnonymouses = new HashSet<>(); } public boolean setUserDisplayedName(User user, String name) { if (!isDisplayedNameTaken(name)) { mAnonymouses.stream().filter(a -> a.getUser().equals(user)).forEach(a -> a.setDisplayedName(name)); return true; } return false; } public boolean removeAnonymous(User user) { return mAnonymouses.removeIf(a -> a.getUser().equals(user)); } public boolean addAnonymous(Anonymous anonymous) { return mAnonymouses.add(anonymous); } public boolean hasAnonymous(User user) { return mAnonymouses.stream().anyMatch(a -> a.getUser().equals(user)); } public String getDisplayedName(User user) { Anonymous anonymous = mAnonymouses.stream().filter(a -> a.getUser().equals(user)).findFirst().orElse(null); if (anonymous == null) { return null; } return anonymous.getDisplayedName(); } public Stream<Anonymous> anonymouses() { return mAnonymouses.stream(); } private boolean isDisplayedNameTaken(String name) { return mAnonymouses.stream().anyMatch(a -> Objects.equals(a.getDisplayedName(), name)); } } 

2. Bot interface


Any custom command must inherit from BotCommand and implement the method
execute(AbsSender sender, User user, Chat chat, String[] strings) , which is used to process user commands.


After we process the user's command, we can send him a response using the AbsSender class's execute method, which accepts the above-mentioned execute(AbsSender sender, User user, Chat chat, String[] strings) as input.


Hereinafter, in order not to wrap the AbsSender.execute method that can throw a TelegramApiException exception into a try-catch each time, and in order not to write the output of uniform logs to each command, create the AnonymizerCommand class, and our custom commands will inherit from it (leave the exception handling in this example):


AnonymizerCommand.java
 package io.example.anonymizerbot.command; import io.example.anonymizerbot.logger.LogLevel; import io.example.anonymizerbot.logger.LogTemplate; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.telegram.telegrambots.extensions.bots.commandbot.commands.BotCommand; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; abstract class AnonymizerCommand extends BotCommand { final Logger log = LogManager.getLogger(getClass()); AnonymizerCommand(String commandIdentifier, String description) { super(commandIdentifier, description); } void execute(AbsSender sender, SendMessage message, User user) { try { sender.execute(message); log.log(Level.getLevel(LogLevel.SUCCESS.getValue()), LogTemplate.COMMAND_SUCCESS.getTemplate(), user.getId(), getCommandIdentifier()); } catch (TelegramApiException e) { log.error(LogTemplate.COMMAND_EXCEPTION.getTemplate(), user.getId(), getCommandIdentifier(), e); } } } 

We define the commands to which our bot will respond:



StartCommand.java
 package io.example.anonymizerbot.command; import io.example.anonymizerbot.logger.LogLevel; import io.example.anonymizerbot.logger.LogTemplate; import io.example.anonymizerbot.model.Anonymous; import io.example.anonymizerbot.service.AnonymousService; import org.apache.logging.log4j.Level; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; public final class StartCommand extends AnonymizerCommand { private final AnonymousService mAnonymouses; //     , //        public StartCommand(AnonymousService anonymouses) { super("start", "start using bot\n"); mAnonymouses = anonymouses; } /** *    BotCommand,    ,   * @param absSender -    * @param user - ,    * @param chat -     * @param strings - ,    */ @Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) { log.info(LogTemplate.COMMAND_PROCESSING.getTemplate(), user.getId(), getCommandIdentifier()); StringBuilder sb = new StringBuilder(); SendMessage message = new SendMessage(); message.setChatId(chat.getId().toString()); if (mAnonymouses.addAnonymous(new Anonymous(user, chat))) { log.info("User {} is trying to execute '{}' the first time. Added to users' list.", user.getId(), getCommandIdentifier()); sb.append("Hi, ").append(user.getUserName()).append("! You've been added to bot users' list!\n") .append("Please execute command:\n'/set_name <displayed_name>'\nwhere &lt;displayed_name&gt; is the name you want to use to hide your real name."); } else { log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} has already executed '{}'. Is he trying to do it one more time?", user.getId(), getCommandIdentifier()); sb.append("You've already started bot! You can send messages if you set your name (/set_name)."); } message.setText(sb.toString()); execute(absSender, message, user); } } 


HelpCommand.java
 package io.example.anonymizerbot.command; import io.example.anonymizerbot.logger.LogTemplate; import org.telegram.telegrambots.extensions.bots.commandbot.commands.ICommandRegistry; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; public final class HelpCommand extends AnonymizerCommand { private final ICommandRegistry mCommandRegistry; public HelpCommand(ICommandRegistry commandRegistry) { super("help", "list all known commands\n"); mCommandRegistry = commandRegistry; } @Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) { log.info(LogTemplate.COMMAND_PROCESSING.getTemplate(), user.getId(), getCommandIdentifier()); StringBuilder helpMessageBuilder = new StringBuilder("<b>Available commands:</b>"); mCommandRegistry.getRegisteredCommands().forEach(cmd -> helpMessageBuilder.append(cmd.toString()).append("\n")); SendMessage helpMessage = new SendMessage(); helpMessage.setChatId(chat.getId().toString()); helpMessage.enableHtml(true); helpMessage.setText(helpMessageBuilder.toString()); execute(absSender, helpMessage, user); } } 


SetNameCommand.java
 package io.example.anonymizerbot.command; import io.example.anonymizerbot.logger.LogLevel; import io.example.anonymizerbot.logger.LogTemplate; import io.example.anonymizerbot.service.AnonymousService; import org.apache.logging.log4j.Level; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; public final class SetNameCommand extends AnonymizerCommand { private final AnonymousService mAnonymouses; public SetNameCommand(AnonymousService anonymouses) { super("set_name", "set or change name that will be displayed with your messages\n"); mAnonymouses = anonymouses; } @Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) { log.info(LogTemplate.COMMAND_PROCESSING.getTemplate(), user.getId(), getCommandIdentifier()); SendMessage message = new SendMessage(); message.setChatId(chat.getId().toString()); if (!mAnonymouses.hasAnonymous(user)) { log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to execute '{}' without starting the bot!", user.getId(), getCommandIdentifier()); message.setText("Firstly you should start the bot! Execute '/start' command!"); execute(absSender, message, user); return; } String displayedName = getName(strings); if (displayedName == null) { log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to set empty name.", user.getId()); message.setText("You should use non-empty name!"); execute(absSender, message, user); return; } StringBuilder sb = new StringBuilder(); if (mAnonymouses.setUserDisplayedName(user, displayedName)) { if (mAnonymouses.getDisplayedName(user) == null) { log.info("User {} set a name '{}'", user.getId(), displayedName); sb.append("Your displayed name: '").append(displayedName) .append("'. Now you can send messages to bot!"); } else { log.info("User {} has changed name to '{}'", user.getId(), displayedName); sb.append("Your new displayed name: '").append(displayedName).append("'."); } } else { log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to set taken name '{}'", user.getId(), displayedName); sb.append("Name ").append(displayedName).append(" is already in use! Choose another name!"); } message.setText(sb.toString()); execute(absSender, message, user); } private String getName(String[] strings) { if (strings == null || strings.length == 0) { return null; } String name = String.join(" ", strings); return name.replaceAll(" ", "").isEmpty() ? null : name; } } 


MyNameCommand.java
 package io.example.anonymizerbot.command; import io.example.anonymizerbot.logger.LogLevel; import io.example.anonymizerbot.logger.LogTemplate; import io.example.anonymizerbot.service.AnonymousService; import org.apache.logging.log4j.Level; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; public final class MyNameCommand extends AnonymizerCommand { private final AnonymousService mAnonymouses; public MyNameCommand(AnonymousService anonymouses) { super("my_name", "show your current name that will be displayed with your messages\n"); mAnonymouses = anonymouses; } @Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) { log.info(LogTemplate.COMMAND_PROCESSING.getTemplate(), user.getId(), getCommandIdentifier()); StringBuilder sb = new StringBuilder(); SendMessage message = new SendMessage(); message.setChatId(chat.getId().toString()); if (!mAnonymouses.hasAnonymous(user)) { sb.append("You are not in bot users' list! Send /start command!"); log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to execute '{}' without starting the bot.", user.getId(), getCommandIdentifier()); } else if(mAnonymouses.getDisplayedName(user) == null) { sb.append("Currently you don't have a name.\nSet it using command:\n'/set_name &lt;displayed_name&gt;'"); log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to execute '{}' without having a name.", user.getId(), getCommandIdentifier()); } else { log.info("User {} is executing '{}'. Name is '{}'.", user.getId(), getCommandIdentifier(), mAnonymouses.getDisplayedName(user)); sb.append("Your current name: ").append(mAnonymouses.getDisplayedName(user)); } message.setText(sb.toString()); execute(absSender, message, user); } } 


StopCommand.java
 package io.example.anonymizerbot.command; import io.example.anonymizerbot.logger.LogLevel; import io.example.anonymizerbot.logger.LogTemplate; import io.example.anonymizerbot.service.AnonymousService; import org.apache.logging.log4j.Level; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.bots.AbsSender; public final class StopCommand extends AnonymizerCommand { private final AnonymousService mAnonymouses; public StopCommand(AnonymousService anonymouses) { super("stop", "remove yourself from bot users' list\n"); mAnonymouses = anonymouses; } @Override public void execute(AbsSender absSender, User user, Chat chat, String[] strings) { log.info(LogTemplate.COMMAND_PROCESSING.getTemplate(), user.getId(), getCommandIdentifier()); StringBuilder sb = new StringBuilder(); SendMessage message = new SendMessage(); message.setChatId(chat.getId().toString()); if (mAnonymouses.removeAnonymous(user)) { log.info("User {} has been removed from users list!", user.getId()); sb.append("You've been removed from bot's users list! Bye!"); } else { log.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to execute '{}' without having executed 'start' before!", user.getId(), getCommandIdentifier()); sb.append("You were not in bot users' list. Bye!"); } message.setText(sb.toString()); execute(absSender, message, user); } } 

3. Initialization and launch of the bot


The bot class in which all custom commands are registered, non-command message handlers, and unknown commands.


AnonymizerBot.java
 package io.example.anonymizerbot.bot; import io.example.anonymizerbot.command.*; import io.example.anonymizerbot.logger.LogLevel; import io.example.anonymizerbot.logger.LogTemplate; import io.example.anonymizerbot.model.Anonymous; import io.example.anonymizerbot.service.AnonymousService; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.telegram.telegrambots.bots.DefaultBotOptions; 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 java.util.stream.Stream; public final class AnonymizerBot extends TelegramLongPollingCommandBot { private static final Logger LOG = LogManager.getLogger(AnonymizerBot.class); //  ,        BotFather //  ,     private static final String BOT_NAME = "AnonymizerBotExample"; private static final String BOT_TOKEN = "7xxxxxxx2:Axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0"; private final AnonymousService mAnonymouses; public AnonymizerBot(DefaultBotOptions botOptions) { super(botOptions, BOT_NAME); LOG.info("Initializing Anonymizer Bot..."); LOG.info("Initializing anonymouses list..."); mAnonymouses = new AnonymousService(); //     LOG.info("Registering commands..."); LOG.info("Registering '/start'..."); register(new StartCommand( mAnonymouses)); LOG.info("Registering '/set_name'..."); register(new SetNameCommand(mAnonymouses)); LOG.info("Registering '/stop'..."); register(new StopCommand(mAnonymouses)); LOG.info("Registering '/my_name'..."); register(new MyNameCommand(mAnonymouses)); HelpCommand helpCommand = new HelpCommand(this); LOG.info("Registering '/help'..."); register(helpCommand); //    LOG.info("Registering default action'..."); registerDefaultAction(((absSender, message) -> { LOG.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to execute unknown command '{}'.", message.getFrom().getId(), message.getText()); SendMessage text = new SendMessage(); text.setChatId(message.getChatId()); text.setText(message.getText() + " command not found!"); try { absSender.execute(text); } catch (TelegramApiException e) { LOG.error("Error while replying unknown command to user {}.", message.getFrom(), e); } helpCommand.execute(absSender, message.getFrom(), message.getChat(), new String[] {}); })); } @Override public String getBotToken() { return BOT_TOKEN; } //      '/' @Override public void processNonCommandUpdate(Update update) { LOG.info("Processing non-command update..."); if (!update.hasMessage()) { LOG.error("Update doesn't have a body!"); throw new IllegalStateException("Update doesn't have a body!"); } Message msg = update.getMessage(); User user = msg.getFrom(); LOG.info(LogTemplate.MESSAGE_PROCESSING.getTemplate(), user.getId()); if (!canSendMessage(user, msg)) { return; } String clearMessage = msg.getText(); String messageForUsers = String.format("%s:\n%s", mAnonymouses.getDisplayedName(user), msg.getText()); SendMessage answer = new SendMessage(); //     ,     answer.setText(clearMessage); answer.setChatId(msg.getChatId()); replyToUser(answer, user, clearMessage); //       answer.setText(messageForUsers); Stream<Anonymous> anonymouses = mAnonymouses.anonymouses(); anonymouses.filter(a -> !a.getUser().equals(user)) .forEach(a -> { answer.setChatId(a.getChat().getId()); sendMessageToUser(answer, a.getUser(), user); }); } //  ,        private boolean canSendMessage(User user, Message msg) { SendMessage answer = new SendMessage(); answer.setChatId(msg.getChatId()); if (!msg.hasText() || msg.getText().trim().length() == 0) { LOG.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to send empty message!", user.getId()); answer.setText("You shouldn't send empty messages!"); replyToUser(answer, user, msg.getText()); return false; } if(!mAnonymouses.hasAnonymous(user)) { LOG.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to send message without starting the bot!", user.getId()); answer.setText("Firstly you should start bot! Use /start command!"); replyToUser(answer, user, msg.getText()); return false; } if (mAnonymouses.getDisplayedName(user) == null) { LOG.log(Level.getLevel(LogLevel.STRANGE.getValue()), "User {} is trying to send message without setting a name!", user.getId()); answer.setText("You must set a name before sending messages.\nUse '/set_name <displayed_name>' command."); replyToUser(answer, user, msg.getText()); return false; } return true; } private void sendMessageToUser(SendMessage message, User receiver, User sender) { try { execute(message); LOG.log(Level.getLevel(LogLevel.SUCCESS.getValue()), LogTemplate.MESSAGE_RECEIVED.getTemplate(), receiver.getId(), sender.getId()); } catch (TelegramApiException e) { LOG.error(LogTemplate.MESSAGE_LOST.getTemplate(), receiver.getId(), sender.getId(), e); } } private void replyToUser(SendMessage message, User user, String messageText) { try { execute(message); LOG.log(Level.getLevel(LogLevel.SUCCESS.getValue()), LogTemplate.MESSAGE_SENT.getTemplate(), user.getId(), messageText); } catch (TelegramApiException e) { LOG.error(LogTemplate.MESSAGE_EXCEPTION.getTemplate(), user.getId(), e); } } } 

Finally, launch the bot:


BotInitializer.java
 package io.example.anonymizerbot; import io.example.anonymizerbot.bot.AnonymizerBot; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.telegram.telegrambots.ApiContextInitializer; import org.telegram.telegrambots.bots.DefaultBotOptions; import org.telegram.telegrambots.meta.ApiContext; import org.telegram.telegrambots.meta.TelegramBotsApi; import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; public final class BotInitializer { private static final Logger LOG = LogManager.getLogger(BotInitializer.class); private static final String PROXY_HOST = "xx.xx.xxx.xxx"; private static final int PROXY_PORT = 9999; public static void main(String[] args) { try { LOG.info("Initializing API context..."); ApiContextInitializer.init(); TelegramBotsApi botsApi = new TelegramBotsApi(); LOG.info("Configuring bot options..."); DefaultBotOptions botOptions = ApiContext.getInstance(DefaultBotOptions.class); botOptions.setProxyHost(PROXY_HOST); botOptions.setProxyPort(PROXY_PORT); botOptions.setProxyType(DefaultBotOptions.ProxyType.SOCKS4); LOG.info("Registering Anonymizer..."); botsApi.registerBot(new AnonymizerBot(botOptions)); LOG.info("Anonymizer bot is ready for work!"); } catch (TelegramApiRequestException e) { LOG.error("Error while initializing bot!", e); } } } 

That's all! The bot is ready for the first tests.


Usage example


As an example, consider the following scenario:


  1. 'A' starts working with the bot ( /start );
  2. 'A' is trying to send a message;
  3. 'A' tries to set a name ( /set_name );
  4. 'A' sets the name ( /set_name Pendalf );
  5. 'A' sends a message to other users (who do not);
  6. 'B' starts working with the bot ( /start );
  7. 'B' sets the name ( /set_name Chuck Norris );
  8. 'B' sends the message to other users;
  9. 'A' sees the message from 'B' and sends the message in reply;
  10. 'B' sees the answer from 'A' and doesn't write to him anymore ...




')

Source: https://habr.com/ru/post/432548/


All Articles