Author: Ernest Benedito
Date: 2025-10-26

# Advanced Filters

#### Ernest Benedito

#### 2025-10-26

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)

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

#### Message is a forwarded photo

    handler <- MessageHandler(
      callback,
      MessageFilters$forwarded & MessageFilters$photo
    )

#### Message is a photo and it’s not forwarded

    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, we would like to filter that command so to make it accessible only for a specific `USER_ID`. Thereby, you could add a filter:

    filter_user <- function(message) message$from_user == "USER_ID"

You can make the function an instance of `BaseFilter` either with its generator:

    filter_user <- BaseFilter(filter = filter_user)

Or by coercing it with `as.BaseFilter`:

    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:

    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:

    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:

    handler <- MessageHandler(callback, MessageFilters$text_or_command)