Procházet zdrojové kódy

loading commands now works, along with 'help' and 'test'; docstring fixes, etc

tags/v0.1^2
Ben Kurtovic před 12 roky
rodič
revize
99d0e7588f
5 změnil soubory, kde provedl 66 přidání a 46 odebrání
  1. +10
    -3
      bot/classes/base_command.py
  2. +1
    -1
      bot/classes/base_task.py
  3. +48
    -34
      bot/commands/__init__.py
  4. +6
    -7
      bot/commands/help.py
  5. +1
    -1
      bot/tasks/__init__.py

+ 10
- 3
bot/classes/base_command.py Zobrazit soubor

@@ -14,6 +14,13 @@ class BaseCommand(object):
hooks = ["msg"]

def __init__(self, connection):
"""Constructor for new commands.
This is called once when the command is loaded (from
commands._load_command()). `connection` is a Connection object,
allowing us to do self.connection.say(), self.connection.send(), etc,
from within a method.
"""
self.connection = connection

def check(self, data):
@@ -34,8 +41,8 @@ class BaseCommand(object):
"""Main entry point for doing a command.

Handle an activity (usually a message) on IRC. At this point, thanks
to self.check() which is called automatically by command_handler, we
know this is something we should respond to, so (usually) a
'if data.command != "command_name": return' is unnecessary.
to self.check() which is called automatically by the command handler,
we know this is something we should respond to, so (usually) something
like 'if data.command != "command_name": return' is unnecessary.
"""
pass

+ 1
- 1
bot/classes/base_task.py Zobrazit soubor

@@ -8,7 +8,7 @@ class BaseTask(object):
"""Constructor for new tasks.

This is called once immediately after the task class is loaded by
the task manager (in tasks._load_class_from_file()).
the task manager (in tasks._load_task()).
"""
pass



+ 48
- 34
bot/commands/__init__.py Zobrazit soubor

@@ -8,53 +8,67 @@ In __init__, you can find some functions used to load and run these commands.
"""

import os
import sys
import traceback

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 = {}

def _load_class_from_file(connection, module):
"""Add."""
global commands
objects = dir(module)
def _load_command(connection, filename):
"""Try to load a specific command from a module, identified by file name.

for this_obj in objects: # go through everything in the file
obj = eval("module.%s" % this_obj) # this_obj is a string, so get the actual object corresponding to that string
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

try:
bases = obj.__bases__
except AttributeError: # object isn't a valid class, so ignore it
continue
# Strip .py from the end of the filename and join with our package name:
name = ".".join(("commands", filename[:-3]))
try:
__import__(name)
except:
print "Couldn't load file {0}:".format(filename)
traceback.print_exc()
return

for base in bases:
if base.__name__ == "BaseCommand": # this inherits BaseCommand, so it must be a command class
command = obj(connection) # initialize a new command object
_commands.append(command)
print "Added command class %s from %s..." % (this_obj, module.__name__)
continue
command = sys.modules[name].Command(connection)
if not isinstance(command, BaseCommand):
return
_commands[command.name] = command
print "Added command {0}...".format(command.name)

def load(connection):
"""Load all valid commands into the _commands global variable."""
files = os.listdir(os.path.join("bot", "commands"))
"""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 f in files:
if f.startswith("_") or not f.endswith(".py"): # ignore non-python files or files beginning with "_"
for filename in files:
if filename.startswith("_") or not filename.endswith(".py"):
continue
module = f[:-3] # strip .py from end
try:
exec "from irc.commands import %s" % module
except: # importing the file failed for some reason...
print "Couldn't load file %s:" % f
traceback.print_exc()
continue
process_module(connection, eval(module)) # 'module' is a string, so get the actual object for processing by eval-ing it
_load_command(connection, filename)
except AttributeError:
pass # The file is doesn't contain a command, so just move on

pretty_cmnds = map(lambda c: c.__class__.__name__, commands)
print "Found %s command classes: %s." % (len(commands), ', '.join(pretty_cmnds))
msg = "Found {0} command classes: {1}."
print msg.format(len(_commands), ", ".join(_commands.keys()))

def get_all():
"""Return our dict of all loaded commands."""
@@ -62,15 +76,15 @@ def get_all():

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
# Parse command arguments into data.command and data.args:
data.parse_args()

for command in _commands:
if hook in command.get_hooks():
for command in _commands.values():
if hook in command.hooks:
if command.check(data):
try:
command.process(data)
except:
print "Error executing command '{}':".format(data.command)
traceback.print_exc() # catch exceptions and print them
print "Error executing command '{0}':".format(data.command)
traceback.print_exc()
break

+ 6
- 7
bot/commands/help.py Zobrazit soubor

@@ -4,11 +4,11 @@ from classes import BaseCommand, Data
import commands

class Command(BaseCommand):
"""Generates help information."""
"""Displays help information."""
name = "help"

def process(self, data):
self.cmnds = commands.get_all().keys()
self.cmnds = commands.get_all()
if not data.args:
self.do_main_help(data)
else:
@@ -17,7 +17,7 @@ class Command(BaseCommand):
def do_main_help(self, data):
"""Give the user a general help message with a list of all commands."""
msg = "I am a bot! I have {0} commands loaded: {1}. You can get help for any command with '!help <command>'."
msg.format(len(self.cmnds), ', '.join(self.cmnds))
msg = msg.format(len(self.cmnds.keys()), ', '.join(self.cmnds))
self.connection.reply(data, msg)

def do_command_help(self, data):
@@ -26,17 +26,16 @@ class Command(BaseCommand):

# Create a dummy message to test which commands pick up the user's
# input:
dummy = Data()
dummy = Data(1)
dummy.command = command.lower()
dummy.is_command = True

for cmnd in self.cmnds:
for cmnd in self.cmnds.values():
if cmnd.check(dummy):
doc = cmnd.__doc__
if doc:
msg = "info for command \x0303{0}\x0301: \"{1}\""
msg.format(command, doc)
self.connection.reply(data, msg)
self.connection.reply(data, msg.format(command, doc))
return
break



+ 1
- 1
bot/tasks/__init__.py Zobrazit soubor

@@ -20,7 +20,7 @@ __all__ = ["load", "schedule", "start"]
# an instance of the task class:
_tasks = {}

def _load_class_from_file(f):
def _load_task(f):
"""Look in a given file for the task class."""
global _tasks



Načítá se…
Zrušit
Uložit