diff --git a/plugins/MessageParser/config.py b/plugins/MessageParser/config.py
index 6003bc121..f0ee0c4ba 100644
--- a/plugins/MessageParser/config.py
+++ b/plugins/MessageParser/config.py
@@ -48,6 +48,11 @@ conf.registerChannelValue(MessageParser, 'enable',
registry.Boolean(True, """Determines whether the
message parser is enabled. If enabled, will trigger on regexps
added to the regexp db."""))
-
+conf.registerChannelValue(MessageParser, 'keepRankInfo',
+ registry.Boolean(True, """Determines whether we keep updating the usage
+ count for each regexp, for popularity ranking."""))
+conf.registerChannelValue(MessageParser, 'rankListLength',
+ registry.Integer(20, """Determines the number of regexps returned
+ by the triggerrank command."""))
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/plugins/MessageParser/plugin.py b/plugins/MessageParser/plugin.py
index bef351690..acf808075 100644
--- a/plugins/MessageParser/plugin.py
+++ b/plugins/MessageParser/plugin.py
@@ -34,29 +34,191 @@ import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
+import supybot.conf as conf
+import supybot.ircdb as ircdb
+
import re
+import os
+import time
-## will add db stuff later
+try:
+ import sqlite
+except ImportError:
+ raise callbacks.Error, 'You need to have PySQLite installed to use this ' \
+ 'plugin. Download it at ' \
+ ''
-class MessageParser(callbacks.PluginRegexp):
+
+class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
"""This plugin can set regexp triggers to activate the bot.
Use 'add' command to add regexp trigger, 'remove' to remove."""
threaded = True
- regexps = ['regexpSnarfer']
def __init__(self, irc):
- self.__parent = super(MessageParser, self)
- self.__parent.__init__(irc)
+ callbacks.Plugin.__init__(self, irc)
+ plugins.ChannelDBHandler.__init__(self)
- def regexpSnarfer(self, irc, msg, match):
- r".*"
+ def makeDb(self, filename):
+ if os.path.exists(filename):
+ return sqlite.connect(filename)
+ db = sqlite.connect(filename)
+ cursor = db.cursor()
+ cursor.execute("""CREATE TABLE triggers (
+ id INTEGER PRIMARY KEY,
+ regexp TEXT UNIQUE ON CONFLICT REPLACE,
+ added_by TEXT,
+ added_at TIMESTAMP,
+ usage_count INTEGER,
+ action TEXT,
+ locked BOOLEAN
+ )""")
+ db.commit()
+ return db
+
+ def _updateRank(self, channel, regexp):
+ if self.registryValue('keepRankInfo', channel):
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("""SELECT usage_count
+ FROM triggers
+ WHERE regexp=%s""", regexp)
+ old_count = cursor.fetchall()[0][0]
+ cursor.execute("UPDATE triggers SET usage_count=%s WHERE regexp=%s", old_count + 1, regexp)
+ db.commit()
+
+ def doPrivmsg(self, irc, msg):
channel = msg.args[0]
- msgtext = match.group(0)
if not irc.isChannel(channel):
return
if self.registryValue('enable', channel):
- if re.search('some stuff', msgtext):
- irc.reply('some stuff detected', prefixNick=False)
- regexpSnarfer = urlSnarfer(regexpSnarfer)
+ actions = []
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("SELECT regexp, action FROM triggers")
+ if cursor.rowcount == 0:
+ return
+ for (regexp, action) in cursor.fetchall():
+ match = re.search(regexp, msg.args[1])
+ if match is not None:
+ self._updateRank(channel, regexp)
+ for (i, j) in enumerate(match.groups()):
+ action = re.sub(r'\$' + str(i+1), match.group(i+1), action)
+ actions.append(action)
+
+ if len(actions) > 0:
+ irc.replies(actions, prefixNick=False)
+
+ #if re.search('some stuff', msgtext):
+ # irc.reply('some stuff detected', prefixNick=False)
+
+ def add(self, irc, msg, args, channel, regexp, action):
+ """[]
+
+ Associates with . is only
+ necessary if the message isn't sent on the channel
+ itself. Action is echoed upon regexp match, with variables $1, $2,
+ etc. being interpolated from the regexp match groups."""
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("SELECT id, locked FROM triggers WHERE regexp=%s", regexp)
+ if cursor.rowcount != 0:
+ (id, locked) = map(int, cursor.fetchone())
+ else:
+ locked = False
+ #capability = ircdb.makeChannelCapability(channel, 'factoids')
+ if not locked:
+ if ircdb.users.hasUser(msg.prefix):
+ name = ircdb.users.getUser(msg.prefix).name
+ else:
+ name = msg.nick
+ cursor.execute("""INSERT INTO triggers VALUES
+ (NULL, %s, %s, %s, %s, %s, %s)""",
+ regexp, name, int(time.time()), 0, action, 0)
+ db.commit()
+ irc.replySuccess()
+ else:
+ irc.error('That trigger is locked.')
+ add = wrap(add, ['channel', 'something', 'something'])
+
+ def remove(self, irc, msg, args, channel, regexp):
+ """[] ]
+
+ Removes the trigger for from the triggers database.
+ is only necessary if
+ the message isn't sent in the channel itself.
+ """
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("SELECT id, locked FROM triggers WHERE regexp=%s", regexp)
+ if cursor.rowcount != 0:
+ (id, locked) = map(int, cursor.fetchone())
+ else:
+ irc.error('There is no such regexp trigger.')
+
+ if locked:
+ irc.error('This regexp trigger is locked.')
+
+ cursor.execute("""DELETE FROM triggers WHERE id=%s""", id)
+ db.commit()
+ irc.replySuccess()
+ remove = wrap(remove, ['channel', 'something'])
+
+ def show(self, irc, msg, args, channel, regexp):
+ """[]
+
+ Looks up the value of in the triggers database.
+ is only necessary if the message isn't sent in the channel
+ itself.
+ """
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("SELECT regexp, action FROM triggers WHERE regexp=%s", regexp)
+ if cursor.rowcount != 0:
+ (regexp, action) = cursor.fetchone()
+ else:
+ irc.error('There is no such regexp trigger.')
+
+ irc.reply("The trigger for regexp '%s' is '%s'" % (regexp, action))
+ show = wrap(show, ['channel', 'something'])
+
+ def listall(self, irc, msg, args, channel):
+ """[]
+
+ Lists regexps present in the triggers database.
+ is only necessary if the message isn't sent in the channel
+ itself.
+ """
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("SELECT regexp FROM triggers")
+ if cursor.rowcount != 0:
+ regexps = cursor.fetchall()
+ else:
+ irc.error('There is no available regexp triggers.')
+
+ s = [ regexp[0] for regexp in regexps ]
+ irc.reply("'" + "','".join(s) + "'")
+ listall = wrap(listall, ['channel'])
+
+ def triggerrank(self, irc, msg, args, channel):
+ """[]
+
+ Returns a list of top-ranked regexps, sorted by usage count
+ (rank). The number of regexps returned is set by the
+ rankListLength registry value. is only necessary if the
+ message isn't sent in the channel itself.
+ """
+ numregexps = self.registryValue('rankListLength', channel)
+ db = self.getDb(channel)
+ cursor = db.cursor()
+ cursor.execute("""SELECT regexp, usage_count
+ FROM triggers
+ ORDER BY usage_count DESC
+ LIMIT %s""", numregexps)
+ regexps = cursor.fetchall()
+ s = [ "#%d %s (%d)" % (i+1, regexp[0], regexp[1]) for i, regexp in enumerate(regexps) ]
+ irc.reply(", ".join(s))
+ triggerrank = wrap(triggerrank, ['channel'])
+
Class = MessageParser