Пишемо telegram бота мовою R (частина 2): Додаємо боту підтримку команд та фільтри повідомлень

В попередній публікації ми розібралися як створити бота, ініціалізували екземпляр класу Bot та ознайомилися з методами надсилання повідомлень за його допомогою.

У цій статті я продовжую цю тему, тому приступати до читання цієї статті я рекомендую лише після прочитання першій частині.

На цей раз ми розберемося як пожвавити нашого бота і додамо йому підтримку команд, а також познайомимося з класом Updater.

У ході статті ми напишемо кількох простих ботів, останній за заданою датою та кодом країни визначатиме чи є день у цій країні вихідним чи робочим згідно з виробничим календарем. Але, як і раніше, мета статті ознайомити вас з інтерфейсом пакету telegram.bot для вирішення власних завдань.

Пишемо telegram бота мовою R (частина 2): Додаємо боту підтримку команд та фільтри повідомлень

Всі статті із серії "Пишемо telegram бота мовою R"

  1. Створюємо бота і відправляємо за його допомогою повідомлення в telegram
  2. Додаємо боту підтримку команд та фільтри повідомлень

Зміст

Якщо ви цікавитеся аналізом даних можливо вам будуть цікаві мої телеграма и YouTube канали. Більшість контенту яких присвячені мові R.

  1. Клас Updater
  2. Handlers - обробники
  3. Додаємо першу команду боту, обробник команд
  4. Обробник текстових повідомлень та фільтри
  5. Додавання команд із параметрами
  6. Запускаємо бота у фоновому режимі
  7. Висновок

Клас Updater

Updater — це клас, який спрощує розробку телеграм бота, і використовує під капотом клас Dispetcher. Призначення класу Updater полягає в тому, щоб отримати оновлення від бота (у попередній статті ми використовували для цієї мети метод getUpdates()), і передати їх далі в Dispetcher.

Зі свого боку Dispetcher містить у собі створені вами оброблювачі, тобто. об'єкти класу Handler.

Handlers - обробники

За допомогою обробників ви додаєте в 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()

Запустіть наведений вище приклад коду, попередньо замінивши 'ТОКЕН ВАШОГО БОТА' на реальний токен, який ви отримали під час створення бота через BotFather (про створення бота я розповідав у першій статті).

метод start_polling() класу Updater, який використовується в кінці коду, запускає нескінченний цикл запиту та обробки оновлень від бота.

Тепер відкриємо телеграм і напишемо нашому боту першу команду /hi.

Пишемо telegram бота мовою R (частина 2): Додаємо боту підтримку команд та фільтри повідомлень

Тепер наш бот розуміє команду /hi, і вміє з нами вітатись.

Схематично процес побудови такого найпростішого бота можна зобразити в такий спосіб.

Пишемо telegram бота мовою R (частина 2): Додаємо боту підтримку команд та фільтри повідомлень

  1. Створюємо екземпляр класу Updater;
  2. Створюємо способи, тобто. функції, які буде виконувати наш бот. У прикладі коду це функція say_hello(). Функції, які ви використовуватимете як методи бота повинні мати два обов'язкові аргументи — морда и оновлення, і один необов'язковий аргументи. Аргумент мордаЦе і є ваш бот, за його допомогою ви можете відповідати на повідомлення, відправляти повідомлення, або використовувати будь-які інші доступні боту методи. Аргумент оновлення це те, що бот отримав від користувача, по суті, те, що в першій статті ми отримували методом getUpdates(). Аргумент аргументи дозволяє вам обробляти додаткові дані, надіслані користувачем разом з командою, до цієї теми ми ще повернемося трохи пізніше;
  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().

Обробник текстових повідомлень та фільтри

Як відправляти роботу команди ми розібралися, але іноді нам потрібно, щоб бот реагував не тільки на команди, але і на якісь звичайні, текстові повідомлення. Для цього необхідно використовувати обробники повідомлень. MessageHandler.

звичайний MessageHandler буде реагувати на всі вхідні повідомлення. Тому найчастіше обробники повідомлень використовуються разом із фільтрами. Давайте навчимо бота вітатись не тільки за командою /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()

Запустіть наведений вище приклад коду, попередньо замінивши 'ТОКЕН ВАШОГО БОТА' на реальний токен, який ви отримали під час створення бота через BotFather (про створення бота я розповідав у першій статті).

Тепер спробуємо надіслати боту кілька повідомлень, у яких будуть зустрічатися перелічені раніше слова привітання:
Пишемо telegram бота мовою R (частина 2): Додаємо боту підтримку команд та фільтри повідомлень

Отже, насамперед ми навчили бота не просто вітатися, а відповідати на вітання. Зробили ми це за допомогою аргументу reply_to_message_id, який доступний у методі sendMessage(), в який необхідно передати id повідомлення, на яке потрібно відповісти. Отримати id повідомлення можна так: update$message$message_id.

Але головне, що ми зробили - додали фільтр боту за допомогою функції BaseFilter():

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

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

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

)

Як ви могли помітити, фільтри необхідно додавати до об'єкту MessageFilters, В якому спочатку вже є невеликий набір готових фільтрів. У нашому прикладі об'єкт MessageFilters ми додали елемент hiце новий фільтр.

У функцію BaseFilter() вам необхідно передати функцію, що фільтрує. По суті, фільтр – це просто функція, яка отримує екземпляр повідомлення та повертає ІСТИНА або ПОМИЛКОВИЙ. У нашому прикладі ми написали найпростішу функцію, яка за допомогою базової функції grepl() перевіряє текст повідомлення, і якщо він відповідає регулярному виразу привет|здравствуй|салют|хай|бонжур повертає ІСТИНА.

Далі ми створюємо обробник повідомлень hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi). Перший аргумент функції MessageHandler() — метод, який буде викликати обробник, а другий аргумент — це фільтр, яким він буде викликатися. У нашому випадку це створений нами фільтр MessageFilters$hi.

Ну і в результаті, ми додаємо до диспетчера створений тільки, що обробник hi_txt_hnd.

updater <- updater + 
             hi_hendler +
             hi_txt_hnd

Як я вже писав вище, у пакеті telegram.bot та об'єкт MessageFilters вже є набір вбудованих фільтрів, які можна використовувати:

  • all — Всі повідомлення
  • text — Текстові повідомлення
  • command - Команди, тобто. повідомлення які починаються на /
  • reply — Повідомлення, які відповідають на інше повідомлення
  • audio — Повідомлення, які містять аудіо файл
  • document — Повідомлення з надісланим документом
  • photo — Повідомлення з надісланими зображеннями
  • sticker — Повідомлення з надісланим стікером
  • video — Повідомлення з відео
  • voice — Голосові повідомлення
  • contact — Повідомлення, які містять контант телеграм користувача
  • location — Повідомлення з геолокацією
  • venue — Надсилання повідомлень
  • game — Ігри

Якщо ви хочете поєднати деякі фільтри в одному обробнику, просто використовуйте знак | — як логічний АБО, і знак & як логічний И. Наприклад, якщо ви хочете, щоб бот викликав один і той же метод коли він отримує відео, зображення або документ використовуйте наступний приклад створення обробника повідомлень:

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()

Запустіть наведений вище приклад коду, попередньо замінивши 'ТОКЕН ВАШОГО БОТА' на реальний токен, який ви отримали під час створення бота через BotFather (про створення бота я розповідав у першій статті).

Ми створили бота, який в арсеналі має лише один метод check_date, даний метод викликається однойменною командою.

Але, крім імені команди, цей метод чекає від вас введення двох параметрів, код країни та дату. Далі бот перевіряється, чи є заданий день у зазначеній країні вихідним, скороченим чи робітником згідно з офіційним виробничим календарем.

Щоб створюваний нами метод приймав додаткові параметри разом із командою, використовуйте аргумент pass_args = TRUE у функції CommandHandler(), і під час створення методу, крім обов'язкових аргументів морда, оновлення створіть опціональний - аргументи. Створений таким чином метод прийматиме параметри, які ви передаєте боту після назви команди. Параметри необхідно між собою розділяти пробілом, метод вони надійдуть у вигляді текстового вектора.

Давайте запустимо і протестуємо нашого бота.

Пишемо telegram бота мовою R (частина 2): Додаємо боту підтримку команд та фільтри повідомлень

Запускаємо бота у фоновому режимі

Останній крок, який нам залишилося виконати - запустити бота у фоновому режимі.

Для цього виконайте описаний нижче алгоритм:

  1. Збережіть код бота у файл з розширенням R. Під час роботи в RStudio це робиться через меню філе, командою Зберегти як.
  2. Додати шлях до папки bin, яка в свою чергу знаходиться в папці в яку ви встановили мову R в змінну Path, інструкція тут.
  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

Додати коментар або відгук