Filters

Filters control which messages trigger which handlers. They are composable, reusable predicates that you pass to @client.on_message().

Built-in filters

Using filters

Pass a filter as the argument to @client.on_message():

from astra import Filters

@client.on_message(Filters.command(".help"))
async def help_cmd(msg):
 await msg.respond("Here's the help text...")

@client.on_message(Filters.text_contains("thanks"))
async def thanks(msg):
 await msg.react("❤️")

Combining filters

Filters can be combined with & (AND), | (OR), and ~ (NOT):

# Only group messages that start with .admin
@client.on_message(Filters.is_group & Filters.command(".admin"))
async def admin_in_group(msg):
 ...

# Private messages OR messages from me
@client.on_message(Filters.is_private | Filters.from_me)
async def private_or_self(msg):
 ...

# Any message that is NOT from me
@client.on_message(~Filters.from_me)
async def from_others(msg):
 ...

Command filter details

Filters.command(prefix) checks if the message text starts with the given prefix string. It is case-sensitive and matches from the beginning:

Filters.command(".ping") # matches ".ping", ".ping extra args"
Filters.command("!ban")  # matches "!ban user123"

To extract the argument after the command:

@client.on_message(Filters.command(".say"))
async def say(msg):
 # msg.text is ".say Hello world"
 args = msg.text.split(None, 1)
 text = args[1] if len(args) > 1 else ""
 await msg.respond(text)

Regex filter

Filters.regex(pattern) compiles a regular expression and matches it against the full message body:

import re

@client.on_message(Filters.regex(r"(?i)good\s*(morning|evening)"))
async def greeting(msg):
 await msg.respond("Hey, good to see you!")

Catch-all

Filters.all matches every single message. Useful for logging:

@client.on_message(Filters.all)
async def log_all(msg):
 print(f"[{msg.chat_id}] {msg.sender}: {msg.text}")