Een telegram bot schrijven in R (deel 2): We voegen ondersteuning voor commando's en filters voor berichten toe aan de bot

In vorige publicatie We hebben geleerd hoe we een bot kunnen maken en een exemplaar van de klasse hebben geïnitialiseerd. Bot en we hebben kennisgemaakt met de methoden om berichten ermee te verzenden.

In dit artikel ga ik verder met dit onderwerp, dus ik raad aan deze tekst pas na het lezen van het vorige artikel te lezen. het eerste deel.

Deze keer gaan we bekijken hoe we onze bot tot leven kunnen brengen, hem ondersteuning voor commando's geven en kennismaken met de klasse Updater.

In het artikel zullen we enkele eenvoudige bots schrijven. De laatste zal op basis van een gegeven datum en een landcode bepalen of een dag in dat land een werkdag of een vrije dag is volgens de arbeidscalender. Maar, zoals voorheen, is het doel van het artikel om u vertrouwd te maken met de interface van het pakket telegram.bot om uw eigen taken op te lossen.

Een telegram bot schrijven in R (deel 2): We voegen ondersteuning voor commando's en filters voor berichten toe aan de bot

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

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. De Updater-klasse
  2. Handlers — handlers
  3. We voegen het eerste commando aan de bot toe, de commando-handler
  4. De handler voor tekstberichten en filters
  5. Het toevoegen van commando's met parameters
  6. De bot in de achtergrond uitvoeren
  7. Conclusie

De Updater-klasse

Updater is een klasse die het voor u gemakkelijker maakt om een telegram bot te ontwikkelen en onder de motorkap de klasse Dispatcherkan worden gebruikt. Het doel van de klasse Updater is om updates van de bot te ontvangen (in het vorige artikel gebruikten we hiervoor de methode getUpdates()), en deze door te geven aan Dispatcher.

Op zijn beurt Dispatcher bevat de door u gemaakte handlers, dat wil zeggen objecten van de klasse Handler.

Handlers — handlers

Met behulp van handlers voegt u reacties van de bot toe op verschillende gebeurtenissen. Op het moment van schrijven zijn in Dispatcher de volgende types handlers toegevoegd: telegram.bot MessageHandler — Handler voor berichten

  • CommandHandler — Handler voor commando's
  • CallbackQueryHandler — Handler voor gegevens verzonden vanaf inline toetsenborden
  • ErrorHandler — Handler voor fouten bij het aanvragen van updates van de bot
  • Als u nog nooit bots hebt gebruikt en niet weet wat een commando is, dan moet het commando naar de bot worden verzonden met een directe schuine streep

We voegen het eerste commando aan de bot toe, de commando-handler

als prefix. / Laten we beginnen met eenvoudige commando's, dat wil zeggen, we leren onze bot groeten op commando

Code 1: We leren de bot groeten /hi.

Code 1: We leren de bot groeten

library(telegram.bot)

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

# Schrijf een methode voor de begroeting
say_hello <- function(bot, update) {

  # De gebruikersnaam waarmee begroet moet worden
  user_name <- update$message$from$first_name

  # Stuur het begroetingsbericht
  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Mijn respect, ", user_name, "!"), 
                  parse_mode = "Markdown")

}

# Maak een handler
hi_hendler <- CommandHandler('hi', say_hello)

# Voeg de handler toe aan de dispatcher
updater <- updater + hi_hendler

# 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).

Methode start_polling() klasse Updater, dat aan het einde van de code wordt gebruikt, start een oneindige loop om verzoeken en updates van de bot te verwerken.

Laten we nu Telegram openen en onze bot het eerste commando geven. /hi.

Een telegram bot schrijven in R (deel 2): We voegen ondersteuning voor commando's en filters voor berichten toe aan de bot

Nu begrijpt onze bot het commando /hi, en kan hij ons begroeten.

Schematisch kan het proces van het opbouwen van zo'n eenvoudige bot als volgt worden weergegeven.

