Limnoria/plugins/Infobot.py

216 lines
8.0 KiB
Python
Executable File

#!/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.
###
"""
A plugin that tries to emulate Infobot somewhat faithfully.
"""
__revision__ = "$Id$"
import plugins
import re
import os.path
import conf
import ircmsgs
import 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/>'
dbfilename = os.path.join(conf.dataDir, 'Infobot.db')
def configure(onStart, afterConnect, advanced):
from questions import expect, anything, something, yn
onStart.append('load Infobot')
def makeDb(filename):
if os.path.exists(filename):
return sqlite.connect(filename)
db = sqlite.connect(filename)
cursor = db.cursor()
cursor.execute("""CREATE TABLE is_factoids (
key TEXT UNIQUE ON CONFLICT REPLACE,
value TEXT
)""")
cursor.execute("""CREATE TABLE are_factoids (
key TEXT UNIQUE ON CONFLICT REPLACE,
value TEXT
)""")
cursor.execute("""CREATE TABLE dont_knows (saying TEXT)""")
for s in ('I don\'t know.', 'No idea.', 'I don\'t have a clue.', 'Dunno.'):
cursor.execute("""INSERT INTO dont_knows VALUES (%s)""", s)
cursor.execute("""CREATE TABLE statements (saying TEXT)""")
for s in ('I heard', 'Rumor has it', 'I think', 'I\'m pretty sure'):
cursor.execute("""INSERT INTO statements VALUES (%s)""", s)
cursor.execute("""CREATE TABLE confirms (saying TEXT)""")
for s in ('Gotcha', 'Ok', '10-4', 'I hear ya', 'Got it'):
cursor.execute("""INSERT INTO confirms VALUES (%s)""", s)
cursor.execute("""CREATE INDEX is_key ON is_factoids (key)""")
cursor.execute("""CREATE INDEX are_key ON are_factoids (key)""")
db.commit()
return db
class Infobot(callbacks.PrivmsgRegexp):
def __init__(self):
callbacks.PrivmsgRegexp.__init__(self)
self.db = makeDb(dbfilename)
def die(self):
self.db.commit()
self.db.close()
def getRandomSaying(self, table):
cursor = self.db.cursor()
sql = 'SELECT saying FROM %s ORDER BY random() LIMIT 1' % table
cursor.execute(sql)
return cursor.fetchone()[0]
def getFactoid(self, key):
cursor = self.db.cursor()
cursor.execute('SELECT value FROM is_factoids WHERE key=%s', key)
if cursor.rowcount != 0:
statement = self.getRandomSaying('statements')
value = cursor.fetchone()[0]
return '%s %s is %s' % (statement, key, value)
cursor.execute('SELECT value FROM are_factoids WHERE key=%s', key)
if cursor.rowcount != 0:
statement = self.getRandomSaying('statements')
value = cursor.fetchone()[0]
return '%s %s are %s' % (statement, key, value)
raise KeyError, key
def hasFactoid(self, key, isAre):
cursor = self.db.cursor()
sql = 'SELECT COUNT(*) FROM %s_factoids WHERE key=%%s' % isAre
cursor.execute(sql, key)
return int(cursor.fetchone()[0])
def insertFactoid(self, key, isAre, value):
cursor = self.db.cursor()
sql = 'INSERT INTO %s_factoids VALUES (%%s, %%s)' % isAre
cursor.execute(sql, key, value)
self.db.commit()
def forget(self, irc, msg, match):
r"^forget\s+(.+?)(?!\?+)[?.! ]*$"
key = match.group(1)
cursor = self.db.cursor()
cursor.execute('DELETE FROM is_factoids WHERE key=%s', key)
cursor.execute('DELETE FROM are_factoids WHERE key=%s', key)
irc.reply(msg, self.getRandomSaying('confirms'))
def tell(self, irc, msg, match):
r"^tell\s+(.+?)\s+about\s+(.+?)(?!\?+)[.! ]*$"
(nick, key) = match.groups()
try:
s = '%s wants you to know that %s' %(msg.nick,self.getFactoid(key))
irc.reply(nick, s)
except KeyError:
irc.reply(msg, 'I don\'t know anything about %s' % key)
def factoid(self, irc, msg, match):
r"^(no[ :,-]+)?(.+?)\s+(was|is|am|were|are)\s+(also\s+)?(.+?)(?!\?+)$"
(correction, key, isAre, addition, value) = match.groups()
if self.hasFactoid(key, isAre):
if not correction:
factoid = self.getFactoid(key)
irc.reply(msg, 'No, %s %s %s' % (key, isAre, factoid))
elif addition:
factoid = self.getFactoid(key)
newFactoid = '%s, or %s' % (factoid, value)
self.insertFactoid(key, isAre, newFactoid)
irc.reply(msg, self.getRandomSaying('confirms'))
else:
self.insertFactoid(key, isAre, value)
irc.reply(msg, self.getRandomSaying('confirms'))
return
else:
self.insertFactoid(key, isAre, value)
irc.reply(msg, self.getRandomSaying('confirms'))
def unknown(self, irc, msg, match):
r"^(.+?)\?[?.! ]*$"
key = match.group(1)
try:
irc.reply(msg, self.getFactoid(key))
except KeyError:
irc.reply(msg, self.getRandomSaying('dont_knows'))
def info(self, irc, msg, match):
r"^info$"
cursor = self.db.cursor()
cursor.execute("SELECT COUNT(*) FROM is_factoids")
numIs = cursor.fetchone()[0]
cursor.execute("SELECT COUNT(*) FROM are_factoids")
numAre = cursor.fetchone()[0]
s = 'I have %s is factoids and %s are factoids' % (numIs, numAre)
irc.reply(msg, s)
Class = Infobot
if __name__ == '__main__':
import sys
if len(sys.argv) < 2 and sys.argv[1] not in ('is', 'are'):
print 'Usage: %s <is|are> <factpack> [<factpack> ...]' % sys.argv[0]
sys.exit(-1)
r = re.compile(r'\s+=>\s+')
db = makeDb(dbfilename)
cursor = db.cursor()
if sys.argv[1] == 'is':
table = 'is_factoids'
else:
table = 'are_factoids'
sql = 'INSERT INTO %s VALUES (%%s, %%s)' % table
for filename in sys.argv[2:]:
fd = file(filename)
for line in fd:
line = line.strip()
if not line or line[0] in ('*', '#'):
continue
else:
try:
(key, value) = r.split(line, 1)
cursor.execute(sql, key, value)
except Exception, e:
print 'Invalid line (%s): %r' %(utils.exnToString(e),line)
db.commit()
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: