Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Това е третата статия от серията "Пишем telegram бота на езика R". В предишните публикации научихме как да създаваме телеграм бот, да изпращаме съобщения чрез него, добавихме команди и филтри за съобщения. Затова преди да преминете към четенето на тази статия, силно препоръчвам да се запознаете с предишните, тъй като тук няма да се спирам на описаните по-рано основи на ботостроението.

В тази статия ще подобрим удобството на нашия бот, като добавим клавиатура, която ще направи интерфейса на бота интуитивно понятен и лесен за използване.

Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

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

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

Съдържание

Ако се интересувате от анализ на данни, вероятно ще ви бъдат интересни моите telegram и youtube канали. Голямата част от съдържанието, което се отнася до езика R.

  1. Какви типове клавиатури поддържа телеграм бот
  2. Reply клавиатура
  3. Inline клавиатура
    3.1. Пример за прост бот с поддръжка на InLine бутони
    3.2. Пример за бот, който съобщава текущото време в избрания град
    3.3. Пример за бот, който показва списък с най-новите статии с връзки към указания Хаб от habr.com
  4. Заключение

Какви типове клавиатури поддържа телеграм бот

В момента на написването на статията telegram.bot ви позволява да създавате клавиатури от два типа:

  • Reply — Основна, обикновена клавиатура, която се намира под панела за въвеждане на текст. Тази клавиатура просто изпраща текстово съобщение на бота, като текстът, който ще бъде изпратен, е текстът написан на самата кнопка.
  • Inline — Клавиатура, свързана с конкретно съобщение от бота. Тази клавиатура изпраща на бота данни, свързани с натиснатия бутон, тези данни могат да се различават от текста, написан на самата кнопка. И тези бутони се обработват чрез CallbackQueryHandler.

За да може ботът да отвори клавиатурата, е необходимо при изпращането на съобщение чрез метода sendMessage(), да предадете създадената по-рано клавиатура в аргумента reply_markup.

По-долу ще разгледаме няколко примера.

Reply клавиатура

Както вече споменах, това е основната клавиатура за управление на бота.

Пример за създаване на Reply клавиатура от официалната документация

bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"

# Създаване на персонализирана клавиатура
text <- "Не е ли тази персонализирана клавиатура страхотна?"
RKM <- ReplyKeyboardMarkup(
  keyboard = list(
    list(KeyboardButton("Да, определено!")),
    list(KeyboardButton("Не съм сигурен")),
    list(KeyboardButton("Не..."))
  ),
  resize_keyboard = FALSE,
  one_time_keyboard = TRUE
)

# Изпращане на персонализирана клавиатура
bot$sendMessage(chat_id, text, reply_markup = RKM)

По-горе е приведен пример от официалната документация на пакета telegram.bot. За създаване на клавиатура се използва функцията ReplyKeyboardMarkup(), която от своя страна приема списък от списъци с бутони, които се създават чрез функцията KeyboardButton().

Защо в ReplyKeyboardMarkup() необходимо да се предава не просто списък, а списък от списъци? Факт е, че предавате основния списък, и в него задавате всеки ред от бутони с отделни списъци, тъй като в един ред може да се разположат няколко бутона.

Аргумент resize_keyboard позволява автоматично да се подбира оптимален размер на бутоните на клавиатурата, а аргументът one_time_keyboard позволява да се скрие клавиатурата след всяко натискане на бутон.

Нека напишем прост бот с 3 бутона:

  • Чат ID — Запитайте чат ID на диалога с бота
  • Моето име — Запитайте своето име
  • Моят логин — Запитайте своето потребителско име в Телеграм

Код 1: Прост бот с Reply клавиатура

library(telegram.bot)

# създаваме екземпляр на класа Updater
updater <- Updater('ТОКЕН НА ВАШИЯ БОТ')

# създаваме методи
## метод за стартиране на клавиатурата
start <- function(bot, update) {

  # създаваме клавиатура
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton("Чат ID")),
      list(KeyboardButton("Моето име")),
      list(KeyboardButton("Моят логин"))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
  )

  # изпращаме клавиатурата
  bot$sendMessage(update$message$chat_id,
                  text = 'Изберете команда', 
                  reply_markup = RKM)

}

## метод, който връща id на чата
chat_id <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Чат id на този диалог: ", update$message$chat_id),
                  parse_mode = "Markdown")

}

## метод, който връща име
my_name <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Вас зоват ", update$message$from$first_name),
                  parse_mode = "Markdown")

}

