@@ -71,6 +71,8 @@ class BaseCommand(object): | |||||
Given a Data() instance, return True if we should respond to this | Given a Data() instance, return True if we should respond to this | ||||
activity, or False if we should ignore it or it doesn't apply to us. | activity, or False if we should ignore it or it doesn't apply to us. | ||||
Be aware that since this is called for each message sent on IRC, it | |||||
should not be cheap to execute and unlikely to throw exceptions. | |||||
Most commands return True if data.command == self.name, otherwise they | Most commands return True if data.command == self.name, otherwise they | ||||
return False. This is the default behavior of check(); you need only | return False. This is the default behavior of check(); you need only | ||||
@@ -97,6 +99,10 @@ class CommandManager(object): | |||||
self._commands = {} | self._commands = {} | ||||
self._command_access_lock = Lock() | self._command_access_lock = Lock() | ||||
def __iter__(self): | |||||
for name in self._commands: | |||||
yield name | |||||
def _load_command(self, name, path): | def _load_command(self, name, path): | ||||
"""Load a specific command from a module, identified by name and path. | """Load a specific command from a module, identified by name and path. | ||||
@@ -148,10 +154,6 @@ class CommandManager(object): | |||||
commands = ", ".join(self._commands.keys()) | commands = ", ".join(self._commands.keys()) | ||||
self.logger.info(msg.format(len(self._commands), commands)) | self.logger.info(msg.format(len(self._commands), commands)) | ||||
def get_all(self): | |||||
"""Return our dict of all loaded commands.""" | |||||
return self._commands | |||||
def check(self, hook, data): | def check(self, hook, data): | ||||
"""Given an IRC event, check if there's anything we can respond to.""" | """Given an IRC event, check if there's anything we can respond to.""" | ||||
with self._command_access_lock: | with self._command_access_lock: | ||||
@@ -164,3 +166,10 @@ class CommandManager(object): | |||||
e = "Error executing command '{0}':" | e = "Error executing command '{0}':" | ||||
self.logger.exception(e.format(data.command)) | self.logger.exception(e.format(data.command)) | ||||
break | break | ||||
def get(self, command_name): | |||||
"""Return the class instance associated with a certain command name. | |||||
Will raise KeyError if the command is not found. | |||||
""" | |||||
return self._command[command_name] |
@@ -30,7 +30,6 @@ class Command(BaseCommand): | |||||
name = "help" | name = "help" | ||||
def process(self, data): | def process(self, data): | ||||
self.cmnds = self.bot.commands.get_all() | |||||
if not data.args: | if not data.args: | ||||
self.do_main_help(data) | self.do_main_help(data) | ||||
else: | else: | ||||
@@ -39,7 +38,7 @@ class Command(BaseCommand): | |||||
def do_main_help(self, data): | def do_main_help(self, data): | ||||
"""Give the user a general help message with a list of all commands.""" | """Give the user a general help message with a list of all commands.""" | ||||
msg = "Hi, I'm a bot! I have {0} commands loaded: {1}. You can get help for any command with '!help <command>'." | msg = "Hi, I'm a bot! I have {0} commands loaded: {1}. You can get help for any command with '!help <command>'." | ||||
cmnds = sorted(self.cmnds.keys()) | |||||
cmnds = sorted(self.bot.commands) | |||||
msg = msg.format(len(cmnds), ', '.join(cmnds)) | msg = msg.format(len(cmnds), ', '.join(cmnds)) | ||||
self.connection.reply(data, msg) | self.connection.reply(data, msg) | ||||
@@ -53,13 +52,14 @@ class Command(BaseCommand): | |||||
dummy.command = command.lower() | dummy.command = command.lower() | ||||
dummy.is_command = True | dummy.is_command = True | ||||
for cmnd in self.cmnds.values(): | |||||
for cmnd_name in self.bot.commands: | |||||
cmnd = self.bot.commands.get(cmnd_name) | |||||
if not cmnd.check(dummy): | if not cmnd.check(dummy): | ||||
continue | continue | ||||
if cmnd.__doc__: | if cmnd.__doc__: | ||||
doc = cmnd.__doc__.replace("\n", "") | doc = cmnd.__doc__.replace("\n", "") | ||||
doc = re.sub("\s\s+", " ", doc) | doc = re.sub("\s\s+", " ", doc) | ||||
msg = "info for command \x0303{0}\x0301: \"{1}\"" | |||||
msg = "help for command \x0303{0}\x0301: \"{1}\"" | |||||
self.connection.reply(data, msg.format(command, doc)) | self.connection.reply(data, msg.format(command, doc)) | ||||
return | return | ||||
break | break | ||||
@@ -103,13 +103,9 @@ class Command(BaseCommand): | |||||
def do_listall(self): | def do_listall(self): | ||||
"""With !tasks listall or !tasks all, list all loaded tasks, and report | """With !tasks listall or !tasks all, list all loaded tasks, and report | ||||
whether they are currently running or idle.""" | whether they are currently running or idle.""" | ||||
all_tasks = self.bot.tasks.get_all().keys() | |||||
threads = threading.enumerate() | threads = threading.enumerate() | ||||
tasklist = [] | tasklist = [] | ||||
all_tasks.sort() | |||||
for task in all_tasks: | |||||
for task in sorted(self.bot.tasks): | |||||
threadlist = [t for t in threads if t.name.startswith(task)] | threadlist = [t for t in threads if t.name.startswith(task)] | ||||
ids = [str(t.ident) for t in threadlist] | ids = [str(t.ident) for t in threadlist] | ||||
if not ids: | if not ids: | ||||
@@ -144,9 +140,9 @@ class Command(BaseCommand): | |||||
self.connection.reply(data, msg) | self.connection.reply(data, msg) | ||||
return | return | ||||
if task_name not in self.bot.tasks.get_all().keys(): | |||||
if task_name not in self.bot.tasks: | |||||
# This task does not exist or hasn't been loaded: | # This task does not exist or hasn't been loaded: | ||||
msg = "task could not be found; either tasks/{0}.py doesn't exist, or it wasn't loaded correctly." | |||||
msg = "task could not be found; either it doesn't exist, or it wasn't loaded correctly." | |||||
self.connection.reply(data, msg.format(task_name)) | self.connection.reply(data, msg.format(task_name)) | ||||
return | return | ||||
@@ -139,6 +139,10 @@ class TaskManager(object): | |||||
self._tasks = {} | self._tasks = {} | ||||
self._task_access_lock = Lock() | self._task_access_lock = Lock() | ||||
def __iter__(self): | |||||
for name in self._tasks: | |||||
yield name | |||||
def _wrapper(self, task, **kwargs): | def _wrapper(self, task, **kwargs): | ||||
"""Wrapper for task classes: run the task and catch any errors.""" | """Wrapper for task classes: run the task and catch any errors.""" | ||||
try: | try: | ||||
@@ -239,7 +243,3 @@ class TaskManager(object): | |||||
Will raise KeyError if the task is not found. | Will raise KeyError if the task is not found. | ||||
""" | """ | ||||
return self._tasks[task_name] | return self._tasks[task_name] | ||||
def get_all(self): | |||||
"""Return our dict of all loaded tasks.""" | |||||
return self._tasks |