ProHoster > блог > адміністраванне > Пішам telegram бота на мове R (частка 2): Дадаем боту падтрымку каманд і фільтры паведамленняў
Пішам telegram бота на мове R (частка 2): Дадаем боту падтрымку каманд і фільтры паведамленняў
В папярэдняй публікацыі мы разабраліся як стварыць бота, ініцыялізавалі асобнік класа Bot і азнаёміліся з метадамі адпраўкі паведамленняў з яго дапамогай.
У гэтым артыкуле я працягваю дадзеную тэму, таму прыступаць да чытання дадзенага артыкула я рэкамендую толькі пасля прачытання першай частцы.
У гэты раз мы разбярэмся як ажывіць нашага робата і дадамо яму падтрымку каманд, а таксама пазнаёмімся з класам. Updater.
У ходзе артыкула мы напішам некалькіх простых ботаў, апошні будзе па зададзенай даце і коду краіны вызначаць ці з'яўляецца дзень у дадзенай краіне выходным ці працоўным паводле вытворчага календара. Але, як і раней мэта артыкула азнаёміць вас з інтэрфейсам пакета telegram.bot для вырашэння вашых уласных задач.
Усе артыкулы з серыі "Пішам telegram бота на мове R"
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()
Запусціце прыведзены вышэй прыклад кода, папярэдне замяніўшы 'ТОКЕН ВАШАГА БОТА' на рэальны токен, які вы атрымалі пры стварэнні бота праз БотБацька (аб стварэнні бота я распавядаў у першым артыкуле).
метад start_polling() класа Updater, Які выкарыстоўваецца ў канцы кода, запускае бясконцы цыкл запыту і апрацоўкі абнаўленняў ад бота.
Цяпер адкрыем тэлеграм, і напішам нашаму боту першую каманду /hi.
Цяпер наш бот разумее каманду /hi, і ўмее з намі вітацца.
Схематычна працэс пабудовы такога найпростага робата можна адлюстраваць наступным чынам.
Ствараем экзэмпляр класа Updater;
Ствараем метады, г.зн. функцыі якія будзе выконваць наш бот. У прыкладзе кода гэта функцыя say_hello(). Функцыі, якія вамі будуць выкарыстоўвацца як метады бота павінны мець два абавязковыя аргументы. бот и абнаўленне, і адзін неабавязковы - аргі. Аргумент бот, гэта і ёсць ваш бот, з яго дапамогай вы можаце адказваць на паведамленні, адпраўляць паведамленні, ці выкарыстоўваць любыя іншыя даступныя боту метады. Аргумент абнаўленне гэта тое, што робат атрымаў ад карыстача, у сутнасці, тое што ў першым артыкуле мы атрымлівалі метадам getUpdates(). Аргумент аргі дазваляе вам апрацоўваць дадатковыя дадзеныя адпраўленыя карыстальнікам разам з камандай, да гэтай тэмы мы яшчэ вернемся крыху пазней;
Ствараем апрацоўшчыкі, г.зн. злучаем нейкія дзеянні карыстача са створанымі на мінулым кроку метадамі. У сутнасці апрацоўшчык гэта трыгер, падзея якое выклікае нейкую функцыю робата. У нашым прыкладзе такім трыгерам з'яўляецца адпраўка каманды /hi, і рэалізуецца камандай hi_hendler <- CommandHandler('hi', say_hello). Першы аргумент функцыі CommandHandler() дазваляе вам задаць каманду, у нашым выпадку hi, на якую будзе рэагаваць бот. Другі аргумент дазваляе паказаць метад бота, мы будзем выклікаць метад say_hello, які будзе выконвацца калі карыстач выклікаў паказаную ў першым аргуменце каманду;
Далей дадаем створаны апрацоўшчык у дыспетчар нашага экзэмпляра класа Updater. Дадаваць апрацоўшчыкі можна некалькімі спосабамі, у прыкладзе вышэй я выкарыстоўваў найпросты, з дапамогай знака +, Г.зн. updater <- updater + hi_hendler. Тое ж самае можна зрабіць з дапамогай метаду add_handler(), які адносіцца да класа Dispatcher, знайсці гэты метад можна так: updater$dispatcher$add_handler();
Запускаем бота з дапамогай каманды 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()
Запусціце прыведзены вышэй прыклад кода, папярэдне замяніўшы 'ТОКЕН ВАШАГА БОТА' на рэальны токен, які вы атрымалі пры стварэнні бота праз БотБацька (аб стварэнні бота я распавядаў у першым артыкуле).
Цяпер паспрабуем адправіць боту некалькі паведамленняў, у якіх будуць сустракацца пералічаныя раней словы прывітання:
Такім чынам, у першую чаргу мы навучылі робата не проста вітацца, а адказваць на прывітанне. Зрабілі мы гэта з дапамогай аргумента 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, або ХЛУСНЯ. У нашым прыкладзе, мы напісалі найпростую функцыю, якая з дапамогай базавай функцыі 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 - Гульні
Калі вы хочаце сумясціць некаторыя фільтры ў адным апрацоўшчыку проста выкарыстоўвайце знак | - у якасці лагічнага АБО, і знак & у якасці лагічнага И. Напрыклад, калі вы хочаце што б бот выклікаў адзін і той жа метад калі ён атрымлівае відэа, малюнак або дакумент выкарыстоўвайце наступны прыклад стварэння апрацоўшчыка паведамленняў:
Мы ўжо ведаем, што такое каманды, як іх ствараць і як прымусіць робата выканаць неабходную каманду. Але ў некаторых выпадках апроч назвы каманды, нам неабходна перадаць некаторыя дадзеныя для яе выканання.
Ніжэй прыклад робата, які па зададзенай даце і краіне вяртае вам тып дня з вытворчага календара.
Прыведзены ніжэй бот выкарыстоўвае 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()
Запусціце прыведзены вышэй прыклад кода, папярэдне замяніўшы 'ТОКЕН ВАШАГА БОТА' на рэальны токен, які вы атрымалі пры стварэнні бота праз БотБацька (аб стварэнні бота я распавядаў у першым артыкуле).
Мы стварылі робата, які ў арсенале мае ўсяго адзін метад check_date, дадзены метад выклікаецца аднайменнай камандай.
Але, акрамя імя каманды, дадзены метад чакае ад вас увядзення двух параметраў, код краіны і дату. Далей робат правяраецца, ці з'яўляецца зададзены дзень у паказанай краіне выходным, скарочаным ці працоўным паводле афіцыйнага вытворчага календара.
Каб створаны метад прымаў дадатковыя параметры разам з камандай, выкарыстоўвайце аргумент pass_args = TRUE у функцыі CommandHandler(), і пры стварэнні метаду, акрамя абавязковых аргументаў бот, абнаўленне стварыце апцыянальны - аргі. Створаны такім чынам метад будзе прымаць параметры, якія вы перадаеце робату пасля назвы каманды. Параметры неабходна паміж сабой падзяляць прабелам, у метад яны паступяць у выглядзе тэкставага вектара.
Давайце запусцім, і пратэстуем нашага робата.
Запускаем бота ў фонавым рэжыме
Апошні крок які нам засталося выканаць – запусціць робата ў фонавым рэжыме.
Для гэтага прытрымлівайцеся па апісаным ніжэй алгарытме:
Захавайце код робата ў файл з пашырэннем R. Пры працы ў RStudio гэта робіцца праз меню Размовы, камандай Захаваць як….
Дадайце шлях да тэчкі bin, якая ў сваю чаргу знаходзіцца ў тэчцы у якую вы ўсталявалі мову R у зменную Path, інструкцыя тут.
Стварыце звычайны тэкставы файл, у якім прапішыце 1 радок: R CMD BATCH C:UsersAlseyDocumentsmy_bot.R. Замест C:UsersAlseyDocumentsmy_bot.R прапішыце шлях да свайго скрыпту бота. Пры гэтым важна, што б у дарозе не сустракалася кірыліца і прабелы, т.я. гэта можа выклікаць праблемы пры запуску робата. Захавайце яго, і заменіце яго пашырэнне з TXT на кажан.
Адкрыйце планавальнік заданняў Windows, ёсць мноства спосабаў гэта зрабіць, напрыклад адкрыйце любую тэчку і ў адрас увядзіце %windir%system32taskschd.msc /s. Іншыя спосабы запуску можна знайсці тут.
У верхнім правым меню планавальніка націсніце "Стварыць задачу…".
На ўкладцы "Агульныя" задайце адвольнае імя вашай задачы, і перамыкач перабачыце ў стан "Выконваць для ўсіх карыстачоў".
Перайдзіце на ўкладку "Дзеянні", націсніце "Стварыць". У полі "Праграма або сцэнар" націсніце "Агляд", знайдзіце створаны на другім кроку кажан файл, і націсніце ОК.
Ціснем ОК, пры неабходнасці ўводны пароль ад вашага ўліковага запісу аперацыйнай сістэмы.
Знаходзім у планавальніку створаную задачу, вылучаем і ў ніжнім правым куце ціснем кнопку "Выканаць".
Наш бот запушчаны ў фонавым рэжыме, і будзе працаваць да таго часу, пакуль вы не спыніце задачу, ці не выключыце ваш ПК або сервер на якім яго запусцілі.
Заключэнне
У гэтым артыкуле мы разабраліся як напісаць паўнавартаснага робата, які не толькі ўмее адпраўляць паведамленні, але і рэагаваць на ўваходныя паведамленні і каманды. Атрыманых ведаў ужо дастаткова для вырашэння большасці вашых задач.
У наступным артыкуле гаворка пойдзе пра тое, як дадаць робату клавіятуру, для зручнейшай працы.