## метод, който връща логин
my_username <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Вашият логин е ", update$message$from$username),
                  parse_mode = "Markdown")

}

# създаваме филтри
## съобщения с текст Чат ID
MessageFilters$chat_id <- BaseFilter(function(message) {

  # проверяваме текста на съобщението
  message$text == "Чат ID"

}
)

## съобщения с текст Моето име
MessageFilters$name <- BaseFilter(function(message) {

  # проверяваме текста на съобщението
  message$text == "Моето име"

}
)

## съобщения с текст Моят логин
MessageFilters$username <- BaseFilter(function(message) {

  # проверяваме текста на съобщението
  message$text == "Моят логин"
)

# създаваме обработчици
h_start    <- CommandHandler('start', start)
h_chat_id  <- MessageHandler(chat_id, filters = MessageFilters$chat_id)
h_name     <- MessageHandler(my_name, filters = MessageFilters$name)
h_username <- MessageHandler(my_username, filters = MessageFilters$username)

# добавяме обработчиците в диспетчера
updater <- updater + 
            h_start +
            h_chat_id +
            h_name +
            h_username

# стартираме бота 
updater$start_polling()

Стартирайте предоставения по-горе примерен код, предварително заменяйки ‘ТОКЕНА НА ВАШИЯ БОТ’ с реален токен, който сте получили при създаването на бота чрез BotFather (за създаването на бота разказах в първата статия).

След стартиране задайте команда на бота /start, тъй като именно тя определя за стартиране на клавиатурата.

Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Ако в момента ви е трудно да разберете дадения код, който включва създаването на методи, филтри и обработчици, трябва да се върнете към предишната статии, в която подробно описах всичко това.

Създадохме 4 метода:

  • start — Стартиране на клавиатурата
  • chat_id — Запитване на идентификатора на чата
  • my_name — Запитване на собственото име
  • my_username — Запитване на потребителското име

В обекта MessageFilters добавихме 3 филтъра за съобщения, по техния текст:

  • chat_id — Съобщения с текста "Чат ID"
  • name — Съобщения с текста "Моето име"
  • username — Съобщения с текста "Моето потребителско име"

И създадохме 4 обработчика, които по зададени команди и филтри ще изпълняват указани методи.

# создаём обработчики
h_start    <- CommandHandler('start', start)
h_chat_id  <- MessageHandler(chat_id, filters = MessageFilters$chat_id)
h_name     <- MessageHandler(my_name, filters = MessageFilters$name)
h_username <- MessageHandler(my_username, filters = MessageFilters$username)

Самата клавиатура се създава вътре в метода start() с командата ReplyKeyboardMarkup().

RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton("Чат ID")),
      list(KeyboardButton("Моето име")),
      list(KeyboardButton("Моето потребителско име"))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)

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

RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
          KeyboardButton("Чат ID"),
          KeyboardButton("Моето име"),
          KeyboardButton("Моето потребителско име")
     )
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)

Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Клавиатурата се изпраща в чата с метода sendMessage(), в аргумента reply_markup.

  bot$sendMessage(update$message$chat_id,
                  text = 'Изберете команда', 
                  reply_markup = RKM)

Inline клавиатура

Както вече споменах по-горе, Inline клавиатурата е прикрепена към конкретно съобщение. Работата с нея е малко по-сложна, отколкото с основната клавиатура.

Първоначално трябва да добавите на бота метод за извикване на Inline клавиатурата.

За отговор на натискане на Inline бутона можете също така да използвате метода на бота answerCallbackQuery(), който може да изведе уведомление в интерфейса на Telegram за потребителя, натиснал Inline бутона.

Данните, изпратени от Inline бутона, не са текст, затова за тяхната обработка е необходимо да създадете специален обработчик с помощта на командата CallbackQueryHandler().

Кодът за изграждане на Inline клавиатура, койта е приведена в официалната документация на пакета telegram.bot.

Кодът за изграждане на Inline клавиатура от официалната документация

# Initialize bot
bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"

# Create Inline Keyboard
text <- "Could you type their phone number, please?"
IKM <- InlineKeyboardMarkup(
  inline_keyboard = list(
    list(
      InlineKeyboardButton(1),
      InlineKeyboardButton(2),
      InlineKeyboardButton(3)
    ),
    list(
      InlineKeyboardButton(4),
      InlineKeyboardButton(5),
      InlineKeyboardButton(6)
    ),
    list(
      InlineKeyboardButton(7),
      InlineKeyboardButton(8),
      InlineKeyboardButton(9)
    ),
    list(
      InlineKeyboardButton("*"),
      InlineKeyboardButton(0),
      InlineKeyboardButton("#")
    )
  )
)

