ProHoster > Blog > Pentadbiran > Menulis bot telegram dalam R (bahagian 3): Cara menambah sokongan papan kekunci pada bot
Menulis bot telegram dalam R (bahagian 3): Cara menambah sokongan papan kekunci pada bot
Ini adalah artikel ketiga dalam siri "Menulis bot telegram dalam R". Dalam penerbitan sebelumnya, kami belajar cara membuat bot telegram, menghantar mesej melaluinya, menambah arahan dan penapis mesej ke bot. Oleh itu, sebelum anda mula membaca artikel ini, saya sangat mengesyorkan anda membaca sebelumnya, kerana Di sini saya tidak akan lagi memikirkan asas pembinaan bot yang diterangkan sebelum ini.
Dalam artikel ini, kami akan meningkatkan kebolehgunaan bot kami dengan menambahkan papan kekunci, yang akan menjadikan antara muka bot intuitif dan mudah digunakan.
Semua artikel dari siri "Menulis bot telegram dalam R"
Jika anda berminat dengan analisis data, anda mungkin berminat dengan saya telegram и youtube saluran. Kebanyakan kandungan didedikasikan untuk bahasa R.
Apakah jenis papan kekunci yang disokong bot telegram?
Pada masa penulisan ini telegram.bot membolehkan anda mencipta dua jenis papan kekunci:
Balas - Papan kekunci biasa yang utama, yang terletak di bawah panel input teks mesej. Papan kekunci sedemikian hanya menghantar mesej teks ke bot, dan sebagai teks ia akan menghantar teks yang ditulis pada butang itu sendiri.
Sebaris - Papan kekunci yang dikaitkan dengan mesej bot tertentu. Papan kekunci ini menghantar data bot yang dikaitkan dengan butang yang ditekan; data ini mungkin berbeza daripada teks yang ditulis pada butang itu sendiri. Dan butang sedemikian diproses melalui CallbackQueryHandler.
Agar bot membuka papan kekunci, adalah perlu apabila menghantar mesej melalui kaedah tersebut sendMessage(), lulus papan kekunci yang dibuat sebelum ini sebagai hujah reply_markup.
Di bawah ini kita akan melihat beberapa contoh.
Balas papan kekunci
Seperti yang saya tulis di atas, ini ialah papan kekunci kawalan bot utama.
Contoh mencipta papan kekunci Balas daripada bantuan rasmi
Di atas adalah contoh daripada bantuan rasmi pakej telegram.bot. Untuk mencipta papan kekunci, gunakan fungsi ReplyKeyboardMarkup(), yang seterusnya mengambil senarai senarai butang yang dicipta oleh fungsi tersebut KeyboardButton().
Mengapa dalam ReplyKeyboardMarkup() Adakah anda perlu lulus bukan sahaja senarai, tetapi senarai senarai? Hakikatnya ialah anda melepasi senarai utama, dan di dalamnya anda menentukan setiap baris butang dalam senarai berasingan, kerana Anda boleh meletakkan beberapa butang dalam satu baris.
hujah resize_keyboard membolehkan anda memilih saiz optimum butang papan kekunci secara automatik, dan hujah one_time_keyboard membolehkan anda menyembunyikan papan kekunci selepas setiap butang ditekan.
Mari kita tulis bot mudah yang akan mempunyai 3 butang:
ID Sembang - Minta ID sembang dialog dengan bot
Nama saya - Minta nama anda
Log masuk saya - Minta nama pengguna anda dalam telegram
Kod 1: Bot ringkas dengan papan kekunci Balas
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()
Jalankan contoh kod di atas, selepas menggantikan 'TOKEN BOT ANDA' dengan token sebenar yang anda terima semasa membuat bot melalui BotBapa (Saya bercakap tentang mencipta bot dalam artikel pertama).
Selepas pelancaran, berikan bot arahan /start, kerana Inilah yang kami takrifkan untuk melancarkan papan kekunci.
Jika pada masa ini sukar untuk anda menghuraikan contoh kod yang diberikan, dengan penciptaan kaedah, penapis dan pengendali, maka anda harus kembali ke yang sebelumnya artikel, di mana saya menerangkan semua ini secara terperinci.
Kami mencipta 4 kaedah:
mula — Lancarkan papan kekunci
chat_id — Minta ID sembang
nama_saya — Minta nama anda
my_username — Minta log masuk anda
Untuk membantah MessageFilters menambah 3 penapis mesej berdasarkan teksnya:
chat_id — Mesej dengan teks "Чат ID"
nama — Mesej dengan teks "Моё имя"
nama pengguna — Mesej dengan teks "Мой логин"
Dan kami mencipta 4 pengendali yang, berdasarkan arahan dan penapis yang diberikan, akan melaksanakan kaedah yang ditentukan.
Dalam kes kami, kami meletakkan semua butang di bawah satu sama lain, tetapi kami boleh menyusunnya dalam satu baris dengan membuat perubahan pada senarai senarai butang. Kerana satu baris di dalam papan kekunci dibuat melalui senarai butang bersarang, maka untuk memaparkan butang kami dalam satu baris, kami perlu menulis semula sebahagian daripada kod untuk membina papan kekunci seperti ini:
Papan kekunci dihantar ke sembang menggunakan kaedah sendMessage(), dalam hujah reply_markup.
bot$sendMessage(update$message$chat_id,
text = 'Выберите команду',
reply_markup = RKM)
Papan kekunci sebaris
Seperti yang saya tulis di atas, papan kekunci Sebaris terikat pada mesej tertentu. Ia agak sukar untuk digunakan daripada papan kekunci utama.
Pada mulanya, anda perlu menambah kaedah pada bot untuk memanggil papan kekunci Sebaris.
Untuk membalas klik butang Sebaris, anda juga boleh menggunakan kaedah bot answerCallbackQuery(), yang boleh memaparkan pemberitahuan dalam antara muka telegram kepada pengguna yang menekan butang Sebaris.
Data yang dihantar daripada butang Inline bukan teks, jadi untuk memprosesnya anda perlu mencipta pengendali khas menggunakan arahan CallbackQueryHandler().
Kod untuk membina papan kekunci Sebaris yang diberikan dalam bantuan rasmi pakej telegram.bot.
Kod untuk membina papan kekunci Dalam Talian daripada bantuan rasmi
Anda perlu membina papan kekunci Sebaris menggunakan arahan InlineKeyboardMarkup(), pada prinsip yang sama seperti papan kekunci Balas. DALAM InlineKeyboardMarkup() adalah perlu untuk lulus senarai senarai butang Sebaris, setiap butang individu dicipta oleh fungsi tersebut InlineKeyboardButton().
Butang sebaris boleh sama ada menghantar beberapa data kepada bot menggunakan argumen callback_data, atau buka mana-mana halaman HTML yang ditentukan menggunakan hujah url.
Hasilnya ialah senarai di mana setiap elemen juga merupakan senarai butang Sebaris yang perlu digabungkan menjadi satu baris.
Seterusnya kita akan melihat beberapa contoh bot dengan butang Sebaris.
Contoh bot ringkas dengan sokongan untuk butang InLine
Pertama, kami akan menulis bot untuk ujian ekspres untuk covid-19. Dengan arahan /test, ia akan menghantar kepada anda papan kekunci dengan dua butang, bergantung pada butang yang ditekan ia akan menghantar mesej kepada anda dengan hasil ujian anda.
Kod 2: Bot paling ringkas dengan papan kekunci Sebaris
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()
Jalankan contoh kod di atas, selepas menggantikan 'TOKEN BOT ANDA' dengan token sebenar yang anda terima semasa membuat bot melalui BotBapa (Saya bercakap tentang mencipta bot dalam artikel pertama).
Keputusan:
Kami mencipta dua kaedah:
ujian — Untuk menghantar ke papan kekunci Sebaris sembang
jawapan_cb — Untuk memproses data yang dihantar daripada papan kekunci.
Data yang akan dihantar dari setiap butang dinyatakan dalam hujah callback_data, apabila membuat butang. Anda boleh menerima data yang dihantar dari butang menggunakan konstruk update$callback_query$data, di dalam kaedah jawapan_cb.
Untuk bot bertindak balas kepada papan kekunci Sebaris, kaedah jawapan_cb diproses oleh pengendali khas: CallbackQueryHandler(answer_cb). Yang menjalankan kaedah yang ditentukan apabila butang Sebaris diklik. Pengendali CallbackQueryHandler mengambil dua hujah:
callback — Kaedah yang perlu dijalankan
pattern — Tapis mengikut data yang terikat pada butang menggunakan hujah callback_data.
Sehubungan itu, menggunakan hujah pattern Kita boleh menulis kaedah berasingan untuk menekan setiap butang:
Kod 3: Kaedah berasingan untuk setiap butang Sebaris
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()
Jalankan contoh kod di atas, selepas menggantikan 'TOKEN BOT ANDA' dengan token sebenar yang anda terima semasa membuat bot melalui BotBapa (Saya bercakap tentang mencipta bot dalam artikel pertama).
Sekarang kami telah menulis 2 kaedah berasingan i.e. satu kaedah, untuk setiap butang tekan, dan menggunakan hujah pattern, apabila membuat pengendali mereka:
Kod kaedah tamat jawapan_cb pasukan bot$answerCallbackQuery(callback_query_id = update$callback_query$id), yang memberitahu bot bahawa data daripada papan kekunci sebaris telah diterima.
Contoh bot yang melaporkan cuaca semasa untuk bandar terpilih
Mari cuba tulis bot yang meminta data cuaca.
Logik kerjanya adalah seperti berikut. Pada mulanya oleh pasukan /start anda memanggil papan kekunci utama, yang mempunyai hanya satu butang "Cuaca". Dengan mengklik pada butang ini, anda akan menerima mesej dengan papan kekunci Sebaris untuk memilih bandar yang anda ingin ketahui cuaca semasa. Pilih salah satu bandar dan dapatkan cuaca semasa.
Dalam contoh kod ini kami akan menggunakan beberapa pakej tambahan:
httr — pakej untuk bekerja dengan permintaan HTTP, berdasarkan mana kerja dengan mana-mana API dibina. Dalam kes kami, kami akan menggunakan API percuma openweathermap.org.
stringr — pakej untuk bekerja dengan teks, dalam kes kami, kami akan menggunakannya untuk menjana mesej tentang cuaca di bandar yang dipilih.
Kod 4: Bot yang melaporkan cuaca semasa untuk bandar yang dipilih
Jalankan contoh kod di atas, selepas menggantikan 'TOKEN BOT ANDA' dengan token sebenar yang anda terima semasa membuat bot melalui BotBapa (Saya bercakap tentang mencipta bot dalam artikel pertama).
Akibatnya, bot kami akan berfungsi seperti ini:
Secara skematik, bot ini boleh digambarkan seperti ini:
Kami telah mencipta 3 kaedah yang tersedia di dalam bot cuaca kami:
permulaan — Lancarkan papan kekunci bot utama
cuaca — Lancarkan papan kekunci Sebaris untuk memilih bandar
jawapan_cb — Kaedah utama yang meminta cuaca daripada API untuk bandar tertentu dan menghantarnya ke sembang.
Kaedah permulaan kami melancarkannya dengan arahan /start, yang dilaksanakan oleh pengendali CommandHandler('start', start).
Untuk menjalankan kaedah cuaca kami mencipta penapis dengan nama yang sama:
# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {
# проверяем текст сообщения
message$text == "Погода"
}
)
Dan kami memanggil kaedah ini dengan pengendali mesej berikut: MessageHandler(weather, filters = MessageFilters$weather).
Dan pada akhirnya, kaedah utama kami jawapan_cb bertindak balas terhadap menekan butang Sebaris, yang dilaksanakan oleh pengendali khas: CallbackQueryHandler(answer_cb).
Di dalam kaedah jawapan_cb, kami membaca data yang dihantar dari papan kekunci dan menulisnya kepada pembolehubah city: city <- update$callback_query$data. Kemudian kami meminta data cuaca daripada API, menjana dan menghantar mesej, dan akhirnya menggunakan kaedah tersebut answerCallbackQuery untuk memaklumkan bot bahawa kami memproses klik butang Sebaris.
Contoh bot yang memaparkan senarai artikel terkini dengan pautan ke Hab yang ditentukan daripada www.habr.com.
Saya membentangkan bot ini untuk menunjukkan kepada anda cara memaparkan butang Sebaris yang menuju ke halaman web.
Logik bot ini serupa dengan yang sebelumnya; pada mulanya kami melancarkan papan kekunci utama dengan arahan /start. Seterusnya, bot memberikan kami senarai 6 hab untuk dipilih, kami memilih hab yang kami minati, dan menerima 5 penerbitan terbaharu daripada Hab yang dipilih.
Seperti yang anda faham, dalam kes ini kita perlu mendapatkan senarai artikel, dan untuk ini kita akan menggunakan pakej khas habR, yang membolehkan anda meminta artikel daripada Habra dan beberapa statistik mengenainya dalam R.
Pasang pakej habR hanya mungkin dari github, yang mana anda memerlukan pakej tambahan devtools. Untuk memasang, gunakan kod di bawah.
Sekarang mari kita lihat kod untuk membina bot yang diterangkan di atas:
Kod 5: Bot yang memaparkan senarai artikel terbaharu pada Hab yang dipilih
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()
Jalankan contoh kod di atas, selepas menggantikan 'TOKEN BOT ANDA' dengan token sebenar yang anda terima semasa membuat bot melalui BotBapa (Saya bercakap tentang mencipta bot dalam artikel pertama).
Hasilnya, kami akan mendapat keputusan ini:
Kami mengekodkan senarai Hab yang tersedia untuk dipilih dalam kaedah tersebut habs:
Kami mendapat senarai artikel daripada Hab yang ditentukan dengan arahan habr_hub_posts(), daripada pakej habR. Pada masa yang sama, kami menunjukkan bahawa kami tidak memerlukan senarai artikel untuk sepanjang masa, tetapi hanya halaman pertama yang terdapat 20 artikel. Daripada jadual yang dihasilkan menggunakan arahan head() Kami meninggalkan hanya 5 teratas, iaitu artikel terkini.
Logiknya sangat serupa dengan bot sebelumnya, tetapi dalam kes ini kami menjana papan kekunci Sebaris dengan senarai artikel secara dinamik menggunakan fungsi lapply().
Kami memasukkan tajuk artikel ke dalam teks butang posts$title[x], dan dalam hujah url pautan ke artikel: url = posts$link[x].
Seterusnya, kami mencipta penapis, pengendali dan melancarkan bot kami.
Kesimpulan
Kini bot yang anda tulis akan menjadi lebih mudah untuk digunakan, kerana fakta bahawa ia akan dikawal dari papan kekunci, dan bukannya dengan memasukkan arahan. Sekurang-kurangnya, apabila berinteraksi dengan bot melalui telefon pintar, papan kekunci akan memudahkan proses menggunakannya dengan ketara.
Dalam artikel seterusnya kita akan memikirkan cara membina dialog logik dengan bot dan bekerja dengan pangkalan data.