JavaRush /Java 博客 /Random-ZH /向项目中添加电报机器人 - 《Java 项目从 A 到 Z》
Roman Beekeeper
第 35 级

向项目中添加电报机器人 - 《Java 项目从 A 到 Z》

已在 Random-ZH 群组中发布
问候,我亲爱的朋友们。是的,是的,完全是朋友。我已经对这一系列文章变得如此熟悉,以至于那些经常在评论中写下感激之情和/或表明他们已阅读并理解这些材料的人已经变得很亲密。你我正从双方朝着同一个目标前进。你想明白,但我想解释。我们有相同的最终目标 - 一份您从头到尾都可以理解的书面申请。您可能已经听说过我将在本文中描述的大部分内容。我不认为我会告诉你任何新的和非凡的东西(但在项目的框架内有必要知道/重复这一点)。 “Java 项目从头到尾”:向项目添加电报机器人 - 1今年春天,我为自己编写了一个机器人,因此我们将依赖它的“模式”。

我们写JRTB-2

我们将执行与任务JRTB-0文章中相同的操作:
  1. 我们使用ctrl + t组合更新本地项目中的分支。“Java 项目从头到尾”:向项目添加电报机器人 - 2
  2. 基于主分支,我们创建:“Java 项目从头到尾”:向项目添加电报机器人 - 3
  3. 添加机器人。
  4. 我们创建一个新的提交,其中包含已完成操作的描述,并将其推送到 GitHub。
  5. 为主分支创建拉取请求并再次检查。我们正在等待构建完成(github actions),将其合并到主分支中。
  6. 关闭相应的任务。

什么是电报机器人

我们,开发人员,可以想象与这样的电报机器人一起工作:我们使用他们的客户端与他们一起工作。我们有一个现成的工作库。在执行一系列操作后,电报机器人就会知道它与我们的程序相关联。在程序中我们将学习如何接收信件、命令并以某种方式处理它们。电报机器人中存在命令这样的东西:它以斜杠“/”开头。之后,我们立即将这个词写在一起,这将被视为一个命令。比如有两个命令大家都应该知道:
  • /start — 开始使用机器人;
  • /stop - 结束与机器人的工作。
剩下的我们自己来做。让我立即预订:我们将按照我学到的方式去做。当与机器人合作时,我确信可以做得更好。如果有人愿意这样做,我会很高兴,并将尽一切可能支持这一努力。 顺便说一句,如果有人向我解释如何通过代码而不是通过电报中的机器人设置来编程命令描述,那就太酷了。我没学过这个。 我们的资源中有几篇文章描述了如何制作基本的机器人:今天我们将做类似的事情。如果您还有其他疑问,我建议您浏览一下本文

使用 BotFather 创建机器人

要连接机器人,您首先需要创建它。Telegram 有一种方法 - 创建一个具有自己独特名称的机器人。它还会附带一个令牌(一个类似于密码的大字符串)。我已经为 JavaRush 创建了一个机器人 - @javarush_community_bot。这个机器人仍然是空的,什么也做不了。最主要的是名称末尾应该有_bot。为了展示如何做到这一点,我将创建一个机器人,我们将在其上测试我们的功能。就实际项目而言,这将是一个测试环境。我们的主要环境将是 prod 环境(prod - 生产,即项目将执行的真实环境)。当然,可以添加另一个环境——沙箱环境:一个通用的沙箱,对所有开发参与者来说更加可变和可访问。但这只会使项目创建阶段的情况变得更加复杂。现在,我们再创建两个机器人用于测试和沙箱环境。第一步是在 Telegram 本身中创建(注册)一个机器人。我们需要找到机器人:@BotFather并向其写入命令: /newbot“Java 项目从头到尾”:向项目添加电报机器人 - 4接下来,我们需要为此机器人命名。由于这是一个用于测试任务的机器人,因此它的名称将是合适的: [TEST] JavarushBot“Java 项目从头到尾”:向项目添加电报机器人 - 5现在是时候给出一个可以始终找到它的唯一名称 - 它的用户名: test_javarush_community“Java 项目从头到尾”:向项目添加电报机器人 - 6正如我上面所说,您需要添加 _bot用户名的后缀,所以我们再次编写: test_javarush_community_bot“Java 项目从 A 到 Z”:向项目添加电报机器人 - 7就这样!机器人已创建。现在,使用用户名和令牌,它可以连接到我们的项目。当然,为了测试服务器的顺利运行,我不会将这个机器人的令牌(本质上是访问机器人的密码)显示给公众查看。

我们将机器人连接到项目

