每个在日常生活中使用Telegram的开发人员(不仅如此),至少曾经考虑过创建自己的bot的感觉,难易程度以及最佳使用哪种编程语言。
对于所有这些问题,我都可以给出最简单(也可能是最正确)的答案:这完全取决于您自己,您的知识和意图。
...但是在这篇简短的文章中,我将展示如何使用Java语言创建自己的bot,它非常有趣且不复杂。
我们将使用该库来与Telegram Bots API及其扩展一起使用 ,这使我们能够创建自己的命令(' /custom_cmd
')并以简单的方式对其进行处理。
该机器人的任务是注册用户,并以指定的名称向其他机器人用户发送消息。
创建一个新项目并进行准备
1.向项目添加依赖项
创建一个新的maven项目并编辑pom.xml
,向其中添加必要的依赖项:
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> <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- 用于与Telegram Bots API配合使用的库 ,包含用于与Telegram服务进行交互的类和方法以及这些类的某些扩展。
2.为漫游器创建一个帐户
为此,我们需要联系BotFather机器人以寻求帮助:
- 在搜索中找到机器人;
- 执行命令“ /开始”;
- 执行命令“ / newbot”;
- 让我们为我们的机器人设置一个名称(应该以“ Bot”结尾)。 我称它为“ ExampleOfAnonymizerBot”。
执行完这些命令后,我们将获得使用Bot API所需的令牌。 (7xxxxxxx2:Axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0)



实作
1.匿名消息发送者模型
我们需要每个用户提供的数据:
- 用户mUser-有关电报用户的信息;
- 聊天mChat-用户和机器人聊天信息;
- 字符串mDisplayedName-用户将从其发送消息给机器人其他用户的名称。
匿名.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; } }
添加一个包含用于操纵许多匿名用户的常用方法的服务。
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界面
任何自定义命令都应继承自BotCommand
并实现一个方法
execute(AbsSender sender, User user, Chat chat, String[] strings)
,用于处理用户命令。
处理完用户的命令后,我们可以使用AbsSender
类的execute
方法向他发送响应,该方法采用上述execute(AbsSender sender, User user, Chat chat, String[] strings)
。
在下文中,为了不每次都包装在AbsSender.execute
方法中,该方法可以在try-catch
抛出TelegramApiException
,并且为了不在每个命令中写入单调日志,我们将创建AnonymizerCommand
类,并从中继承自定义命令(在此示例中,我们将保留异常处理):
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); } } }
定义我们的机器人将响应的命令:
/start
-创建一个没有名称的新Anonymous
并将其添加到Anonymouses
集合中;
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;
/help
help-向用户显示有关所有可用命令的信息(构造函数与其他构造函数的不同之处在于,您需要将ICommandRegistry
传递ICommandRegistry
,其中包含所有自定义命令);
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); } }
/set_name
用户/set_name
一个将从其发送匿名消息的名称;
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 <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); } }
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.机器人的初始化和启动
一个bot类,其中注册了所有自定义命令,非命令消息处理程序和未知命令。
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);
最后,启动机器人:
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); } } }
仅此而已! 该机器人已准备好进行首次测试。
使用范例
例如,请考虑以下情形:
- 'A'开始使用机器人(
/start
); - “ A”正在尝试发送消息;
- 'A'试图设置一个名字(
/set_name
); - 'A'设置名称(
/set_name Pendalf
); - 'A'向其他用户(不是)发送消息;
- 'B'开始使用机器人(
/start
); - 'B'设置名称(
/set_name Chuck Norris
); - “ B”向其他用户发送消息;
- “ A”看到来自“ B”的消息并发送消息作为响应;
- 'B'看到了'A'的答案,不再写信给他...


