Писање телеграм бота у Р (2. део): Додавање подршке за команде и филтера порука боту

В претходна публикација схватили смо како да направимо бота, иницијализовали смо инстанцу класе Bot и упознао се са начинима слања порука помоћу њега.

У овом чланку настављам ову тему, па препоручујем да почнете да читате овај чланак тек након читања први део.

Овог пута ћемо смислити како да оживимо нашег бота и додамо му подршку за команде, а такође ћемо се упознати са класом Updater.

У току чланка ћемо написати неколико једноставних ботова, који ће на основу датог датума и кода земље одредити да ли је дан у датој земљи викенд или радни дан према производном календару. Али, као и раније, сврха чланка је да вас упозна са интерфејсом пакета telegram.bot да решите сопствене проблеме.

Писање телеграм бота у Р (2. део): Додавање подршке за команде и филтера порука боту

Сви чланци из серије „Писање телеграм бота у Р“

  1. Креирамо бота и користимо га за слање порука у телеграму
  2. Додајте подршку за команде и филтере за поруке боту

Садржина

Ако сте заинтересовани за анализу података, можда ће вас занимати моја телеграм и ИоуТубе канала. Већина садржаја је посвећена Р језику.

  1. Упдатер цласс
  2. Руковаоци - руковаоци
  3. Додајте прву команду боту, руковаоцу командама
  4. Процесор текстуалних порука и филтери
  5. Додавање команди са параметрима
  6. Покрените бот у позадини
  7. Закључак

Упдатер цласс

Updater је класа која вам олакшава развој телеграм бота и користи класу испод хаубе Dispetcher. Часовни задатак Updater је примање ажурирања од бота (у претходном чланку смо користили метод за ову сврху getUpdates()), и пренесите их даље на Dispetcher.

Заузврат Dispetcher садржи руковаоце које сте креирали, тј. објекти класе Handler.

Руковаоци - руковаоци

Са руковаоцима којима додајете Dispetcher реакције бота на разне догађаје. У време писања овог чланка у telegram.bot Додати су следећи типови руковалаца:

  • МессагеХандлер — Руковалац порукама
  • ЦоммандХандлер — Руковалац командама
  • ЦаллбацкКуериХандлер — Руковалац подацима за тастатуре послати са Инлине
  • ЕррорХандлер — Руковалац грешкама када се захтева ажурирање од бота

Додајте прву команду боту, руковаоцу командама

Ако никада раније нисте користили ботове и не знате шта је команда, онда се команде боту морају слати помоћу косе црте унапред / као префикс.

Почећемо са једноставним командама, тј. хајде да научимо нашег бота да каже здраво на команду /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.

Писање телеграм бота у Р (2. део): Додавање подршке за команде и филтера порука боту

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

Шематски, процес изградње тако једноставног бота може се приказати на следећи начин.

Писање телеграм бота у Р (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().

Процесор текстуалних порука и филтери

Схватили смо како да шаљемо команде боту, али понекад нам је потребно да бот одговара не само на команде, већ и на неке обичне текстуалне поруке. Да бисте то урадили, морате да користите руковаоце порукама − МессагеХандлер.

Нормалан МессагеХандлер ће одговорити на апсолутно све долазне поруке. Због тога се руковаоци порукама често користе заједно са филтерима. Научимо бота да се поздравља не само на команду /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()

Покрените горњи пример кода, након што замените „ВАШ БОТА ТОКЕН“ правим токеном који сте добили приликом креирања бота преко БотФатхер (Разговарао сам о стварању бота у први чланак).

Покушајмо сада да пошаљемо боту неколико порука које садрже раније наведене поздравне речи:
Писање телеграм бота у Р (2. део): Додавање подршке за команде и филтера порука боту

Дакле, пре свега, научили смо бота не само да се поздрави, већ и да одговори на поздрав. Ово смо урадили користећи аргумент репли_то_мессаге_ид, који је доступан у методи sendMessage(), у који треба да пренесете ид поруке на коју желите да одговорите. ИД поруке можете добити овако: update$message$message_id.

Али главна ствар коју смо урадили је да додамо филтер боту помоћу функције BaseFilter():

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

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

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

)

Као што сте можда приметили, објекту треба додати филтере МессагеФилтерс, који у почетку већ садржи мали сет готових филтера. У нашем примеру, објекту МессагеФилтерс додали смо елемент hi, ово је нови филтер.

У функцији BaseFilter() морате проћи функцију филтера. У суштини, филтер је само функција која прима инстанцу поруке и враћа ТАЧНО или ЛАЖ. У нашем примеру смо написали једноставну функцију која, користећи основну функцију grepl() проверава текст поруке и да ли се поклапа са регуларним изразом привет|здравствуй|салют|хай|бонжур враћа ТАЧНО.

