""" Karma - handle karma (++ and --) tracking Copyright (C) 2010 Brian S. Stephan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import re import sqlite3 from Module import Module __author__ = "Mike Bloy " __date__ = "$Oct 23, 2010 11:12:33 AM$" class Karma(Module): def __init__(self, irc, config, server): """ Upon creation, determine the save file location """ Module.__init__(self, irc, config, server) pattern = "(?:(\S+)|\((.+)\))" karmapattern = pattern + '(\+\+|--|\+-|-\+)' + '(\s+|$)' querypattern = '^!rank\s+(.*)' reportpattern = '^!karma\s+report\s+(highest|lowest|positive|negative)' statpattern = '^!karma\s+stat\s+(.*)' self.karmare = re.compile(karmapattern) self.queryre = re.compile(querypattern) self.reportre = re.compile(reportpattern) self.statre = re.compile(statpattern) def db_init(self): # need to init the database if karma tables don't already exist version = self.db_module_registered(self.__class__.__name__) if (version == None): # have to create the database tables conn = self.get_db() try: conn.execute(''' CREATE TABLE karma_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, delta INTEGER NOT NULL, who TEXT NOT NULL, userhost TEXT NOT NULL, karmatime TEXT DEFAULT CURRENT_TIMESTAMP )''') conn.execute('CREATE INDEX karma_log_key_ix ON karma_log (key)') conn.execute('CREATE INDEX karma_log_who_ix ON karma_log (who)') conn.execute(''' CREATE VIEW karma_values AS SELECT key, SUM(delta) AS value FROM karma_log GROUP BY key''') sql = 'INSERT INTO drbotzo_modules VALUES (?,?)' conn.execute(sql, (self.__class__.__name__, 1)) conn.commit() version = 1 except sqlite3.Error as e: conn.rollback() print("sqlite error: " + str(e)) raise if (version < 2): conn = self.get_db() try: conn.execute(''' CREATE VIEW karma_users AS SELECT who, COUNT(NULLIF(delta, -1)) AS pos, COUNT(NULLIF(delta, 1)) AS neg FROM karma_log GROUP BY who''') sql = 'UPDATE drbotzo_modules SET version = ? WHERE module = ?' conn.execute(sql, (2, self.__class__.__name__)) conn.commit() version = 2 except sqlite3.Error as e: conn.rollback() print("sqlite error: " + str(e)) raise def do(self, connection, event, nick, userhost, what, admin_unlocked): """look for karma strings at the start of messages""" if (self.karmare.search(what)): return self.handle_karma_change(connection, nick, userhost, what) elif (self.queryre.search(what)): return self.handle_karma_query(connection, nick, userhost, what) elif (self.statre.search(what)): return self.handle_stat_query(connection, nick, userhost, what) elif (self.reportre.search(what)): return self.handle_report_query(connection, nick, userhost, what) def handle_karma_change(self, connection, nick, userhost, what): """ handle the karma change and storage. """ match = self.karmare.search(what) key = match.group(1) if match.group(1) else match.group(2) value = match.group(3) if (value == '++'): return self.karma_modify(key, 1, nick, userhost) elif (value == '--'): return self.karma_modify(key, -1, nick, userhost) elif (value == '+-'): self.karma_modify(key, 1, nick, userhost) return self.karma_modify(key, -1, nick, userhost) elif (value == '-+'): self.karma_modify(key, -1, nick, userhost) return self.karma_modify(key, 1, nick, userhost) def karma_modify(self, key, value, nick, userhost): """ Go out to the database and update the karma value. """ conn = self.get_db() try: sql = ''' INSERT INTO karma_log (key, delta, who, userhost) VALUES (?, ?, ?, ?) ''' conn.execute(sql, (key, value, nick, userhost)) conn.commit() except sqlite3.Error as e: conn.rollback() return "sqlite error: " + str(e) def handle_report_query(self, connection, nick, userhost, what): match = self.reportre.search(what) report = match.group(1) message = '{nick}: the desired report is not yet implemented'.format(nick=nick) query = None header = None if (report == 'highest'): query = 'SELECT key, value FROM karma_values ORDER BY value DESC LIMIT 5' header = 'Top 5 karma recipients:' elif (report == 'lowest'): query = 'SELECT key, value FROM karma_values ORDER BY value ASC LIMIT 5' header = 'Bottom 5 karma recipients:' elif (report == 'positive'): query = 'SELECT who, pos FROM karma_users ORDER BY pos DESC LIMIT 5' header = 'Top 5 Optimists:' elif (report == 'negative'): query = 'SELECT who, neg FROM karma_users ORDER BY neg DESC LIMIT 5' header = 'Top 5 Pessimists:' if (query != None): conn = self.get_db() list = [] try: cursor = conn.execute(query) result = cursor.fetchone() while (result != None): list.append("{key} ({value})".format(key=result[0], value=result[1])) result = cursor.fetchone() list = ', '.join(list) message = '{header} {list}'.format(header=header, list=list) except sqlite3.Error as e: conn.rollback() return "sqlite error: " + str(e) return message def handle_stat_query(self, connection, nick, userhost, what): match = self.statre.search(what) statnick = match.group(1) conn = self.get_db() reply = '{nick}: {statnick} has never given karma'.format(nick=nick, statnick=statnick) try: query = ''' SELECT pos, neg FROM karma_users WHERE who = :who ''' value = conn.execute(query, {'who': statnick}).fetchone() if (value != None): pos = value[0] neg = value[1] total = pos+neg; reply = '{nick}: {statnick} has given {pos} postive karma and {neg} negative karma, for a total of {total} karma'.format(nick=nick, statnick=statnick, pos=pos, neg=neg, total=total) except sqlite3.Error as e: return "sqlite error: " + str(e) return reply def handle_karma_query(self, connection, nick, userhost, what): match = self.queryre.search(what) key = match.group(1) conn = self.get_db() reply = '{nick}: {key} has no karma'.format(nick=nick, key=key) try: query = ''' SELECT value FROM karma_values WHERE key = :key ''' value = conn.execute(query, {'key': key}).fetchone() if (value != None): query = ''' SELECT count(*) FROM karma_values WHERE value > :value ''' rank = conn.execute(query, {'value': value[0]}).fetchone() rank = rank[0] + 1; reply = '{nick}: {key} has {value[0]!s} points of karma (rank {rank})'.format( nick=nick, key=key, value=value, rank=rank) except sqlite3.Error as e: return "sqlite error: " + str(e) return reply if __name__ == "__main__": print "Hello World" # vi:tabstop=4:expandtab:autoindent