Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

Dit is het derde artikel in de serie "Een telegram bot schrijven in de programmeertaal R". In eerdere publicaties leerden we hoe we een telegram bot konden maken, berichten via deze bot konden versturen, we voegden commando's en berichtenfilters toe. Daarom raad ik aan om voor het lezen van dit artikel eerst kennis te nemen van de vorige artikelen, aangezien ik hier niet meer zal stilstaan bij de eerder beschreven basisprincipes van het bouwen van bots.

In dit artikel verbeteren we de bruikbaarheid van onze bot door een toetsenbord toe te voegen, dat de interface van de bot intuïtief en eenvoudig in gebruik maakt.

Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

Alle artikelen uit de serie "We schrijven een telegram bot in R"

  1. We maken een bot en verzenden met behulp daarvan berichten naar telegram
  2. We voegen ondersteuning voor commando's en berichtfilters aan de bot toe
  3. Hoe voeg je ondersteuning voor toetsenborden toe aan de bot

Inhoud

Als u geïnteresseerd bent in data-analyse, is het mogelijk dat mijn telegram en youtube kanalen interessant voor u zijn. Het grootste deel van de inhoud is gewijd aan de taal R.

  1. Welke soorten toetsenborden ondersteunt een telegram bot
  2. Reply toetsenbord
  3. Inline toetsenbord
    3.1. Voorbeeld van de eenvoudigste bot met ondersteuning voor inline-knoppen
    3.2. Voorbeeld van een bot die het actuele weer geeft voor een gekozen stad
    3.3. Voorbeeld van een bot die een lijst van de meest recente artikelen met links geeft van de aangegeven Hub op habr.com
  4. Conclusie

Welke soorten toetsenborden ondersteunt een telegram bot

Op het moment van schrijven wordt telegram.bot stelt je in staat om toetsenborden van twee typen te creëren:

  • Reply — De hoofd, gewone toetsenbord, die zich onder het tekstinvoerveld bevindt. Dit toetsenbord verstuurt eenvoudig een tekstbericht naar de bot en als tekst verzendt het de tekst die op de knop zelf staat.
  • Inline — Toetsenbord dat aan een specifiek bericht van de bot is gekoppeld. Dit toetsenbord verzendt gegevens naar de bot die zijn gekoppeld aan de ingedrukte knop; deze gegevens kunnen verschillen van de tekst die op de knop zelf staat. En zulke knoppen worden verwerkt via CallbackQueryHandler.

Om ervoor te zorgen dat de bot het toetsenbord opent, moet je bij het verzenden van een bericht via de methode sendMessage(), de eerder gemaakte toetsenbord doorgeven als argument reply_markup.

Hieronder bekijken we enkele voorbeelden.

Reply toetsenbord

Zoals ik hierboven al schreef, is dit het hoofdtoetsenbord voor het beheren van de bot.

Voorbeeld van het maken van een Reply-toetsenbord uit de officiële documentatie

bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"

# Maak een aangepast toetsenbord
text <- "Zijn die aangepaste toetsenborden niet gaaf?"
RKM <- ReplyKeyboardMarkup(
  keyboard = list(
    list(KeyboardButton("Ja, dat zijn ze zeker!")),
    list(KeyboardButton("Ik ben er niet helemaal zeker van")),
    list(KeyboardButton("Nee..."))
  ),
  resize_keyboard = FALSE,
  one_time_keyboard = TRUE
)

# Verzend aangepast toetsenbord
bot$sendMessage(chat_id, text, reply_markup = RKM)

Bovenstaand is een voorbeeld uit de officiële documentatie van het pakket telegram.bot. Voor het maken van het toetsenbord wordt de functie ReplyKeyboardMarkup(), die op haar beurt een lijst van lijsten van knoppen accepteert, die worden gemaakt met de functie KeyboardButton().

Waarom in ReplyKeyboardMarkup() Moet je niet gewoon een lijst doorgeven, maar een lijst van lijsten? Het punt is dat je de hoofdlijst doorgeeft, en dat je in die lijst elke rij knoppen als aparte lijsten instelt, omdat je meerdere knoppen in één rij kunt plaatsen.

Het argument resize_keyboard maakt automatisch het optimale formaat van de knoppen op het toetsenbord mogelijk, en het argument one_time_keyboard maakt het mogelijk om het toetsenbord na elke druk op een knop te verbergen.

