There is no mechanism for waiting on a specific future event that matches a condition. Every feature that requires listening for a follow-up event, a confirmation reply, an expected reaction, the next message from a specific user, must wire up and tear down its own event listener manually. The planned Dialog feature would need to solve this too, and doing it twice would produce two diverging implementations.
The idea is to add bot.wait_for(event_type, check=..., timeout=...) which suspends the caller until a matching event arrives. It would register a one-shot waiter internally, resolve it when the condition passes, and cancel it when the timeout expires. Dialog's ctx.ask would then be a thin wrapper over this rather than its own mechanism.
Proposed API
# Wait for any message in the same room from the same sender
message = await bot.wait_for(
"on_message",
check=lambda room, event: event.sender == ctx.sender and room.room_id == ctx.room.room_id,
timeout=30.0,
)
# Wait for a specific reaction on a message
reaction = await bot.wait_for(
"on_react",
check=lambda room, event: event.reacted_to_id == msg.event_id,
timeout=60.0,
)
The implementation sits in _on_matrix_event / _dispatch_matrix_event in bot.py. A dict[str, list[asyncio.Future]] of pending waiters keyed by event name would work cleanly alongside the existing _event_handlers. Each waiter is an asyncio.Future paired with its check callable; when an event fires, the bot walks the waiter list, resolves any future whose check passes, and removes it. Timeout is handled by asyncio.wait_for on the caller side. The main edge case is concurrent waiters for the same event type (e.g. two dialogs running in parallel in different rooms), the list must not be mutated while being iterated, so a copy-on-iterate or deferred-removal strategy is needed.
There is no mechanism for waiting on a specific future event that matches a condition. Every feature that requires listening for a follow-up event, a confirmation reply, an expected reaction, the next message from a specific user, must wire up and tear down its own event listener manually. The planned Dialog feature would need to solve this too, and doing it twice would produce two diverging implementations.
The idea is to add
bot.wait_for(event_type, check=..., timeout=...)which suspends the caller until a matching event arrives. It would register a one-shot waiter internally, resolve it when the condition passes, and cancel it when the timeout expires. Dialog'sctx.askwould then be a thin wrapper over this rather than its own mechanism.Proposed API
The implementation sits in
_on_matrix_event/_dispatch_matrix_eventinbot.py. Adict[str, list[asyncio.Future]]of pending waiters keyed by event name would work cleanly alongside the existing_event_handlers. Each waiter is anasyncio.Futurepaired with its check callable; when an event fires, the bot walks the waiter list, resolves any future whose check passes, and removes it. Timeout is handled byasyncio.wait_foron the caller side. The main edge case is concurrent waiters for the same event type (e.g. two dialogs running in parallel in different rooms), the list must not be mutated while being iterated, so a copy-on-iterate or deferred-removal strategy is needed.