用 R 编写电报机器人(第 2 部分):向机器人添加命令支持和消息过滤器

В 以前的出版物 我们弄清楚了如何创建一个机器人,初始化了该类的一个实例 Bot 并熟悉了使用它发送消息的方法。

在这篇文章中我将继续这个主题,所以我建议在阅读完之后才开始阅读这篇文章 第一部分.

这次我们将弄清楚如何恢复我们的机器人并为其添加命令支持,并熟悉该类 Updater.

在本文中,我们将编写几个简单的机器人,后者将根据给定的日期和国家代码,根据生产日历确定给定国家的一天是周末还是工作日。 但是,和以前一样,本文的目的是让您熟悉包接口 telegram.bot 来解决你自己的问题。

用 R 编写电报机器人(第 2 部分):向机器人添加命令支持和消息过滤器

“用 R 编写电报机器人”系列的所有文章

  1. 我们创建一个机器人并用它来发送电报消息
  2. 向机器人添加命令支持和消息过滤器

内容

如果您对数据分析感兴趣,您可能会对我的文章感兴趣 电报 и YouTube的 渠道。 大部分内容专门介绍 R 语言。

  1. 更新程序类
  2. 处理程序 - 处理程序
  3. 将第一个命令添加到机器人,命令处理程序
  4. 文本消息处理器和过滤器
  5. 添加带参数的命令
  6. 在后台运行机器人
  7. 结论

更新程序类

Updater 是一个可以让您更轻松地开发电报机器人的类,并在幕后使用该类 Dispetcher。课堂作业 Updater 是接收来自机器人的更新(在上一篇文章中我们使用了用于此目的的方法 getUpdates()),并将它们进一步转移到 Dispetcher.

反过来 Dispetcher 包含您创建的处理程序,即类对象 Handler.

处理程序 - 处理程序

使用处理程序添加到 Dispetcher 机器人对各种事件的反应。 在撰写本文时 telegram.bot 添加了以下类型的处理程序:

  • MessageHandler — 消息处理程序
  • CommandHandler - 命令处理程序
  • CallbackQueryHandler - 从 Inline 发送的键盘的数据处理程序
  • ErrorHandler - 向机器人请求更新时的错误处理程序

将第一个命令添加到机器人,命令处理程序

如果您以前从未使用过机器人并且不知道命令是什么,则必须使用正斜杠向机器人发送命令 / 作为前缀。

我们将从简单的命令开始,即让我们教我们的机器人按照命令打招呼 /hi.

代码 1:教机器人打招呼

library(telegram.bot)

# создаём экземпляр класса Updater
updater <- Updater('ТОКЕН ВАШЕГО БОТА')

# Пишем метод для приветсвия
say_hello <- function(bot, update) {

  # Имя пользователя с которым надо поздароваться
  user_name <- update$message$from$first_name

  # Отправка приветственного сообщения
  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Моё почтение, ", user_name, "!"), 
                  parse_mode = "Markdown")

}

# создаём обработчик 
hi_hendler <- CommandHandler('hi', say_hello)

# добаляем обработчик в диспетчер
updater <- updater + hi_hendler

# запускаем бота
updater$start_polling()

将“YOUR BOT TOKEN”替换为您在创建机器人时收到的真实令牌后,运行上面的代码示例 僵尸之父 (我谈到了创建一个机器人 第一篇文章).

方法 start_polling()Updater,在代码末尾使用,启动从机器人请求和处理更新的无限循环。

现在让我们打开 Telegram 并将第一个命令写入我们的机器人 /hi.

用 R 编写电报机器人(第 2 部分):向机器人添加命令支持和消息过滤器

现在我们的机器人理解了这个命令 /hi,并且知道如何向我们打招呼。

概要地,构建这样一个简单的机器人的过程可以描述如下。

