Skip to content

Commit

Permalink
Added a content decorator that allows hippybot plugins to be able to …
Browse files Browse the repository at this point in the history
…be written against any text. A sample plugin based on plusplusbot from http://partychapp.appspot.com/ is included
  • Loading branch information
Devon Jones committed Mar 10, 2013
1 parent 831f03d commit 19731be
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
22 changes: 22 additions & 0 deletions hippybot/bot.py
Expand Up @@ -34,6 +34,7 @@ class HippyBot(JabberBot):
hipchat.com chatroom/IM service.
"""

_content_commands = {}
_global_commands = []
_command_aliases = {}
_all_msg_handlers = []
Expand Down Expand Up @@ -147,6 +148,12 @@ def callback_message(self, conn, mess):
self._last_message = message
if ret:
return ret
for name in self._content_commands:
cmd = self._content_commands[name]
ret = cmd(mess)
if ret:
self.send_simple_reply(mess, ret)
return ret

def join_room(self, room, username=None, password=None):
"""Overridden from JabberBot to provide history limiting.
Expand Down Expand Up @@ -206,6 +213,7 @@ def load_plugins(self, mess=None, args=None):
plugin.bot = self
commands = [c for c in dir(plugin)]
funcs = []
content_funcs = []

for command in commands:
m = getattr(plugin, command)
Expand All @@ -220,6 +228,17 @@ def load_plugins(self, mess=None, args=None):
name = getattr(m, '_jabberbot_command_name', False)
funcs.append((name, m))

if ismethod(m) and getattr(m, '_jabberbot_content_command', False):
if command in RESERVED_COMMANDS:
self.log.error('Plugin "%s" attempted to register '
'reserved command "%s", skipping..' % (
plugin, command
))
continue
self.rewrite_docstring(m)
name = getattr(m, '_jabberbot_command_name', False)
content_funcs.append((name, m))

# Check for commands that don't need to be directed at
# hippybot, e.g. they can just be said in the channel
self._global_commands.extend(getattr(plugin,
Expand All @@ -239,6 +258,9 @@ def load_plugins(self, mess=None, args=None):
for command, func in funcs:
setattr(self, command, func)
self.commands[command] = func
for command, func in content_funcs:
setattr(self, command, func)
self._content_commands[command] = func
if mess:
return 'Reloading plugin modules and classes..'

Expand Down
13 changes: 13 additions & 0 deletions hippybot/decorators.py
Expand Up @@ -8,3 +8,16 @@ def wrapper(self, origin, args):
username = unicode(origin.getFrom()).split('/')[1].replace(" ","")
return u'@%s %s' % (username, message)
return botcmd(wrapper)

def contentcmd(*args, **kwargs):
"""Decorator for bot commentary"""

def decorate(func, name=None):
setattr(func, '_jabberbot_content_command', True)
setattr(func, '_jabberbot_command_name', name or func.__name__)
return func

if len(args):
return decorate(args[0], **kwargs)
else:
return lambda func: decorate(func, **kwargs)
75 changes: 75 additions & 0 deletions hippybot/plugins/plusplusbot.py
@@ -0,0 +1,75 @@
import os
import os.path
import re
import sqlite3dbm
from threading import RLock
from hippybot.hipchat import HipChatApi
from hippybot.decorators import botcmd, contentcmd

CONFIG_DIR = os.path.expanduser("~/.techbot")
DB = os.path.expanduser("~/.techbot/score.db")

class Plugin(object):
"""Plugin to handle knewton replacement of ++ bot in partychatapp
"""
def __init__(self):
self.rlock = RLock()
self.db = self.get_db()

def get_db(self):
self.create_dir()
db = sqlite3dbm.sshelve.open(DB)
return db

def create_dir(self):
if not os.path.exists(CONFIG_DIR):
os.mkdir(CONFIG_DIR)

@contentcmd
def change_score(self, mess, **kwargs):
message = mess.getBody()
if message:
room = str(mess.getFrom()).split("/")[0]
user = str(mess.getFrom()).split("/")[1]
results = []
if message.find('++') > -1 or message.find('--') > -1:
self.bot.log.info("plusplusbot: %s" % mess)
if message.endswith("++") or message.endswith("--"):
results.extend(self.process_message(message, room, user))
for m in re.findall("\((.*?)\)", message):
if m.endswith("++") or m.endswith("--"):
results.extend(self.process_message(m, room, user))
if len(results) > 0:
return "\n".join(results)

def process_message(self, message, room, user):
results = []
victim = message[:-2]
excl = "woot!"
plus = 1
if message.endswith('--'):
excl = "ouch!"
plus = -1
with self.rlock:
scores = self.db.get(room, {})
score = scores.setdefault(victim, 0)
score += plus
scores[victim] = score
self.db[room] = scores
return ["[%s] %s [%s now at %s]" % (user, victim, excl, score)]

@botcmd
def scores(self, mess, args, **kwargs):
"""
Prints all scores from this room
Format: @NickName scores
"""
self.bot.log.info("score: %s" % mess)
room = str(mess.getFrom()).split("/")[0]
ret = []
with self.rlock:
scores = self.db.get(room, {})
for key in scores:
ret.append("%s: %s" %(key, scores[key]))
return '\n'.join(ret)

0 comments on commit 19731be

Please sign in to comment.