Русский
Русский
English
Статистика
Реклама

Как создать телеграм бота

Пишем telegram бота на языке R (часть 2) Добавляем боту поддержку команд и фильтры сообщений

25.08.2020 10:05:02 | Автор: admin

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


В этой статье я продолжаю данную тему, поэтому приступать к чтению данной статьи я рекомендую только после прочтения первой части.


В этот раз мы разберёмся как оживить нашего бота и добавим ему поддержку команд, а также познакомимся с классом Updater.


В ходе статьи мы напишем нескольких простых ботов, последний будет по заданной дате и коду страны определять является ли день в данной стране выходным или рабочим согласно производственного календаря. Но, как и прежде цель статьи ознакомить вас с интерфейсом пакета telegram.bot для решения ваших собственных задач.



Все статьи из серии "Пишем telegram бота на языке R"


  1. Создаём бота, и отправляем с его помощью сообщения в telegram
  2. Добавляем боту поддержку команд и фильтры сообщений

Содержание


  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)# создаём экземпляр класса Updaterupdater <- 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.



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


Схематически процесс построения такого простейшего бота можно изобразить следующим образом.



  1. Создаём экземпляр класса Updater;
  2. Создаём методы, т.е. функции которые будет выполнять наш бот. В примере кода это функция say_hello(). Функции, которые вами будут использоваться как методы бота должны иметь два обязательных аргумента bot и update, и один необязательный args. Аргумент bot, это и есть ваш бот, с его помощью вы можете отвечать на сообщения, отправлять сообщения, или использовать любые другие доступные боту методы. Аргумент update это то, что бот получил от пользователя, по сути, то что в первой статье мы получали методом getUpdates(). Аргумент args позволяет вам обрабатывать дополнительные данные отправленные пользователем вместе с командой, к этой теме мы ещё вернёмся немного позже;
  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)# создаём экземпляр класса Updaterupdater <- 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) # обработчик команды hihi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi)# добаляем обработчики в диспетчерupdater <- updater +              hi_hendler +             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 производственного календаря isdayoff.ru.


Код 3: Бот, который сообщает по дате и стране
library(telegram.bot)# создаём экземпляр класса Updaterupdater <- 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(), и при создании метода, помимо обязательных аргументов bot, update создайте опциональный args. Созданный таким образом метод будет принимать параметры, которые вы передаёте боту после названия команды. Параметры необходимо между собой разделять пробелом, в метод они поступят в виде текстового вектора.


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



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


Последний шаг который нам осталось выполнить запустить бота в фоновом режиме.


Для этого следуйте по описанному ниже алгоритму:


  1. Сохраните код бота в файл с расширением R. При работе в RStudio это делается через меню File, командой Save As....
  2. Добавьте путь к папке bin, которая в свою очередь находится в папке в которую вы установили язык R в переменную Path, инструкция тут.
  3. Создайте обычный текстовый файл, в котором пропишите 1 строку: R CMD BATCH C:\Users\Alsey\Documents\my_bot.R. Вместо C:\Users\Alsey\Documents\my_bot.R пропишите путь к своему скрипту бота. При этом важно, что бы в пути не встречалась кириллица и пробелы, т.к. это может вызвать проблемы при запуске бота. Сохраните его, и замените его расширение с txt на bat.
  4. Откройте планировщик заданий Windows, есть множество способов это сделать, например откройте любую папку и в адресс введите %windir%\system32\taskschd.msc /s. Другие способы запуска можно найти тут.
  5. В верхнем правом меню планировщика нажмите "Создать задачу...".
  6. На вкладке "Общие" задайте произвольное имя вашей задаче, и переключатель перевидите в состояние "Выполнять для всех пользователей".
  7. Перейдите на вкладку "Действия", нажмите "Создать". В поле "Программа или сценарий" нажмите "Обзор", найдите созданный на втором шаге bat файл, и нажмите ОК.
  8. Жмём ОК, при необходимости вводим пароль от вашей учётной записи операционной системы.
  9. Находим в планировщике созданную задачу, выделяем и в нижнем правом углу жмём кнопку "Выполнить".

Наш бот запущен в фоновом режиме, и будет работать до тех пор, пока вы не остановите задачу, или не выключите ваш ПК или сервер на котором его запустили.


Заключение


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


В следующей статье речь пойдёт о том, как добавить боту клавиатуру, для более удобной работы.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru