ProHoster > Blog > Administrazioa > Telegram bot bat idaztea R-n (3. zatia): nola gehitu teklatuaren euskarria bot bati
Telegram bot bat idaztea R-n (3. zatia): nola gehitu teklatuaren euskarria bot bati
Hau da "Telegram bot bat R-n idazten" serieko hirugarren artikulua. Aurreko argitalpenetan, telegram bot bat sortzen ikasi genuen, haren bidez mezuak bidaltzen, komandoak eta mezu-iragazkiak gehitu bot-ari. Horregatik, artikulu hau irakurtzen hasi baino lehen, irakurtzea gomendatzen dizut aurrekoa, zeren Hemen ez naiz jadanik azalduko bot-en eraikuntzaren oinarrietan.
Artikulu honetan, gure botaren erabilgarritasuna hobetuko dugu teklatu bat gehituz, eta horrek bot interfazea intuitiboa eta erabiltzeko erraza izango du.
"Telegram bot bat R-n idazten" serieko artikulu guztiak
Hau idazteko momentuan telegram.bot bi teklatu mota sortzeko aukera ematen du:
Erantzun - Teklatu nagusia, ohikoa, mezuen testua idazteko panelaren azpian dagoena. Horrelako teklatu batek testu-mezu bat bidaltzen dio bot-ari, eta testu gisa botoian bertan idatzitako testua bidaliko du.
Inline - Bot mezu zehatz batekin lotutako teklatua. Teklatu honek sakatuta dagoen botoiari lotutako bot datuak bidaltzen ditu; baliteke datu hauek botoian bertan idatzitako testutik desberdinak izatea. Eta halako botoiak prozesatzen dira CallbackQueryHandler.
Botak teklatua irekitzeko, beharrezkoa da metodoaren bidez mezu bat bidaltzean sendMessage(), pasatu aurretik sortutako teklatua argumentu gisa reply_markup.
Jarraian, hainbat adibide ikusiko ditugu.
Erantzun teklatua
Goian idatzi dudan bezala, hau da bot kontrolatzeko teklatu nagusia.
Laguntza ofizialetik Erantzun teklatua sortzeko adibide bat
Aurrekoa paketearen laguntza ofizialeko adibide bat da telegram.bot. Teklatua sortzeko, erabili funtzioa ReplyKeyboardMarkup(), eta horrek funtzioak sortzen dituen botoien zerrenden zerrenda hartzen du KeyboardButton().
Zergatik sartu ReplyKeyboardMarkup() Zerrenda bat ez ezik, zerrenden zerrenda bat gainditu behar duzu? Kontua da zerrenda nagusia pasatzen duzula, eta bertan botoi-lerro bakoitza zerrenda ezberdinetan definitzen duzula, zeren Hainbat botoi jar ditzakezu errenkada batean.
Argudioa resize_keyboard teklatuko botoien tamaina optimoa eta argumentua automatikoki hautatzeko aukera ematen du one_time_keyboard botoia sakatu ondoren teklatua ezkutatzeko aukera ematen du.
Idatzi dezagun 3 botoi izango dituen bot sinple bat:
Txataren IDa - Eskatu bot-arekin elkarrizketaren txataren IDa
Nire izena - Eskatu zure izena
Nire saioa - Eskatu zure erabiltzaile-izena telegram-en
1. kodea: Erantzun teklatua duen bot sinplea
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()
Exekutatu goiko kodearen adibidea, "ZURE BOT TOKENA" bot-a sortzean jasotako benetako tokenarekin ordezkatu ondoren. BotAita (Bot bat sortzeaz hitz egin nuen lehen artikulua).
Abiarazi ondoren, eman komando bat bot-ari /start, zeren Hau da teklatua abiarazteko definitu duguna.
Momentuz zaila bazaizu emandako kodearen adibidea analizatzea, metodoak, iragazkiak eta kudeatzaileak sortzearekin, aurrekora itzuli beharko zenuke. Artikulu, eta bertan deskribatu nuen hori guztia zehatz-mehatz.
4 metodo sortu ditugu:
hasi — Abiarazi teklatua
chat_id — Eskatu txataren IDa
my_name — Eskatu zure izena
my_username — Eskatu zure saioa hasteko
Objektatzeko Mezu-iragazkiak 3 mezu-iragazki gehitu ditu haien testuan oinarrituta:
chat_id — Testudun mezuak "Чат ID"
izena — Testudun mezuak "Моё имя"
username — Testudun mezuak "Мой логин"
Eta 4 kudeatzaile sortu ditugu, emandako komando eta iragazkietan oinarrituta, zehaztutako metodoak exekutatuko dituztenak.
Gure kasuan, botoi guztiak bata bestearen azpian jarri ditugu, baina ilara batean antola ditzakegu botoi-zerrenden zerrendan aldaketak eginez. Zeren Teklatuaren barruko errenkada bat habiaratutako botoien zerrenda baten bidez sortzen da, gero gure botoiak errenkada batean bistaratzeko kodearen zati bat berridatzi behar dugu teklatua eraikitzeko honela:
Teklatua txatera bidaltzen da metodoa erabiliz sendMessage(), argudioan reply_markup.
bot$sendMessage(update$message$chat_id,
text = 'Выберите команду',
reply_markup = RKM)
Sareko teklatua
Goian idatzi dudan bezala, Inline teklatua mezu zehatz bati lotuta dago. Teklatu nagusia baino zertxobait zailagoa da lan egitea.
Hasieran, metodo bat gehitu behar diozu bot-ari Inline teklatura deitzeko.
Inline botoiaren klik bati erantzuteko, bot metodoa ere erabil dezakezu answerCallbackQuery(), zeinak jakinarazpen bat bistara dezake telegramen interfazean Inline botoia sakatzen duen erabiltzaileari.
Inline botoitik bidalitako datuak ez dira testuak, beraz, prozesatzeko kudeatzaile berezi bat sortu behar duzu komandoa erabiliz CallbackQueryHandler().
Paketearen laguntza ofizialean ematen den Inline teklatua eraikitzeko kodea telegram.bot.
Laguntza ofizialetik Inline teklatua eraikitzeko kodea
Inline teklatua eraiki behar duzu komandoa erabiliz InlineKeyboardMarkup(), Erantzun teklatuaren printzipio berean. IN InlineKeyboardMarkup() beharrezkoa da Inline botoien zerrenda zerrenda bat pasatzea, botoi bakoitza funtzioak sortzen du InlineKeyboardButton().
Sareko botoi batek argumentu bat erabiliz datu batzuk pasa diezazkioke bot-ari callback_data, edo ireki argumentua erabiliz zehaztutako edozein HTML orrialde url.
Emaitza zerrenda bat izango da, zeinetan elementu bakoitza errenkada batean konbinatu behar diren Inline botoien zerrenda ere bada.
Jarraian, Inline botoiak dituzten bot-en hainbat adibide ikusiko ditugu.
InLine botoiak onartzen dituen bot sinple baten adibidea
Lehenik eta behin, bot bat idatziko dugu covid-19rako probak egiteko. Aginduz /test, bi botoi dituen teklatua bidaliko dizu, sakatzen den botoiaren arabera mezu bat bidaliko dizu zure proben emaitzekin.
2. kodea: Inline teklatua duen bot errazena
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()
Exekutatu goiko kodearen adibidea, "ZURE BOT TOKENA" bot-a sortzean jasotako benetako tokenarekin ordezkatu ondoren. BotAita (Bot bat sortzeaz hitz egin nuen lehen artikulua).
Emaitza:
Bi metodo sortu ditugu:
test — Sareko teklatua txateara bidaltzeko
erantzun_cb — Teklatutik bidalitako datuak prozesatzeko.
Botoi bakoitzetik bidaliko diren datuak argumentuan zehazten dira callback_data, botoi bat sortzean. Botoitik bidalitako datuak konstrukzioa erabiliz jaso ditzakezu update$callback_query$data, metodoaren barruan erantzun_cb.
Botak Inline teklatuaren aurrean erreakzionatzeko, metodoa erantzun_cb kudeatzaile berezi batek prozesatu: CallbackQueryHandler(answer_cb). Zehaztutako metodoa exekutatzen duena Inline botoia sakatzen denean. Kudeatzailea CallbackQueryHandler bi argudio hartzen ditu:
callback — Exekutatu behar den metodoa
pattern — Iragazi botoiari loturiko datuen arabera argumentu bat erabiliz callback_data.
Horren arabera, argumentua erabiliz pattern Botoi bakoitza sakatzeko metodo bereizi bat idatz dezakegu:
3. kodea: Inline botoi bakoitzeko metodo bereiziak
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()
Exekutatu goiko kodearen adibidea, "ZURE BOT TOKENA" bot-a sortzean jasotako benetako tokenarekin ordezkatu ondoren. BotAita (Bot bat sortzeaz hitz egin nuen lehen artikulua).
Orain 2 metodo bereizi idatzi ditugu, hau da. metodo bat, botoi sakatu bakoitzeko, eta argumentua erabili pattern, haien kudeatzaileak sortzean:
Metodoaren kodea amaitzen da erantzun_cb taldeak bot$answerCallbackQuery(callback_query_id = update$callback_query$id), eta horrek bot-ari esaten dio lineako teklatuaren datuak jaso direla.
Hautatutako hiri bateko uneko eguraldiaren berri ematen duen bot baten adibidea
Saia gaitezen eguraldiaren datuak eskatzen dituen bot bat idazten.
Bere lanaren logika hau izango da. Hasieran, taldearen eskutik /start teklatu nagusiari deitzen diozu, "Eguraldia" botoi bakarra baitu. Botoi honetan klik eginez gero, Inline teklatuarekin mezu bat jasoko duzu uneko eguraldia ezagutu nahi duzun hiria hautatzeko. Aukeratu hirietako bat eta lortu uneko eguraldia.
Kode adibide honetan hainbat pakete gehigarri erabiliko ditugu:
httr — HTTP eskaerekin lan egiteko pakete bat, zeinaren arabera edozein APIrekin lana eraikitzen den. Gure kasuan doako APIa erabiliko dugu openweathermap.org.
stringr — testuarekin lan egiteko pakete bat, gure kasuan hautatutako hirian eguraldiari buruzko mezu bat sortzeko erabiliko dugu.
4. kodea: hautatutako hiriko uneko eguraldiaren berri ematen duen bot bat
Exekutatu goiko kodearen adibidea, "ZURE BOT TOKENA" bot-a sortzean jasotako benetako tokenarekin ordezkatu ondoren. BotAita (Bot bat sortzeaz hitz egin nuen lehen artikulua).
Ondorioz, gure bot-ak honela funtzionatuko du:
Eskematikoki, bot hau honela irudikatu daiteke:
Gure eguraldi bot barruan eskuragarri dauden 3 metodo sortu ditugu:
Hasi — Abiarazi bot teklatu nagusia
Eguraldi — Abiarazi Inline teklatua hiri bat hautatzeko
erantzun_cb — Hiri jakin bateko APIari eguraldia eskatu eta txatera bidaltzen duen metodo nagusia.
Метод Hasi komandoarekin abiarazten dugu /start, kudeatzaileak inplementatzen duena CommandHandler('start', start).
Metodoa exekutatzeko Eguraldi izen bereko iragazki bat sortu dugu:
# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {
# проверяем текст сообщения
message$text == "Погода"
}
)
Eta metodo honi deitzen diogu mezu-kudeatzaile honekin: MessageHandler(weather, filters = MessageFilters$weather).
Eta azkenean, gure metodo nagusia erantzun_cb Inline botoiak sakatzean erreakzionatzen du, kudeatzaile berezi batek inplementatzen duena: CallbackQueryHandler(answer_cb).
Metodo baten barruan erantzun_cb, teklatutik bidalitako datuak irakurri eta aldagai batean idazten ditugu city: city <- update$callback_query$data. Ondoren, eguraldi-datuak APIari eskatzen dizkiogu, mezu bat sortu eta bidali, eta, azkenik, metodoa erabiltzen dugu answerCallbackQuery Inline botoiaren klika prozesatu genuela bot-ari jakinarazteko.
Zehaztutako Hubrako estekak dituzten azken artikuluen zerrenda bistaratzen duen bot baten adibidea www.habr.com.
Bot hau aurkezten dizut web orrietara eramaten duten Inline botoiak nola bistaratu erakusteko.
Bot honen logika aurrekoaren antzekoa da; hasieran teklatu nagusia abiarazten dugu komandoarekin /start. Ondoren, bot-ak 6 hub-en zerrenda bat ematen digu aukeran, interesatzen zaigun zentroa hautatzen dugu eta hautatutako Hub-etik azken 5 argitalpenak jasotzen ditugu.
Ulertzen duzun bezala, kasu honetan artikulu zerrenda bat lortu behar dugu, eta horretarako pakete berezi bat erabiliko dugu habR, Habra-ri artikuluak eta haiei buruzko zenbait estatistika R-n eskatzeko aukera ematen duena.
Instalatu paketea habR Github-etik bakarrik posible da, horretarako pakete gehigarri bat beharko duzu devtools. Instalatzeko, erabili beheko kodea.
Ikus dezagun goian deskribatutako bot-a eraikitzeko kodea:
5. kodea: hautatutako Hub-en azken artikuluen zerrenda bistaratzen duen bot bat
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()
Exekutatu goiko kodearen adibidea, "ZURE BOT TOKENA" bot-a sortzean jasotako benetako tokenarekin ordezkatu ondoren. BotAita (Bot bat sortzeaz hitz egin nuen lehen artikulua).
Ondorioz, emaitza hau lortuko dugu:
Metodoan aukeratzeko erabilgarri dauden Huben zerrenda gogor kodetu dugu habs:
Aginduarekin zehaztutako Hub-etik artikuluen zerrenda bat lortzen dugu habr_hub_posts(), paketetik habR. Aldi berean, azpimarratzen dugu ez dugula denbora osorako artikuluen zerrendarik behar, 20 artikulu dauden lehen orrialdea baizik. Sortutako taulatik komandoa erabiliz head() Top 5ak bakarrik uzten ditugu, hau da, artikulu berrienak.
Logika aurreko bot-aren oso antzekoa da, baina kasu honetan Inline teklatua sortzen dugu artikulu zerrenda batekin dinamikoki funtzioa erabiliz. lapply().
Artikuluaren izenburua botoiaren testuan txertatzen dugu posts$title[x], eta argudioan url artikuluaren esteka: url = posts$link[x].
Ondoren, iragazki bat, kudeatzaileak eta gure bot-a abiarazten dugu.
Ondorioa
Orain idazten dituzun bot-ak askoz erosoagoak izango dira erabiltzeko, komandoak sartu beharrean teklatutik kontrolatuko direlako. Gutxienez, smartphone baten bidez bot batekin elkarreraginean, teklatuak erabilera-prozesua nabarmen erraztuko du.
Hurrengo artikuluan bot batekin elkarrizketa logikoa nola eraiki eta datu-baseekin nola lan egin asmatuko dugu.