我们不会像往常一样包含该库,但会立即利用我们的骨架 - SpringBoot。他有一个像Starter这样的东西。通过包含该库,我们可以使用它让 SpringBoot 知道我们想要正确配置项目。如果我们要走通常的路线(在很多地方都有描述),我们需要在某个地方创建一个配置,其中包含如下内容:
ApiContextInitializer.init();
TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
try {
  telegramBotsApi.registerBot(Bot.getBot());
} catch (TelegramApiRequestException e) {
  e.printStackTrace();
}
这里创建了一个对象,您可以用它与机器人建立连接。在我们的例子中,我们想要连接的启动器将在“引擎盖下”的某个地方为我们做所有事情(这也是 IT 中经常使用的短语 - under the hood 的翻译)。这是此入门指南的链接。您可以立即从 README.md 文件中看到它是什么、为什么以及如何使用它。要连接它,你只需要将这个依赖添加到内存中即可。这就是全部:) 这是所需的依赖项:
<dependency>
        <groupId>org.telegram</groupId>
        <artifactId>telegrambots-spring-boot-starter</artifactId>
        <version>5.0.1</version>
    </dependency>
我们将它添加到我们的记忆中。我们按预期安装版本并更新 Maven 项目。“Java 项目从头到尾”:向项目添加电报机器人 - 8根据描述,我们只需要创建一个新类,继承自TelegramLongPollingBot,并将该类添加到我们的SpringBoot的Application Context中。 应用程序上下文是存储运行项目所创建的对象的地方。要添加类,需要使用以下注解之一:@Component、@Service、@Repository、@Controller。或者,如果通过配置类(即使用 Configuration 注释标记的类)中的方法创建,则为 @Bean 注释。 我知道这一切可能仍然令人难以理解。但当你开始弄清楚这一点时,你会发现这并没有什么复杂的。为了快速理解Spring Boot,我推荐一本很酷的书——Spring In Action 5th edition。如果有愿望,我可以根据这本书写一系列文章。我们回去吧。在包含 JavarushTelegramBotApplication 的包中,我们创建bot包,其中将包含我们的电报机器人。它的名称将是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;
   }
}
这个类是抽象的,必须实现三个方法。让我们更详细地讨论它们:
  • onUpdateReceived(Update update) - 这是来自用户的消息到达的入口点。所有新的逻辑都将来自这里;
  • getBotUsername() - 在这里您需要添加我们将连接的机器人的用户名;
  • getBotToken() - 因此,这是机器人令牌。
本质上,它就像网站的登录名和密码。我们暂时不会显式地写入该值。这称为“硬编码”(即绑定一些特定值 - 像往常一样,从英文硬代码中绑定描图纸)。你不应该这样做。我们将采用另一种方式 - 我们将这些数据写入application.properties类并从这里读取它。为什么这是必要的?然后,这样当应用程序启动时,我们就可以在外部设置这些值。很灵活,就对了。转到文件 src/main/resources/application.properties。在那里我们将为这些变量命名。具有 .properties 扩展名的文件被读取为由“=”分隔的键值结构,每一对都是单独的行。所以我想出了这些变量:
  • 机器人.用户名;
  • 机器人令牌
它看起来像这样:“Java 项目从头到尾”:向项目添加电报机器人 - 9SpringBoot 有一个很棒的注释 - @Value。如果使用正确,它将从 application.properties 文件中提取值。我们用这个更新项目:
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;
   }
}
可以看到我们将变量的值传递给了注解。当 SpringBoot 创建我们的 bot 对象时,将从属性中获取值(同样,来自英语的描图纸 - 属性)。我们快到了。您需要让机器人回答一些问题。因此,我们来更新一下onUpdateReceived方法。我们需要检索发送给机器人的消息并将其传回。这样我们就知道机器人正在工作。为此,我们将粗略地快速写出需要的内容:
@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();
       }
   }
}
这里的一切都非常简单:我们检查消息是否确实存在,因此我们提取消息本身 ( message ) 和发生通信的聊天 ID ( chatId )。接下来,我们创建一个用于发送消息的对象SendMessage,将消息本身和聊天 ID 传递到其中 - 即发送给机器人的内容和发送地点。我们已经受够了。接下来,我们运行JavarushTelegramBotApplication类中的 main 方法,并在 Telegram 中查找我们的机器人:“Java 项目从头到尾”:向项目添加电报机器人 - 10从日志中我们看到机器人已经启动。所以,是时候去 Telegram 给机器人写信了:“Java 项目从头到尾”:向项目添加电报机器人 - 11我们点击开始,我们立即收到答案:“Java 项目从头到尾”:向项目添加电报机器人 - 12让我们再写一些废话来检查:“Java 项目从头到尾”:向项目添加电报机器人 - 13就是这样,此时我们可以说我们的 JRTB-2 任务已经完成。您还不能真正在这里编写任何测试,因此我们将保留一切原样。接下来,您需要创建一个新的提交:“Java 项目从头到尾”:向项目添加电报机器人 - 14请注意提交的名称:我再次提请您注意这一点。提交首先包含任务的名称,然后是已完成操作的更详细描述。单击“提交并推送...” ,然后再次单击“推送”进行确认:“Java 项目从头到尾”:向项目添加电报机器人 - 15转到我们的项目。和以前一样,GitHub 已经看到了新分支,并提出为 main 创建拉取请求。我们不抗拒并创造它:“Java 项目从头到尾”:向项目添加电报机器人 - 16像往常一样,我们已经选择了一个标签、一个项目并将其分配给我。最后,单击“创建拉取请求”。让我们等一下构建完成 - 就这样,拉取请求已准备好合并:“Java 项目从头到尾”:向项目添加电报机器人 - 17