# Send Inline Keyboard
bot$sendMessage(chat_id, text, reply_markup = IKM)

За изграждане на Inline клавиатура е необходимо да се използва командата InlineKeyboardMarkup(), по същия принцип, както и клавиатурата Reply. В InlineKeyboardMarkup() е необходимо да се предаде списък, списъци от Inline бутони, всеки отделен бутон се създава с функцията InlineKeyboardButton().

Inline бутонът може да предаде на бота някакви данни чрез аргумента callback_data, или да отваря определена HTML страница, зададена с аргумента url.

В резултат ще имаме списък, в който всеки елемент също е списък от Inline бутони, които трябва да бъдат комбинирани в един ред.

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

Пример за прост бот с поддръжка на InLine бутони

За начало ще напишем бот за експресно тестване за covid-19. По команда /test, той ще ви изпрати клавиатура с два бутона, в зависимост от натиснатия бутон, той ще ви изпраща съобщение с резултатите от вашето тестване.

Код 2: Най-простият бот с Inline клавиатура

library(telegram.bot)

# създаваме екземпляр на класа Updater
updater <- Updater('ТОКЕН НА ВАШИЯ БУТ')

# метод за изпращане на InLine клавиатура
test <- function(bot, update) {

  # създаваме InLine клавиатура
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("Да", callback_data = 'yes'),
        InlineKeyboardButton("Не", callback_data = 'no')
      )
    )
  )

  # Изпращаме клавиатурата в чата
  bot$sendMessage(update$message$chat_id, 
                  text = "Със COVID ли сте болни?", 
                  reply_markup = IKM)
}

# метод за обработка на натискането на бутона
answer_cb <- function(bot, update) {

  # получените данни от бутона
  data <- update$callback_query$data

  # получаваме името на потребителя, натиснал бутона
  uname <- update$effective_user()$first_name

  # обработка на резултата
  if ( data == 'no' ) {

    msg <- paste0(uname, ", поздравления, вашият тест за covid-19 е отрицателен.")

  } else {

    msg <- paste0(uname, ", за съжаление, вашият тест за covid-19 е положителен.")

  }

  # Изпращане на съобщението
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # уведомяваме бота, че заявката от бутона е приета
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# създаваме обработчици
inline_h      <- CommandHandler('test', test)
query_handler <- CallbackQueryHandler(answer_cb)

# добавяме обработчиците в диспетчера
updater <- updater + inline_h + query_handler

# стартираме бота
updater$start_polling()

Стартирайте предоставения по-горе примерен код, предварително заменяйки ‘ТОКЕНА НА ВАШИЯ БОТ’ с реален токен, който сте получили при създаването на бота чрез BotFather (за създаването на бота разказах в първата статия).

Резултат:
Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Създадохме два метода:

  • test — За изпращане в чата на Inline клавиатурата
  • answer_cb — За обработка на данните, изпратени от клавиатурата.

Данните, които ще бъдат изпратени с всеки бутон, се задават в аргумента callback_data, при създаването на бутона. Получаването на изпратените данни от бутона може да стане с конструкцията update$callback_query$data, вътре в метода answer_cb.

За да може ботът да реагира на Inline клавиатурата, методът answer_cb обработва се от специален обработчик: CallbackQueryHandler(answer_cb). Който стартира определения метод при натискане на Inline бутон. Обработчик CallbackQueryHandler приема два аргумента:

  • callback — Метод, който трябва да стартира
  • pattern — Филтър по данни, свързани с бутона чрез аргумент callback_data.

Съответно с помощта на аргумента pattern можем да напишем отделен метод за натискане на всеки бутон:

Код 3: Разделяме методите под всеки Inline бутон

library(telegram.bot)

# създаваме екземпляр на клас Updater
updater <- Updater('ТОКЕН НА ВАШИЯ БОТ')

# метод за изпращане на InLine клавиатура
test <- function(bot, update) {  

  # създаваме InLine клавиатура
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("Да", callback_data = 'yes'),
        InlineKeyboardButton("Не", callback_data = 'no')
      )
    )
  )

  # Изпращаме клавиатурата в чата
  bot$sendMessage(update$message$chat_id, 
                  text = "Имате ли коронавирус?", 
                  reply_markup = IKM)
}

