[commands] Add support for registering more than one event listener.
This commit is contained in:
		| @@ -66,6 +66,9 @@ class Bot(GroupMixin, discord.Client): | |||||||
|     def __init__(self, command_prefix, **options): |     def __init__(self, command_prefix, **options): | ||||||
|         super().__init__(**options) |         super().__init__(**options) | ||||||
|         self.command_prefix = command_prefix |         self.command_prefix = command_prefix | ||||||
|  |         self.extra_events = {} | ||||||
|  |  | ||||||
|  |     # internal helpers | ||||||
|  |  | ||||||
|     def _get_variable(self, name): |     def _get_variable(self, name): | ||||||
|         stack = inspect.stack() |         stack = inspect.stack() | ||||||
| @@ -81,6 +84,28 @@ class Bot(GroupMixin, discord.Client): | |||||||
|         else: |         else: | ||||||
|             return prefix |             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 |     @asyncio.coroutine | ||||||
|     def say(self, content): |     def say(self, content): | ||||||
|         """|coro| |         """|coro| | ||||||
| @@ -179,6 +204,74 @@ class Bot(GroupMixin, discord.Client): | |||||||
|         destination = self._get_variable('_internal_channel') |         destination = self._get_variable('_internal_channel') | ||||||
|         yield from self.send_typing(destination) |         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 |     @asyncio.coroutine | ||||||
|     def process_commands(self, message): |     def process_commands(self, message): | ||||||
|         """|coro| |         """|coro| | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user