# -*- coding: utf-8 -*- """ EarwigBot's IRC Command Manager This package provides the IRC "commands" used by the bot's front-end component. In __init__, you can find some functions used to load and run these commands. """ import logging import os import sys from classes import BaseCommand import config __all__ = ["load", "get_all", "check"] # Base directory when searching for commands: base_dir = os.path.join(config.root_dir, "bot", "commands") # Store commands in a dict, where the key is the command's name and the value # is an instance of the command's class: _commands = {} # Logger for this module: logger = logging.getLogger("tasks") def _load_command(connection, filename): """Try to load a specific command from a module, identified by file name. Given a Connection object and a filename, we'll first try to import it, and if that works, make an instance of the 'Command' class inside (assuming it is an instance of BaseCommand), add it to _commands, and report the addition to the user. Any problems along the way will either be ignored or reported. """ global _commands # Strip .py from the end of the filename and join with our package name: name = ".".join(("commands", filename[:-3])) try: __import__(name) except: logger.exception("Couldn't load file {0}".format(filename)) return command = sys.modules[name].Command(connection) if not isinstance(command, BaseCommand): return _commands[command.name] = command logger.debug("Added command {0}".format(command.name)) def load(connection): """Load all valid commands into the _commands global variable. `connection` is a Connection object that is given to each command's constructor. """ files = os.listdir(base_dir) files.sort() for filename in files: if filename.startswith("_") or not filename.endswith(".py"): continue try: _load_command(connection, filename) except AttributeError: pass # The file is doesn't contain a command, so just move on msg = "Found {0} commands: {1}" logger.info(msg.format(len(_commands), ", ".join(_commands.keys()))) def get_all(): """Return our dict of all loaded commands.""" return _commands def check(hook, data): """Given an event on IRC, check if there's anything we can respond to.""" # Parse command arguments into data.command and data.args: data.parse_args() for command in _commands.values(): if hook in command.hooks: if command.check(data): try: command.process(data) except: logger.exception("Error executing command '{0}'".format(data.command)) break