Een telegram bot schrijven in R (deel 2): We voegen ondersteuning voor commando's en filters voor berichten toe aan de bot

  1. We maken een instantie van de klasse Updater;
  2. We creëren methoden, d.w.z. functies die onze bot zal uitvoeren. In het voorbeeld van de code is dit de functie say_hello(). Functies die je als methods voor de bot gebruikt, moeten twee verplichte argumenten hebben - bot en update, en één optioneel - args. Het argument bot, dit is jouw bot, waarmee je op berichten kunt antwoorden, berichten kunt verzenden, of andere beschikbare methoden van de bot kunt gebruiken. Het argument update is dat wat de bot van de gebruiker heeft ontvangen, in wezen wat we in het eerste artikel hebben verkregen met de methode getUpdates(). Het argument args laat je extra gegevens verwerken die door de gebruiker samen met de opdracht zijn verzonden, daar komen we later nog op terug;
  3. We maken handlers, d.w.z. we koppelen bepaalde acties van de gebruiker aan de in de vorige stap gemaakte methoden. In wezen is een handler een trigger, een gebeurtenis die een functie van de bot oproept. In ons voorbeeld is zo'n trigger het verzenden van het commando /hi, en wordt geïmplementeerd met het commando hi_hendler <- CommandHandler('hi', say_hello). Het eerste argument van de functie CommandHandler() maakt het mogelijk om het commando dat in ons geval In elke structuur wordt het, waarop de bot zal reageren, op te geven. Het tweede argument maakt het mogelijk om de methode van de bot aan te geven, we zullen de methode aanroepen say_hello, dat zal worden uitgevoerd wanneer de gebruiker het in de eerste parameter opgegeven commando aanroept;
  4. Vervolgens voegen we de gemaakte handler toe aan de dispatcher van ons klasse-exemplaar. Updater. Handlers kunnen op verschillende manieren worden toegevoegd; in het bovenstaande voorbeeld heb ik de eenvoudigste manier gebruikt, met behulp van het teken. +, d.w.z. updater <- updater + hi_handler. Hetzelfde kan worden gedaan met de methode add_handler(), die behoort tot de klasse Dispatcher, dit kan als volgt worden gevonden: updater$dispatcher$add_handler();
  5. We starten de bot met het commando start_polling().

De handler voor tekstberichten en filters

We hebben begrepen hoe we de bot opdrachten kunnen geven, maar soms willen we dat de bot niet alleen reageert op opdrachten, maar ook op gewone tekstberichten. Hiervoor moeten we berichthandlers gebruiken — MessageHandler.

Normaal MessageHandler zal reageren op alle binnenkomende berichten. Daarom worden berichthandlers vaak samen met filters gebruikt. Laten we de bot leren om niet alleen te groeten via een commando, /hi, maar ook altijd wanneer een van de volgende woorden in een aan de bot verzonden bericht voorkomt: hallo, goeiedag, groet, hi, bonjour.

Tot nu toe gaan we geen nieuwe methoden schrijven, aangezien we al een methode hebben waarmee de bot ons groet. Het enige dat we hoeven te doen, is de juiste filter en berichthandler creëren.

Code 2: Voeg een handler voor tekstberichten en een filter toe

library(telegram.bot)

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

# Schrijf een methode voor begroeting
## begroetingscommando
say_hello <- function(bot, update) {

  # De gebruiker met wie begroet moet worden
  user_name <- update$message$from$first_name

  # Stuur het begroetingsbericht
  bot$sendMessage(update$message$chat_id, 
                  text = paste0("Mijn eer, ", user_name, "!"),
                  parse_mode = "Markdown",
                  reply_to_message_id = update$message$message_id)

}

# creër filters
MessageFilters$hi <- BaseFilter(function(message) {

  # controleren of de woorden: hallo, goeiedag, groet, hi, bonjour in de tekst van het bericht voorkomen
  grepl(x           = message$text, 
        pattern     = 'hallo|goeiedag|groet|hi|bonjour',
        ignore.case = TRUE)
  }
)

# maak de handler
hi_handler <- CommandHandler('hi', say_hello) # handler voor het 'hi' commando
hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi)

# voeg handlers toe aan de dispatcher
updater <- updater + 
             hi_handler +
             hi_txt_hnd

# 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).

Laten we de bot nu enkele berichten sturen waarin de eerder genoemde begroetingen voorkomen:
Een telegram bot schrijven in R (deel 2): We voegen ondersteuning voor commando's en filters voor berichten toe aan de bot

Dus, in de eerste plaats hebben we de bot geleerd niet alleen te groeten, maar ook te reageren op begroetingen. Dit hebben we gedaan met behulp van het argument reply_to_message_id, dat beschikbaar is in de methode sendMessage(), waarin we de ID van het bericht moeten doorgeven waarop we willen antwoorden. Je kunt de ID van het bericht zo verkrijgen: update$message$message_id.

Maar het belangrijkste dat we hebben gedaan is dat we de bot een filter hebben toegevoegd met behulp van de functie BaseFilter():

# создаём фильтры
MessageFilters$hi <- BaseFilter( 

  # анонимная фильтрующая функция
  function(message) {

    # проверяем, встречается ли в тексте сообщения слова приветствия
    grepl(x           = message$text, 
          pattern     = 'привет|здравствуй|салют|хай|бонжур',
          ignore.case = TRUE)
  }

)