用 R 编写电报机器人(第 2 部分):向机器人添加命令支持和消息过滤器

  1. 创建类的实例 Updater;
  2. 我们创建方法,即我们的机器人将执行的功能。 在代码示例中,这是一个函数 say_hello()。 您将用作机器人方法的函数必须有两个必需参数 - BOT и 更新,以及一个可选的 - ARGS。 争论 BOT,这是您的机器人,在它的帮助下您可以回复消息、发送消息或使用机器人可用的任何其他方法。争论 更新 这是机器人从用户那里收到的内容,事实上,我们在第一篇文章中使用该方法收到的内容 getUpdates()。 争论 ARGS 允许您处理用户随命令发送的附加数据,我们稍后将回到这个主题;
  3. 我们创建处理程序,即我们将一些用户操作与上一步中创建的方法关联起来。 本质上,处理程序是一个触发器,一个调用某些机器人函数的事件。 在我们的示例中,此类触发器正在发送命令 /hi,并由团队实施 hi_hendler <- CommandHandler('hi', say_hello)。第一个函数参数 CommandHandler() 允许您指定一个命令,在我们的例子中 hi,机器人将对此做出响应。第二个参数允许您指定机器人方法,我们将调用该方法 say_hello,如果用户调用第一个参数中指定的命令,则会执行该命令;
  4. 接下来,我们将创建的处理程序添加到类实例的调度程序中 Updater。 您可以通过多种方式添加处理程序;在上面的示例中,我使用了最简单的一种,使用符号 +updater <- updater + hi_hendler。使用该方法也可以完成相同的操作 add_handler(),属于该类 Dispatcher,你可以这样找到这个方法: updater$dispatcher$add_handler();
  5. 使用命令启动机器人 start_polling().

文本消息处理器和过滤器

我们弄清楚了如何向机器人发送命令,但有时我们需要机器人不仅响应命令,还需要响应一些常规短信。 为此,您需要使用消息处理程序 - 消息处理器.

正常 消息处理器 将响应绝对所有传入消息。因此,消息处理程序经常与过滤器一起使用。让我们教机器人不仅按照命令打招呼 /hi,而且每当发送给机器人的消息中出现以下单词之一时:你好、你好、致敬、海伊、你好。

现在我们不会编写任何新方法,因为...... 我们已经有了机器人向我们打招呼的方法。 我们需要做的就是创建所需的过滤器和消息处理程序。

代码 2:添加短信处理程序和过滤器

library(telegram.bot)

# создаём экземпляр класса Updater
updater <- Updater('ТОКЕН ВАШЕГО БОТА')

# Пишем метод для приветсвия
## команда приветвия
say_hello <- function(bot, update) {

  # Имя пользователя с которым надо поздароваться
  user_name <- update$message$from$first_name

  # Отправляем приветсвенное сообщение
  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Моё почтение, ", user_name, "!"),
                  parse_mode = "Markdown",
                  reply_to_message_id = update$message$message_id)

}

# создаём фильтры
MessageFilters$hi <- BaseFilter(function(message) {

  # проверяем, встречается ли в тексте сообщения слова: привет, здравствуй, салют, хай, бонжур
  grepl(x           = message$text, 
        pattern     = 'привет|здравствуй|салют|хай|бонжур',
        ignore.case = TRUE)
  }
)

# создаём обработчик 
hi_hendler <- CommandHandler('hi', say_hello) # обработчик команды hi
hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi)

# добаляем обработчики в диспетчер
updater <- updater + 
             hi_hendler +
             hi_txt_hnd

# запускаем бота
updater$start_polling()

将“YOUR BOT TOKEN”替换为您在创建机器人时收到的真实令牌后,运行上面的代码示例 僵尸之父 (我谈到了创建一个机器人 第一篇文章).

现在,我们尝试向机器人发送几条包含前面列出的问候语的消息:
用 R 编写电报机器人(第 2 部分):向机器人添加命令支持和消息过滤器

因此,首先,我们教机器人不仅要打招呼,还要回应问候。 我们使用参数来做到这一点 回复消息 ID,在方法中可用 sendMessage(),您需要将要响应的消息的 id 传输到其中。 您可以这样获取消息 id: update$message$message_id.

但我们做的主要事情是使用该函数向机器人添加过滤器 BaseFilter():

