--- title: "Basic Functionalities" author: "Ernest Benedito" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Basic Functionalities} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` In the *Introduction* we saw how to build a Telegram Bot with R. However, it can now only answer to the `/start` command, so now we are going to add a couple of functionalities, including: - Text responses - Commands with arguments - Unknown command handling - Stopping the Bot ### Text responses Let's add another handler that listens for regular messages. Use the `MessageHandler`, another `Handler` subclass, to echo to all text messages: ```{r, eval = FALSE} echo <- function(bot, update){ bot$sendMessage(chat_id = update$message$chat_id, text = update$message$text) } updater <- updater + MessageHandler(echo, MessageFilters$text) ``` From now on, your bot should echo all non-command messages it receives. **Note:** As soon as you add new handlers to the `updaters`'s `dispatcher` (done with the `+` operator), they are in effect. **Note:** The `MessageFilters` object contains a number of functions that filter incoming messages for text, images, status updates and more. Any message that returns `TRUE` for at least one of the filters passed to `MessageHandler` will be accepted. You can also write your own filters if you want. ### Commands with arguments Let's add some actual functionality to your bot. We want to implement a `/caps` command that will take some text as an argument and reply to it in CAPS. To make things easy, you can receive the arguments (as a `vector`, split on spaces) that were passed to a command in the callback function: ```{r, eval = FALSE} caps <- function(bot, update, args){ if (length(args > 0L)){ text_caps <- toupper(paste(args, collapse = " ")) bot$sendMessage(chat_id = update$message$chat_id, text = text_caps) } } updater <- updater + CommandHandler("caps", caps, pass_args = TRUE) ``` **Note:** Take a look at the `pass_args = TRUE` in the `CommandHandler` initiation. This is required to let the handler know that you want it to pass the list of command arguments to the callback. All handler classes have keyword arguments like this. Some are the same among all handlers, some are specific to the handler class. If you use a new type of handler for the first time, look it up in the docs and see if one of them is useful to you. ### Unknown command handling Not bad! However, some confused users might try to send commands to the bot that it doesn't understand, so you can use a `MessageHandler` with a `command` filter to reply to all commands that were not recognized by the previous handlers. ```{r, eval = FALSE} unknown <- function(bot, update){ bot$sendMessage(chat_id = update$message$chat_id, text = "Sorry, I didn't understand that command.") } updater <- updater + MessageHandler(unknown, MessageFilters$command) ``` ### Stopping the Bot If you're done playing around, you can stop the Bot either by using the the `interrupt R` command in the session menu (in *RStudio* you can press the `STOP` button) or by calling the `updater$stop_polling()` method. Below we will define a command that uses this method: ```{r, eval = FALSE} # Example of a 'kill' command kill <- function(bot, update){ bot$sendMessage(chat_id = update$message$chat_id, text = "Bye!") # Clean 'kill' update bot$getUpdates(offset = update$update_id + 1L) # Stop the updater polling updater$stop_polling() } updater <<- updater + CommandHandler("kill", kill) ``` Now you can send the command `/kill` from Telegram to stop the Bot. However, in a production environment it wouldn't be recommendable to leave this command as it is now, as anyone could stop the bot. To solve this, you can create a customized filter in order to make this command available only for a certain `user_id`, for instance. This is explained in the next section. **Note:** With the [*superassignment* operator `<<-`](https://stat.ethz.ch/pipermail/r-help/2011-April/275905.html) we assign the `updater` in the enclosing environment so to call it from inside the `kill` function.