Zoals je hebt kunnen opmerken, moeten filters worden toegevoegd aan het object MessageFilters, waarin aanvankelijk al een kleine set kant-en-klare filters is. In ons voorbeeld hebben we in het object MessageFilters een element toegevoegd In elke structuur wordt het, dit is het nieuwe filter.

In de functie BaseFilter() je moet de filterfunctie doorgeven. In wezen is een filter gewoon een functie die een instantie van een bericht ontvangt en TRUE of FALSEteruggeeft. In ons voorbeeld hebben we de eenvoudigste functie geschreven die met behulp van de basisfunctie grepl() de tekst van het bericht controleert, en als deze overeenkomt met de reguliere expressie hallo|hoi|groet|hey|bonjour geeft hij TRUE.

Vervolgens maken we een berichtenhandler aan hi_txt_hnd <- MessageHandler(say_hello, filters = MessageFilters$hi). Het eerste argument van de functie MessageHandler() is de methode die de handler aanroept, en het tweede argument is de filter waarop het zal worden aangeroepen. In ons geval is dat de filter die we hebben gemaakt MessageFilters$hi.

En uiteindelijk voegen we de zojuist gemaakte handler toe aan de dispatcher hi_txt_hnd.

updater <- updater + 
             hi_hendler +
             hi_txt_hnd

Zoals ik eerder heb geschreven, zijn er al ingebouwde filters in het pakket telegram.bot en het object MessageFilters die je kunt gebruiken:

  • all — Alle berichten
  • text — Tekstberichten
  • command — Commando's, d.w.z. berichten die beginnen met /
  • reply — Berichten die een antwoord zijn op een ander bericht
  • audio — Berichten waarin een audiobestand zit
  • document — Berichten met een verzonden document
  • photo — Berichten met verzonden afbeeldingen
  • sticker — Berichten met een verzonden sticker
  • video — Berichten met video
  • voice — Spraakberichten
  • contact — Berichten waarin contactinformatie van een Telegram-gebruiker zit
  • location — Berichten met geolocatie
  • venue — Doorstuurberichten
  • game — Spellen

Als je enkele filters in één handler wilt combineren, gebruik dan gewoon het teken | — als logisch OF, en het teken & als logische En. Bijvoorbeeld, als u wilt dat de bot dezelfde methode aanroept wanneer hij een video, afbeelding of document ontvangt, gebruik dan het volgende voorbeeld voor het maken van een berichtverwerker:

handler <- MessageHandler(callback, 
  MessageFilters$video | MessageFilters$photo | MessageFilters$document
)

Het toevoegen van commando's met parameters

We weten al wat commando's zijn, hoe we ze moeten maken en hoe we de bot kunnen laten uitvoeren wat nodig is. Maar in sommige gevallen moeten we naast de naam van het commando ook enkele gegevens doorgeven voor de uitvoering.

Hieronder een voorbeeld van een bot die op basis van de opgegeven datum en het land het type dag uit de productie kalender teruggeeft.

De onderstaande bot gebruikt de API van de productie kalender isdayoff.ru.

Code 3: Een bot die de datum en het land meldt

library(telegram.bot)

# Maak een instantie van de Updater-klasse
updater <- Updater('1165649194:AAFkDqIzQ6Wq5GV0YU7PmEZcv1gmWIFIB_8')

# Schrijf een method voor de begroeting
## Begroetingscommando
check_date <- function(bot, update, args) {

  # binnenkomende gegevens
  day <- args[1]  # datum
  country <- args[2]  # land

  # Controleer de ingevoerde parameters
  if ( !grepl('\d{4}-\d{2}-\d{2}', day) ) {

    # Stuur een aangepaste toetsenbord
    bot$sendMessage(update$message$chat_id, 
                    text = paste0(day, " - onjuiste datum, voer een datum in het formaat JJJJ-MM-DD in"),
                    parse_mode = "Markdown")

  } else {
    day <- as.Date(day)
    # converteer naar POSIXtl-formaat
    y <- format(day, "%Y")
    m <- format(day, "%m")
    d <- format(day, "%d")

  }

  # Land voor controle
  ## Controleer of het land is opgegeven
  ## Als het niet is opgegeven, stel in op ru
  if ( ! country %in% c('ru', 'ua', 'by', 'kz', 'us') ) {

    # Stuur een aangepaste toetsenbord
    bot$sendMessage(update$message$chat_id, 
                    text = paste0(country, " - onjuiste landcode, mogelijke waarden: ru, by, kz, ua, us. Gevraagd gegevens voor Rusland."),
                    parse_mode = "Markdown")

    country <- 'ru'

  }

  # Vraag gegevens van de API op
  # samenstelling van de HTTP-aanroep
  url <- paste0("https://isdayoff.ru/api/getdata?",
                "year=",  y, "&",
                "month=", m, "&",
                "day=",   d, "&",
                "cc=",    country, "&",
                "pre=1&",
                "covid=1")

  # krijg antwoord
  res <- readLines(url)

  # interpretatie van het antwoord
  out <- switch(res, 
                "0"   = "Werkdag",
                "1"   = "Vrije dag",
                "2"   = "Ingekorte werkdag",
                "4"   = "covid-19",
                "100" = "Fout in de datum",
                "101" = "Gegevens niet gevonden",
                "199" = "Fout van de service")

  # Stuur een bericht
  bot$sendMessage(update$message$chat_id, 
                  text = paste0(day, " - ", out),
                  parse_mode = "Markdown")

}