Laten we een eenvoudige bot schrijven die drie knoppen heeft:

  • Chat ID — Vraag de chat ID van het dialoog met de bot aan
  • Mijn naam — Vraag je eigen naam aan
  • Mijn gebruikersnaam — Vraag je gebruikersnaam in Telegram aan

Code 1: Eenvoudige bot met Reply toetsenbord

library(telegram.bot)

# Creëer een instantie van de Updater klasse
updater <- Updater('TOKEN VAN JE BOT')

# Creëer de methoden
## Methode om het toetsenbord te starten
start <- function(bot, update) {

  # Creëer het toetsenbord
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton("Chat ID")),
      list(KeyboardButton("Mijn naam")),
      list(KeyboardButton("Mijn gebruikersnaam"))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
  )

  # Verzend het toetsenbord
  bot$sendMessage(update$message$chat_id,
                  text = 'Kies een opdracht', 
                  reply_markup = RKM)

}

## Methode die de chat ID retourneert
chat_id <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Chat id van deze dialoog: ", update$message$chat_id),
                  parse_mode = "Markdown")

}

## Methode die de naam retourneert
my_name <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Je heet ", update$message$from$first_name),
                  parse_mode = "Markdown")

}

## Methode die de gebruikersnaam retourneert
my_username <- function(bot, update) {

  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Je gebruikersnaam is ", update$message$from$username),
                  parse_mode = "Markdown")

}

# Creëer filters
## Berichten met tekst Chat ID
MessageFilters$chat_id <- BaseFilter(function(message) {

  # Controleer de tekst van het bericht
  message$text == "Chat ID"

}
)

## Berichten met tekst Mijn naam
MessageFilters$name <- BaseFilter(function(message) {

  # Controleer de tekst van het bericht
  message$text == "Mijn naam"

}
)

## Berichten met tekst Mijn gebruikersnaam
MessageFilters$username <- BaseFilter(function(message) {

  # Controleer de tekst van het bericht
  message$text == "Mijn gebruikersnaam"
)

# Creëer handlers
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)

# Voeg handlers toe aan de dispatcher
updater <- updater + 
            h_start +
            h_chat_id +
            h_name +
            h_username

# Start de bot 
updater$start_polling()

Voer het bovenstaande voorbeeld van de code uit, terwijl je 'DE TOKEN VAN JE BOTS' vervangt door de daadwerkelijke token die je hebt verkregen bij het aanmaken van een bot via BotFather (over het aanmaken van een bot heb ik verteld in eerste artikel).

Geef de bot een opdracht na het starten /start, omdat we deze hebben gedefinieerd voor het starten van het toetsenbord.

Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

Als het momenteel moeilijk voor u is om het gegeven codevoorbeeld met het maken van methoden, filters en handlers te begrijpen, moet u terugkeren naar het vorige artikel, waarin ik dit alles in detail heb beschreven.

We hebben 4 methoden gemaakt:

  • start — Start het toetsenbord
  • chat_id — Vraag het chat-ID
  • my_name — Vraag uw naam
  • my_username — Vraag uw gebruikersnaam

In het object MessageFilters hebben we 3 filters voor berichten toegevoegd, op basis van hun tekst:

  • chat_id — Berichten met de tekst "Chat ID"
  • name — Berichten met de tekst "Mijn naam"
  • username — Berichten met de tekst "Mijn gebruikersnaam"

En we hebben 4 handlers gemaakt die de opgegeven methoden uitvoeren op basis van de gegeven commands en filters.

# создаём обработчики
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)

Het toetsenbord zelf wordt gemaakt binnen de methode start() met het commando ReplyKeyboardMarkup().

RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(KeyboardButton("Chat ID")),
      list(KeyboardButton("Mijn naam")),
      list(KeyboardButton("Mijn gebruikersnaam"))
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)

In ons geval hebben we alle knoppen onder elkaar geplaatst, maar we kunnen ze ook in één rij plaatsen door wijzigingen aan te brengen in de lijst van knoppen. Aangezien één rij binnen het toetsenbord wordt gemaakt via een geneste lijst van knoppen, moeten we een deel van de code voor het bouwen van het toetsenbord als volgt herschrijven om onze knoppen in één rij weer te geven:

RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
          KeyboardButton("Chat ID"),
          KeyboardButton("Mijn naam"),
          KeyboardButton("Mijn gebruikersnaam")
     )
    ),
    resize_keyboard = FALSE,
    one_time_keyboard = TRUE
)

Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

Het toetsenbord wordt naar de chat gestuurd met de methode sendMessage(), in de argument reply_markup.

  bot$sendMessage(update$message$chat_id,
                  text = 'Kies een opdracht', 
                  reply_markup = RKM)

Inline toetsenbord

Zoals ik hierboven al aangaf, is het Inline toetsenbord gekoppeld aan een specifiek bericht. Het is iets ingewikkelder om ermee te werken dan met het hoofdtoetsenbord.

U moet de bot aanvankelijk een methode toevoegen om het Inline toetsenbord op te roepen.

Voor het reageren op het indrukken van de Inline knop kan ook de methode van de bot worden gebruikt answerCallbackQuery(), die een melding kan weergeven in de interface van Telegram, voor de gebruiker die op de Inline knop heeft gedrukt.

De gegevens die met de Inline knop zijn verzonden, zijn geen tekst, dus om deze te verwerken, moet een speciale handler worden gemaakt met behulp van de opdracht CallbackQueryHandler().

De code voor het bouwen van het Inline toetsenbord die in de officiële documentatie van het pakket wordt genoemd telegram.bot.

De code voor het bouwen van het Inline toetsenbord uit de officiële documentatie

# Initialize bot
bot <- Bot(token = "TOKEN")
chat_id <- "CHAT_ID"

# Create Inline Keyboard
text <- "Could you type their phone number, please?"
IKM <- InlineKeyboardMarkup(
  inline_keyboard = list(
    list(
      InlineKeyboardButton(1),
      InlineKeyboardButton(2),
      InlineKeyboardButton(3)
    ),
    list(
      InlineKeyboardButton(4),
      InlineKeyboardButton(5),
      InlineKeyboardButton(6)
    ),
    list(
      InlineKeyboardButton(7),
      InlineKeyboardButton(8),
      InlineKeyboardButton(9)
    ),
    list(
      InlineKeyboardButton("*"),
      InlineKeyboardButton(0),
      InlineKeyboardButton("#")
    )
  )
)

# Send Inline Keyboard
bot$sendMessage(chat_id, text, reply_markup = IKM)

Het bouwen van een Inline toetsenbord moet gebeuren met behulp van de opdracht InlineKeyboardMarkup(), op dezelfde manier als de Reply toetsenbord. In InlineKeyboardMarkup() moet een lijst worden doorgegeven, lijsten met Inline knoppen, elke aparte knop wordt aangemaakt met de functie InlineKeyboardButton().

Een Inline knop kan ofwel gegevens aan de bot doorgeven met behulp van het argument callback_data, ofwel een bepaalde HTML-pagina openen die is opgegeven met behulp van het argument url.

Als resultaat zal er een lijst zijn, waarin elk element ook een lijst van Inline knoppen is, die in één rij moeten worden samengevoegd.

Laten we vervolgens enkele voorbeelden van bots met Inline knoppen bekijken.

Voorbeeld van de eenvoudigste bot met ondersteuning voor inline-knoppen

Laten we beginnen met het schrijven van een bot voor een snelle test op covid-19. Op het commando /test, zal hij je een toetsenbord met twee knoppen sturen, afhankelijk van welke knop er is ingedrukt, zal hij je een bericht met de resultaten van je test sturen.

Code 2: De eenvoudigste bot met een Inline toetsenbord

library(telegram.bot)

# maak een instantie van de Updater klasse aan
updater <- Updater('JE BOT TOKEN')

# methode om een InLine toetsenbord te versturen
test <- function(bot, update) {

  # maak een InLine toetsenbord aan
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("Ja", callback_data = 'yes'),
        InlineKeyboardButton("Nee", callback_data = 'no')
      )
    )
  )

  # Stuur het toetsenbord in de chat
  bot$sendMessage(update$message$chat_id, 
                  text = "Heb je coronavirus?", 
                  reply_markup = IKM)
}

