ProHoster > Blog > administrasie > Skryf 'n telegram-bot in R (deel 3): Hoe om sleutelbordondersteuning by 'n bot te voeg
Skryf 'n telegram-bot in R (deel 3): Hoe om sleutelbordondersteuning by 'n bot te voeg
Dit is die derde artikel in die reeks "Skryf 'n telegram-bot in R". In vorige publikasies het ons geleer hoe om 'n telegrambot te skep, boodskappe daardeur te stuur, opdragte en boodskapfilters by die bot gevoeg het. Daarom, voordat jy hierdie artikel begin lees, beveel ek sterk aan dat jy lees vorige, omdat Hier sal ek nie meer stilstaan by die voorheen beskryfde basiese beginsels van botbou nie.
In hierdie artikel sal ons die bruikbaarheid van ons bot verbeter deur 'n sleutelbord by te voeg, wat die bot-koppelvlak intuïtief en maklik om te gebruik sal maak.
Alle artikels uit die reeks "Skryf 'n telegram-bot in R"
Watter tipe sleutelborde ondersteun die telegram-bot?
Ten tyde van hierdie skrywe telegram.bot laat jou toe om twee tipes sleutelborde te skep:
Antwoord - Die hoof, gewone sleutelbord, wat onder die boodskapteksinvoerpaneel geleë is. So 'n sleutelbord stuur eenvoudig 'n teksboodskap na die bot, en as die teks sal dit die teks stuur wat op die knoppie self geskryf is.
Inlyn - Sleutelbord wat met 'n spesifieke botboodskap geassosieer word. Hierdie sleutelbord stuur die botdata wat verband hou met die knoppie wat gedruk word; hierdie data kan verskil van die teks wat op die knoppie self geskryf is. En sulke knoppies word deur verwerk CallbackQueryHandler.
Vir die bot om die sleutelbord oop te maak, is dit nodig wanneer 'n boodskap deur die metode gestuur word sendMessage(), gee die voorheen geskep sleutelbord as 'n argument reply_markup.
Hieronder sal ons na verskeie voorbeelde kyk.
Antwoord sleutelbord
Soos ek hierbo geskryf het, is dit die belangrikste botbeheer-sleutelbord.
'n Voorbeeld van die skep van 'n Antwoord-sleutelbord vanaf die amptelike hulp
Bogenoemde is 'n voorbeeld van die amptelike hulp van die pakket telegram.bot. Om 'n sleutelbord te skep, gebruik die funksie ReplyKeyboardMarkup(), wat op sy beurt 'n lys van lyste knoppies neem wat deur die funksie geskep word KeyboardButton().
Waarom in ReplyKeyboardMarkup() Moet jy nie net 'n lys slaag nie, maar 'n lys van lyste? Die feit is dat jy die hooflys slaag, en daarin definieer jy elke ry knoppies in aparte lyste, want Jy kan verskeie knoppies in een ry plaas.
argument resize_keyboard laat jou toe om outomaties die optimale grootte van sleutelbordknoppies en die argument te kies one_time_keyboard laat jou toe om die sleutelbord te versteek na elke druk op die knoppie.
Kom ons skryf 'n eenvoudige bot wat 3 knoppies sal hê:
Klets-ID - Versoek klets-ID van dialoog met bot
My naam - Versoek jou naam
My login - Versoek jou gebruikersnaam in telegram
Kode 1: Eenvoudige bot met Antwoord-sleutelbord
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()
Begin die kodevoorbeeld hierbo, nadat jy 'JOU BOT-TOKEN' vervang het met die regte teken wat jy ontvang het toe jy die bot geskep het via BotVader (Ek het gepraat oor die skep van 'n bot in eerste artikel).
Nadat u begin het, gee die bot 'n opdrag /start, omdat Dit is presies wat ons gedefinieer het om die sleutelbord te begin.
As dit op die oomblik vir jou moeilik is om die gegewe kodevoorbeeld te ontleed, met die skepping van metodes, filters en hanteerders, dan moet jy terugkeer na die vorige een Artikel, waarin ek dit alles in besonderhede beskryf het.
Ons het 4 metodes geskep:
begin — Begin die sleutelbord
chat_id — Versoek klets-ID
my_name — Versoek jou naam
my_username — Versoek jou aanmelding
Om beswaar te maak Boodskapfilters bygevoeg 3 boodskap filters gebaseer op hul teks:
chat_id — Boodskappe met teks "Чат ID"
naam — Boodskappe met teks "Моё имя"
gebruikernaam — Boodskappe met teks "Мой логин"
En ons het 4 hanteerders geskep wat, gebaseer op gegewe opdragte en filters, die gespesifiseerde metodes sal uitvoer.
In ons geval het ons al die knoppies onder mekaar geplaas, maar ons kan hulle in een ry rangskik deur veranderinge aan die lys knoppielyste aan te bring. Omdat een ry binne die sleutelbord word geskep deur 'n geneste lys van knoppies, en om ons knoppies in een ry te vertoon, moet ons 'n deel van die kode vir die bou van die sleutelbord soos volg herskryf:
Die sleutelbord word met die metode na die klets gestuur sendMessage(), in die argument reply_markup.
bot$sendMessage(update$message$chat_id,
text = 'Выберите команду',
reply_markup = RKM)
Inlyn sleutelbord
Soos ek hierbo geskryf het, is die Inline-sleutelbord gekoppel aan 'n spesifieke boodskap. Dit is ietwat moeiliker om mee te werk as die hoofsleutelbord.
Aanvanklik moet jy 'n metode by die bot voeg om die Inline-sleutelbord te roep.
Om op 'n Inline-knoppie te reageer, kan jy ook die botmetode gebruik answerCallbackQuery(), wat 'n kennisgewing in die telegram-koppelvlak kan vertoon aan die gebruiker wat die Inlyn-knoppie druk.
Die data wat vanaf die Inlyn-knoppie gestuur word, is nie teks nie, so om dit te verwerk moet jy 'n spesiale hanteerder skep deur die opdrag te gebruik CallbackQueryHandler().
Die kode vir die bou van 'n inlynsleutelbord wat in die amptelike hulp van die pakket gegee word telegram.bot.
Kode vir die bou van 'n inlyn sleutelbord vanaf die amptelike hulp
Jy moet 'n inlynsleutelbord bou deur die opdrag te gebruik InlineKeyboardMarkup(), op dieselfde beginsel as die Antwoord-sleutelbord. IN InlineKeyboardMarkup() dit is nodig om 'n lys lyste van Inline-knoppies deur te gee, elke individuele knoppie word deur die funksie geskep InlineKeyboardButton().
'n Inlynknoppie kan sekere data aan die bot deurgee deur 'n argument te gebruik callback_data, of maak enige HTML-bladsy oop wat gespesifiseer is deur die argument te gebruik url.
Die resultaat sal 'n lys wees waarin elke element ook 'n lys van Inline-knoppies is wat in een ry gekombineer moet word.
Volgende sal ons kyk na verskeie voorbeelde van bots met Inline-knoppies.
'n Voorbeeld van 'n eenvoudige bot met ondersteuning vir InLine-knoppies
Eerstens sal ons 'n bot skryf vir uitdruklike toetsing vir covid-19. Op bevel /test, dit sal vir jou 'n sleutelbord met twee knoppies stuur, afhangende van die knoppie wat gedruk word, sal dit vir jou 'n boodskap stuur met die resultate van jou toetsing.
Kode 2: Die eenvoudigste bot met 'n inlynsleutelbord
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()
Begin die kodevoorbeeld hierbo, nadat jy 'JOU BOT-TOKEN' vervang het met die regte teken wat jy ontvang het toe jy die bot geskep het via BotVader (Ek het gepraat oor die skep van 'n bot in eerste artikel).
Gevolg:
Ons het twee metodes geskep:
toets — Om te stuur na klets Inlyn sleutelbord
antwoord_cb — Om data wat vanaf die sleutelbord gestuur is, te verwerk.
Die data wat vanaf elke knoppie gestuur sal word, word in die argument gespesifiseer callback_data, wanneer 'n knoppie geskep word. U kan die data ontvang wat vanaf die knoppie gestuur word deur die konstruk te gebruik update$callback_query$data, binne die metode antwoord_cb.
Vir die bot om te reageer op die Inline-sleutelbord, metode antwoord_cb verwerk deur 'n spesiale hanteerder: CallbackQueryHandler(answer_cb). Wat die gespesifiseerde metode uitvoer wanneer die Inline-knoppie geklik word. Hanteerder CallbackQueryHandler neem twee argumente:
callback — Die metode wat uitgevoer moet word
pattern — Filtreer volgens data wat aan die knoppie gebind is deur 'n argument te gebruik callback_data.
Gevolglik, die gebruik van die argument pattern Ons kan 'n aparte metode skryf om elke knoppie te druk:
Kode 3: Afsonderlike metodes vir elke Inlyn-knoppie
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()
Begin die kodevoorbeeld hierbo, nadat jy 'JOU BOT-TOKEN' vervang het met die regte teken wat jy ontvang het toe jy die bot geskep het via BotVader (Ek het gepraat oor die skep van 'n bot in eerste artikel).
Nou het ons 2 aparte metodes geskryf m.a.w. een metode, vir elke knoppie druk, en gebruik die argument pattern, wanneer hulle hul hanteerders skep:
Metodekode eindig antwoord_cb per span bot$answerCallbackQuery(callback_query_id = update$callback_query$id), wat die bot vertel dat data vanaf die inlynsleutelbord ontvang is.
'n Voorbeeld van 'n bot wat die huidige weer vir 'n geselekteerde stad rapporteer
Kom ons probeer om 'n bot te skryf wat weerdata versoek.
Die logika van sy werk sal soos volg wees. Aanvanklik deur die span /start jy roep die hoofsleutelbord, wat net een "Weer"-knoppie het. Deur op hierdie knoppie te klik sal jy 'n boodskap met die inlyn sleutelbord ontvang om die stad te kies waarvoor jy die huidige weer wil uitvind. Kies een van die stede en kry die huidige weer.
In hierdie kodevoorbeeld sal ons verskeie bykomende pakkette gebruik:
httr - 'n pakket om met HTTP-versoeke te werk, op grond waarvan werk met enige API gebou word. In ons geval sal ons die gratis API gebruik openweathermap.org.
stringr - 'n pakket om met teks te werk, in ons geval sal ons dit gebruik om 'n boodskap oor die weer in die geselekteerde stad te genereer.
Kode 4: 'n Bot wat die huidige weer vir die geselekteerde stad rapporteer
Begin die kodevoorbeeld hierbo, nadat jy 'JOU BOT-TOKEN' vervang het met die regte teken wat jy ontvang het toe jy die bot geskep het via BotVader (Ek het gepraat oor die skep van 'n bot in eerste artikel).
As gevolg hiervan sal ons bot iets soos volg werk:
Skematies kan hierdie bot soos volg uitgebeeld word:
Ons het 3 metodes beskikbaar in ons weerbot geskep:
Begin - Begin die hoofbot-sleutelbord
weer — Begin inlynsleutelbord om 'n stad te kies
antwoord_cb - Die hoofmetode wat die weer van die API vir 'n gegewe stad versoek en dit na die klets stuur.
metode Begin ons begin dit met die opdrag /start, wat deur die hanteerder geïmplementeer word CommandHandler('start', start).
Om 'n metode uit te voer weer ons het 'n filter met dieselfde naam geskep:
# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {
# проверяем текст сообщения
message$text == "Погода"
}
)
En ons noem hierdie metode met die volgende boodskap hanteerder: MessageHandler(weather, filters = MessageFilters$weather).
En op die ou end, ons hoofmetode antwoord_cb reageer op die druk van Inline-knoppies, wat deur 'n spesiale hanteerder geïmplementeer word: CallbackQueryHandler(answer_cb).
Binne 'n metode antwoord_cb, lees ons die data wat vanaf die sleutelbord gestuur word en skryf dit na 'n veranderlike city: city <- update$callback_query$data. Dan versoek ons weerdata van die API, genereer en stuur 'n boodskap, en gebruik uiteindelik die metode answerCallbackQuery om die bot in te lig dat ons die klik van die Inlyn-knoppie verwerk het.
'n Voorbeeld van 'n bot wat 'n lys van die nuutste artikels met skakels na die gespesifiseerde Hub vanaf vertoon will.com.
Ek bied hierdie bot aan om jou te wys hoe om Inline-knoppies te vertoon wat na webblaaie lei.
Die logika van hierdie bot is soortgelyk aan die vorige een; aanvanklik begin ons die hoofsleutelbord met die opdrag /start. Vervolgens gee die bot vir ons 'n lys van 6 hubs om van te kies, ons kies die hub waarin ons belangstel en ontvang die 5 mees onlangse publikasies van die geselekteerde Hub.
Soos u verstaan, moet ons in hierdie geval 'n lys van artikels kry, en hiervoor sal ons 'n spesiale pakket gebruik habR, waarmee u artikels van Habra en 'n paar statistieke daaroor in R kan aanvra.
Installeer pakket habR slegs moontlik vanaf github, waarvoor u 'n bykomende pakket benodig devtools. Gebruik die kode hieronder om te installeer.
Kom ons kyk nou na die kode vir die bou van die bot wat hierbo beskryf word:
Kode 5: 'n Bot wat 'n lys van die mees onlangse artikels op die geselekteerde Hub vertoon
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()
Begin die kodevoorbeeld hierbo, nadat jy 'JOU BOT-TOKEN' vervang het met die regte teken wat jy ontvang het toe jy die bot geskep het via BotVader (Ek het gepraat oor die skep van 'n bot in eerste artikel).
As gevolg hiervan sal ons hierdie resultaat kry:
Ons het die lys van Hubs wat beskikbaar is vir keuse in die metode hardkodeer habs:
Ons kry 'n lys van artikels van die gespesifiseerde Hub met die opdrag habr_hub_posts(), uit die pakkie habR. Terselfdertyd wys ons daarop dat ons nie 'n lys van artikels vir die hele tyd nodig het nie, maar slegs die eerste bladsy waarop 20 artikels geleë is. Van die resulterende tabel met behulp van die opdrag head() Ons laat net die top 5, wat die mees onlangse artikels is.
Die logika is baie soortgelyk aan die vorige bot, maar in hierdie geval genereer ons 'n Inline-sleutelbord met 'n lys artikels dinamies deur die funksie te gebruik lapply().
Ons voeg die titel van die artikel in die knoppieteks in posts$title[x], en in die argument url skakel na artikel: url = posts$link[x].
Vervolgens skep ons 'n filter, hanteerders en begin ons bot.
Gevolgtrekking
Nou sal die bots wat jy skryf baie geriefliker wees om te gebruik, as gevolg van die feit dat hulle vanaf die sleutelbord beheer sal word, eerder as deur opdragte in te voer. Op 'n minimum, wanneer interaksie met 'n bot via 'n slimfoon, sal die sleutelbord die proses om dit te gebruik aansienlik vereenvoudig.
In die volgende artikel sal ons uitvind hoe om 'n logiese dialoog met 'n bot te bou en met databasisse te werk.