ProHoster > Blog > administration > Écrire un bot de télégramme dans R (partie 3) : comment ajouter la prise en charge du clavier à un bot
Écrire un bot de télégramme dans R (partie 3) : comment ajouter la prise en charge du clavier à un bot
Il s'agit du troisième article de la série « Écrire un robot télégramme en R ». Dans des publications précédentes, nous avons appris à créer un robot télégramme, à envoyer des messages via celui-ci, à ajouter des commandes et des filtres de messages au robot. Par conséquent, avant de commencer à lire cet article, je vous recommande fortement de lire précédent, parce que Ici, je ne m'attarderai plus sur les bases décrites précédemment de la création de bots.
Dans cet article, nous allons améliorer la convivialité de notre bot en ajoutant un clavier, ce qui rendra l'interface du bot intuitive et facile à utiliser.
Tous les articles de la série « Écrire un bot télégramme en R »
Si vous êtes intéressé par l'analyse des données, vous pourriez être intéressé par mon télégramme и Youtube canaux. La plupart du contenu est dédié au langage R.
Quels types de claviers le robot Telegram prend-il en charge ?
Au moment de la rédaction telegram.bot permet de créer deux types de claviers :
Répondre : le clavier principal normal, situé sous le panneau de saisie du texte du message. Un tel clavier envoie simplement un message texte au bot, et comme texte, il enverra le texte écrit sur le bouton lui-même.
Inline - Clavier associé à un message de bot spécifique. Ce clavier envoie les données du bot associées au bouton enfoncé ; ces données peuvent différer du texte écrit sur le bouton lui-même. Et ces boutons sont traités via Gestionnaire de requêtes de rappel.
Pour que le bot ouvre le clavier, cela est nécessaire lors de l'envoi d'un message via la méthode sendMessage(), passez le clavier créé précédemment en argument reply_markup.
Ci-dessous, nous examinerons plusieurs exemples.
Clavier de réponse
Comme je l'ai écrit ci-dessus, il s'agit du clavier principal de contrôle du robot.
Un exemple de création d'un clavier de réponse à partir de l'aide officielle
Ce qui précède est un exemple tiré de l'aide officielle du package telegram.bot. Pour créer un clavier, utilisez la fonction ReplyKeyboardMarkup(), qui à son tour prend une liste de listes de boutons créés par la fonction KeyboardButton().
Pourquoi ReplyKeyboardMarkup() Avez-vous besoin de transmettre non seulement une liste, mais une liste de listes ? Le fait est que vous passez la liste principale et que vous y définissez chaque rangée de boutons dans des listes séparées, car Vous pouvez placer plusieurs boutons sur une seule rangée.
Argument resize_keyboard vous permet de sélectionner automatiquement la taille optimale des boutons du clavier et l'argument one_time_keyboard vous permet de masquer le clavier après chaque pression sur un bouton.
Écrivons un bot simple qui aura 3 boutons :
ID de chat - Demander l'ID de chat du dialogue avec le bot
Mon nom - Demandez votre nom
Mon identifiant - Demandez votre nom d'utilisateur par télégramme
Code 1 : bot simple avec clavier de réponse
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()
Exécutez l'exemple de code ci-dessus, après avoir remplacé « VOTRE JETON DE BOT » par le vrai jeton que vous avez reçu lors de la création du bot via BotFather (J'ai parlé de créer un bot dans premier article).
Après le lancement, donnez une commande au bot /start, parce que C'est exactement ce que nous avons défini pour lancer le clavier.
Si pour le moment il vous est difficile d'analyser l'exemple de code donné, avec la création de méthodes, de filtres et de gestionnaires, alors vous devriez revenir au précédent article, dans lequel j'ai décrit tout cela en détail.
Nous avons créé 4 méthodes :
start — Lance le clavier
chat_id — Demander un identifiant de chat
my_name — Demandez votre nom
my_username — Demandez votre connexion
Pour s'opposer Filtres de messages ajout de 3 filtres de messages en fonction de leur texte :
chat_id — Messages avec texte "Чат ID"
nom — Messages avec texte "Моё имя"
nom d'utilisateur — Messages avec texte "Мой логин"
Et nous avons créé 4 gestionnaires qui, sur la base de commandes et de filtres donnés, exécuteront les méthodes spécifiées.
Dans notre cas, nous avons placé tous les boutons les uns sous les autres, mais nous pouvons les disposer sur une seule ligne en modifiant la liste des listes de boutons. Parce que une ligne à l'intérieur du clavier est créée via une liste imbriquée de boutons, puis afin d'afficher nos boutons sur une seule ligne, nous devons réécrire une partie du code pour construire le clavier comme ceci :
Le clavier est envoyé au chat en utilisant la méthode sendMessage(), dans l'argumentation reply_markup.
bot$sendMessage(update$message$chat_id,
text = 'Выберите команду',
reply_markup = RKM)
Clavier en ligne
Comme je l'ai écrit ci-dessus, le clavier en ligne est lié à un message spécifique. Il est un peu plus difficile à utiliser que le clavier principal.
Initialement, vous devez ajouter une méthode au bot pour appeler le clavier en ligne.
Pour répondre à un clic sur un bouton en ligne, vous pouvez également utiliser la méthode bot answerCallbackQuery(), qui peut afficher une notification dans l'interface de télégramme à l'utilisateur qui appuie sur le bouton Inline.
Les données envoyées depuis le bouton Inline ne sont pas du texte, donc pour les traiter, vous devez créer un gestionnaire spécial à l'aide de la commande CallbackQueryHandler().
Le code pour construire un clavier Inline qui est donné dans l'aide officielle du package telegram.bot.
Code pour créer un clavier en ligne à partir de l'aide officielle
Vous devez créer un clavier en ligne à l'aide de la commande InlineKeyboardMarkup(), sur le même principe que le clavier Réponse. DANS InlineKeyboardMarkup() il est nécessaire de passer une liste de listes de boutons Inline, chaque bouton individuel est créé par la fonction InlineKeyboardButton().
Un bouton en ligne peut soit transmettre des données au bot à l'aide d'un argument callback_data, ou ouvrez n'importe quelle page HTML spécifiée à l'aide de l'argument url.
Le résultat sera une liste dans laquelle chaque élément est également une liste de boutons en ligne qui doivent être combinés en une seule ligne.
Nous examinerons ensuite plusieurs exemples de robots dotés de boutons Inline.
Un exemple de bot simple prenant en charge les boutons InLine
Tout d’abord, nous allons écrire un bot pour des tests express pour covid-19. Par commande /test, il vous enverra un clavier avec deux boutons, en fonction du bouton enfoncé il vous enverra un message avec les résultats de vos tests.
Code 2 : Le bot le plus simple avec un clavier en ligne
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()
Exécutez l'exemple de code ci-dessus, après avoir remplacé « VOTRE JETON DE BOT » par le vrai jeton que vous avez reçu lors de la création du bot via BotFather (J'ai parlé de créer un bot dans premier article).
Résultat:
Nous avons créé deux méthodes :
tester — Pour envoyer au chat Clavier en ligne
réponse_cb — Pour traiter les données envoyées depuis le clavier.
Les données qui seront envoyées depuis chaque bouton sont spécifiées dans l'argument callback_data, lors de la création d'un bouton. Vous pouvez recevoir les données envoyées depuis le bouton en utilisant la construction update$callback_query$data, à l'intérieur de la méthode réponse_cb.
Pour que le bot réagisse au clavier Inline, méthode réponse_cb traité par un gestionnaire spécial : CallbackQueryHandler(answer_cb). Qui exécute la méthode spécifiée lorsque vous cliquez sur le bouton Inline. Gestionnaire Gestionnaire de requêtes de rappel prend deux arguments :
callback — La méthode à exécuter
pattern — Filtrer par données liées au bouton à l'aide d'un argument callback_data.
En conséquence, en utilisant l’argument pattern Nous pouvons écrire une méthode distincte pour appuyer sur chaque bouton :
Code 3 : méthodes distinctes pour chaque bouton en ligne
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()
Exécutez l'exemple de code ci-dessus, après avoir remplacé « VOTRE JETON DE BOT » par le vrai jeton que vous avez reçu lors de la création du bot via BotFather (J'ai parlé de créer un bot dans premier article).
Nous avons maintenant écrit 2 méthodes distinctes, à savoir une méthode, pour chaque pression sur un bouton, et utilisé l'argument pattern, lors de la création de leurs gestionnaires :
Le code de la méthode se termine réponse_cb l'équipe bot$answerCallbackQuery(callback_query_id = update$callback_query$id), qui indique au bot que les données du clavier en ligne ont été reçues.
Un exemple de bot qui rapporte la météo actuelle pour une ville sélectionnée
Essayons d'écrire un bot qui demande des données météorologiques.
La logique de son travail sera la suivante. Initialement par l'équipe /start vous appelez le clavier principal, qui n'a qu'un seul bouton « Météo ». En cliquant sur ce bouton, vous recevrez un message avec le clavier Inline pour sélectionner la ville pour laquelle vous souhaitez connaître la météo actuelle. Sélectionnez l'une des villes et obtenez la météo actuelle.
Dans cet exemple de code, nous utiliserons plusieurs packages supplémentaires :
httr — un package pour travailler avec des requêtes HTTP, sur la base duquel le travail avec n'importe quelle API est construit. Dans notre cas nous utiliserons l'API gratuite openweathermap.org.
stringr — un package pour travailler avec du texte, dans notre cas nous l'utiliserons pour générer un message sur la météo dans la ville sélectionnée.
Code 4 : Un bot qui rapporte la météo actuelle pour la ville sélectionnée
Exécutez l'exemple de code ci-dessus, après avoir remplacé « VOTRE JETON DE BOT » par le vrai jeton que vous avez reçu lors de la création du bot via BotFather (J'ai parlé de créer un bot dans premier article).
En conséquence, notre bot fonctionnera à peu près comme ceci :
Schématiquement, ce bot peut être représenté comme ceci :
Nous avons créé 3 méthodes disponibles dans notre bot météo :
Commencer — Lancez le clavier principal du bot
météo — Lancez le clavier en ligne pour sélectionner une ville
réponse_cb — La méthode principale qui demande la météo à l'API pour une ville donnée et l'envoie au chat.
méthode Commencer on le lance avec la commande /start, qui est implémenté par le gestionnaire CommandHandler('start', start).
Pour exécuter une méthode météo nous avons créé un filtre du même nom :
# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {
# проверяем текст сообщения
message$text == "Погода"
}
)
Et nous appelons cette méthode avec le gestionnaire de messages suivant : MessageHandler(weather, filters = MessageFilters$weather).
Et au final, notre méthode principale réponse_cb réagit à l'appui sur les boutons Inline, qui est implémenté par un gestionnaire spécial : CallbackQueryHandler(answer_cb).
À l'intérieur d'une méthode réponse_cb, nous lisons les données envoyées depuis le clavier et les écrivons dans une variable city: city <- update$callback_query$data. Ensuite, nous demandons des données météorologiques à l'API, générons et envoyons un message, et enfin utilisons la méthode answerCallbackQuery afin d'informer le bot que nous avons traité le clic sur le bouton Inline.
Un exemple de bot qui affiche une liste des derniers articles avec des liens vers le Hub spécifié à partir de habr.com.
Je présente ce bot pour vous montrer comment afficher les boutons en ligne qui mènent à des pages Web.
La logique de ce bot est similaire au précédent ; dans un premier temps on lance le clavier principal avec la commande /start. Ensuite, le bot nous propose une liste de 6 hubs parmi lesquels choisir, nous sélectionnons le hub qui nous intéresse et recevons les 5 publications les plus récentes du Hub sélectionné.
Comme vous le comprenez, dans ce cas, nous devons obtenir une liste d'articles et pour cela, nous utiliserons un package spécial. habR, qui vous permet de demander des articles à Habra et quelques statistiques à leur sujet dans R.
Installer le paquet habR uniquement possible depuis github, pour lequel vous aurez besoin d'un package supplémentaire devtools. Pour installer, utilisez le code ci-dessous.
Examinons maintenant le code de construction du bot décrit ci-dessus :
Code 5 : Un bot qui affiche une liste des articles les plus récents sur le Hub sélectionné
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()
Exécutez l'exemple de code ci-dessus, après avoir remplacé « VOTRE JETON DE BOT » par le vrai jeton que vous avez reçu lors de la création du bot via BotFather (J'ai parlé de créer un bot dans premier article).
En conséquence, nous obtiendrons ce résultat :
Nous avons codé en dur la liste des Hubs disponibles pour la sélection dans la méthode habs:
Nous obtenons une liste d'articles du Hub spécifié avec la commande habr_hub_posts(), du paquet habR. Dans le même temps, nous soulignons que nous n'avons pas besoin d'une liste d'articles pour tout le temps, mais seulement de la première page sur laquelle se trouvent 20 articles. À partir du tableau résultant à l'aide de la commande head() Nous ne laissons que le top 5, qui sont les articles les plus récents.
La logique est très similaire au bot précédent, mais dans ce cas nous générons dynamiquement un clavier Inline avec une liste d'articles en utilisant la fonction lapply().
Nous insérons le titre de l'article dans le texte du bouton posts$title[x], et dans l'argumentation url lien vers l'article : url = posts$link[x].
Ensuite, nous créons un filtre, des gestionnaires et lançons notre bot.
Conclusion
Désormais, les robots que vous écrivez seront beaucoup plus pratiques à utiliser, car ils seront contrôlés à partir du clavier plutôt qu'en saisissant des commandes. Au minimum, lors de l'interaction avec un bot via un smartphone, le clavier simplifiera considérablement le processus d'utilisation de celui-ci.
Dans le prochain article, nous verrons comment construire un dialogue logique avec un bot et travailler avec des bases de données.