# methode om het drukken van de knop te verwerken
answer_cb <- function(bot, update) {

  # verkregen gegevens van de knop
  data <- update$callback_query$data

  # krijg de gebruikersnaam van de persoon die op de knop heeft gedrukt
  uname <- update$effective_user()$first_name

  # resultaat verwerking
  if ( data == 'no' ) {

    msg <- paste0(uname, ", gefeliciteerd, je test op covid-19 is negatief.")

  } else {

    msg <- paste0(uname, ", helaas is je test op covid-19 positief.")

  }

  # Bericht versturen
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # meld de bot dat de verzoek van de knop is ontvangen
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# maak de handlers aan
inline_h      <- CommandHandler('test', test)
query_handler <- CallbackQueryHandler(answer_cb)

# voeg de handlers toe aan de dispatcher
updater <- updater + inline_h + query_handler

# start de bot
updater$start_polling()

Voer het bovenstaande voorbeeld van de code uit, terwijl je 'DE TOKEN VAN JE BOTS' vervangt door de daadwerkelijke token die je hebt verkregen bij het aanmaken van een bot via BotFather (over het aanmaken van een bot heb ik verteld in eerste artikel).

Resultaat:
Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

We hebben twee methoden gemaakt:

  • test — Voor het verzenden van een Inline toetsenbord in de chat
  • answer_cb — Voor het verwerken van gegevens verzonden vanaf het toetsenbord.

De gegevens die van elke knop worden verzonden, worden ingesteld in het argument callback_data, bij het aanmaken van de knop. De verzonden gegevens van de knop kunnen worden verkregen met behulp van de constructie update$callback_query$data, binnen de methode answer_cb.

Om ervoor te zorgen dat de bot reageert op het Inline toetsenbord, moet de methode answer_cb wordt verwerkt door een speciale handler: CallbackQueryHandler(answer_cb). Die de opgegeven methode activeert bij het indrukken van een inline-knop. De handler CallbackQueryHandler ontvangt twee argumenten:

  • callback — De methode die moet worden uitgevoerd
  • pattern — Een filter op de gegevens die aan de knop zijn gekoppeld met behulp van het argument callback_data.

Bijgevolg kunnen we met behulp van het argument pattern voor iedere knop een aparte methode schrijven:

Code 3: Verdeel methoden voor elke Inline-knop

library(telegram.bot)

# maak een instantie van de Updater class
updater <- Updater('UW BOT TOKEN')

# methode voor het verzenden van een Inline toetsenbord
test <- function(bot, update) {  

  # maak het Inline toetsenbord
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton("Ja", callback_data = 'yes'),
        InlineKeyboardButton("Nee", callback_data = 'no')
      )
    )
  )

  # verstuur het toetsenbord in de chat
  bot$sendMessage(update$message$chat_id, 
                  text = "Heb je corona?", 
                  reply_markup = IKM)
}