# метод за обработка на натискането на бутона Да
answer_cb_yes <- function(bot, update) {

  # получаваме името на потребителя, който е натиснал бутона
  uname <- update$effective_user()$first_name

  # обработка на резултата
  msg <- paste0(uname, ", съжалявам, вашият тест за covid-19 е положителен.")

  # Изпращане на съобщение
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # уведомяваме бота, че заявката от бутона е приета
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# метод за обработка на натискането на бутона Не
answer_cb_no <- function(bot, update) {

  # получаваме името на потребителя, който е натиснал бутона
  uname <- update$effective_user()$first_name

  msg <- paste0(uname, ", поздравления, вашият тест за covid-19 е отрицателен.")

  # Изпращане на съобщение
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # уведомяваме бота, че заявката от бутона е приета
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# създаваме обработчици
inline_h          <- CommandHandler('test', test)
query_handler_yes <- CallbackQueryHandler(answer_cb_yes, pattern = 'yes')
query_handler_no  <- CallbackQueryHandler(answer_cb_no, pattern = 'no')

# добавяме обработчиците в диспетчера
updater <- updater + 
            inline_h + 
            query_handler_yes +
            query_handler_no

# стартираме бота
updater$start_polling()

Стартирайте предоставения по-горе примерен код, предварително заменяйки ‘ТОКЕНА НА ВАШИЯ БОТ’ с реален токен, който сте получили при създаването на бота чрез BotFather (за създаването на бота разказах в първата статия).

Сега написахме 2 отделни метода, т.е. по един метод за натискане на всеки бутон, и използвахме аргумент pattern, при създаването на техните обработчици:

query_handler_yes <- CallbackQueryHandler(answer_cb_yes, pattern = 'yes')
query_handler_no  <- CallbackQueryHandler(answer_cb_no, pattern = 'no')

Завършва кода на метода answer_cb с командата bot$answerCallbackQuery(callback_query_id = update$callback_query$id), който уведомява бота, че данните от inline клавиатурата са получени.

Пример за бот, който съобщава текущото време в избрания град

Нека да опитаме да създадем бот, който извлича данни за времето.

Логиката на неговата работа ще бъде следната. Първоначално с команда /start вие извиквате основната клавиатура, на която присъства само един бутон "Времето". Когато натиснете този бутон, получавате съобщение с Inline клавиатура за избор на град, за който искате да научите текущото време. Избирате един от градовете и получавате текущото време.

В този пример на код ще използваме няколко допълнителни пакета:

  • httr — пакет за работа с HTTP заявки, на базата на който е изградена работата с всяко API. В нашия случай ще използваме безплатно API openweathermap.org.
  • stringr — пакет за работа с текст, в нашия случай ще го използваме за форматиране на съобщение за времето в избрания град.

Код 4: Бот, който съобщава текущото време за избрания град

library(telegram.bot)
library(httr)
library(stringr)

# създаваме инстанция на класа Updater
updater <- Updater('ТОКЕН НА ВАШИЯ БОТ')

# създаваме методи
## метод за стартиране на основната клавиатура
start <- function(bot, update) {

  # създаваме клавиатура
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton("Времето")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  # изпращаме клавиатурата
  bot$sendMessage(update$message$chat_id,
                  text = 'Изберете команда', 
                  reply_markup = RKM)

}

## Метод за извикване на Илайн клавиатурата
weather <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'Москва', callback_data = 'New York,us'),
        InlineKeyboardButton(text = 'Санкт-Петербург', callback_data = 'Saint Petersburg'),
        InlineKeyboardButton(text = 'Ню Йорк', callback_data = 'New York')
      ),
      list(
        InlineKeyboardButton(text = 'Екатеринбург', callback_data = 'Yekaterinburg,ru'),
        InlineKeyboardButton(text = 'Берлин', callback_data = 'Berlin,de'),
        InlineKeyboardButton(text = 'Париж', callback_data = 'Paris,fr')
      ),
      list(
        InlineKeyboardButton(text = 'Рим', callback_data = 'Rome,it'),
        InlineKeyboardButton(text = 'Одеса', callback_data = 'Odessa,ua'),
        InlineKeyboardButton(text = 'Киев', callback_data = 'Kyiv,fr')
      ),
      list(
        InlineKeyboardButton(text = 'Токио', callback_data = 'Tokyo'),
        InlineKeyboardButton(text = 'Амстердам', callback_data = 'Amsterdam,nl'),
        InlineKeyboardButton(text = 'Вашингтон', callback_data = 'Washington,us')
      )
    )
  )

  # Изпращане на Илайн клавиатура
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Изберете град", 
                  reply_markup = IKM)
}