# создаём фильтры
MessageFilters$hi <- BaseFilter( 

  # анонимная фильтрующая функция
  function(message) {

    # проверяем, встречается ли в тексте сообщения слова приветствия
    grepl(x           = message$text, 
          pattern     = 'привет|здравствуй|салют|хай|бонжур',
          ignore.case = TRUE)
  }

)

您可能已经注意到,需要将过滤器添加到对象中 消息过滤器,它最初已经包含一小组现成的过滤器。 在我们的例子中,对于对象 消息过滤器 我们添加了一个元素 hi,这是一个新的过滤器。

发挥作用 BaseFilter() 你需要通过过滤功能。 本质上,过滤器只是一个接收消息实例并返回的函数 TRUE или FALSE。在我们的示例中,我们编写了一个简单的函数,使用基本函数 grepl() 检查消息文本以及它是否与正则表达式匹配 привет|здравствуй|салют|хай|бонжур 回报 TRUE.

接下来我们创建一个消息处理程序 hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi)。第一个函数参数 MessageHandler() 是将调用处理程序的方法,第二个参数是调用它的过滤器。 在我们的例子中,这是我们创建的过滤器 MessageFilters$hi.

好吧,最后,我们将创建的处理程序添加到调度程序中 hi_txt_hnd.

updater <- updater + 
             hi_hendler +
             hi_txt_hnd

正如我上面写的,在包中 telegram.bot 和对象 消息过滤器 您已经可以使用一组内置过滤器:

  • 全部 — 所有消息
  • 文本 — 短信
  • 命令——命令,即以以下内容开头的消息 /
  • 回复 — 回复另一条消息的消息
  • 音频 - 包含音频文件的消息
  • document — 带有已发送文档的消息
  • 照片 - 带有已发送图像的消息
  • 贴纸 — 带有已发送贴纸的消息
  • 视频 — 带视频的消息
  • 语音 - 语音消息
  • contact——包含用户电报内容的消息
  • location——带有地理位置的消息
  • 地点——转发的消息
  • 游戏 — 游戏

如果您想在一个处理程序中组合一些过滤器,只需使用符号 | - 作为一个逻辑 ,并签名 & 合乎逻辑的 И。例如,如果您希望机器人在接收视频、图像或文档时调用相同的方法,请使用以下示例创建消息处理程序:

handler <- MessageHandler(callback, 
  MessageFilters$video | MessageFilters$photo | MessageFilters$document
)

添加带参数的命令

我们已经知道命令是什么、如何创建它们以及如何强制机器人执行所需的命令。但在某些情况下,除了命令名称之外,我们还需要传递一些数据来执行它。

下面是一个机器人示例,在给定给定日期和国家/地区的情况下,该机器人会从生产日历中返回日期类型。

下面的机器人使用生产日历 API isdayoff.ru.

代码 3:按日期和国家/地区报告的机器人

library(telegram.bot)

# создаём экземпляр класса Updater
updater <- Updater('1165649194:AAFkDqIzQ6Wq5GV0YU7PmEZcv1gmWIFIB_8')

# Пишем метод для приветсвия
## команда приветвия
check_date <- function(bot, update, args) {

  # входящие данные
  day     <- args[1]  # дата
  country <- args[2]  # страна

  # проверка введённых параметров
  if ( !grepl('\d{4}-\d{2}-\d{2}', day) ) {

    # Send Custom Keyboard
    bot$sendMessage(update$message$chat_id, 
                    text = paste0(day, " - некорреткная дата, введите дату в формате ГГГГ-ММ-ДД"),
                    parse_mode = "Markdown")

  } else {
    day <- as.Date(day)
    # переводим в формат POSIXtl
    y <- format(day, "%Y")
    m <- format(day, "%m")
    d <- format(day, "%d")

  }

  # страна для проверки
  ## проверяем задана ли страна
  ## если не задана устанавливаем ru
  if ( ! country %in% c('ru', 'ua', 'by', 'kz', 'us') ) {

    # Send Custom Keyboard
    bot$sendMessage(update$message$chat_id, 
                    text = paste0(country, " - некорретктный код страны, возможнные значения: ru, by, kz, ua, us. Запрошены данные по России."),
                    parse_mode = "Markdown")

    country <- 'ru'

  }

  # запрос данных из API
  # компоновка HTTP запроса
  url <- paste0("https://isdayoff.ru/api/getdata?",
                "year=",  y, "&",
                "month=", m, "&",
                "day=",   d, "&",
                "cc=",    country, "&",
                "pre=1&",
                "covid=1")

  # получаем ответ
  res <- readLines(url)

  # интрепретация ответа
  out <- switch(res, 
                "0"   = "Рабочий день",
                "1"   = "Нерабочий день",
                "2"   = "Сокращённый рабочий день",
                "4"   = "covid-19",
                "100" = "Ошибка в дате",
                "101" = "Данные не найдены",
                "199" = "Ошибка сервиса")

  # отправляем сообщение
  bot$sendMessage(update$message$chat_id, 
                  text = paste0(day, " - ", out),
                  parse_mode = "Markdown")

}