# Maak een handler
 date_hendler <- CommandHandler('check_date', check_date, pass_args = TRUE)

# Voeg de handler toe aan de dispatcher
updater <- updater + date_hendler

# 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).

We hebben een bot gemaakt die slechts één methode in zijn arsenaal heeft. check_date, deze methode wordt aangeroepen met hetzelfde commando.

Maar naast de naam van het commando verwacht deze methode dat je twee parameters invoert, de landcode en de datum. Vervolgens controleert de bot of de opgegeven dag in het opgegeven land een vrije, ingekorte of werkdag is volgens de officiële arbeidskalender.

Om ervoor te zorgen dat de door ons gemaakte methode extra parameters samen met het commando accepteert, gebruik de argumenten pass_args = TRUE in de functie CommandHandler(), en bij het maken van de methode, naast de verplichte argumenten, bot, update maak een optionele aan — argsDe op deze manier gemaakte methode zal parameters aannemen die je aan de bot doorgeeft na de naam van de opdracht. De parameters moeten door spaties van elkaar worden gescheiden; ze komen in de vorm van een tekstvector in de methode binnen.

Laten we onze bot starten en testen.

Een telegram bot schrijven in R (deel 2): We voegen ondersteuning voor commando's en filters voor berichten toe aan de bot

De bot in de achtergrond uitvoeren

De laatste stap die we nog moeten uitvoeren is de bot op de achtergrond starten.

Volg hiervoor het onderstaande algoritme:

  1. Sla de botcode op in een bestand met de extensie R. In RStudio doe je dit via het menu Bestand, via het commando Opslaan als….
  2. Voeg het pad naar de bin-map toe, die op zijn beurt zich in de map bevindt waar je de R-taal hebt geïnstalleerd, in de Path-variabele. here.
  3. Maak een gewone tekstbestand aan waarin je 1 regel schrijft: R CMD BATCH C:UsersAlseyDocumentsmy_bot.R. In plaats van C:UsersAlseyDocumentsmy_bot.R schrijf je het pad naar jouw botscript. Het is belangrijk dat er geen Cyrillisch schrift of spaties in het pad voorkomen, omdat dit problemen kan veroorzaken bij het starten van de bot. Sla het op en vervang de extensie met txt en een werkende opdracht krijgen. bat.
  4. Open de Windows Taakplanner; er zijn verschillende manieren om dit te doen, bijvoorbeeld door een willekeurige map te openen en het adres in te voeren %windir%system32taskschd.msc /s. Andere manieren om het te starten kun je vinden. here.
  5. Klik in het rechterbovenmenu van de planner op "Taak maken...".
  6. Op het tabblad "Algemeen" geef je een willekeurige naam voor jouw taak op en zet je de schakelaar in de staat "Uitvoeren voor alle gebruikers".
  7. Ga naar het tabblad "Acties", klik op "Maken". In het veld "Programma of script" klik je op "Bladeren", zoek de aanmaak die je in de tweede stap bat hebt gedaan, en klik op OK.
  8. Klik op OK en voer indien nodig het wachtwoord van je gebruikersaccount in het besturingssysteem in.
  9. Zoek de gemaakte taak in de planner, selecteer deze en klik rechtsonder op de knop "Uitvoeren".

Onze bot is op de achtergrond gestart en zal blijven draaien totdat je de taak stopt of je PC of server uitschakelt waarop deze is gestart.

Conclusie

In dit artikel hebben we geleerd hoe we een volledige bot kunnen schrijven die niet alleen berichten kan verzenden, maar ook reageert op binnenkomende berichten en opdrachten. De opgedane kennis is al voldoende om de meeste van jouw taken op te lossen.

In het volgende artikel gaat het erover hoe je een toetsenbord aan de bot kunt toevoegen voor een comfortabeler gebruik.

Abonneer je op mijn telegram en youtube kanalen.

Bron: habr.com

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