# метод за изпращане на времето
answer_cb <- function(bot, update) {

  # получаваме града от съобщението
  city <- update$callback_query$data

  # изпращаме заявка
  ans <- GET('https://api.openweathermap.org/data/2.5/weather', 
             query = list(q     = city,
                          lang  = 'bg',
                          units = 'metric',
                          appid = '4776568ccea136ffe4cda9f1969af340')) 

  # парсираме отговора
  result <- content(ans)

  # формираме съобщението
  msg <- str_glue("{result$name} времето:n",
                  "Текуща температура: {result$main$temp}n",
                  "Скорост на вятъра: {result$wind$speed}n",
                  "Описание: {result$weather[[1]]$description}")

  # изпращаме информация за времето
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = msg)

  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# създаваме филтри
## съобщения с текст 'Времето'
MessageFilters$weather <- BaseFilter(function(message) {

  # проверяваме текста на съобщението
  message$text == "Времето"

}
)

# създаваме обработчици
h_start         <- CommandHandler('start', start)
h_weather       <- MessageHandler(weather, filters = MessageFilters$weather)
h_query_handler <- CallbackQueryHandler(answer_cb)

# добавяме обработчиците в диспетчера
updater <- updater + 
              h_start +
              h_weather +
              h_query_handler

# стартираме бота
updater$start_polling()

Стартирайте предоставения по-горе примерен код, предварително заменяйки ‘ТОКЕНА НА ВАШИЯ БОТ’ с реален токен, който сте получили при създаването на бота чрез BotFather (за създаването на бота разказах в първата статия).

В резултат на това нашият бот ще работи по следния начин:
Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Схематично този бот може да изглежда така:
Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Създадохме 3 метода, достъпни в нашия метеорологичен бот:

  • стартиране — Стартиране на основната клавиатура на бота
  • погода — Стартиране на Inline клавиатура за избор на град
  • answer_cb — Основен метод, който по зададен град запитва в API времето и го изпраща в чата.

Методът стартиране при нас се стартира с командата /start, което е реализирано с обработчик CommandHandler('start', start).

За стартиране на метода погода създадохме аналогичен филтър:

# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {

  # проверяем текст сообщения
  message$text == "Погода"

}
)

И извикваме този метод с следния обработчик на съобщения: MessageHandler(weather, filters = MessageFilters$weather).

И накрая, нашият основен метод answer_cb реагира на натискането на Inline бутони, което е реализирано със специален обработчик: CallbackQueryHandler(answer_cb).

Вътре в метода answer_cb, четем данните, изпратени от клавиатурата, и ги записваме в променлива град: city <- update$callback_query$data. След което запитваме API за данни за времето, оформяме и изпращаме съобщение, и накрая използваме метода answerCallbackQuery за да уведомим бота, че сме обработили натискането на Inline бутона.

Пример на бот, който извежда списък с най-новите статии с линкове по посочения Хаб от habr.com.

Този бот представям, за да ви покажа как да изведете Inline бутони, които водят към уеб страници.

Логиката на този бот е подобна на предишния, първоначално стартираме основната клавиатура с командата /start. След това ботът ни предлага списък от 6 хаба, избираме интересния хаб и получаваме 5-те най-нови публикации от избрания Хаб.

Както разбирате, в този случай трябва да получим списък с статии, за което ще използваме специален пакет habR, който позволява да запитваме статии от Хабра и някаква статистика за тях в R.

Пакетът habR може да бъде инсталиран само от github, за което ще ви трябва допълнителен пакет devtools. За инсталация използвайте предоставения по-долу код.

install.packages('devtools')
devtools::install_github('selesnow/habR')

Сега нека разгледаме кода за построяване на описания по-горе бот:

Код 5: Бот, който извежда списък с най-новите статии по избрания Хаб

library(telegram.bot)
library(habR)

# Създаваме инстанция на класа Updater
updater <- Updater('ТОКЕН НА ВАШИЯ БОТ')

