📥 Listeners#

When handling updates, most of the time you ask the user for input (e.g. a reply, text, button press, etc.). This is where listeners come in. With listeners, you can create an inline handler that waits for a specific user input and returns the result.

Listen#

Let’s see an example of how to use a listener:

 1from pywa import WhatsApp, types, filters
 2
 3wa = WhatsApp(...)
 4
 5@wa.on_message(filters.command("start"))
 6def start(client: WhatsApp, msg: types.Message):
 7    msg.reply("Hello! How old are you?")
 8    age: types.Message = client.listen( # Now we want to wait for the user to send their age
 9        to=msg.sender,
10        filters=filters.message & filters.text # We only want to listen for `Message` updates that contain text
11    )
12    msg.reply(f"Your age is {age.text}.")

In the example above, we are waiting for the user to send their age. The client.listen method will wait for the user to send a message that matches the filter pywa.filters.text.

Tip

You can use one of the shortcuts in order to create a listener when sending a message. For example, you can use the wait_for_reply() method to create a listener that waits for a Message reply from the user.

Cancel#

Now, listeners have a few options that you can use to customize the behavior. for example, you can set a timeout for the listener, or cancel the listener if the user sends a specific message. let’s see an example:

 1from pywa import WhatsApp, types, filters
 2
 3wa = WhatsApp(...)
 4
 5@wa.on_message(filters.command("start"))
 6def start(client: WhatsApp, msg: types.Message):
 7    msg.reply(
 8        text="Hello! How old are you?",
 9        buttons=[types.Button("Cancel", callback_data="cancel")]
10    )
11    age = client.listen(
12        to=msg.sender,
13        filters=filters.message & filters.text,
14        timeout=20, # 20 seconds
15        # If the user presses "cancel" the listener will be canceled
16        cancelers=filters.callback_button & filters.matches("cancel")
17    )
18    msg.reply(f"Your age is {age.text}.")

In the example above, we added a button to the message that the user can press to cancel the listener. The listener will be canceled if the user sends a message that matches the filter filters.callback_button & filters.matches("cancel").

Handle cancel and timeout#

You can also handle listener exceptions. For example, you can handle the case when the listener times out or when the listener is canceled. Let’s see an example:

 1from pywa import WhatsApp, types, filters, listeners
 2
 3wa = WhatsApp(...)
 4
 5@wa.on_message(filters.command("start"))
 6def start(client: WhatsApp, msg: types.Message):
 7    msg.reply("Hello! Please send me your age.", buttons=[types.Button("Cancel", callback_data="cancel")])
 8
 9    try:
10        age = client.listen(
11            to=msg.sender,
12            filters=filters.message & filters.text,
13            cancelers=filters.callback_button & filters.matches("cancel"),
14            timeout=20
15        )
16        msg.reply(f"Your age is {age.text}.")
17    except ListenerTimeout:
18        msg.reply("You took too long to send your age.")
19    except ListenerCanceled:
20        msg.reply("You canceled the operation.")

In the example above, we added a try-except block to handle the listener exceptions. If the listener times out, the ListenerTimeout exception will be raised. If the listener is canceled, the ListenerCanceled exception will be raised.

Shortcuts#

PyWa also provides a few shortcuts to create listeners when sending messages. Let’s see an example:

1from pywa import WhatsApp, types, filters
2
3wa = WhatsApp(...)
4
5@wa.on_message(filters.command("start"))
6def start(client: WhatsApp, msg: types.Message):
7    age: types.Message = m.reply("Hello! How old are you?").wait_for_reply(filters.text)
8    m.reply(f"You are {age.text} years old")

In the example above, we used the wait_for_reply() method to create a listener that waits for a text reply from the user.

1from pywa import WhatsApp, types, filters
2
3wa = WhatsApp(...)
4
5@wa.on_message(filters.command("start"))
6def start(client: WhatsApp, msg: types.Message):
7    msg.reply(f"Hello {msg.from_user.name}!").wait_until_delivered()
8    msg.reply("How can I help you?")

In the example above, we used the wait_until_delivered() method to create a listener that waits until the message is delivered to the user.

Other shortcuts are available, such as wait_for_click(), wait_for_selection(), wait_until_read(), and more.