# создаём обработчик 
date_hendler <- CommandHandler('check_date', check_date, pass_args = TRUE)

# добаляем обработчик в диспетчер
updater <- updater + date_hendler

# запускаем бота
updater$start_polling()

将“YOUR BOT TOKEN”替换为您在创建机器人时收到的真实令牌后,运行上面的代码示例 僵尸之父 (我谈到了创建一个机器人 第一篇文章).

我们创建了一个机器人,其武器库中只有一种方法 check_date,该方法由同名命令调用。

但是,除了命令名称之外,此方法还要求您输入两个参数:国家/地区代码和日期。 接下来,机器人根据官方生产日历检查指定国家/地区的给定日期是否为周末、缩短日或工作日。

为了使我们创建的方法能够接受其他参数以及命令,请使用参数 pass_args = TRUE 在功能上 CommandHandler(),并且在创建方法时,除了必需的参数之外 BOT, 更新 创建一个可选的 - ARGS。 以这种方式创建的方法将接受您在命令名称之后传递给机器人的参数。 参数必须用空格分隔;它们将作为文本向量发送到该方法。

让我们启动并测试我们的机器人。

用 R 编写电报机器人(第 2 部分):向机器人添加命令支持和消息过滤器

在后台运行机器人

我们需要完成的最后一步是在后台启动机器人。

为此,请遵循下面描述的算法:

  1. 将机器人代码保存到扩展名为 R 的文件中。在 RStudio 中工作时,这是通过菜单完成的 文件, 团队 另存为….
  2. 将bin文件夹的路径添加到Path变量中,该文件夹又位于安装R语言的文件夹中,说明 这里.
  3. 创建一个常规文本文件,其中写入 1 行: R CMD BATCH C:UsersAlseyDocumentsmy_bot.R... 反而 C:UsersAlseyDocumentsmy_bot.R 写入您的机器人脚本的路径。 同时,重要的是一路上没有西里尔字符或空格,因为这可能会在运行机器人时导致问题。 保存它,并将其扩展名替换为 TXT蝙蝠.
  4. 打开Windows任务计划程序,有很多方法可以做到这一点,例如打开任意文件夹并输入地址 %windir%system32taskschd.msc /s。 其他启动方式可参见 这里.
  5. 在调度程序的右上角菜单中,单击“创建任务...”。
  6. 在“常规”选项卡上,为您的任务指定一个自定义名称,并将开关切换到“为所有用户运行”状态。
  7. 转到“操作”选项卡,单击“创建”。 在“程序或脚本”一栏,点击“浏览”,找到第二步中创建的 蝙蝠 文件并单击“确定”。
  8. 单击“确定”,如有必要,请输入操作系统帐户的密码。
  9. 在调度程序中找到创建的任务,选择它并单击右下角的“运行”按钮。

我们的机器人在后台运行,并将一直工作,直到您停止任务,或关闭启动它的电脑或服务器。

结论

在本文中,我们了解了如何编写一个成熟的机器人,它不仅可以发送消息,还可以响应传入的消息和命令。 所获得的知识已经足以解决您的大部分问题。

下一篇文章会讲如何给机器人添加键盘,以方便工作。

订阅我的 电报 и YouTube的 渠道。

来源: habr.com

添加评论