mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-26 20:59:27 +01:00
228 lines
9.0 KiB
Python
228 lines
9.0 KiB
Python
#!/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.
|
|
###
|
|
|
|
"""
|
|
Handles "factoids," little tidbits of information held in a database and
|
|
available on demand via several commands.
|
|
|
|
Commands include:
|
|
addfactoid
|
|
removefactoid
|
|
lookupfactoid
|
|
lockfactoid
|
|
unlockfactoid
|
|
randomfactoid
|
|
factoidinfo
|
|
"""
|
|
|
|
from baseplugin import *
|
|
|
|
import time
|
|
import os.path
|
|
|
|
import sqlite
|
|
|
|
import conf
|
|
import ircdb
|
|
import privmsgs
|
|
import callbacks
|
|
|
|
class Factoids(DBHandler, callbacks.Privmsg):
|
|
def __init__(self):
|
|
DBHandler.__init__(self)
|
|
callbacks.Privmsg.__init__(self)
|
|
|
|
def makeDb(self, filename):
|
|
if os.path.exists(filename):
|
|
return sqlite.connect(filename)
|
|
db = sqlite.connect(filename)
|
|
cursor = db.cursor()
|
|
cursor.execute("""CREATE TABLE keys (
|
|
id INTEGER PRIMARY KEY,
|
|
key TEXT,
|
|
locked BOOLEAN
|
|
)""")
|
|
cursor.execute("""CREATE TABLE factoids (
|
|
id INTEGER PRIMARY KEY,
|
|
key_id INTEGER,
|
|
added_by TEXT,
|
|
added_at TIMESTAMP,
|
|
fact TEXT
|
|
)""")
|
|
cursor.execute("""CREATE TRIGGER remove_factoids
|
|
BEFORE DELETE ON keys
|
|
BEGIN
|
|
DELETE FROM factoids WHERE key_id = old.id;
|
|
END
|
|
""")
|
|
db.commit()
|
|
return db
|
|
|
|
def addfactoid(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself) <key> <value>"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
(key, factoid) = privmsgs.getArgs(args, needed=2)
|
|
db = self.getDb(channel)
|
|
cursor = db.cursor()
|
|
cursor.execute("""SELECT id, locked FROM keys WHERE key=%s""", key)
|
|
if cursor.rowcount == 0:
|
|
cursor.execute("""INSERT INTO keys VALUES (NULL, %s, 0)""", key)
|
|
db.commit()
|
|
cursor.execute("""SELECT id, locked FROM keys WHERE key=%s""", key)
|
|
(id, locked) = map(int, cursor.fetchone())
|
|
capability = ircdb.makeChannelCapability(channel, 'factoids')
|
|
if not locked:
|
|
if not ircdb.checkCapability(msg.prefix, capability):
|
|
irc.error(msg, conf.replyNoCapability % capability)
|
|
return
|
|
if ircdb.users.hasUser(msg.prefix):
|
|
name = ircdb.users.getUserName(msg.prefix)
|
|
else:
|
|
name = msg.nick
|
|
cursor.execute("""INSERT INTO factoids VALUES
|
|
(NULL, %s, %s, %s, %s)""",
|
|
id, name, int(time.time()), factoid)
|
|
db.commit()
|
|
irc.reply(msg, conf.replySuccess)
|
|
else:
|
|
irc.error(msg, 'That factoid is locked.')
|
|
|
|
def lookupfactoid(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself) <key> [<number>]"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
(key, number) = privmsgs.getArgs(args, optional=1)
|
|
try:
|
|
number = int(number)
|
|
except ValueError:
|
|
key += number
|
|
number = 0
|
|
db = self.getDb(channel)
|
|
cursor = db.cursor()
|
|
cursor.execute("""SELECT factoids.fact FROM factoids, keys WHERE
|
|
keys.key=%s AND factoids.key_id=keys.id
|
|
ORDER BY factoids.id""", key)
|
|
results = cursor.fetchall()
|
|
if len(results) == 0:
|
|
irc.error(msg, 'No factoid matches that key.')
|
|
else:
|
|
factoid = results[number][0]
|
|
irc.reply(msg, '%s/%s: %s' % (key, number, factoid))
|
|
|
|
def lockfactoid(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself) <key>"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
key = privmsgs.getArgs(args)
|
|
db = self.getDb(channel)
|
|
capability = ircdb.makeChannelCapability(channel, 'factoids')
|
|
if ircdb.checkCapability(msg.prefix, capability):
|
|
cursor = db.cursor()
|
|
cursor.execute("""UPDATE keys SET locked = 1 WHERE key=%s""", key)
|
|
db.commit()
|
|
irc.reply(msg, conf.replySuccess)
|
|
else:
|
|
irc.error(msg, conf.replyNoCapability % capability)
|
|
|
|
def unlockfactoid(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself) <key>"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
key = privmsgs.getArgs(args)
|
|
db = self.getDb(channel)
|
|
capability = ircdb.makeChannelCapability(channel, 'factoids')
|
|
if ircdb.checkCapability(msg.prefix, capability):
|
|
cursor = db.cursor()
|
|
cursor.execute("""UPDATE keys SET locked = 0 WHERE key=%s""", key)
|
|
db.commit()
|
|
irc.reply(msg, conf.replySuccess)
|
|
else:
|
|
irc.error(msg, conf.replyNoCapability % capability)
|
|
|
|
def removefactoid(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself) <key>"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
key = privmsgs.getArgs(args)
|
|
db = self.getDb(channel)
|
|
capability = ircdb.makeChannelCapability(channel, 'factoids')
|
|
if ircdb.checkCapability(msg.prefix, capability):
|
|
cursor = db.cursor()
|
|
cursor.execute("""DELETE FROM keys WHERE key=%s""", key)
|
|
db.commit()
|
|
irc.reply(msg, conf.replySuccess)
|
|
else:
|
|
irc.error(msg, conf.replyNoCapability % capability)
|
|
|
|
def randomfactoid(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself)"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
db = self.getDb(channel)
|
|
cursor = db.cursor()
|
|
cursor.execute("""SELECT fact, key_id FROM factoids
|
|
ORDER BY random()
|
|
LIMIT 1""")
|
|
if cursor.rowcount != 0:
|
|
(factoid, keyId) = cursor.fetchone()
|
|
cursor.execute("""SELECT key FROM keys WHERE id=%s""", keyId)
|
|
key = cursor.fetchone()[0]
|
|
irc.reply(msg, '%s: %s' % (key, factoid))
|
|
else:
|
|
irc.error(msg, 'I couldn\'t find a factoid.')
|
|
|
|
def factoidinfo(self, irc, msg, args):
|
|
"[<channel>] (If not sent in the channel itself) <key>"
|
|
channel = privmsgs.getChannel(msg, args)
|
|
key = privmsgs.getArgs(args)
|
|
db = self.getDb(channel)
|
|
cursor = db.cursor()
|
|
cursor.execute("""SELECT id, locked FROM keys WHERE key=%s""", key)
|
|
if cursor.rowcount == 0:
|
|
irc.error(msg, 'No factoid matches that key.')
|
|
return
|
|
(id, locked) = map(int, cursor.fetchone())
|
|
cursor.execute("""SELECT added_by, added_at FROM factoids
|
|
WHERE key_id=%s
|
|
ORDER BY id""", id)
|
|
factoids = cursor.fetchall()
|
|
L = []
|
|
counter = 0
|
|
for (added_by, added_at) in factoids:
|
|
added_at = time.strftime(conf.timestampFormat,
|
|
time.localtime(int(added_at)))
|
|
L.append('#%s was added by %s at %s' % (counter,added_by,added_at))
|
|
counter += 1
|
|
factoids = '; '.join(L)
|
|
s = 'Key %r is %s and has %s factoids associated with it: %s' % \
|
|
(key, locked and 'locked' or 'not locked', counter, '; '.join(L))
|
|
irc.reply(msg, s)
|
|
|
|
|
|
|
|
Class = Factoids
|
|
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|