aboutsummaryrefslogtreecommitdiff
path: root/discord/ext/commands/bot.py
diff options
context:
space:
mode:
Diffstat (limited to 'discord/ext/commands/bot.py')
-rw-r--r--discord/ext/commands/bot.py110
1 files changed, 106 insertions, 4 deletions
diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py
index 5387df1a..fbdaa75a 100644
--- a/discord/ext/commands/bot.py
+++ b/discord/ext/commands/bot.py
@@ -28,7 +28,7 @@ import asyncio
import discord
import inspect
-from .core import GroupMixin
+from .core import GroupMixin, Command
from .view import StringView
from .context import Context
from .errors import CommandNotFound
@@ -67,6 +67,7 @@ class Bot(GroupMixin, discord.Client):
super().__init__(**options)
self.command_prefix = command_prefix
self.extra_events = {}
+ self.cogs = {}
# internal helpers
@@ -231,20 +232,40 @@ class Bot(GroupMixin, discord.Client):
name = func.__name__ if name is None else name
if not asyncio.iscoroutinefunction(func):
- func = asyncio.coroutine(func)
+ raise discord.ClientException('Listeners must be coroutines')
if name in self.extra_events:
self.extra_events[name].append(func)
else:
self.extra_events[name] = [func]
+ def remove_listener(self, func, name=None):
+ """Removes a listener from the pool of listeners.
+
+ Parameters
+ -----------
+ func
+ The function that was used as a listener to remove.
+ name
+ The name of the event we want to remove. Defaults to
+ ``func.__name__``.
+ """
+
+ name = func.__name__ if name is None else name
+
+ if name in self.extra_events:
+ try:
+ self.extra_events[name].remove(func)
+ except ValueError:
+ pass
+
+
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`.
+ The functions being listened to must be a coroutine.
Examples
---------
@@ -262,6 +283,11 @@ class Bot(GroupMixin, discord.Client):
print('two')
Would print one and two in an unspecified order.
+
+ Raises
+ -------
+ discord.ClientException
+ The function being listened to is not a coroutine.
"""
def decorator(func):
@@ -270,6 +296,82 @@ class Bot(GroupMixin, discord.Client):
return decorator
+ # cogs
+
+ def add_cog(self, cog):
+ """Adds a "cog" to the bot.
+
+ A cog is a class that has its own event listeners and commands.
+
+ They are meant as a way to organize multiple relevant commands
+ into a singular class that shares some state or no state at all.
+
+ More information will be documented soon.
+
+ Parameters
+ -----------
+ cog
+ The cog to register to the bot.
+ """
+
+ self.cogs[type(cog).__name__] = cog
+ members = inspect.getmembers(cog)
+ for name, member in members:
+ # register commands the cog has
+ if isinstance(member, Command):
+ member.instance = cog
+ if member.parent is None:
+ self.add_command(member)
+ continue
+
+ # register event listeners the cog has
+ if name.startswith('on_'):
+ self.add_listener(member)
+
+ def get_cog(self, name):
+ """Gets the cog instance requested.
+
+ If the cog is not found, ``None`` is returned instead.
+
+ Parameters
+ -----------
+ name : str
+ The name of the cog you are requesting.
+ """
+ return self.cogs.get(name)
+
+ def remove_cog(self, name):
+ """Removes a cog the bot.
+
+ All registered commands and event listeners that the
+ cog has registered will be removed as well.
+
+ If no cog is found then ``None`` is returned, otherwise
+ the cog instance that is being removed is returned.
+
+ Parameters
+ -----------
+ name : str
+ The name of the cog to remove.
+ """
+
+ cog = self.cogs.pop(name, None)
+ if cog is None:
+ return cog
+
+ members = inspect.getmembers(cog)
+ for name, member in members:
+ # remove commands the cog has
+ if isinstance(member, Command):
+ member.instance = None
+ if member.parent is None:
+ self.remove_command(member.name)
+ continue
+
+ # remove event listeners the cog has
+ if name.startswith('on_'):
+ self.remove_listener(member)
+
# command processing
@asyncio.coroutine