# methode voor het verwerken van het indrukken van de Ja-knop
answer_cb_yes <- function(bot, update) {

  # verkregen gebruikersnaam die op de knop heeft gedrukt
  uname <- update$effective_user()$first_name

  # verwerking van het resultaat
  msg <- paste0(uname, ", helaas is uw test op covid-19 positief.")

  # verstuur bericht
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # informeer de bot dat het verzoek van de knop is ontvangen
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# methode voor het verwerken van het indrukken van de Nee-knop
answer_cb_no <- function(bot, update) {

  # verkregen gebruikersnaam die op de knop heeft gedrukt
  uname <- update$effective_user()$first_name

  msg <- paste0(uname, ", gefeliciteerd, uw test op covid-19 is negatief.")

  # verstuur bericht
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text = msg)

  # informeer de bot dat het verzoek van de knop is ontvangen
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# maak handlers
inline_h          <- CommandHandler('test', test)
query_handler_yes <- CallbackQueryHandler(answer_cb_yes, pattern = 'yes')
query_handler_no  <- CallbackQueryHandler(answer_cb_no, pattern = 'no')

# voeg handlers toe aan de dispatcher
updater <- updater + 
            inline_h + 
            query_handler_yes +
            query_handler_no

# start de bot
updater$start_polling()

Voer het bovenstaande voorbeeld van de code uit, terwijl je 'DE TOKEN VAN JE BOTS' vervangt door de daadwerkelijke token die je hebt verkregen bij het aanmaken van een bot via BotFather (over het aanmaken van een bot heb ik verteld in eerste artikel).

Nu hebben we 2 aparte methoden geschreven, dat wil zeggen, één methode voor het indrukken van elke knop, en gebruikten het argument pattern, bij het creëren van hun handlers:

query_handler_yes <- CallbackQueryHandler(answer_cb_yes, pattern = 'yes')
query_handler_no  <- CallbackQueryHandler(answer_cb_no, pattern = 'no')

de code van de methode eindigt answer_cb met het commando bot$answerCallbackQuery(callback_query_id = update$callback_query$id), die de bot informeert dat de gegevens van het inline toetsenbord zijn ontvangen.

Voorbeeld van een bot die het actuele weer geeft voor een gekozen stad

Laten we proberen een bot te schrijven die gegevens over het weer opvraagt.

De logica van zijn werking zal als volgt zijn. Initiieel /start roept u het hoofdtoetsenbord op, waar slechts één knop "Weer" aanwezig is. Door op deze knop te drukken ontvangt u een bericht met een inline toetsenbord om een stad te kiezen waarvan u de huidige weersinformatie wilt weten. U kiest een van de steden en ontvangt de huidige weersinformatie.

In dit voorbeeld van de code gaan we verschillende extra pakketten gebruiken:

  • httr — een pakket voor het werken met HTTP verzoeken, waar onze API-functies op zijn gebaseerd. In ons geval gaan we de gratis API gebruiken openweathermap.org.
  • stringr — een pakket voor tekstverwerking, dat we in dit geval gaan gebruiken om het weerbericht voor de gekozen stad samen te stellen.

Code 4: Een bot die het huidige weer voor de geselecteerde stad rapporteert

library(telegram.bot)
library(httr)
library(stringr)

# Maak een instantie van de Updater klasse
updater <- Updater('UW BOT TOKEN')

# Maak methoden
## Methode om het hoofdtoetsenbord te starten
start <- function(bot, update) {

  # Maak het toetsenbord
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton("Weer")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  # Stuur het toetsenbord
  bot$sendMessage(update$message$chat_id,
                  text = 'Kies een opdracht', 
                  reply_markup = RKM)

}

## Methode voor het oproepen van het Inline-toetsenbord
weather <- function(bot, update) {

  IKM <- InlineKeyboardMarkup(
    inline_keyboard = list(
      list(
        InlineKeyboardButton(text = 'Moskou', callback_data = 'New York,us'),
        InlineKeyboardButton(text = 'Sint-Petersburg', callback_data = 'Saint Petersburg'),
        InlineKeyboardButton(text = 'New York', callback_data = 'New York')
      ),
      list(
        InlineKeyboardButton(text = 'Jekaterinenburg', callback_data = 'Yekaterinburg,ru'),
        InlineKeyboardButton(text = 'Berlijn', callback_data = 'Berlin,de'),
        InlineKeyboardButton(text = 'Parijs', callback_data = 'Paris,fr')
      ),
      list(
        InlineKeyboardButton(text = 'Rome', callback_data = 'Rome,it'),
        InlineKeyboardButton(text = 'Odessa', callback_data = 'Odessa,ua'),
        InlineKeyboardButton(text = 'Kiev', callback_data = 'Kyiv,fr')
      ),
      list(
        InlineKeyboardButton(text = 'Tokio', callback_data = 'Tokyo'),
        InlineKeyboardButton(text = 'Amsterdam', callback_data = 'Amsterdam,nl'),
        InlineKeyboardButton(text = 'Washington', callback_data = 'Washington,us')
      )
    )
  )

  # Stuur het Inline-toetsenbord
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Kies een stad", 
                  reply_markup = IKM)
}

# Methode voor het weerbericht
answer_cb <- function(bot, update) {

  # Verkrijg de stad uit het bericht
  city <- update$callback_query$data

  # Verzend de aanvraag
  ans <- GET('https://api.openweathermap.org/data/2.5/weather', 
             query = list(q = city,
                          lang = 'nl',
                          units = 'metric',
                          appid = '4776568ccea136ffe4cda9f1969af340')) 

  # Parse het antwoord
  result <- content(ans)

  # Vorm het bericht
  msg <- str_glue("{result$name} weer:n",
                  "Huidige temperatuur: {result$main$temp}n",
                  "Windsnelheid: {result$wind$speed}n",
                  "Beschrijving: {result$weather[[1]]$description}")

  # Stuur de weerinformatie
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = msg)

  bot$answerCallbackQuery(callback_query_id = update$callback_query$id) 
}

