ProHoster > Blogs > Administrācija > Telegrammas robota rakstīšana programmā R (3. daļa): kā robotam pievienot tastatūras atbalstu
Telegrammas robota rakstīšana programmā R (3. daļa): kā robotam pievienot tastatūras atbalstu
Šis ir trešais raksts sērijā “Telegrammas robota rakstīšana R”. Iepriekšējās publikācijās mēs uzzinājām, kā izveidot telegrammas robotu, sūtīt ziņojumus caur to, pievienojām robotam komandas un ziņojumu filtrus. Tāpēc, pirms sākat lasīt šo rakstu, ļoti iesaku izlasīt iepriekšējā, jo Šeit es vairs nekavēšos pie iepriekš aprakstītajiem botu veidošanas pamatiem.
Šajā rakstā mēs uzlabosim mūsu bota lietojamību, pievienojot tastatūru, kas padarīs bota interfeisu intuitīvu un ērti lietojamu.
Visi raksti no sērijas “Telegrammas robota rakstīšana R”
Kādus tastatūras veidus atbalsta telegrammas robots?
Šīs rakstīšanas laikā telegram.bot ļauj izveidot divu veidu tastatūras:
Atbildēt — galvenā parastā tastatūra, kas atrodas zem ziņojuma teksta ievades paneļa. Šāda tastatūra vienkārši nosūta īsziņu robotam, un kā tekstu tā nosūtīs tekstu, kas ir uzrakstīts uz pašas pogas.
Iekļauts — tastatūra, kas saistīta ar konkrētu robota ziņojumu. Šī tastatūra nosūta robota datus, kas saistīti ar nospiesto pogu; šie dati var atšķirties no teksta, kas rakstīts uz pašas pogas. Un šādas pogas tiek apstrādātas cauri CallbackQueryHandler.
Lai robots varētu atvērt tastatūru, tas ir nepieciešams, nosūtot ziņojumu, izmantojot metodi sendMessage(), nododiet iepriekš izveidoto tastatūru kā argumentu reply_markup.
Tālāk mēs aplūkosim vairākus piemērus.
Atbildes tastatūra
Kā jau rakstīju iepriekš, šī ir galvenā robotprogrammatūras vadības tastatūra.
Atbildes tastatūras izveides piemērs no oficiālās palīdzības
Iepriekš minētais ir piemērs no paketes oficiālās palīdzības telegram.bot. Lai izveidotu tastatūru, izmantojiet funkciju ReplyKeyboardMarkup(), kas savukārt iegūst funkcijas izveidoto pogu sarakstu sarakstu KeyboardButton().
Kāpēc ReplyKeyboardMarkup() Vai jums ir jānodod ne tikai saraksts, bet arī sarakstu saraksts? Fakts ir tāds, ka jūs izietat galveno sarakstu un tajā katru pogu rindu definējat atsevišķos sarakstos, jo Jūs varat ievietot vairākas pogas vienā rindā.
Arguments resize_keyboard ļauj automātiski atlasīt optimālo tastatūras pogu izmēru un argumentu one_time_keyboard ļauj paslēpt tastatūru pēc katras pogas nospiešanas.
Uzrakstīsim vienkāršu robotprogrammu, kurai būs 3 pogas:
Tērzēšanas ID — pieprasiet dialoga tērzēšanas ID ar robotu
Mans vārds - Pieprasiet savu vārdu
Mans pieteikšanās vārds - Pieprasiet savu lietotājvārdu telegrammā
1. kods: vienkāršs robots ar atbildes tastatūru
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()
Palaidiet iepriekš norādīto koda piemēru pēc tam, kad esat aizstājis 'YOUR BOOT TOKEN' ar īsto marķieri, ko saņēmāt, veidojot robotu, izmantojot BotFather (Es runāju par robota izveidi pirmais raksts).
Pēc palaišanas dodiet robotam komandu /start, jo Tas ir tieši tas, ko mēs definējām, lai palaistu tastatūru.
Ja šobrīd jums ir grūti parsēt dotā koda piemēru, veidojot metodes, filtrus un apstrādātājus, tad jums vajadzētu atgriezties pie iepriekšējā raksts, kurā es to visu sīki aprakstīju.
Mēs izveidojām 4 metodes:
start — palaidiet tastatūru
chat_id — pieprasiet tērzēšanas ID
my_name — pieprasiet savu vārdu
my_username — pieprasiet savu pieteikšanos
Iebilst Ziņojumu filtri pievienoja 3 ziņojumu filtrus, pamatojoties uz to tekstu:
chat_id — ziņojumi ar tekstu "Чат ID"
nosaukums — ziņas ar tekstu "Моё имя"
lietotājvārds — ziņas ar tekstu "Мой логин"
Un mēs izveidojām 4 apstrādātājus, kas, pamatojoties uz dotajām komandām un filtriem, izpildīs norādītās metodes.
Mūsu gadījumā visas pogas novietojām vienu zem otras, taču varam tās sakārtot vienā rindā, veicot izmaiņas pogu sarakstu sarakstā. Jo viena rinda tastatūras iekšpusē tiek izveidota, izmantojot ligzdotu pogu sarakstu, tad, lai mūsu pogas parādītu vienā rindā, mums ir jāpārraksta daļa no koda, lai izveidotu tastatūru šādi:
Tastatūra tiek nosūtīta uz tērzēšanu, izmantojot metodi sendMessage(), argumentācijā reply_markup.
bot$sendMessage(update$message$chat_id,
text = 'Выберите команду',
reply_markup = RKM)
Iekļautā tastatūra
Kā jau rakstīju iepriekš, iekļautā tastatūra ir saistīta ar konkrētu ziņojumu. Ar to strādāt ir nedaudz grūtāk nekā ar galveno tastatūru.
Sākotnēji robotam jāpievieno metode, lai izsauktu iekļauto tastatūru.
Lai atbildētu uz iekļautās pogas klikšķi, varat izmantot arī robotprogrammatūras metodi answerCallbackQuery(), kas telegrammas saskarnē var parādīt paziņojumu lietotājam, kurš nospiež Inline pogu.
No Inline pogas nosūtītie dati nav teksts, tāpēc, lai tos apstrādātu, ir jāizveido īpašs apstrādātājs, izmantojot komandu CallbackQueryHandler().
Inline tastatūras izveides kods, kas ir norādīts pakotnes oficiālajā palīdzībā telegram.bot.
Kods iekļautās tastatūras izveidei no oficiālās palīdzības
Izmantojot komandu, jums ir jāizveido iekļauta tastatūra InlineKeyboardMarkup(), pēc tāda paša principa kā tastatūra Atbildēt. IN InlineKeyboardMarkup() nepieciešams nodot Inline pogu sarakstu sarakstu, katru atsevišķu pogu izveido funkcija InlineKeyboardButton().
Iekļautā poga var vai nu nodot dažus datus robotam, izmantojot argumentu callback_datavai atveriet jebkuru HTML lapu, kas norādīta, izmantojot argumentu url.
Rezultātā tiks izveidots saraksts, kurā katrs elements ir arī saraksts ar iekļautajām pogām, kuras ir jāapvieno vienā rindā.
Tālāk mēs apskatīsim vairākus robotu piemērus ar iekļautajām pogām.
Vienkārša robota piemērs ar InLine pogu atbalstu
Pirmkārt, mēs uzrakstīsim robotprogrammatūru Covid-19 ātrai pārbaudei. Pēc komandas /test, tas jums nosūtīs tastatūru ar divām pogām, atkarībā no nospiestās pogas tas nosūtīs jums ziņojumu ar jūsu pārbaudes rezultātiem.
2. kods: vienkāršākais robots ar iekļautu tastatūru
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()
Palaidiet iepriekš norādīto koda piemēru pēc tam, kad esat aizstājis 'YOUR BOOT TOKEN' ar īsto marķieri, ko saņēmāt, veidojot robotu, izmantojot BotFather (Es runāju par robota izveidi pirmais raksts).
Rezultāts:
Mēs izveidojām divas metodes:
pārbaude — lai nosūtītu uz tērzēšanu iekļautā tastatūra
atbilde_cb — lai apstrādātu no tastatūras nosūtītos datus.
Dati, kas tiks nosūtīti no katras pogas, ir norādīti argumentā callback_data, veidojot pogu. Jūs varat saņemt no pogas nosūtītos datus, izmantojot konstrukciju update$callback_query$data, metodes iekšpusē atbilde_cb.
Lai robots reaģētu uz iekļauto tastatūru, metode atbilde_cb apstrādā īpašs apstrādātājs: CallbackQueryHandler(answer_cb). Kas palaiž norādīto metodi, kad tiek noklikšķināts uz Iekļautās pogas. Apdarinātājs CallbackQueryHandler ir divi argumenti:
callback — Metode, kas jāpalaiž
pattern — Filtrējiet pēc datiem, kas ir saistīti ar pogu, izmantojot argumentu callback_data.
Attiecīgi, izmantojot argumentu pattern Katras pogas nospiešanai varam uzrakstīt atsevišķu metodi:
3. kods: katrai iekļautajai pogai atsevišķas metodes
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()
Palaidiet iepriekš norādīto koda piemēru pēc tam, kad esat aizstājis 'YOUR BOOT TOKEN' ar īsto marķieri, ko saņēmāt, veidojot robotu, izmantojot BotFather (Es runāju par robota izveidi pirmais raksts).
Tagad esam uzrakstījuši 2 atsevišķas metodes, t.i. viena metode, katrai pogas nospiešanai, un izmantoja argumentu pattern, veidojot to apdarinātājus:
Metodes kods beidzas atbilde_cb komanda bot$answerCallbackQuery(callback_query_id = update$callback_query$id), kas paziņo robotam, ka dati no iekļautās tastatūras ir saņemti.
Bota piemērs, kas ziņo par pašreizējiem laikapstākļiem atlasītajā pilsētā
Mēģināsim uzrakstīt robotu, kas pieprasa laikapstākļu datus.
Tās darba loģika būs šāda. Sākumā komanda /start jūs izsaucat galveno tastatūru, kurai ir tikai viena poga "Laiks". Noklikšķinot uz šīs pogas, jūs saņemsiet ziņojumu ar iekļauto tastatūru, lai izvēlētos pilsētu, kurā vēlaties uzzināt pašreizējos laikapstākļus. Izvēlieties kādu no pilsētām un uzziniet pašreizējos laikapstākļus.
Šajā koda piemērā mēs izmantosim vairākas papildu pakotnes:
httr — pakotne darbam ar HTTP pieprasījumiem, uz kuras pamata tiek veidots darbs ar jebkuru API. Mūsu gadījumā mēs izmantosim bezmaksas API openweathermap.org.
stringr — pakotne darbam ar tekstu, mūsu gadījumā to izmantosim, lai ģenerētu ziņu par laikapstākļiem izvēlētajā pilsētā.
Kods 4: robots, kas ziņo par pašreizējiem laikapstākļiem atlasītajā pilsētā
Palaidiet iepriekš norādīto koda piemēru pēc tam, kad esat aizstājis 'YOUR BOOT TOKEN' ar īsto marķieri, ko saņēmāt, veidojot robotu, izmantojot BotFather (Es runāju par robota izveidi pirmais raksts).
Rezultātā mūsu robots darbosies šādi:
Shematiski šo robotprogrammatūru var attēlot šādi:
Mēs esam izveidojuši 3 metodes, kas pieejamas mūsu laikapstākļu robotā:
sākums — Palaidiet galveno robota tastatūru
laiks — Palaidiet iekļauto tastatūru, lai atlasītu pilsētu
atbilde_cb — Galvenā metode, kas pieprasa laika ziņas no API konkrētai pilsētai un nosūta tos uz tērzēšanu.
Metode sākums mēs to palaižam ar komandu /start, ko ievieš apdarinātājs CommandHandler('start', start).
Lai palaistu metodi laiks mēs izveidojām filtru ar tādu pašu nosaukumu:
# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {
# проверяем текст сообщения
message$text == "Погода"
}
)
Un mēs izsaucam šo metodi ar šādu ziņojumu apstrādātāju: MessageHandler(weather, filters = MessageFilters$weather).
Un galu galā mūsu galvenā metode atbilde_cb reaģē uz Inline pogu nospiešanu, ko īsteno īpašs apstrādātājs: CallbackQueryHandler(answer_cb).
Metodes iekšpusē atbilde_cb, mēs nolasām no tastatūras nosūtītos datus un ierakstām tos mainīgajā city: city <- update$callback_query$data. Pēc tam mēs pieprasām laikapstākļu datus no API, ģenerējam un nosūtām ziņojumu un visbeidzot izmantojam metodi answerCallbackQuery lai informētu robotu, ka esam apstrādājuši Inline pogas klikšķi.
Bota piemērs, kas parāda jaunāko rakstu sarakstu ar saitēm uz norādīto centrmezglu no www.habr.com.
Es piedāvāju šo robotprogrammatūru, lai parādītu, kā parādīt iekļautās pogas, kas ved uz tīmekļa lapām.
Šī robota loģika ir līdzīga iepriekšējai; sākotnēji mēs palaižam galveno tastatūru ar komandu /start. Pēc tam robots sniedz mums sarakstu ar 6 centrmezgliem, no kuriem izvēlēties, mēs atlasām mūs interesējošo centru un saņemam 5 jaunākās publikācijas no atlasītā centrmezgla.
Kā jūs saprotat, šajā gadījumā mums ir jāiegūst rakstu saraksts, un šim nolūkam mēs izmantosim īpašu paketi habR, kas ļauj pieprasīt rakstus no Habra un dažus statistikas datus par tiem R.
Instalējiet pakotni habR iespējams tikai no github, kam jums būs nepieciešama papildu pakete devtools. Lai instalētu, izmantojiet tālāk norādīto kodu.
Tagad apskatīsim iepriekš aprakstīto robota izveides kodu:
Kods 5: robotprogrammatūra, kas parāda jaunāko rakstu sarakstu atlasītajā centrmezglā
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()
Palaidiet iepriekš norādīto koda piemēru pēc tam, kad esat aizstājis 'YOUR BOOT TOKEN' ar īsto marķieri, ko saņēmāt, veidojot robotu, izmantojot BotFather (Es runāju par robota izveidi pirmais raksts).
Rezultātā mēs iegūsim šādu rezultātu:
Mēs iekodējām to centrmezglu sarakstu, kas ir pieejami atlasei metodē habs:
Mēs iegūstam rakstu sarakstu no norādītā centrmezgla ar komandu habr_hub_posts(), no iepakojuma habR. Vienlaikus norādām, ka mums nav vajadzīgs rakstu saraksts visam laikam, bet tikai pirmā lapa, kurā atrodas 20 raksti. No iegūtās tabulas, izmantojot komandu head() Mēs atstājam tikai top 5, kas ir jaunākie raksti.
Loģika ir ļoti līdzīga iepriekšējam robotam, taču šajā gadījumā mēs dinamiski ģenerējam iekļauto tastatūru ar rakstu sarakstu, izmantojot funkciju lapply().
Pogas tekstā ievietojam raksta nosaukumu posts$title[x], un argumentā url saite uz rakstu: url = posts$link[x].
Tālāk mēs izveidojam filtru, apdarinātājus un palaižam robotu.
Secinājums
Tagad jūsu rakstītās robotprogrammatūras būs daudz ērtāk lietojamas, jo tās tiks vadītas no tastatūras, nevis ievadot komandas. Vismaz, mijiedarbojoties ar botu, izmantojot viedtālruni, tastatūra ievērojami vienkāršos tā lietošanas procesu.
Nākamajā rakstā mēs izdomāsim, kā izveidot loģisku dialogu ar robotprogrammatūru un strādāt ar datu bāzēm.