Затим креирамо руковалац порукама hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi). Први аргумент функције MessageHandler() је метод који ће позвати руковалац, а други аргумент је филтер помоћу којег ће бити позван. У нашем случају, ово је филтер који смо креирали MessageFilters$hi.

Па, на крају, додамо диспечеру креирани руковалац хи_ткт_хнд.

updater <- updater + 
             hi_hendler +
             hi_txt_hnd

Као што сам горе написао, у пакету telegram.bot и објекат МессагеФилтерс Већ постоји скуп уграђених филтера које можете користити:

  • све — Све поруке
  • текст — Текстуалне поруке
  • команда — Команде, тј. поруке које почињу са /
  • одговор — Поруке које представљају одговор на другу поруку
  • аудио — Поруке које садрже аудио датотеку
  • документ — Поруке са послатим документом
  • пхото - Поруке са послатим сликама
  • налепница — Поруке са послатом налепницом
  • видео — Поруке са видео снимком
  • глас - Гласовне поруке
  • контакт — Поруке које садрже садржај телеграма корисника
  • локација — Поруке са геолокацијом
  • место — Прослеђене поруке
  • игра — Игре

Ако желите да комбинујете неке филтере у једном руковаоцу, само користите знак | - као логично ИЛИ, и потпишите & као логично И. На пример, ако желите да бот позове исти метод када прими видео, слику или документ, користите следећи пример да креирате руковалац порукама:

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

Додавање команди са параметрима

Већ знамо шта су команде, како их креирати и како натерати бота да изврши жељену команду. Али у неким случајевима, поред имена команде, потребно је да проследимо неке податке да бисмо је извршили.

Испод је пример бота који вам, с обзиром на дати датум и земљу, враћа тип дана из производног календара.

Доњи бот користи АПИ календара производње исдаиофф.ру.

Код 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(), а приликом креирања методе, поред потребних аргумената њушка, ажурирање направите опциони - аргс. Овако креирана метода ће прихватити параметре које проследите боту након имена команде. Параметри морају бити раздвојени размаком; они ће бити послати методу као вектор текста.

Хајде да покренемо и тестирамо нашег бота.

Писање телеграм бота у Р (2. део): Додавање подршке за команде и филтера порука боту

Покрените бот у позадини

Последњи корак који треба да завршимо је да покренемо бот у позадини.

Да бисте то урадили, следите алгоритам описан у наставку:

  1. Сачувајте код бота у датотеку са екстензијом Р. Када радите у РСтудиу, то се ради преко менија Фајл, тим Сачувај као.
  2. Додајте путању до директоријума бин, који се заузврат налази у фасцикли у којој сте инсталирали Р језик, у променљиву Путања, упутства овде.
  3. Направите обичну текстуалну датотеку у коју упишите 1 ред: R CMD BATCH C:UsersAlseyDocumentsmy_bot.R... Уместо Ц:УсерсАлсеиДоцументсми_бот.Р напишите путању до ваше бот скрипте. При томе је важно да успут нема ћириличких знакова или размака, јер ово може изазвати проблеме при покретању бота. Сачувајте га и замените његово проширење са ТКСТ на Бат.
  4. Отворите Виндовс Таск Сцхедулер, постоји много начина да то урадите, на пример, отворите било коју фасциклу и унесите адресу %windir%system32taskschd.msc /s. Могу се наћи и друге методе покретања овде.
  5. У горњем десном менију планера кликните на „Креирај задатак...“.
  6. На картици „Опште“ дајте свом задатку прилагођено име и пребаците прекидач у стање „Покрени за све кориснике“.
  7. Идите на картицу "Радње", кликните на "Креирај". У пољу „Програм или скрипта“ кликните на „Прегледај“, пронађите онај креиран у другом кораку Бат датотеку и кликните на ОК.
  8. Кликните на ОК и, ако је потребно, унесите лозинку за налог вашег оперативног система.
  9. Пронађите креирани задатак у планеру, изаберите га и кликните на дугме „Покрени“ у доњем десном углу.

Наш бот ради у позадини и радиће све док не зауставите задатак, или искључите рачунар или сервер на којем је покренут.

Закључак

У овом чланку смо схватили како да напишемо пуноправног бота који може не само да шаље поруке, већ и да одговара на долазне поруке и команде. Стечено знање је већ довољно да реши већину ваших проблема.

Следећи чланак ће говорити о томе како додати тастатуру боту за практичнији рад.

Претплатите се на мој телеграм и ИоуТубе канали.

Извор: ввв.хабр.цом

Додај коментар