# Maak filters
## Berichten met de tekst Weer
MessageFilters$weather <- BaseFilter(function(message) {

  # Controleer de tekst van het bericht
  message$text == "Weer"

}
)

# Maak handlers
h_start         <- CommandHandler('start', start)
h_weather       <- MessageHandler(weather, filters = MessageFilters$weather)
h_query_handler <- CallbackQueryHandler(answer_cb)

# Voeg handlers toe aan de dispatcher
updater <- updater + 
              h_start +
              h_weather +
              h_query_handler

# Start de bot
updater$start_polling()

Voer het bovenstaande voorbeeld van de code uit, terwijl je 'DE TOKEN VAN JE BOTS' vervangt door de daadwerkelijke token die je hebt verkregen bij het aanmaken van een bot via BotFather (over het aanmaken van een bot heb ik verteld in eerste artikel).

Als resultaat zal onze bot ongeveer zo werken:
Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

Schematisch kan deze bot als volgt worden weergegeven:
Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

We hebben 3 methoden gemaakt die binnen onze weerbot beschikbaar zijn:

  • start — Start de hoofdtoetsenbord van de bot
  • weer — Start Inline-toetsenbord voor het kiezen van een stad
  • answer_cb — De belangrijkste methode die, voor de opgegeven stad, het weer opvraagt via de API en het naar de chat verstuurt.

Methode start dit wordt gestart met het commando /start, dat is geïmplementeerd door de handler CommandHandler('start', start).

Om de methode te starten weer hebben we een gelijknamige filter gemaakt:

# создаём фильтры
## сообщения с текстом Погода
MessageFilters$weather <- BaseFilter(function(message) {

  # проверяем текст сообщения
  message$text == "Погода"

}
)

En we roepen deze methode aan met de volgende berichthandler: MessageHandler(weather, filters = MessageFilters$weather).

En uiteindelijk, onze belangrijkste methode answer_cb reageert op het indrukken van Inline-knoppen, wat is geïmplementeerd door een speciale handler: CallbackQueryHandler(answer_cb).

Binnen de methode answer_cb, lezen we de gegevens die vanaf het toetsenbord zijn verzonden en schrijven ze in de variabele stad: stad <- update$callback_query$data. Daarna vragen we de API om weergegevens, formuleren en sturen een bericht, en uiteindelijk gebruiken we de methode answerCallbackQuery om de bot te laten weten dat we de druk op de Inline-knop hebben verwerkt.

Een voorbeeld van een bot die een lijst van de nieuwste artikelen met links toont naar de opgegeven Hub van habr.com.

Deze bot geef ik als voorbeeld om je te laten zien hoe je Inline-knoppen kunt weergeven die naar webpagina's leiden.

De logica van deze bot is vergelijkbaar met de vorige, eerst starten we het hoofdtoetsenbord met het commando /start. Vervolgens geeft de bot ons een keuze uit 6 hubs, we kiezen de hub die ons interesseert en krijgen de 5 nieuwste publicaties van de gekozen Hub.

Zoals je begrijpt, moeten we in dit geval een lijst van artikelen ophalen, en daarvoor gaan we een speciaal pakket gebruiken habR, dat het mogelijk maakt om artikelen en bepaalde statistieken van Habr in R op te vragen.

Het pakket habR kan alleen worden geïnstalleerd vanaf github, waarvoor je een extra pakket nodig hebt devtools. Voor installatie gebruik de onderstaande code.

install.packages('devtools')
devtools::install_github('selesnow/habR')

Laten we nu kijken naar de code voor de hierboven beschreven bot:

Code 5: Bot die een lijst van de meest recente artikelen toont volgens de gekozen Hub

library(telegram.bot)
library(habR)

# Maak een instantie van de Updater klasse
updater <- Updater('DE TOKEN VAN UW BOT')

# Creëren van methoden
## Methode om het hoofdtoetsenbord te starten
start <- function(bot, update) {

  # Creëren toetsenbord
  RKM <- ReplyKeyboardMarkup(
    keyboard = list(
      list(
        KeyboardButton("Lijst van artikelen")
      )
    ),
    resize_keyboard = TRUE,
    one_time_keyboard = TRUE
  )

  # Stuur het toetsenbord
  bot$sendMessage(update$message$chat_id,
                  text = 'Kies een commando', 
                  reply_markup = RKM)

}