# Създаваме методи
## Метод за стартиране на основната клавиатура
start <- function(bot, update) {

  # Създаваме клавиатурата
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton("Списък на статии")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  # Изпращаме клавиатурата
  bot$sendMessage(update$message$chat_id,
                  text = 'Изберете команда', 
                  reply_markup = RKM)

}

## Метод за извикване на Inline клавиатура
habs <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'R', callback_data = 'R'),
        InlineKeyboardButton(text = 'Data Mining', callback_data = 'data_mining'),
        InlineKeyboardButton(text = 'Data Engineering', callback_data = 'data_engineering')
      ),
      list(
        InlineKeyboardButton(text = 'Big Data', callback_data = 'bigdata'),
        InlineKeyboardButton(text = 'Python', callback_data = 'python'),
        InlineKeyboardButton(text = 'Визуализация на данни', callback_data = 'data_visualization')
      )
    )
  )

  # Изпращане на Inline клавиатура
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Изберете Хаб", 
                  reply_markup = IKM)
}

# Метод за съобщение за времето
answer_cb <- function(bot, update) {

  # Получаваме от съобщението града
  hub <- update$callback_query$data

  # Съобщение, че данните от бутона са получени
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id, 
                          text = 'Изчакайте няколко минути, заявката се обработва') 

  # Съобщение, че трябва да изчакате, докато ботът получи данните
  mid <- bot$sendMessage(chat_id = update$from_chat_id(),
                         text    = "Изчакайте няколко минути, докато събера данните за избрания Хаб")

  # Парсим Хабр
  posts <- head(habr_hub_posts(hub, 1), 5)

  # Изтриваме съобщението за изчакване
  bot$deleteMessage(update$from_chat_id(), mid$message_id) 

  # Формираме списък с бутони
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  # Формираме клавиатурата
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )

  # Изпращаме информация за времето
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = paste0("5 най-нови статии от Хаба ", hub),
                  reply_markup = IKM)

}

# Създаваме филтри
## Съобщения с текст "Времето"
MessageFilters$hubs <- BaseFilter(function(message) {

  # Проверяваме текста на съобщението
  message$text == "Списък на статии"

}
)

# Създаваме обработчици
h_start         <- CommandHandler('start', start)
h_hubs          <- MessageHandler(habs, filters = MessageFilters$hubs)
h_query_handler <- CallbackQueryHandler(answer_cb)

# Добавяме обработчиците към диспетчера
updater <- updater + 
  h_start +
  h_hubs  +
  h_query_handler

# Стартираме бота
updater$start_polling()

Стартирайте предоставения по-горе примерен код, предварително заменяйки ‘ТОКЕНА НА ВАШИЯ БОТ’ с реален токен, който сте получили при създаването на бота чрез BotFather (за създаването на бота разказах в първата статия).

В крайна сметка, ще получим такъв резултат:
Пишем telegram бот на езика R (част 3): Как да добавим поддръжка на клавиатурата за бота

Списък на наличните Хъбове е зададен в кода, в метода habs:

## Метод вызова Inine клавиатуры
habs <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'R', callback_data = 'r'),
        InlineKeyboardButton(text = 'Data Mining', callback_data = 'data_mining'),
        InlineKeyboardButton(text = 'Data Engineering', callback_data = 'data_engineering')
      ),
      list(
        InlineKeyboardButton(text = 'Big Data', callback_data = 'bigdata'),
        InlineKeyboardButton(text = 'Python', callback_data = 'python'),
        InlineKeyboardButton(text = 'Визуализация данных', callback_data = 'data_visualization')
      )
    )
  )

  # Send Inline Keyboard
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Выберите Хаб", 
                  reply_markup = IKM)
}

Списъкът на статиите от указаното Хъб е получен чрез команда habr_hub_posts(), от пакета habR. В същото време посочваме, че не ни е нужен списък с всички статии, а само първата страница, на която се намират 20 статии. От получената таблица с помощта на команда head() оставяме само 5-те най-горни, които са и най-новите статии.

  # парсим Хабр
  posts <- head(habr_hub_posts(hub, 1), 5)

Логиката е много подобна на предишния бот, но в този случай генерираме Inline клавиатура със списък на статиите динамично с помощта на функцията lapply().

  # формируем список кнопок
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  # формируем клавиатуру
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )

В текста на бутона поставяме заглавието на статията posts$title[x], а в аргумента url поставяме връзката към статията: url = posts$link[x].

След това създаваме филтри, обработватели и стартираме нашия бот.

Заключение

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

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

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

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