Better Event Handling¶
Curious comes with several ways to fine-tune your event handling in your bot.
Note
A full list of events can be found at Event reference.
Basic Event Listeners¶
Basic event listeners are the easiest way to handle events coming in from the bot. All event
listeners take a EventContext
as their first argument, and various other arguments
depending on the event.
# simple client event
@client.event("guild_member_add")
async def member_joined(ctx, member: Member):
print("Member", member.name, "joined!")
Basic event listeners can also be inside plugins:
from curious import event
class MyPlugin(Plugin):
@event("guild_member_add")
async def member_joined(self, ctx, member: Member):
print("Member", member.name, "joined!")
You can also add them manually to the event manager, but you must decorate them with the
event()
decorator.
from curious import event
@event("guild_member_add")
async def member_joined(ctx, member: Member):
print("Member", member.name, "joined!")
client.events.add_event(member_join)
The event decorator sets some attributes on on the function object that are introspected to register the event handler.
Finally, you can have multiple events on one function, but this is usually discouraged in favour of Event Hooks.
@event("ready")
@event("connect")
async def my_function(ctx): ...
Temporary Listeners¶
Temporary listeners are a way of listening to an event temporarily until a condition happens. This is used to implement waiting for a specific event, for example.
A listener is roughly the same as an event handler, but only sticks around for a short while; that is, until it either raises an exception (which is logged) or it raises ListenerExit. Either one will remove it from the list of temporary listeners; and it will not get any more events.
To add a listener, you can use EventManager.add_temporary_listener()
:
# example: adding messages to a queue until STOP is sent
async def message_listener(ctx, message: Message):
if message.content == "STOP":
raise ListenerExit
await my_queue.add(message)
client.events.add_temporary_listener("message_create", message_listener)
If you wish to remove a listener early, then you can do so with
EventManager.remove_listener_early()
; however, it is probably better to use ListenerExit
appropriately.
Waiting For Events¶
Waiting for events from the websocket is a common usecase; curious provides some helper methods to allow waiting for these events easily.
EventManager.wait_for()
allows waiting for an event based on a predicate.EventManager.wait_for_manager()
is a context-manager version ofwait_for
.
Both of these methods take an event name to listen to, and a predicate that should return
True/False based on if this is an event you want. The return result of wait_for
is the normal
arguments provided to the event, without the EventContext
.
pred = lambda message: message.content == "STOP"
stop_message = await client.wait_for("message_create", pred) # shortcut for EventManager
EventManager.wait_for_manager()
is not often useful inside user code.
Event Hooks¶
The final way of managing events is with event hooks. These are hooks that are called upon every
single event fired by the event manager, and can be useful for sub-dispatchers that filter events.
To register an event hook, use EventManager.add_event_hook()
.
async def my_hook(ctx: EventContext, *args):
if ctx.event_name.startswith("guild_"):
# do something
client.events.add_event_hook(my_hook)
Warning
An event hook crashing will bring down the entire bot. Be warned.