## Methode om Inline toetsenbord aan te roepen
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 = 'Gegevensvisualisatie', callback_data = 'data_visualization')
      )
    )
  )

  # Stuur Inline toetsenbord
  bot$sendMessage(chat_id = update$message$chat_id, 
                  text = "Kies een Hub", 
                  reply_markup = IKM)
}

# Methode voor het weerbericht
answer_cb <- function(bot, update) {

  # Verkrijg de stad uit het bericht
  hub <- update$callback_query$data

  # Bericht dat de gegevens via de knop zijn verkregen
  bot$answerCallbackQuery(callback_query_id = update$callback_query$id, 
                          text = 'Even geduld, verzoek wordt verwerkt') 

  # Bericht dat men moet wachten terwijl de bot gegevens verzamelt
  mid <- bot$sendMessage(chat_id = update$from_chat_id(),
                         text = "Even geduld terwijl ik gegevens verzamel over de gekozen Hub")

  # Parse Habr
  posts <- head(habr_hub_posts(hub, 1), 5)

  # Verwijder het wachtoverzicht
  bot$deleteMessage(update$from_chat_id(), mid$message_id) 

  # Vorm een lijst met knoppen
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  # Vorm het toetsenbord
  IKM <- InlineKeyboardMarkup(
    inline_keyboard = keys 
    )

  # Stuur informatie over het weer
  bot$sendMessage(chat_id = update$from_chat_id(),
                  text    = paste0("De 5 meest recente artikelen uit de Hub ", hub),
                  reply_markup = IKM)

}

# Creëren van filters
## Berichten met de tekst Weer
MessageFilters$hubs <- BaseFilter(function(message) {

  # Controleer de tekst van het bericht
  message$text == "Lijst van artikelen"

}
)

# Creëren van handlers
h_start         <- CommandHandler('start', start)
h_hubs          <- MessageHandler(habs, filters = MessageFilters$hubs)
h_query_handler <- CallbackQueryHandler(answer_cb)

# Voeg handlers toe aan de dispatcher
updater <- updater + 
  h_start +
  h_hubs  +
  h_query_handler

# Start de bot
updater$start_polling()

Voer het bovenstaande voorbeeld van de code uit, terwijl je 'DE TOKEN VAN JE BOTS' vervangt door de daadwerkelijke token die je hebt verkregen bij het aanmaken van een bot via BotFather (over het aanmaken van een bot heb ik verteld in eerste artikel).

Uiteindelijk krijgen we zo'n resultaat:
Een telegram bot schrijven in R (deel 3): Hoe ondersteuning voor toetsenborden aan de bot toe te voegen

Lijst van beschikbare hubs hebben we hardcoded in de methode hubs:

## Метод вызова 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)
}

De lijst met artikelen uit de opgegeven hub krijgen we met de opdracht habr_hub_posts(), uit het pakket habR. We geven hierbij aan dat we geen lijst met artikelen voor altijd nodig hebben, maar alleen de eerste pagina met daarop 20 artikelen. Uit de verkregen tabel gebruiken we de opdracht head() en laten we alleen de 5 bovenste over, die de nieuwste artikelen zijn.

  # парсим Хабр
  posts <- head(habr_hub_posts(hub, 1), 5)

De logica is zeer vergelijkbaar met de vorige bot, maar in dit geval genereren we de inline toetsenbord met de lijst van artikelen dynamisch met behulp van de functie lapply().

  # формируем список кнопок
  keys <- lapply(1:5, function(x) list(InlineKeyboardButton(posts$title[x], url = posts$link[x])))

  # формируем клавиатуру
  IKM <- InlineKeyboardMarkup(
    inline_keyboard =  keys 
    )

In de tekst van de knop plaatsen we de titel van het artikel posts$title[x], en in het argument url de link naar het artikel: url = posts$link[x].

Vervolgens creëren we een filter, afhandelaars en starten we onze bot.

Conclusie

Nu zullen de bots die u hebt geschreven veel handiger zijn in gebruik, omdat het beheer ervan zal plaatsvinden via het toetsenbord en niet door commando-invoer. Ten minste bij interactie met de bot via een smartphone zal het toetsenbord het gebruik aanzienlijk vereenvoudigen.

In het volgende artikel zullen we bekijken hoe we een logische dialoog met de bot opbouwen en werken met databases.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster