Създаваме telegram бот на езика R (част 2): Добавяме на бота поддръжка за команди и филтри на съобщенията

В предишната публикация Разбрахме как да създадем бот и инициализирахме экземпляр на класа Бот и се запознахме с методите за изпращане на съобщения с него.

В тази статия продължавам темата, затова препоръчвам да прочетете тази статия само след като сте прочели първата част.

Този път ще разберем как да оживим нашия бот и ще добавим поддръжка за команди, а също така ще се запознаем с класа Updater.

По време на статията ще напишем няколко прости бота, последният от които ще определя дали даден ден в съответната страна е празничен или работен в зависимост от производствения календар. Но, както и преди, целта на статията е да ви запознае с интерфейса на пакета telegram.bot за решаване на ваши собствени задачи.

Създаваме telegram бот на езика R (част 2): Добавяме на бота поддръжка за команди и филтри на съобщенията

Всички статии от серията "Пишем телеграм бот на езика R"

  1. Създаваме бот и изпращаме съобщения с него в телеграм
  2. Добавяме на бота поддръжка за команди и филтри на съобщенията

Съдържание

Ако се интересувате от анализ на данни, вероятно ще ви бъдат интересни моите telegram и 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, който се използва в края на кода, стартира безкраен цикъл на запитвания и обработване на актуализации от бота.

Сега отваряме Telegram и пишем на нашия бот първата команда /hi.

Създаваме telegram бот на езика R (част 2): Добавяме на бота поддръжка за команди и филтри на съобщенията

Сега нашият бот разбира командата /hi, и може да се поздрави с нас.

Схематично процесът на изграждане на такъв прост бот може да бъде изобразен по следния начин.

Създаваме telegram бот на езика 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_handler. Същото може да се направи с метода 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_handler <- CommandHandler('hi', say_hello) # обработчик на командата hi
hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi)

# добавяме обработчиците в диспетчера
updater <- updater + 
             hi_handler +
             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() трябва да предадете функцията за филтриране. По същество, филтърът е просто функция, която получава инстанция на съобщение и връща 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 и обекта 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) ) {

    # Изпращане на персонализирана клавиатура
    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') ) {

    # Изпращане на персонализирана клавиатура
    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(), и при създаването на метод, освен задължителните аргументи bot, актуализиране създайте опционален — args. Създаденият по този начин метод ще приема параметрите, които предавате на бота след името на командата. Параметрите трябва да бъдат разделени с интервал, а в метода те ще постъпят като текстов вектор.

Нека стартираме и тестваме нашия бот.

Създаваме telegram бот на езика R (част 2): Добавяме на бота поддръжка за команди и филтри на съобщенията

Стартираме бота във фонов режим

Последната стъпка, която остана да изпълним, е да стартираме бота във фонов режим.

За целта следвайте описания по-долу алгоритъм:

  1. Запазете кода на бота в файл с разширение R. При работа в RStudio това се прави през менюто File, с командата Запази като….
  2. Добавете пътя към папката bin, която от своя страна се намира в папката, в която сте инсталирали език R в променливата Path, инструкция тук.
  3. Създайте обикновен текстов файл, в който напишете 1 ред: R CMD BATCH C:UsersAlseyDocumentsmy_bot.R. Вместо C:UsersAlseyDocumentsmy_bot.R напишете пътя към вашия скрипт на бота. Важно е в пътя да не се срещат кирилица и интервали, тъй като това може да създаде проблеми при стартиране на бота. Запазете го и променете разширението на txt на bat.
  4. Отворете планировщика на задачите в Windows, има множество начини да го направите, например отворете всяка папка и в адреса въведете %windir%system32taskschd.msc /s. Други начини за стартиране могат да бъдат намерени тук.
  5. В горния десен ъгъл на планирача натиснете "Създай задача…".
  6. На таба "Общи" задайте произволно име на задачата и преместете превключвателя в състояние "Изпълнява се за всички потребители".
  7. Придвижете се към таба "Действия", натиснете "Създай". В полето "Програма или сценарий" натиснете "Преглед", намерете създадения на втората стъпка bat файл и натиснете ОК.
  8. Натискаме ОК, при необходимост въвеждаме паролата на вашия операционен акаунт.
  9. Намираме в планираща задачата, която сме създали, маркираме я и долу вдясно натискаме бутона "Изпълни".

Нашият бот е стартиран във фонов режим и ще работи, докато не прекратите задачата или не изключите вашия ПК или сървър, на който е стартиран.

Заключение

В тази статия разгледахме как да напишем пълноценно бота, който не само че може да изпраща съобщения, но и да реагира на входящи съобщения и команди. Получените знания вече са достатъчни за решаване на повечето от вашите задачи.

В следващата статия ще говорим за това как да добавите клавиатура на бота за по-удобна работа.

Абонирайте се за моите telegram и youtube канали.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster