Browse Source

[commands] Add support for registering more than one event listener.

pull/77/merge
Rapptz 9 years ago
parent
commit
c06dbbd1f0
  1. 93
      discord/ext/commands/bot.py

93
discord/ext/commands/bot.py

@ -66,6 +66,9 @@ class Bot(GroupMixin, discord.Client):
def __init__(self, command_prefix, **options):
super().__init__(**options)
self.command_prefix = command_prefix
self.extra_events = {}
# internal helpers
def _get_variable(self, name):
stack = inspect.stack()
@ -81,6 +84,28 @@ class Bot(GroupMixin, discord.Client):
else:
return prefix
@asyncio.coroutine
def _run_extra(self, coro, event_name, *args, **kwargs):
try:
yield from coro(*args, **kwargs)
except asyncio.CancelledError:
pass
except Exception:
try:
yield from self.on_error(event_name, *args, **kwargs)
except asyncio.CancelledError:
pass
def dispatch(self, event_name, *args, **kwargs):
super().dispatch(event_name, *args, **kwargs)
ev = 'on_' + event_name
if ev in self.extra_events:
for event in self.extra_events[ev]:
coro = self._run_extra(event, event_name, *args, **kwargs)
discord.utils.create_task(coro, loop=self.loop)
# utility "send_*" functions
@asyncio.coroutine
def say(self, content):
"""|coro|
@ -179,6 +204,74 @@ class Bot(GroupMixin, discord.Client):
destination = self._get_variable('_internal_channel')
yield from self.send_typing(destination)
# listener registration
def add_listener(self, func, name=None):
"""The non decorator alternative to :meth:`listen`.
Parameters
-----------
func : coroutine
The extra event to listen to.
name : Optional[str]
The name of the command to use. Defaults to ``func.__name__``.
Examples
---------
.. code-block:: python
async def on_ready(): pass
async def my_message(message): pass
bot.add_listener(on_ready)
bot.add_listener(my_message, 'on_message')
"""
name = func.__name__ if name is None else name
if not asyncio.iscoroutinefunction(func):
func = asyncio.coroutine(func)
if name in self.extra_events:
self.extra_events[name].append(func)
else:
self.extra_events[name] = [func]
def listen(self, name=None):
"""A decorator that registers another function as an external
event listener. Basically this allows you to listen to multiple
events from different places e.g. such as :func:`discord.on_ready`
If the function being listened to is not a coroutine, it makes it into
a coroutine a la :meth:`Client.async_event`.
Examples
---------
.. code-block:: python
@bot.listen
async def on_message(message):
print('one')
# in some other file...
@bot.listen('on_message')
async def my_message(message):
print('two')
Would print one and two in an unspecified order.
"""
def decorator(func):
self.add_listener(func, name)
return func
return decorator
# command processing
@asyncio.coroutine
def process_commands(self, message):
"""|coro|

Loading…
Cancel
Save