Filters¶
Filters decide whether a handler should process an event. Any callable returning a truthy value passes.
Built-in filters¶
Command¶
from fastvk.filters import Command
Command("start") # matches /start
Command("start", "help") # matches /start or /help
Command("ban", prefix="/!") # matches /ban and !ban
Command("buy", prefix="/") # matches /buy
CommandStart / CommandHelp¶
from fastvk.filters import CommandStart, CommandHelp
@bot.message(CommandStart())
async def start_handler(message): ...
@bot.message(CommandHelp())
async def help_handler(message): ...
StateFilter¶
from fastvk.filters import StateFilter
from fastvk.fsm import State, StatesGroup
class Form(StatesGroup):
waiting_name = State()
@bot.message(StateFilter(Form.waiting_name))
async def handler(message, state): ...
# match any non-None state:
@bot.message(StateFilter("*"))
async def any_state_handler(message): ...
Text¶
from fastvk.filters import Text
Text("hello") # exact match
Text("hello", "hi") # any of these
Text(contains="world") # substring match
Text(startswith="!") # prefix match
F — Magic filter¶
F builds lazy filter expressions from attribute access and operators.
Attribute access¶
F.text # message.text
F.from_id # message.from_id
F.payload # callback.payload (dict)
F.payload.vote # callback.payload["vote"]
Comparisons¶
String methods¶
F.text.startswith("/")
F.text.endswith("!")
F.text.contains("vk")
F.text.regexp(r"^\d+$") # regex match (re.search)
Membership¶
Existence¶
Logic¶
~F.text.startswith("/") # NOT
(F.text == "a") | (F.text == "b") # OR
(F.from_id > 0) & F.text.exists() # AND
Custom filters¶
Any callable works:
def is_admin(message: Message, data: dict) -> bool:
return message.from_id in ADMIN_IDS
@bot.message(is_admin)
async def admin_cmd(message): ...
Or a class: