Це третя стаття із серії "Пишемо telegram бота мовою R". У попередніх публікаціях ми навчилися створювати телеграм бота, надсилати через нього повідомлення, додали боту команди та фільтри повідомлень. Тому перед тим як приступити до читання цієї статті я вкрай рекомендую ознайомитися з , т.к. тут я вже не зупинятиму на описаних раніше основах ботобудування.
У цій статті ми підвищимо юзабіліті нашого бот за рахунок додавання клавіатури, яка зробить інтерфейс бот інтуїтивно зрозумілим, і простим у використанні.

Всі статті із серії "Пишемо telegram бота мовою R"
Зміст
Якщо ви цікавитеся аналізом даних можливо вам будуть цікаві мої и канали. Більшість контенту яких присвячені мові R.
3.1.
3.2.
3.3.
Які типи клавіатур підтримує телеграм бот
На момент написання статті telegram.bot дозволяє створити клавіатури двох типів:
- Reply — Основна, звичайна клавіатура, яка знаходиться під панеллю текстового повідомлення. Така клавіатура просто надсилає боту текстове повідомлення, і як текст відправить той текст, який написаний на кнопці.
- Inline — Клавіатура, прив'язана до конкретного повідомлення робота. Ця клавіатура відправляє роботу дані, прив'язані до натиснутої кнопки, ці дані можуть відрізнятися від тексту, написаного на самій кнопці. І обробляються такі кнопки через CallbackQueryHandler.
Для того, щоб бот відкрив клавіатуру необхідно при відправці повідомлення через метод sendMessage()передати створену раніше клавіатуру в аргумент reply_markup.
Нижче ми розберемо кілька прикладів.
Reply клавіатура
Як я вже писав вище, це основна клавіатура управління роботом.
Приклад створення клавіатури Reply з офіційної довідки
bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"
# Create Custom Keyboard
text <- "Aren't those custom keyboards cool?"
RKM <- ReplyKeyboardMarkup(
keyboard = list(
list(KeyboardButton("Yes, they certainly are!")),
list(KeyboardButton("I'm not quite sure")),
list(KeyboardButton("No..."))
),
resize_keyboard = FALSE,
one_time_keyboard = TRUE
)
# Send Custom Keyboard
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, т.к. саме її ми визначили для запуску клавіатури.

Якщо на даний момент вам складно розібрати наведений приклад коду, зі створенням методів, фільтрів та обробників, слід повернутися до попередньої , В якій я докладно все це описав.
Ми створили 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
)
Відправляється клавіатура в чат методом 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 = "Вы болете коронавирусом?",
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 (про створення бота я розповідав у ).
Результат:

Ми створили два методи:
- тест — Для надсилання в чат 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 .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)
}
## Метод вызова Inine клавиатуры
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')
)
)
)
# Send Inline Keyboard
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 = 'ru',
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 (про створення бота я розповідав у ).
В результаті наш бот працюватиме приблизно так:

Схематично цього робота можна вибрати так:

Ми створили 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: city <- update$callback_query$data. Після чого запитуємо з API дані про погоду, формуємо та надсилаємо повідомлення, і зрештою використовуємо метод answerCallbackQuery для того, щоб повідомити роботу, про те, що ми обробили натискання Inline кнопки.
Приклад бота, який виводить список найсвіжіших статей з посиланнями на вказане Хабу з .
Цього робота я наводжу для того, щоб показати вам, як вивести 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)
}
## Метод вызова 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)
}
# метод для сообщения погоды
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 (про створення бота я розповідав у ).
У результаті ми отримаємо такий результат:

Список доступних для вибору Хабов ми вбили хардкодом, у методі 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
