diff --git a/plugins/ChannelDB.py b/plugins/ChannelDB.py index ec482f963..e469334c4 100644 --- a/plugins/ChannelDB.py +++ b/plugins/ChannelDB.py @@ -74,15 +74,12 @@ frowns = (':|', ':-/', ':-\\', ':\\', ':/', ':(', ':-(', ':\'(') smileyre = re.compile('|'.join(map(re.escape, smileys))) frownre = re.compile('|'.join(map(re.escape, frowns))) -class ChannelDB(plugins.ChannelDBHandler, - callbacks.PrivmsgCommandAndRegexp, - plugins.Toggleable): - addressedRegexps = sets.Set(['increaseKarma', 'decreaseKarma']) +class ChannelDB(callbacks.Privmsg,plugins.Toggleable,plugins.ChannelDBHandler): toggles = plugins.ToggleDictionary({'selfstats': True}) def __init__(self): - plugins.ChannelDBHandler.__init__(self) - callbacks.PrivmsgCommandAndRegexp.__init__(self) + callbacks.Privmsg.__init__(self) plugins.Toggleable.__init__(self) + plugins.ChannelDBHandler.__init__(self) self.lastmsg = None self.laststate = None self.outFiltering = False @@ -134,14 +131,6 @@ class ChannelDB(plugins.ChannelDBHandler, cursor.execute("""INSERT INTO channel_stats VALUES (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)""") - - cursor.execute("""CREATE TABLE karma ( - id INTEGER PRIMARY KEY, - name TEXT, - normalized TEXT UNIQUE ON CONFLICT IGNORE, - added INTEGER, - subtracted INTEGER - )""") db.commit() def p(s1, s2): return int(ircutils.nickEqual(s1, s2)) @@ -156,10 +145,9 @@ class ChannelDB(plugins.ChannelDBHandler, self.laststate = irc.state.copy() finally: self.lastmsg = msg - callbacks.PrivmsgCommandAndRegexp.__call__(self, irc, msg) + super(ChannelDB, self).__call__(irc, msg) def doPrivmsg(self, irc, msg): - callbacks.PrivmsgCommandAndRegexp.doPrivmsg(self, irc, msg) if ircutils.isChannel(msg.args[0]): self._updatePrivmsgStats(msg) @@ -352,85 +340,6 @@ class ChannelDB(plugins.ChannelDBHandler, (name, utils.timeElapsed(time.time() - seen), m) irc.reply(msg, s) - def karma(self, irc, msg, args): - """[] [] - - Returns the karma of . If is not given, returns the top - three and bottom three karmas. is only necessary if the - message isn't sent on the channel itself. - """ - channel = privmsgs.getChannel(msg, args) - db = self.getDb(channel) - cursor = db.cursor() - if len(args) == 1: - name = args[0] - normalized = name.lower() - cursor.execute("""SELECT added, subtracted - FROM karma - WHERE normalized=%s""", normalized) - if cursor.rowcount == 0: - irc.reply(msg, '%s has no karma.' % name) - else: - (added, subtracted) = map(int, cursor.fetchone()) - total = added - subtracted - s = 'Karma for %r has been increased %s %s ' \ - 'and decreased %s %s for a total karma of %s.' % \ - (name, added, utils.pluralize(added, 'time'), - subtracted, utils.pluralize(subtracted, 'time'), total) - irc.reply(msg, s) - elif len(args) > 1: - normalizedArgs = map(str.lower, args) - criteria = ' OR '.join(['normalized=%s'] * len(args)) - sql = """SELECT name, added-subtracted - FROM karma WHERE %s - ORDER BY added-subtracted DESC""" % criteria - cursor.execute(sql, *normalizedArgs) - if cursor.rowcount > 0: - s = utils.commaAndify(['%s: %s' % (n, t) - for (n,t) in cursor.fetchall()]) - irc.reply(msg, s + '.') - else: - irc.reply(msg, 'I didn\'t know the karma for any ' - 'of those things.') - else: # No name was given. Return the top/bottom 3 karmas. - cursor.execute("""SELECT name, added-subtracted - FROM karma - ORDER BY added-subtracted DESC - LIMIT 3""") - highest = ['%r (%s)' % (t[0], t[1]) for t in cursor.fetchall()] - cursor.execute("""SELECT name, added-subtracted - FROM karma - ORDER BY added-subtracted ASC - LIMIT 3""") - lowest = ['%r (%s)' % (t[0], t[1]) for t in cursor.fetchall()] - s = 'Highest karma: %s. Lowest karma: %s.' % \ - (utils.commaAndify(highest), utils.commaAndify(lowest)) - irc.reply(msg, s) - - def increaseKarma(self, irc, msg, match): - r"^(\S+)\+\+$" - name = match.group(1) - normalized = name.lower() - db = self.getDb(msg.args[0]) - cursor = db.cursor() - cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""", - name, normalized) - cursor.execute("""UPDATE karma - SET added=added+1 - WHERE normalized=%s""", normalized) - - def decreaseKarma(self, irc, msg, match): - r"^(\S+)--$" - name = match.group(1) - normalized = name.lower() - db = self.getDb(msg.args[0]) - cursor = db.cursor() - cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""", - name, normalized) - cursor.execute("""UPDATE karma - SET subtracted=subtracted+1 - WHERE normalized=%s""", normalized) - def stats(self, irc, msg, args): """[] [] diff --git a/plugins/Karma.py b/plugins/Karma.py new file mode 100644 index 000000000..4cbc13f8c --- /dev/null +++ b/plugins/Karma.py @@ -0,0 +1,165 @@ +#!/usr/bin/python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +""" +Plugin for handling basic Karma stuff for a channel. +""" + +import os + +import sqlite + +import utils +import plugins +import privmsgs +import callbacks + + +def configure(onStart, afterConnect, advanced): + # This will be called by setup.py to configure this module. onStart and + # afterConnect are both lists. Append to onStart the commands you would + # like to be run when the bot is started; append to afterConnect the + # commands you would like to be run when the bot has finished connecting. + from questions import expect, anything, something, yn + onStart.append('load Karma') + +example = utils.wrapLines(""" +Add an example IRC session using this module here. +""") + +class Karma(callbacks.PrivmsgCommandAndRegexp, plugins.ChannelDBHandler): + addressedRegexps = ['increaseKarma', 'decreaseKarma'] + def __init__(self): + plugins.ChannelDBHandler.__init__(self) + callbacks.PrivmsgCommandAndRegexp.__init__(self) + + def makeDb(self, filename): + if os.path.exists(filename): + db = sqlite.connect(filename) + else: + db = sqlite.connect(filename) + cursor = db.cursor() + cursor.execute("""CREATE TABLE karma ( + id INTEGER PRIMARY KEY, + name TEXT, + normalized TEXT UNIQUE ON CONFLICT IGNORE, + added INTEGER, + subtracted INTEGER + )""") + db.commit() + def p(s1, s2): + return int(ircutils.nickEqual(s1, s2)) + db.create_function('nickeq', 2, p) + return db + + def karma(self, irc, msg, args): + """[] [] + + Returns the karma of . If is not given, returns the top + three and bottom three karmas. is only necessary if the + message isn't sent on the channel itself. + """ + channel = privmsgs.getChannel(msg, args) + db = self.getDb(channel) + cursor = db.cursor() + if len(args) == 1: + name = args[0] + normalized = name.lower() + cursor.execute("""SELECT added, subtracted + FROM karma + WHERE normalized=%s""", normalized) + if cursor.rowcount == 0: + irc.reply(msg, '%s has no karma.' % name) + else: + (added, subtracted) = map(int, cursor.fetchone()) + total = added - subtracted + s = 'Karma for %r has been increased %s %s ' \ + 'and decreased %s %s for a total karma of %s.' % \ + (name, added, utils.pluralize(added, 'time'), + subtracted, utils.pluralize(subtracted, 'time'), total) + irc.reply(msg, s) + elif len(args) > 1: + normalizedArgs = map(str.lower, args) + criteria = ' OR '.join(['normalized=%s'] * len(args)) + sql = """SELECT name, added-subtracted + FROM karma WHERE %s + ORDER BY added-subtracted DESC""" % criteria + cursor.execute(sql, *normalizedArgs) + if cursor.rowcount > 0: + s = utils.commaAndify(['%s: %s' % (n, t) + for (n,t) in cursor.fetchall()]) + irc.reply(msg, s + '.') + else: + irc.reply(msg, 'I didn\'t know the karma for any ' + 'of those things.') + else: # No name was given. Return the top/bottom 3 karmas. + cursor.execute("""SELECT name, added-subtracted + FROM karma + ORDER BY added-subtracted DESC + LIMIT 3""") + highest = ['%r (%s)' % (t[0], t[1]) for t in cursor.fetchall()] + cursor.execute("""SELECT name, added-subtracted + FROM karma + ORDER BY added-subtracted ASC + LIMIT 3""") + lowest = ['%r (%s)' % (t[0], t[1]) for t in cursor.fetchall()] + s = 'Highest karma: %s. Lowest karma: %s.' % \ + (utils.commaAndify(highest), utils.commaAndify(lowest)) + irc.reply(msg, s) + + def increaseKarma(self, irc, msg, match): + r"^(\S+)\+\+$" + name = match.group(1) + normalized = name.lower() + db = self.getDb(msg.args[0]) + cursor = db.cursor() + cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""", + name, normalized) + cursor.execute("""UPDATE karma + SET added=added+1 + WHERE normalized=%s""", normalized) + + def decreaseKarma(self, irc, msg, match): + r"^(\S+)--$" + name = match.group(1) + normalized = name.lower() + db = self.getDb(msg.args[0]) + cursor = db.cursor() + cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""", + name, normalized) + cursor.execute("""UPDATE karma + SET subtracted=subtracted+1 + WHERE normalized=%s""", normalized) + + +Class = Karma + +# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: diff --git a/test/test_ChannelDB.py b/test/test_ChannelDB.py index 72032a61c..b7fb5beb9 100644 --- a/test/test_ChannelDB.py +++ b/test/test_ChannelDB.py @@ -87,31 +87,6 @@ if sqlite is not None: self.assertNotError('seen %s' % self.nick) self.assertNotError('seen %s' % self.nick.upper()) - def testKarma(self): - self.assertRegexp('karma foobar', 'no karma') - try: - conf.replyWhenNotCommand = True - self.assertNoResponse('foobar++', 2) - finally: - conf.replyWhenNotCommand = False - self.assertRegexp('karma foobar', 'increased 1.*total.*1') - self.assertRegexp('karma FOOBAR', 'increased 1.*total.*1') - self.assertNoResponse('foobar--', 2) - self.assertRegexp('karma foobar', 'decreased 1.*total.*0') - self.assertRegexp('karma FOOBAR', 'decreased 1.*total.*0') - self.assertNoResponse('FOO++', 2) - self.assertNoResponse('BAR--', 2) - self.assertRegexp('karma foo bar foobar', '.*foo.*foobar.*bar.*') - self.assertRegexp('karma FOO BAR FOOBAR', '.*foo.*foobar.*bar.*') - self.assertRegexp('karma FOO BAR FOOBAR', - '.*FOO.*foobar.*BAR.*', flags=0) - # Test case-insensitive - self.assertNoResponse('MOO++', 2) - self.assertRegexp('karma moo', 'Karma for \'moo\'.*increased 1' - '.*total.*1') - self.assertRegexp('karma MoO', 'Karma for \'MoO\'.*increased 1' - '.*total.*1') - # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: diff --git a/test/test_Karma.py b/test/test_Karma.py new file mode 100644 index 000000000..7e62d8d5d --- /dev/null +++ b/test/test_Karma.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +from test import * + +import conf + +try: + import sqlite +except ImportError: + sqlite = None + +if sqlite is not None: + class KarmaTestCase(ChannelPluginTestCase, PluginDocumentation): + plugins = ('Karma',) + def testKarma(self): + self.assertRegexp('karma foobar', 'no karma') + try: + conf.replyWhenNotCommand = True + self.assertNoResponse('foobar++', 2) + finally: + conf.replyWhenNotCommand = False + self.assertRegexp('karma foobar', 'increased 1.*total.*1') + self.assertRegexp('karma FOOBAR', 'increased 1.*total.*1') + self.assertNoResponse('foobar--', 2) + self.assertRegexp('karma foobar', 'decreased 1.*total.*0') + self.assertRegexp('karma FOOBAR', 'decreased 1.*total.*0') + self.assertNoResponse('FOO++', 2) + self.assertNoResponse('BAR--', 2) + self.assertRegexp('karma foo bar foobar', '.*foo.*foobar.*bar.*') + self.assertRegexp('karma FOO BAR FOOBAR', '.*foo.*foobar.*bar.*') + self.assertRegexp('karma FOO BAR FOOBAR', + '.*FOO.*foobar.*BAR.*', flags=0) + # Test case-insensitive + self.assertNoResponse('MOO++', 2) + self.assertRegexp('karma moo', 'Karma for \'moo\'.*increased 1' + '.*total.*1') + self.assertRegexp('karma MoO', 'Karma for \'MoO\'.*increased 1' + '.*total.*1') + + + +# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: +