--- title: "Advanced Filters" author: "Ernest Benedito" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Advanced Filters} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` This vignette describes advanced use cases for the filters used with `MessageHandler` or `CommandHandler`. ## Combining filters When using `MessageHandler` it is sometimes useful to have more than one filter. This can be done using so called binary operators. Using `telegram.bot`, you can operate `BaseFilter` instances with `&`, `|` and `!` meaning AND, OR and NOT respectively. ### Examples #### Message is either video, photo, or document (generic file) ```{r, eval = FALSE} handler <- MessageHandler(callback, MessageFilters$video | MessageFilters$photo | MessageFilters$document ) ``` #### Message is a forwarded photo ```{r, eval = FALSE} handler <- MessageHandler(callback, MessageFilters$forwarded & MessageFilters$photo ) ``` #### Message is a photo and it's not forwarded ```{r, eval = FALSE} handler <- MessageHandler(callback, MessageFilters$photo & (!MessageFilters$forwarded) ) ``` ## Custom filters It is also possible to write your own filters used with `MessageHandler` and `CommandHandler`. In essence, a filter is simply a function that receives a `Message` instance and returns either `TRUE` or `FALSE`. This function has to be implemented in a new class that inherits from `BaseFilter`, which allows it to be combined with other filters. If a filter evaluates to `TRUE`, the message will be handled. ### Examples #### Restricting users Say that for the `kill` example we saw in the [previous page](https://github.com/ebeneditos/telegram.bot/wiki/Basic-Functionalities#stopping-the-bot), we would like to filter that command so to make it accessible only for a specific `USER_ID`. Thereby, you could add a filter: ```{r, eval = FALSE} filter_user <- function(message) message$from_user == "USER_ID" ``` You can make the function an instance of `BaseFilter` either with its generator: ```{r, eval = FALSE} filter_user <- BaseFilter(filter = filter_user) ``` Or by coercing it with `as.BaseFilter`: ```{r, eval = FALSE} filter_user <- as.BaseFilter(function(message) message$from_user == "USER_ID") ``` Remember that to make it work, your filter must be a `function` that takes a `message` as input and returns a boolean: `TRUE` if the message should be handled, `FALSE` otherwise. Now, you could update the handler with this filter: ```{r, eval = FALSE} kill_handler <- CommandHandler("kill", kill, filter_user) ``` #### Text or command filter Filters can also be added to the `MessageFilters` object. Within it, we can see that `MessageFilters$text` and `MessageFilters$command` are mutually exclusive, so we could add a filter for messages that can be either one of them. This would result as: ```{r, eval = FALSE} MessageFilters$text_or_command <- BaseFilter(function(message) { !is.null(message$text)) } ``` The class can of cause be named however you want, the only important things are: - The class has to inherit from `BaseFilter`. - It has to implement a `filter` method. - The filter must be a `function` that takes a `message` as input and returns a boolean. The filter can then be used as: ```{r, eval = FALSE} handler <- MessageHandler(callback, MessageFilters$text_or_command) ```