A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.7 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. EarwigBot's IRC Command Manager
  4. This package provides the IRC "commands" used by the bot's front-end component.
  5. In __init__, you can find some functions used to load and run these commands.
  6. """
  7. import os
  8. import sys
  9. import traceback
  10. from classes import BaseCommand
  11. import config
  12. __all__ = ["load", "get_all", "check"]
  13. # Base directory when searching for commands:
  14. base_dir = os.path.join(config.root_dir, "bot", "commands")
  15. # Store commands in a dict, where the key is the command's name and the value
  16. # is an instance of the command's class:
  17. _commands = {}
  18. def _load_command(connection, filename):
  19. """Try to load a specific command from a module, identified by file name.
  20. Given a Connection object and a filename, we'll first try to import it,
  21. and if that works, make an instance of the 'Command' class inside (assuming
  22. it is an instance of BaseCommand), add it to _commands, and report the
  23. addition to the user. Any problems along the way will either be ignored or
  24. reported.
  25. """
  26. global _commands
  27. # Strip .py from the end of the filename and join with our package name:
  28. name = ".".join(("commands", filename[:-3]))
  29. try:
  30. __import__(name)
  31. except:
  32. print "Couldn't load file {0}:".format(filename)
  33. traceback.print_exc()
  34. return
  35. command = sys.modules[name].Command(connection)
  36. if not isinstance(command, BaseCommand):
  37. return
  38. _commands[command.name] = command
  39. print "Added command {0}...".format(command.name)
  40. def load(connection):
  41. """Load all valid commands into the _commands global variable.
  42. `connection` is a Connection object that is given to each command's
  43. constructor.
  44. """
  45. files = os.listdir(base_dir)
  46. files.sort()
  47. for filename in files:
  48. if filename.startswith("_") or not filename.endswith(".py"):
  49. continue
  50. try:
  51. _load_command(connection, filename)
  52. except AttributeError:
  53. pass # The file is doesn't contain a command, so just move on
  54. msg = "Found {0} commands: {1}."
  55. print msg.format(len(_commands), ", ".join(_commands.keys()))
  56. def get_all():
  57. """Return our dict of all loaded commands."""
  58. return _commands
  59. def check(hook, data):
  60. """Given an event on IRC, check if there's anything we can respond to."""
  61. # Parse command arguments into data.command and data.args:
  62. data.parse_args()
  63. for command in _commands.values():
  64. if hook in command.hooks:
  65. if command.check(data):
  66. try:
  67. command.process(data)
  68. except:
  69. print "Error executing command '{0}':".format(data.command)
  70. traceback.print_exc()
  71. break