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.
Create a new maven project and edit pom.xml
, adding the necessary dependencies to it:
<?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.
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)
The data we need from each user:
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.
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)); } }
Any custom command must inherit from BotCommand
and implement the methodexecute(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):
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:
/start
- creates a new Anonymous
without a name and adds it to the Anonymouses
collection; 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 <displayed_name> 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); } }
/help
- displays to the user information about all available commands (the constructor differs from others in that it is necessary to transfer ICommandRegistry
, which contains all custom commands, to it); 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); } }
/set_name
- will /set_name
user a name from which anonymous messages will be sent; 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; } }
/my_name
- displays the current username; 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 <displayed_name>'"); 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); } }
/stop
- removes the user from the anonymus collection. 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); } }
The bot class in which all custom commands are registered, non-command message handlers, and unknown commands.
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:
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.
As an example, consider the following scenario:
/start
);/set_name
);/set_name Pendalf
);/start
);/set_name Chuck Norris
);Source: https://habr.com/ru/post/432548/
All Articles