mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-23 11:09:23 +01:00
Updated to use FlatfileDB.
This commit is contained in:
parent
8a835a0b15
commit
42bd2d42ae
574
plugins/FunDB.py
574
plugins/FunDB.py
@ -38,14 +38,10 @@ __revision__ = "$Id$"
|
|||||||
import supybot.plugins as plugins
|
import supybot.plugins as plugins
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import csv
|
||||||
import sets
|
import sets
|
||||||
import time
|
import random
|
||||||
import getopt
|
import itertools
|
||||||
import string
|
|
||||||
import os.path
|
|
||||||
from itertools import imap
|
|
||||||
|
|
||||||
import supybot.registry as registry
|
|
||||||
|
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
import supybot.ircdb as ircdb
|
import supybot.ircdb as ircdb
|
||||||
@ -54,74 +50,165 @@ import supybot.world as world
|
|||||||
import supybot.ircmsgs as ircmsgs
|
import supybot.ircmsgs as ircmsgs
|
||||||
import supybot.ircutils as ircutils
|
import supybot.ircutils as ircutils
|
||||||
import supybot.privmsgs as privmsgs
|
import supybot.privmsgs as privmsgs
|
||||||
|
import supybot.registry as registry
|
||||||
import supybot.callbacks as callbacks
|
import supybot.callbacks as callbacks
|
||||||
|
|
||||||
try:
|
|
||||||
import sqlite
|
|
||||||
except ImportError:
|
|
||||||
raise callbacks.Error, 'You need to have PySQLite installed to use this ' \
|
|
||||||
'plugin. Download it at <http://pysqlite.sf.net/>'
|
|
||||||
|
|
||||||
tableCreateStatements = {
|
class FunDBDBInterface(object):
|
||||||
'larts': ("""CREATE TABLE larts (
|
def close(self):
|
||||||
id INTEGER PRIMARY KEY,
|
pass
|
||||||
lart TEXT,
|
|
||||||
added_by TEXT
|
def flush(self):
|
||||||
)""",),
|
pass
|
||||||
'praises': ("""CREATE TABLE praises (
|
|
||||||
id INTEGER PRIMARY KEY,
|
def get(self, channel, type, id):
|
||||||
praise TEXT,
|
"""Returns just the text associated with the channel, type, and id."""
|
||||||
added_by TEXT
|
raise NotImplementedError
|
||||||
)""",),
|
|
||||||
'insults': ("""CREATE TABLE insults (
|
def info(self, channel, type, id):
|
||||||
id INTEGER PRIMARY KEY,
|
"""Returns the test and the metadata associated with the
|
||||||
insult TEXT,
|
channel, type, and id."""
|
||||||
added_by TEXT
|
raise NotImplementedError
|
||||||
)""",),
|
|
||||||
'excuses': ("""CREATE TABLE excuses (
|
def add(self, channel, type, text, by):
|
||||||
id INTEGER PRIMARY KEY,
|
raise NotImplementedError
|
||||||
excuse TEXT,
|
|
||||||
added_by TEXT
|
def remove(self, channel, type, id):
|
||||||
)""",),
|
raise NotImplementedError
|
||||||
}
|
|
||||||
|
def change(self, channel, type, id, f):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def random(self, channel, type):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def size(self, channel, type):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def search(self, channel, type, p):
|
||||||
|
"""Returns a list of (id, text) pairs whose text matches predicate p"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
class FlatfileFunDBDB(FunDBDBInterface):
|
||||||
|
class FunDBDB(plugins.FlatfileDB):
|
||||||
|
def serialize(self, v):
|
||||||
|
return csv.join(map(str, v))
|
||||||
|
|
||||||
|
def deserialize(self, s):
|
||||||
|
return csv.split(s)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.dbs = ircutils.IrcDict()
|
||||||
|
self.filenames = sets.Set()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
for filename in self.filenames:
|
||||||
|
try:
|
||||||
|
db = self.FunDBDB(filename)
|
||||||
|
db.close()
|
||||||
|
except EnvironmentError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _getDb(self, channel, type):
|
||||||
|
type = type.lower()
|
||||||
|
if channel not in self.dbs:
|
||||||
|
self.dbs[channel] = {}
|
||||||
|
if type not in self.dbs[channel]:
|
||||||
|
filename = type.capitalize() + '.db'
|
||||||
|
filename = plugins.makeChannelFilename(channel, filename)
|
||||||
|
self.filenames.add(filename)
|
||||||
|
self.dbs[channel][type] = self.FunDBDB(filename)
|
||||||
|
return self.dbs[channel][type]
|
||||||
|
|
||||||
|
def get(self, channel, type, id):
|
||||||
|
return self.info(channel, type, id)[1]
|
||||||
|
|
||||||
|
def info(self, channel, type, id):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
return db.getRecord(id)
|
||||||
|
|
||||||
|
def add(self, channel, type, text, by):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
return db.addRecord([by, text])
|
||||||
|
|
||||||
|
def remove(self, channel, type, id):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
db.delRecord(id)
|
||||||
|
|
||||||
|
def change(self, channel, type, id, f):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
(by, text) = db.getRecord(id)
|
||||||
|
db.setRecord(id, [by, f(text)])
|
||||||
|
|
||||||
|
def random(self, channel, type):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
t = random.choice(db.records())
|
||||||
|
if t is not None:
|
||||||
|
(id, (by, text)) = t
|
||||||
|
t = (id, text)
|
||||||
|
return t
|
||||||
|
|
||||||
|
def size(self, channel, type):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
return itertools.ilen(db.records())
|
||||||
|
|
||||||
|
def search(self, channel, type, p):
|
||||||
|
db = self._getDb(channel, type)
|
||||||
|
L = []
|
||||||
|
for (id, record) in db.records():
|
||||||
|
text = record[1]
|
||||||
|
if p(text):
|
||||||
|
L.append((id, text))
|
||||||
|
return L
|
||||||
|
|
||||||
|
|
||||||
|
def FunDBDB():
|
||||||
|
return FlatfileFunDBDB()
|
||||||
|
|
||||||
conf.registerPlugin('FunDB')
|
conf.registerPlugin('FunDB')
|
||||||
conf.registerChannelValue(conf.supybot.plugins.FunDB, 'showIds',
|
conf.registerChannelValue(conf.supybot.plugins.FunDB, 'showIds',
|
||||||
registry.Boolean(True, """Determine whether the bot will show the id of an
|
registry.Boolean(True, """Determines whether the bot will show the id of an
|
||||||
excuse/insult/praise/lart."""))
|
insult/praise/lart."""))
|
||||||
|
|
||||||
class FunDB(callbacks.Privmsg, plugins.ChannelDBHandler):
|
class FunDB(callbacks.Privmsg):
|
||||||
"""
|
"""
|
||||||
Contains the 'fun' commands that require a database. Currently includes
|
Contains the 'fun' commands that require a database. Currently includes
|
||||||
database-backed commands for crossword puzzle solving, anagram searching,
|
commands for larting, praising, excusing, and insulting.
|
||||||
larting, praising, excusing, and insulting.
|
|
||||||
"""
|
"""
|
||||||
_tables = sets.Set(['lart', 'insult', 'excuse', 'praise'])
|
_types = ('insult', 'lart', 'praise')
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
callbacks.Privmsg.__init__(self)
|
callbacks.Privmsg.__init__(self)
|
||||||
plugins.ChannelDBHandler.__init__(self)
|
self.db = FunDBDB()
|
||||||
|
|
||||||
def die(self):
|
def die(self):
|
||||||
callbacks.Privmsg.die(self)
|
self.db.die()
|
||||||
plugins.ChannelDBHandler.die(self)
|
|
||||||
|
|
||||||
def makeDb(self, dbfilename, replace=False):
|
def _validType(self, irc, type, error=True):
|
||||||
if os.path.exists(dbfilename):
|
if type not in self._types:
|
||||||
if replace:
|
if error:
|
||||||
os.remove(dbfilename)
|
irc.error('%r is not a valid type. Valid types include %s.' %
|
||||||
db = sqlite.connect(dbfilename)
|
(type, utils.commaAndify(self._types)))
|
||||||
cursor = db.cursor()
|
return False
|
||||||
for table in tableCreateStatements:
|
else:
|
||||||
try:
|
return True
|
||||||
cursor.execute("""SELECT * FROM %s LIMIT 1""" % table)
|
|
||||||
except sqlite.DatabaseError: # The table doesn't exist.
|
def _validId(self, irc, id, error=True):
|
||||||
for sql in tableCreateStatements[table]:
|
try:
|
||||||
cursor.execute(sql)
|
return int(id)
|
||||||
db.commit()
|
except ValueError:
|
||||||
return db
|
if error:
|
||||||
|
irc.error('The <id> argument must be an integer.')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _isRegistered(self, irc, msg):
|
||||||
|
try:
|
||||||
|
return ircdb.users.getUserId(msg.prefix)
|
||||||
|
except KeyError:
|
||||||
|
irc.errorNotRegistered()
|
||||||
|
return None
|
||||||
|
|
||||||
def add(self, irc, msg, args):
|
def add(self, irc, msg, args):
|
||||||
"""[<channel>] <lart|excuse|insult|praise> <text>
|
"""[<channel>] <lart|insult|praise> <text>
|
||||||
|
|
||||||
Adds another record to the data referred to in the first argument. For
|
Adds another record to the data referred to in the first argument. For
|
||||||
commands that will later respond with an ACTION (lart and praise), $who
|
commands that will later respond with an ACTION (lart and praise), $who
|
||||||
@ -132,65 +219,44 @@ class FunDB(callbacks.Privmsg, plugins.ChannelDBHandler):
|
|||||||
the message isn't sent in the channel itself.
|
the message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(table, s) = privmsgs.getArgs(args, required=2)
|
(type, s) = privmsgs.getArgs(args, required=2)
|
||||||
table = table.lower()
|
type = type.lower()
|
||||||
try:
|
userId = self._isRegistered(irc, msg)
|
||||||
name = ircdb.users.getUser(msg.prefix).name
|
if not userId:
|
||||||
except KeyError:
|
|
||||||
irc.errorNotRegistered()
|
|
||||||
return
|
return
|
||||||
if table == "lart" or table == "praise":
|
if not self._validType(irc, type):
|
||||||
|
return
|
||||||
|
if type == "lart" or type == "praise":
|
||||||
if '$who' not in s:
|
if '$who' not in s:
|
||||||
irc.error('There must be a $who in the lart/praise somewhere')
|
irc.error('There must be a $who in the lart/praise somewhere')
|
||||||
return
|
return
|
||||||
elif table not in self._tables:
|
id = self.db.add(channel, type, s, userId)
|
||||||
irc.error('"%s" is not valid. Valid values include %s.' %
|
irc.replySuccess('(%s #%s added)' % (type, id))
|
||||||
(table, utils.commaAndify(self._tables)))
|
|
||||||
return
|
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
sql = """INSERT INTO %ss VALUES (NULL, %%s, %%s)""" % table
|
|
||||||
cursor.execute(sql, s, name)
|
|
||||||
db.commit()
|
|
||||||
sql = """SELECT id FROM %ss WHERE %s=%%s
|
|
||||||
ORDER BY id DESC LIMIT 1""" % (table, table)
|
|
||||||
cursor.execute(sql, s)
|
|
||||||
id = cursor.fetchone()[0]
|
|
||||||
irc.replySuccess('(%s #%s added)' % (table, id))
|
|
||||||
|
|
||||||
def remove(self, irc, msg, args):
|
def remove(self, irc, msg, args):
|
||||||
"""[<channel>] <lart|excuse|insult|praise> <id>
|
"""[<channel>] <lart|insult|praise> <id>
|
||||||
|
|
||||||
Removes the data, referred to in the first argument, with the id
|
Removes the data, referred to in the first argument, with the id
|
||||||
number <id> from the database. <channel> is only necessary if the
|
number <id> from the database. <channel> is only necessary if the
|
||||||
message isn't sent in the channel itself.
|
message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(table, id) = privmsgs.getArgs(args, required=2)
|
(type, id) = privmsgs.getArgs(args, required=2)
|
||||||
table = table.lower()
|
if not self._isRegistered(irc, msg):
|
||||||
|
return
|
||||||
|
if not self._validType(irc, type):
|
||||||
|
return
|
||||||
|
id = self._validId(irc, id)
|
||||||
|
if id is None:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
ircdb.users.getUser(msg.prefix).name
|
self.db.remove(channel, type, id)
|
||||||
|
irc.replySuccess()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
irc.errorNotRegistered()
|
irc.error('There is no %s with that id.' % type)
|
||||||
return
|
|
||||||
try:
|
|
||||||
id = int(id)
|
|
||||||
except ValueError:
|
|
||||||
irc.error('The <id> argument must be an integer.')
|
|
||||||
return
|
|
||||||
if table not in self._tables:
|
|
||||||
irc.error('"%s" is not valid. Valid values include %s.' %
|
|
||||||
(table, utils.commaAndify(self._tables)))
|
|
||||||
return
|
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
sql = """DELETE FROM %ss WHERE id=%%s""" % table
|
|
||||||
cursor.execute(sql, id)
|
|
||||||
db.commit()
|
|
||||||
irc.replySuccess()
|
|
||||||
|
|
||||||
def change(self, irc, msg, args):
|
def change(self, irc, msg, args):
|
||||||
"""[<channel>] <lart|excuse|insult|praise> <id> <regexp>
|
"""[<channel>] <lart|insult|praise> <id> <regexp>
|
||||||
|
|
||||||
Changes the data, referred to in the first argument, with the id
|
Changes the data, referred to in the first argument, with the id
|
||||||
number <id> according to the regular expression <regexp>. <id> is the
|
number <id> according to the regular expression <regexp>. <id> is the
|
||||||
@ -199,130 +265,96 @@ class FunDB(callbacks.Privmsg, plugins.ChannelDBHandler):
|
|||||||
message isn't sent in the channel itself.
|
message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(table, id, regexp) = privmsgs.getArgs(args, required=3)
|
(type, id, regexp) = privmsgs.getArgs(args, required=3)
|
||||||
table = table.lower()
|
if not self._validType(irc, type):
|
||||||
try:
|
|
||||||
name = ircdb.users.getUser(msg.prefix).name
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNotRegistered()
|
|
||||||
return
|
return
|
||||||
try:
|
id = self._validId(irc, id)
|
||||||
id = int(id)
|
if id is None:
|
||||||
except ValueError:
|
|
||||||
irc.error('The <id> argument must be an integer.')
|
|
||||||
return
|
return
|
||||||
if table not in self._tables:
|
if not self._isRegistered(irc, msg):
|
||||||
irc.error('"%s" is not valid. Valid values include %s.' %
|
|
||||||
(table, utils.commaAndify(self._tables)))
|
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
replacer = utils.perlReToReplacer(regexp)
|
replacer = utils.perlReToReplacer(regexp)
|
||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
irc.error('The regexp wasn\'t valid: %s.' % e.args[0])
|
irc.error('That regexp wasn\'t valid: %s.' % e.args[0])
|
||||||
|
return
|
||||||
except re.error, e:
|
except re.error, e:
|
||||||
irc.error(utils.exnToString(e))
|
irc.error(utils.exnToString(e))
|
||||||
return
|
return
|
||||||
db = self.getDb(channel)
|
try:
|
||||||
cursor = db.cursor()
|
self.db.change(channel, type, id, replacer)
|
||||||
sql = """SELECT %s FROM %ss WHERE id=%%s""" % (table, table)
|
|
||||||
cursor.execute(sql, id)
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There is no such %s.' % table)
|
|
||||||
else:
|
|
||||||
old_entry = cursor.fetchone()[0]
|
|
||||||
new_entry = replacer(old_entry)
|
|
||||||
sql = """UPDATE %ss SET %s=%%s, added_by=%%s WHERE id=%%s""" % \
|
|
||||||
(table, table)
|
|
||||||
cursor.execute(sql, new_entry, name, id)
|
|
||||||
db.commit()
|
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
|
except KeyError:
|
||||||
|
irc.error('There is no %s with that id.' % type)
|
||||||
|
|
||||||
def stats(self, irc, msg, args):
|
def stats(self, irc, msg, args):
|
||||||
"""[<channel>] <lart|excuse|insult|praise>
|
"""[<channel>] <lart|insult|praise>
|
||||||
|
|
||||||
Returns the number of records, of the type specified, currently in
|
Returns the number of records, of the type specified, currently in
|
||||||
the database. <channel> is only necessary if the message isn't sent
|
the database. <channel> is only necessary if the message isn't sent
|
||||||
in the channel itself.
|
in the channel itself.
|
||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
table = privmsgs.getArgs(args)
|
type = privmsgs.getArgs(args)
|
||||||
table = table.lower()
|
if not self._validType(irc, type):
|
||||||
if table not in self._tables:
|
|
||||||
irc.error('%r is not valid. Valid values include %s.' %
|
|
||||||
(table, utils.commaAndify(self._tables)))
|
|
||||||
return
|
return
|
||||||
db = self.getDb(channel)
|
total = self.db.size(channel, type)
|
||||||
cursor = db.cursor()
|
|
||||||
sql = """SELECT count(*) FROM %ss""" % table
|
|
||||||
cursor.execute(sql)
|
|
||||||
total = int(cursor.fetchone()[0])
|
|
||||||
irc.reply('There %s currently %s in my database.' %
|
irc.reply('There %s currently %s in my database.' %
|
||||||
(utils.be(total), utils.nItems(table, total)))
|
(utils.be(total), utils.nItems(type, total)))
|
||||||
|
|
||||||
def get(self, irc, msg, args):
|
def get(self, irc, msg, args):
|
||||||
"""[<channel>] <lart|excuse|insult|praise> <id>
|
"""[<channel>] <lart|insult|praise> <id>
|
||||||
|
|
||||||
Gets the record with id <id> from the table specified. <channel> is
|
Gets the record with id <id> from the type specified. <channel> is
|
||||||
only necessary if the message isn't sent in the channel itself.
|
only necessary if the message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(table, id) = privmsgs.getArgs(args, required=2)
|
(type, id) = privmsgs.getArgs(args, required=2)
|
||||||
table = table.lower()
|
if not self._validType(irc, type):
|
||||||
|
return
|
||||||
|
id = self._validId(irc, id)
|
||||||
|
if id is None:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
id = int(id)
|
text = self.db.get(channel, type, id)
|
||||||
except ValueError:
|
irc.reply(text)
|
||||||
irc.error('The <id> argument must be an integer.')
|
except KeyError:
|
||||||
return
|
irc.error('There is no %s with that id.' % type)
|
||||||
if table not in self._tables:
|
|
||||||
irc.error('"%s" is not valid. Valid values include %s.' %
|
|
||||||
(table, utils.commaAndify(self._tables)))
|
|
||||||
return
|
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
sql = """SELECT %s FROM %ss WHERE id=%%s""" % (table, table)
|
|
||||||
cursor.execute(sql, id)
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There is no such %s.' % table)
|
|
||||||
else:
|
|
||||||
reply = cursor.fetchone()[0]
|
|
||||||
irc.reply(reply)
|
|
||||||
|
|
||||||
def info(self, irc, msg, args):
|
def info(self, irc, msg, args):
|
||||||
"""[<channel>] <lart|excuse|insult|praise> <id>
|
"""[<channel>] <lart|insult|praise> <id>
|
||||||
|
|
||||||
Gets the info for the record with id <id> from the table specified.
|
Gets the info for the record with id <id> from the type specified.
|
||||||
<channel> is only necessary if the message isn't sent in the channel
|
<channel> is only necessary if the message isn't sent in the channel
|
||||||
itself.
|
itself.
|
||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(table, id) = privmsgs.getArgs(args, required=2)
|
(type, id) = privmsgs.getArgs(args, required=2)
|
||||||
table = table.lower()
|
if not self._validType(irc, type):
|
||||||
|
return
|
||||||
|
id = self._validId(irc, id)
|
||||||
|
if id is None:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
id = int(id)
|
(text, by) = self.db.info(channel, type, id)
|
||||||
except ValueError:
|
reply = '%s #%s: %r; Created by %s.' % (type, id, text, by)
|
||||||
irc.error('The <id> argument must be an integer.')
|
|
||||||
return
|
|
||||||
if table not in self._tables:
|
|
||||||
irc.error('"%s" is not valid. Valid values include %s.' %
|
|
||||||
(table, utils.commaAndify(self._tables)))
|
|
||||||
return
|
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
sql = """SELECT added_by FROM %ss WHERE id=%%s""" % table
|
|
||||||
cursor.execute(sql, id)
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There is no such %s.' % table)
|
|
||||||
else:
|
|
||||||
add = cursor.fetchone()[0]
|
|
||||||
reply = '%s #%s: Created by %s.' % (table, id, add)
|
|
||||||
irc.reply(reply)
|
irc.reply(reply)
|
||||||
|
except KeyError:
|
||||||
|
irc.error('There is no %s with that id.' % type)
|
||||||
|
|
||||||
def _formatResponse(self, s, id, showids):
|
def _formatResponse(self, s, id, channel):
|
||||||
if showids:
|
if self.registryValue('showIds', channel):
|
||||||
return '%s (#%s)' % (s, id)
|
return '%s (#%s)' % (s, id)
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
_meRe = re.compile(r'\bme\b', re.I)
|
||||||
|
_myRe = re.compile(r'\bmy\b', re.I)
|
||||||
|
def _replaceFirstPerson(self, s, nick):
|
||||||
|
s = self._meRe.sub(nick, s)
|
||||||
|
s = self._myRe.sub('%s\'s' % nick, s)
|
||||||
|
return s
|
||||||
|
|
||||||
def insult(self, irc, msg, args):
|
def insult(self, irc, msg, args):
|
||||||
"""[<channel>] <nick>
|
"""[<channel>] <nick>
|
||||||
|
|
||||||
@ -333,57 +365,16 @@ class FunDB(callbacks.Privmsg, plugins.ChannelDBHandler):
|
|||||||
nick = privmsgs.getArgs(args)
|
nick = privmsgs.getArgs(args)
|
||||||
if not nick:
|
if not nick:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
db = self.getDb(channel)
|
t = self.db.random(channel, 'insult')
|
||||||
cursor = db.cursor()
|
if t is None:
|
||||||
cursor.execute("""SELECT id, insult FROM insults
|
|
||||||
WHERE insult NOT NULL
|
|
||||||
ORDER BY random()
|
|
||||||
LIMIT 1""")
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There are currently no available insults.')
|
irc.error('There are currently no available insults.')
|
||||||
else:
|
else:
|
||||||
(id, insult) = cursor.fetchone()
|
(id, insult) = t
|
||||||
nick = re.sub(r'\bme\b', msg.nick, nick)
|
nick = self._replaceFirstPerson(nick, msg.nick)
|
||||||
nick = re.sub(r'\bmy\b', '%s\'s' % msg.nick, nick)
|
|
||||||
insult = '%s: %s' % (nick, insult.replace('$who', nick))
|
insult = '%s: %s' % (nick, insult.replace('$who', nick))
|
||||||
showid = self.registryValue('showIds', channel)
|
irc.reply(self._formatResponse(insult, id, channel),
|
||||||
irc.reply(self._formatResponse(insult, id, showid),
|
|
||||||
prefixName=False)
|
prefixName=False)
|
||||||
|
|
||||||
def excuse(self, irc, msg, args):
|
|
||||||
"""[<channel>] [<id>]
|
|
||||||
|
|
||||||
Gives you a standard, random BOFH excuse or the excuse with the given
|
|
||||||
<id>. <channel> is only necessary if the message isn't sent in the
|
|
||||||
channel itself.
|
|
||||||
"""
|
|
||||||
channel = privmsgs.getChannel(msg, args)
|
|
||||||
id = privmsgs.getArgs(args, required=0, optional=1)
|
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
if id:
|
|
||||||
try:
|
|
||||||
id = int(id)
|
|
||||||
except ValueError:
|
|
||||||
irc.error('The <id> argument must be an integer.')
|
|
||||||
return
|
|
||||||
cursor.execute("""SELECT id, excuse FROM excuses WHERE id=%s""",
|
|
||||||
id)
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There is no such excuse.')
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
cursor.execute("""SELECT id, excuse FROM excuses
|
|
||||||
WHERE excuse NOTNULL
|
|
||||||
ORDER BY random()
|
|
||||||
LIMIT 1""")
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There are currently no available excuses.')
|
|
||||||
else:
|
|
||||||
(id, excuse) = cursor.fetchone()
|
|
||||||
showid = self.registryValue('showIds', channel)
|
|
||||||
irc.reply(self._formatResponse(excuse, id, showid))
|
|
||||||
|
|
||||||
def lart(self, irc, msg, args):
|
def lart(self, irc, msg, args):
|
||||||
"""[<channel>] [<id>] <text> [for <reason>]
|
"""[<channel>] [<id>] <text> [for <reason>]
|
||||||
|
|
||||||
@ -393,51 +384,39 @@ class FunDB(callbacks.Privmsg, plugins.ChannelDBHandler):
|
|||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(id, nick) = privmsgs.getArgs(args, optional=1)
|
(id, nick) = privmsgs.getArgs(args, optional=1)
|
||||||
try:
|
id = self._validId(irc, id, error=False)
|
||||||
id = int(id)
|
if id is None:
|
||||||
if id < 1:
|
nick = privmsgs.getArgs(args)
|
||||||
irc.error('There is no such lart.')
|
|
||||||
return
|
|
||||||
except ValueError:
|
|
||||||
nick = ' '.join([id, nick]).strip()
|
|
||||||
id = 0
|
|
||||||
nick = nick.rstrip('.')
|
nick = nick.rstrip('.')
|
||||||
if not nick:
|
if not nick:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
if nick == irc.nick:
|
if nick == irc.nick:
|
||||||
nick = msg.nick
|
nick = msg.nick
|
||||||
try:
|
try:
|
||||||
(nick, reason) = imap(' '.join,
|
(nick, reason) = itertools.imap(' '.join,
|
||||||
utils.itersplit('for'.__eq__, nick.split(), 1))
|
utils.itersplit('for'.__eq__, nick.split(), 1))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
reason = ''
|
reason = ''
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
if id:
|
if id:
|
||||||
cursor.execute("""SELECT id, lart FROM larts WHERE id=%s""", id)
|
try:
|
||||||
if cursor.rowcount == 0:
|
lart = self.db.get(channel, 'lart', id)
|
||||||
|
t = (id, lart)
|
||||||
|
except KeyError:
|
||||||
irc.error('There is no such lart.')
|
irc.error('There is no such lart.')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
cursor.execute("""SELECT id, lart FROM larts
|
t = self.db.random(channel, 'lart')
|
||||||
WHERE lart NOTNULL
|
if t is None:
|
||||||
ORDER BY random()
|
|
||||||
LIMIT 1""")
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There are currently no available larts.')
|
irc.error('There are currently no available larts.')
|
||||||
else:
|
else:
|
||||||
(id, lart) = cursor.fetchone()
|
(id, lart) = t
|
||||||
nick = re.sub(r'\bme\b', msg.nick, nick)
|
nick = self._replaceFirstPerson(nick, msg.nick)
|
||||||
reason = re.sub(r'\bme\b', msg.nick, reason)
|
reason = self._replaceFirstPerson(reason, msg.nick)
|
||||||
nick = re.sub(r'\bmy\b', '%s\'s' % msg.nick, nick)
|
s = lart.replace('$who', nick)
|
||||||
reason = re.sub(r'\bmy\b', '%s\'s' % msg.nick, reason)
|
|
||||||
lartee = nick
|
|
||||||
s = lart.replace('$who', lartee)
|
|
||||||
if reason:
|
if reason:
|
||||||
s = '%s for %s' % (s, reason)
|
s = '%s for %s' % (s, reason)
|
||||||
s = s.rstrip('.')
|
s = s.rstrip('.')
|
||||||
showid = self.registryValue('showIds', channel)
|
irc.reply(self._formatResponse(s, id, channel), action=True)
|
||||||
irc.reply(self._formatResponse(s, id, showid), action=True)
|
|
||||||
|
|
||||||
def praise(self, irc, msg, args):
|
def praise(self, irc, msg, args):
|
||||||
"""[<channel>] [<id>] <text> [for <reason>]
|
"""[<channel>] [<id>] <text> [for <reason>]
|
||||||
@ -449,90 +428,39 @@ class FunDB(callbacks.Privmsg, plugins.ChannelDBHandler):
|
|||||||
"""
|
"""
|
||||||
channel = privmsgs.getChannel(msg, args)
|
channel = privmsgs.getChannel(msg, args)
|
||||||
(id, nick) = privmsgs.getArgs(args, optional=1)
|
(id, nick) = privmsgs.getArgs(args, optional=1)
|
||||||
try:
|
id = self._validId(irc, id, error=False)
|
||||||
id = int(id)
|
if id is None:
|
||||||
if id < 1:
|
nick = privmsgs.getArgs(args)
|
||||||
irc.error('There is no such praise.')
|
|
||||||
return
|
|
||||||
except ValueError:
|
|
||||||
nick = ' '.join([id, nick]).strip()
|
|
||||||
id = 0
|
|
||||||
nick = nick.rstrip('.')
|
nick = nick.rstrip('.')
|
||||||
if not nick:
|
if not nick:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
try:
|
try:
|
||||||
(nick, reason) = imap(' '.join,
|
(nick, reason) = itertools.imap(' '.join,
|
||||||
utils.itersplit('for'.__eq__, nick.split(), 1))
|
utils.itersplit('for'.__eq__, nick.split(), 1))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
reason = ''
|
reason = ''
|
||||||
db = self.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
if id:
|
if id:
|
||||||
cursor.execute("""SELECT id, praise FROM praises WHERE id=%s""",id)
|
try:
|
||||||
if cursor.rowcount == 0:
|
praise = self.db.get(channel, 'praise', id)
|
||||||
|
t = (id, praise)
|
||||||
|
except KeyError:
|
||||||
irc.error('There is no such praise.')
|
irc.error('There is no such praise.')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
cursor.execute("""SELECT id, praise FROM praises
|
t = self.db.random(channel, 'praise')
|
||||||
WHERE praise NOTNULL
|
if t is None:
|
||||||
ORDER BY random()
|
|
||||||
LIMIT 1""")
|
|
||||||
if cursor.rowcount == 0:
|
|
||||||
irc.error('There are currently no available praises.')
|
irc.error('There are currently no available praises.')
|
||||||
else:
|
else:
|
||||||
(id, praise) = cursor.fetchone()
|
(id, praise) = t
|
||||||
nick = re.sub(r'\bme\b', msg.nick, nick)
|
nick = self._replaceFirstPerson(nick, msg.nick)
|
||||||
reason = re.sub(r'\bme\b', msg.nick, reason)
|
reason = self._replaceFirstPerson(reason, msg.nick)
|
||||||
nick = re.sub(r'\bmy\b', '%s\'s' % msg.nick, nick)
|
s = praise.replace('$who', nick)
|
||||||
reason = re.sub(r'\bmy\b', '%s\'s' % msg.nick, reason)
|
|
||||||
praisee = nick
|
|
||||||
s = praise.replace('$who', praisee)
|
|
||||||
if reason:
|
if reason:
|
||||||
s = '%s for %s' % (s, reason)
|
s = '%s for %s' % (s, reason)
|
||||||
s = s.rstrip('.')
|
s = s.rstrip('.')
|
||||||
showid = self.registryValue('showIds', channel)
|
irc.reply(self._formatResponse(s, id, channel), action=True)
|
||||||
irc.reply(self._formatResponse(s, id, showid), action=True)
|
|
||||||
|
|
||||||
Class = FunDB
|
Class = FunDB
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
if len(sys.argv) < 3 or len(sys.argv) > 4:
|
|
||||||
print 'Usage: %s <channel> <larts|excuses|insults|zipcodes> file' \
|
|
||||||
' [<console>]' % sys.argv[0]
|
|
||||||
sys.exit(-1)
|
|
||||||
if len(sys.argv) == 4:
|
|
||||||
added_by = sys.argv.pop()
|
|
||||||
else:
|
|
||||||
added_by = '<console>'
|
|
||||||
(channel, category, filename) = sys.argv[1:]
|
|
||||||
plugin = Class()
|
|
||||||
db = plugin.getDb(channel)
|
|
||||||
cursor = db.cursor()
|
|
||||||
for line in open(filename, 'r'):
|
|
||||||
line = line.rstrip()
|
|
||||||
if not line:
|
|
||||||
continue
|
|
||||||
elif category == 'larts':
|
|
||||||
if '$who' in line:
|
|
||||||
cursor.execute("""INSERT INTO larts VALUES (NULL, %s, %s)""",
|
|
||||||
line, added_by)
|
|
||||||
else:
|
|
||||||
print 'Invalid lart: %s' % line
|
|
||||||
elif category == 'praises':
|
|
||||||
if '$who' in line:
|
|
||||||
cursor.execute("""INSERT INTO praises VALUES (NULL, %s, %s)""",
|
|
||||||
line, added_by)
|
|
||||||
else:
|
|
||||||
print 'Invalid praise: %s' % line
|
|
||||||
elif category == 'insults':
|
|
||||||
cursor.execute("""INSERT INTO insults VALUES (NULL, %s, %s)""",
|
|
||||||
line, added_by)
|
|
||||||
elif category == 'excuses':
|
|
||||||
cursor.execute("""INSERT INTO excuses VALUES (NULL, %s, %s )""",
|
|
||||||
line, added_by)
|
|
||||||
db.commit()
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||||
|
@ -122,20 +122,6 @@ if sqlite is not None:
|
|||||||
self.assertNotError('remove praise 1')
|
self.assertNotError('remove praise 1')
|
||||||
self.assertNotError('remove insult 1')
|
self.assertNotError('remove insult 1')
|
||||||
|
|
||||||
def testExcuse(self):
|
|
||||||
self.assertNotError('add excuse Power failure')
|
|
||||||
self.assertResponse('excuse', 'Power failure (#1)')
|
|
||||||
self.assertError('excuse a few random words')
|
|
||||||
self.assertRegexp('stats excuse', r'currently 1 excuse')
|
|
||||||
self.assertNotError('add excuse /pub/lunch')
|
|
||||||
self.assertResponse('excuse 1', 'Power failure (#1)')
|
|
||||||
self.assertNotError('remove excuse 1')
|
|
||||||
self.assertRegexp('stats excuse', r'currently 1 excuse')
|
|
||||||
self.assertResponse('excuse', '/pub/lunch (#2)')
|
|
||||||
self.assertNotError('remove excuse 2')
|
|
||||||
self.assertRegexp('stats excuse', r'currently 0')
|
|
||||||
self.assertError('excuse')
|
|
||||||
|
|
||||||
def testInsult(self):
|
def testInsult(self):
|
||||||
self.assertNotError('add insult Fatty McFatty')
|
self.assertNotError('add insult Fatty McFatty')
|
||||||
self.assertResponse('insult jemfinch',
|
self.assertResponse('insult jemfinch',
|
||||||
@ -152,8 +138,6 @@ if sqlite is not None:
|
|||||||
self.assertNotError('add lart stubs $who')
|
self.assertNotError('add lart stubs $who')
|
||||||
self.assertNotError('add #tester insult nimrod')
|
self.assertNotError('add #tester insult nimrod')
|
||||||
self.assertNotError('add insult nimwit')
|
self.assertNotError('add insult nimwit')
|
||||||
self.assertNotError('add #tester excuse He did it!')
|
|
||||||
self.assertNotError('add excuse She did it!')
|
|
||||||
self.assertResponse('praise jemfinch',
|
self.assertResponse('praise jemfinch',
|
||||||
'\x01ACTION pats jemfinch (#1)\x01')
|
'\x01ACTION pats jemfinch (#1)\x01')
|
||||||
self.assertResponse('praise #tester jemfinch',
|
self.assertResponse('praise #tester jemfinch',
|
||||||
@ -165,8 +149,6 @@ if sqlite is not None:
|
|||||||
self.assertResponse('insult jemfinch', 'jemfinch: nimwit (#1)')
|
self.assertResponse('insult jemfinch', 'jemfinch: nimwit (#1)')
|
||||||
self.assertResponse('insult #tester jemfinch',
|
self.assertResponse('insult #tester jemfinch',
|
||||||
'jemfinch: nimrod (#1)')
|
'jemfinch: nimrod (#1)')
|
||||||
self.assertResponse('excuse', 'She did it! (#1)')
|
|
||||||
self.assertResponse('excuse #tester', 'He did it! (#1)')
|
|
||||||
|
|
||||||
def testPraise(self):
|
def testPraise(self):
|
||||||
self.assertNotError('add praise pets $who')
|
self.assertNotError('add praise pets $who')
|
||||||
@ -211,7 +193,6 @@ if sqlite is not None:
|
|||||||
self.assertError('stats 1')
|
self.assertError('stats 1')
|
||||||
self.assertRegexp('stats praise', r'currently 0')
|
self.assertRegexp('stats praise', r'currently 0')
|
||||||
self.assertRegexp('stats lart', r'currently 0')
|
self.assertRegexp('stats lart', r'currently 0')
|
||||||
self.assertRegexp('stats excuse', r'currently 0')
|
|
||||||
self.assertRegexp('stats insult', r'currently 0')
|
self.assertRegexp('stats insult', r'currently 0')
|
||||||
|
|
||||||
def testChange(self):
|
def testChange(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user