В Разбрахме как да създадем бот и инициализирахме экземпляр на класа Бот и се запознахме с методите за изпращане на съобщения с него.
В тази статия продължавам темата, затова препоръчвам да прочетете тази статия само след като сте прочели .
Този път ще разберем как да оживим нашия бот и ще добавим поддръжка за команди, а също така ще се запознаем с класа Updater.
По време на статията ще напишем няколко прости бота, последният от които ще определя дали даден ден в съответната страна е празничен или работен в зависимост от производствения календар. Но, както и преди, целта на статията е да ви запознае с интерфейса на пакета telegram.bot за решаване на ваши собствени задачи.

Всички статии от серията "Пишем телеграм бот на езика R"
Съдържание
Ако се интересувате от анализ на данни, вероятно ще ви бъдат интересни моите и канали. Голямата част от съдържанието, което се отнася до езика R.
Клас 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.

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

- Създаваме екземпляр на класа
Updater; - Създаваме методи, т.е. функции, които нашият бот ще изпълнява. В предоставения пример код това е функцията
say_hello(). Функциите, които ще използвате като методи на бота, трябва да имат два задължителни аргумента — bot и актуализиране, и един незадължителен — args. Аргументът bot, това е вашият бот, с него можете да отговаряте на съобщения, да изпращате съобщения или да използвате всички налични методи на бота. Аргументът актуализиране това е, което ботът е получил от потребителя, по същество, това което в първата статия получавахме чрез методаgetUpdates(). Аргументът args позволява ви да обработвате допълнителни данни, изпратени от потребителя заедно с командата, към тази тема ще се върнем малко по-късно; - Създаваме обработчици, т.е. свързваме определени действия на потребителя с методите, създадени на предишната стъпка. По същество обработчикът е спусък, събитие, което извиква определена функция на бота. В нашия случай, такъв спусък е изпращането на заповедта
/hi, и се реализира с командатаhi_hendler <- CommandHandler('hi', say_hello). Първият аргумент на функциятаCommandHandler()ви позволява да зададете командата, в нашия случайhi, на която ботът ще реагира. Вторият аргумент позволява да зададете метода на бота, ще извикаме методаsay_hello, който ще се изпълни, ако потребителят е извикал командата, посочена в първия аргумент; - След това добавяме създадения обработчик в диспетчера на нашия клас.
Updater. Обработчиците могат да се добавят по няколко начина, в примера по-горе използвах най-простия, с помощта на знака+, т.е.updater <- updater + hi_handler. Същото може да се направи с методаadd_handler(), който принадлежи на класаDispatcher, този метод може да се намери така:updater$dispatcher$add_handler(); - Стартираме бота с помощта на командата
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 (за създаването на бота разказах в ).
Сега ще опитаме да изпратим на бота няколко съобщения, в които ще срещнете предходно изброените поздравителни думи:

Следователно, на първо място, научихме бота не просто да се поздравява, а да отговаря на поздравите. Направихме това с помощта на аргумента 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 на производствения календар .
Код 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. Създаденият по този начин метод ще приема параметрите, които предавате на бота след името на командата. Параметрите трябва да бъдат разделени с интервал, а в метода те ще постъпят като текстов вектор.
Нека стартираме и тестваме нашия бот.

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