Permalink
Browse files

Hey look, @Mythmon reorganized plugins again!

This way allows multiple commands per plugin, which makes things nicer.
  • Loading branch information...
1 parent 93436cd commit 29502de00a2ebc4129995ab252478e9b40d878b8 @mythmon mythmon committed Jul 30, 2011
Showing with 200 additions and 173 deletions.
  1. +0 −17 hamper/commander.py
  2. +49 −9 hamper/interfaces.py
  3. +59 −51 hamper/plugins/commands.py
  4. +4 −7 hamper/plugins/friendly.py
  5. +68 −71 hamper/plugins/plugin_utils.py
  6. +20 −18 hamper/plugins/quote.py
View
@@ -86,23 +86,6 @@ def privmsg(self, user, channel, msg):
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback)
-
- #matchedPlugins = []
- #for cmd in self.factory.plugins:
- # match = cmd.regex.match(msg)
- # if match and (directed or (not cmd.onlyDirected)):
- # matchedPlugins.append((match, cmd))
-
- ## High priority plugins first
- #matchedPlugins.sort(key=lambda x: x[1].priority, reverse=True)
-
- #for match, cmd in matchedPlugins:
- # proc_comm = comm.copy()
- # proc_comm.update({'groups': match.groups()})
- # if not cmd(self, proc_comm):
- # # The plugin asked us to not run any more.
- # break
-
if not channel in self.factory.history:
self.factory.history[channel] = deque(maxlen=100)
self.factory.history[channel].append(comm)
View
@@ -24,31 +24,71 @@ def process(bot, comm):
"""
-class Command(object):
- """Specialized plugin to implement a simple command"""
+class Plugin(object):
+ """
+ Base class for a plugin.
+
+ If any of a classes children are Command classes, automatically call out to
+ them.
+ """
implements(IPlugin)
priority = 0
+ def __init__(self):
+ self.commands = []
+ for name in dir(self):
+ cls = self.__getattribute__(name)
+ try:
+ if ICommand.implementedBy(cls):
+ self.commands.append(cls())
+ except (AttributeError, TypeError):
+ pass
+
+ def setup(self, factory):
+ pass
+
+ def process(self, bot, comm):
+ for cmd in self.commands:
+ stop = cmd.process(bot, comm)
+ if stop:
+ return stop
+
+
+class ICommand(Interface):
+ """Interface for a command."""
+
+ regex = Attribute('The regex to trigger this command for.')
+ caseSensitive = Attribute("The case sensitivity of the trigger regex.")
+ onlyDirected = Attribute("Only respond to command directed at the bot.")
+
+ def process(bot, comm):
+ """Chooses whether or not to trigger the command."""
+
+ def command(bot, comm, groups):
+ """This function gets called when the command is triggered."""
+
+
+class Command(object):
+ """
+ A convenience wrapper to implement a single command.
+
+ To use it, define a clas that inherits from Command inside a Plugin.
+ """
+ implements(ICommand)
+
caseSensitive = False
- regex = ''
onlyDirected = True
def __init__(self):
if type(self.regex) == str:
opts = 0 if self.caseSensitive else re.I
self.regex = re.compile(self.regex, opts)
- def setup(self, factory):
- pass
-
def process(self, bot, comm):
if self.onlyDirected and not comm['directed']:
return
match = self.regex.match(comm['message'])
if match:
self.command(bot, comm, match.groups())
return True
-
- def command(self, bot, comm, groups):
- pass
View
@@ -3,73 +3,81 @@
from zope.interface import implements, Interface, Attribute
-from hamper.interfaces import Command
+from hamper.interfaces import Command, Plugin
-class QuitCommand(Command):
+class Quit(Plugin):
"""Know when hamper isn't wanted."""
-
name = 'quit'
- regex = 'go away'
- def command(self, bot, comm, groups):
- bot.msg(comm['channel'], 'Bye!')
- bot.leaveChannel(comm['channel'])
- return True
+ class QuitCommand(Command):
+ regex = 'go away'
+
+ def command(self, bot, comm, groups):
+ bot.msg(comm['channel'], 'Bye!')
+ bot.leaveChannel(comm['channel'])
+ return True
-class Sed(Command):
+class Sed(Plugin):
"""To be honest, I feel strange in channels that don't have this."""
name = 'sed'
- regex = r's/(.*)/(.*)/(g?i?m?)'
- onlyDirected = False
priority = -1
- def command(self, bot, comm, groups):
- options = groups[2]
-
- regex_opts = re.I if 'i' in options else 0
- usr_regex = re.compile(groups[0], regex_opts)
- usr_replace = groups[1]
-
- count = 0 if 'g' in options else 1
-
- key = comm['channel']
- if key not in bot.factory.history:
- bot.msg(comm['channel'], 'Who are you?! How did you get in my house?!')
- return
-
- for hist in reversed(bot.factory.history[key]):
- # Only look at our own if only-me was specified
- if 'm' in options and hist['user'] != comm['user']:
- continue
- # Don't look at other sed commands
- if hist['directed'] and hist['message'].startswith('s/'):
- continue
-
- if usr_regex.search(hist['message']):
- new_msg = usr_regex.sub(usr_replace, hist['message'], count)
- bot.msg(comm['channel'], '{0} actually meant: {1}'
- .format(hist['user'], new_msg))
- break
- else:
- bot.msg(comm['channel'], "Sorry, I couldn't match /{0}/.".format(usr_regex.pattern))
-
-class LetMeGoogleThatForYou(Command):
+ class SedCommand(Command):
+ regex = r's/(.*)/(.*)/(g?i?m?)'
+ onlyDirected = False
+
+ def command(self, bot, comm, groups):
+ options = groups[2]
+
+ regex_opts = re.I if 'i' in options else 0
+ usr_regex = re.compile(groups[0], regex_opts)
+ usr_replace = groups[1]
+
+ g = 0 if 'g' in options else 1
+
+ key = comm['channel']
+ if key not in bot.factory.history:
+ bot.msg(comm['channel'], 'Who are you?! How did you get in my '
+ 'house?!')
+ return False
+
+ for hist in reversed(bot.factory.history[key]):
+ if 'm' in options and hist['user'] != comm['user']:
+ # Only look at the user's messages
+ continue
+
+ # Don't look at other sed commands
+ if hist['directed'] and hist['message'].startswith('s/'):
+ continue
+
+ if usr_regex.search(hist['message']):
+ new_msg = usr_regex.sub(usr_replace, hist['message'], g)
+ bot.msg(comm['channel'], '{0} actually meant: {1}'
+ .format(hist['user'], new_msg))
+ break
+ else:
+ bot.msg(comm['channel'],
+ "Sorry, I couldn't match /{0}/.".format(usr_regex.pattern))
+
+class LetMeGoogleThatForYou(Plugin):
"""Link to the sarcastic letmegooglethatforyou.com."""
name = 'lmgtfy'
- regex = '^lmgtfy\s+(.*)'
- onlyDirected = False
- def command(self, bot, comm, groups):
- target = ''
- if comm['target']:
- target = comm['target'] + ': '
- args = groups[0].replace(' ', '+')
- bot.msg(comm['channel'], target + 'http://lmgtfy.com/?q=' + args)
+ class LMGTFYCommand(Command):
+ regex = '^lmgtfy\s+(.*)'
+ onlyDirected = False
+
+ def command(self, bot, comm, groups):
+ target = ''
+ if comm['target']:
+ target = comm['target'] + ': '
+ args = groups[0].replace(' ', '+')
+ bot.msg(comm['channel'], target + 'http://lmgtfy.com/?q=' + args)
lmgtfy = LetMeGoogleThatForYou()
sed = Sed()
-quit = QuitCommand()
+quit = Quit()
View
@@ -4,12 +4,11 @@
from zope.interface import implements
-from hamper.interfaces import IPlugin
+from hamper.interfaces import Plugin
-class Friendly(object):
+class Friendly(Plugin):
"""Be polite. When people say hello, response."""
- implements(IPlugin)
name = 'friendly'
priority = 2
@@ -27,9 +26,8 @@ def process(self, bot, comm):
return True
-class OmgPonies(object):
+class OmgPonies(Plugin):
"""The classics never die."""
- implements(IPlugin)
name = 'ponies'
priority = 3
@@ -55,9 +53,8 @@ def process(self, bot, comm):
return False
-class BotSnack(object):
+class BotSnack(Plugin):
"""Reward a good bot."""
- implements(IPlugin)
name = 'botsnack'
priority = 0
Oops, something went wrong.

0 comments on commit 29502de

Please sign in to comment.