版本控制

我不知何故错过了我们需要进行版本控制的这一点。为此,我们将在我们的分支中进行更多更改。我们回到IDEA,查看内存中的项目版本:“Java 项目从头到尾”:向项目添加电报机器人 - 18版本为0.0.1-SNAPSHOT。这是值班版本。我们将首先用每个新解决的问题更新项目的版本。在我们达到 MVP 之前,该版本将带有后缀 -SNAPSHOT。版本控制方案是什么? XYZ-快照 其中:
  • X——主要版本更新,经常包含与先前版本向后兼容的问题;
  • Y——变化不大,完全兼容之前的版本;
  • Z 是我们发现并修复的缺陷的计数器。
基于此,我们将拥有第一个版本 - 0.1.0-SNAPSHOT - 也就是说,我们还没有进行重大更新,只是所有内容都有一点点,而且我们还没有达到 MVP,所以有一个后缀 -SNAPSHOT 。让我们在内存中更改此内容:“Java 项目从头到尾”:向项目添加电报机器人 - 19转到 RELEASE_NOTES 文件,我们将在其中描述每个新版本对项目的更改:“Java 项目从头到尾”:向项目添加电报机器人 - 20我们的第一个条目。现在,随着后续的每个版本更新,我们将在这里描述到底发生了什么。我们提交这个案例,写一个描述: JRTB-2:更新了项目版本并添加到 RELEASE_NOTES 一切都和以前一模一样。我们正在等待构建通过,然后可以合并我们的更改。只是这里会有点不同。我想确保主分支中的每个任务都是单独的提交,因此简单地推送合并拉取请求对我们来说不起作用。Git 有 git squash 选项,它将所有提交收集到一起并合并它们。我们选择这个选项:“Java 项目从 A 到 Z”:向项目添加 Telegram 机器人 - 21点击“挤压并合并”,然后我们就可以编辑消息了,最后会是:“Java 项目从头到尾”:向项目添加电报机器人 - 22非常方便,最重要的是,需要什么。顺便说一句,我在bitbucket上还没看到这样的功能=/确认合并。剩下的唯一一件事就是在我们的面板中将任务更改为“完成”状态,写一条带有拉取请求链接的评论并关闭它:“Java 项目从头到尾”:向项目添加电报机器人 - 23我们的面板现在看起来像这样:“Java 项目从头到尾”:向项目添加电报机器人 - 24

结论

今天我们一步步创建了一个telegram bot,并在我们的SpringBoot项目中实现了它。机器人工作并给出答案。我们立即通过属性访问机器人数据。更多内容:我们将做一件大事 - 执行JRTB-3 - 为我们的项目添加命令模式。哦,还有一件事... 我告诉过你我不会发布令牌,这样它就不会被使用。但由于我是在接近午夜下班后写这篇文章的,结果发现我在存储库中发布了一个有效的令牌,GitGuardian 在一封信中告诉我这一点:“Java 项目从头到尾”:向项目添加电报机器人 - 25感谢他们!现在做什么?将不再可能从 git 中删除它,因为即使我上传一个没有此令牌的新提交,它仍然会保留在旧的提交中。但我不想删除并回滚提交。所以我去激活了已经提到的 BotFather 的令牌。现在令牌在那里,但不再有效。在发布文章之前,请订阅我的 GitHub 帐户以查看其所有代码。感谢大家的阅读,很快再见。

该系列所有材料的列表位于本文开头。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION