🔬 Filters#
Filters are conditions that decide whether an incoming update should be handled or ignored. Pass them to any handler and pywa will only call your callback when the filter matches.
The library ships with a wide range of built-in filters in the pywa.filters module,
and you can write your own in a single function.
Basic Usage#
from pywa import WhatsApp, types, filters
wa = WhatsApp(...)
@wa.on_message(filters.startswith("Hello", "Hi", ignore_case=True))
def handle_hello(wa: WhatsApp, msg: types.Message):
msg.react("👋")
msg.reply(
f"Hello {msg.from_user.name}!",
buttons=[types.Button("Click me!", "click")]
)
@wa.on_callback_button(filters.matches("click"))
def handle_click(wa: WhatsApp, clb: types.CallbackButton):
clb.reply("You clicked me!")
Combining Filters#
Filters can be combined with logical operators:
&→ and|→ or~→ not
from pywa import filters
# image with caption
filters.image & filters.has_caption
# text or image
filters.text | filters.image
# message must not contain "bad word"
~filters.contains("bad word")
Tip
All match-filters (matches(), contains() etc.) return True if any of the given options match.
So instead of writing:
filters.matches("hello") | filters.matches("hi")
You can simply write:
filters.matches("hello", "hi")
Custom Filters#
Write a function that accepts the client and the update, and returns a boolean.
True means the handler runs; False means the update is skipped.
Note
Custom filters must be wrapped with
pywa.filters.new().You can combine custom and built-in filters using logical operators.
Async functions can be used as filters only with the async client.
from pywa import WhatsApp, types, filters
def without_xyz_filter(_: WhatsApp, msg: types.Message) -> bool:
return msg.text and "xyz" not in msg.text
wa = WhatsApp(...)
@wa.on_message(filters.new(without_xyz_filter))
def messages_without_xyz(wa: WhatsApp, msg: types.Message):
msg.reply("You said something without xyz!")
# Or inline with a lambda — combine with built-in filters:
@wa.on_message(filters.text & filters.new(lambda _, msg: "xyz" not in msg.text))
def messages_without_xyz(wa: WhatsApp, msg: types.Message):
msg.reply("You said something without xyz!")
Built-in Filters#
- Common filters
new()filters.messagefilters.callback_buttonfilters.callback_selectionfilters.message_statusfilters.flow_completionfilters.call_connectfilters.call_terminatefilters.call_statusfilters.call_permission_updatefilters.user_marketing_preferencesfilters.template_statusfilters.template_categoryfilters.template_qualityfilters.template_componentsfilters.phone_number_changefilters.identity_changefilters.account_updatefilters.privatefilters.groupsent_to()update_id()waba_id()filters.sent_to_mefrom_users()without_wa_id()from_countries()matches()contains()startswith()endswith()regex()
- Message Filters
filters.forwardedfilters.forwarded_many_timesfilters.replyreplays_to()filters.has_referred_productfilters.textfilters.is_commandcommand()filters.mediamimetypes()extensions()filters.has_captionfilters.imagefilters.videofilters.audiofilters.audio_onlyfilters.voicefilters.documentfilters.stickerfilters.animated_stickerfilters.static_stickerfilters.reactionfilters.reaction_addedfilters.reaction_removedreaction_emojis()filters.unsupportedfilters.locationfilters.current_locationlocation_in_radius()filters.contactsfilters.contact_info_sharedfilters.contacts_has_wafilters.order
- Message Status Filters
- Account Update Filters
filters.account_deletedfilters.account_restrictionfilters.account_violationfilters.ad_account_linkedfilters.auth_intl_price_eligibility_updatefilters.business_primary_location_country_updatefilters.account_disabledfilters.partner_addedfilters.partner_app_installedfilters.partner_app_uninstalledfilters.partner_client_certification_status_updatefilters.partner_removedfilters.volume_based_pricing_tier_updatefilters.account_offboardedfilters.account_reconnected
- Calls Filters