convert to a MySQL backend

WARNING!
there's no going back now. this change is *huge* but it was overdue.
WARNING!

the database backend is now mysql. modules that should use a database
but don't yet were left untouched, they'll come later. scripts haven't
been converted yet, though i'm pretty sure i'll need to soon.

while i was going through everything, connection/cursor idioms were
cleaned up, as were a bunch of log messages and exception handling. this
change is so gross i'm happy things appear to be working, which is
the case --- all modules are lightly tested.
This commit is contained in:
Brian S. Stephan 2012-07-27 02:18:01 -05:00
parent deedf330e3
commit 1a36becead
14 changed files with 760 additions and 763 deletions

View File

@ -21,9 +21,10 @@ from ConfigParser import NoSectionError, NoOptionError
import logging import logging
import re import re
import sys import sys
import sqlite3
from threading import Timer from threading import Timer
import MySQLdb as mdb
from extlib import irclib from extlib import irclib
class Module(object): class Module(object):
@ -165,7 +166,7 @@ class Module(object):
def get_db(self): def get_db(self):
""" """
Get a database connection to sqlite3. Once grabbed, it should be closed Get a database connection to mdb. Once grabbed, it should be closed
when work is done. Modules that need a database connection should when work is done. Modules that need a database connection should
test for and create (or, eventually, alter) required table structure test for and create (or, eventually, alter) required table structure
in their __init__ IF that structure does not already exist. Well-behaved in their __init__ IF that structure does not already exist. Well-behaved
@ -175,17 +176,13 @@ class Module(object):
See also db_module_registered, below. See also db_module_registered, below.
""" """
dbfile = self.config.get('dr.botzo', 'database') dbhost = self.config.get('dr.botzo', 'dbhost')
conn = sqlite3.connect(dbfile, isolation_level=None) dbuser = self.config.get('dr.botzo', 'dbuser')
conn.row_factory = sqlite3.Row dbpass = self.config.get('dr.botzo', 'dbpass')
dbname = self.config.get('dr.botzo', 'dbname')
db = mdb.connect(dbhost, dbuser, dbpass, dbname, use_unicode=True)
# setup regexp function in sqlite return db
def regexp(expr, item):
reg = re.compile(expr, re.IGNORECASE)
return reg.search(item) is not None
conn.create_function('REGEXP', 2, regexp)
return conn
def db_module_registered(self, modulename): def db_module_registered(self, modulename):
""" """
@ -193,19 +190,20 @@ class Module(object):
number if the module has registered, or None if not number if the module has registered, or None if not
""" """
conn = self.get_db() db = self.get_db()
version = None version = None
try: try:
cur = conn.cursor() cur = db.cursor()
cur.execute("SELECT version FROM drbotzo_modules WHERE module = :name", cur.execute("SELECT version FROM drbotzo_modules WHERE module = %s",
{'name': modulename}) (modulename,))
version = cur.fetchone() version = cur.fetchone()
if (version != None): if (version != None):
version = version[0] version = version[0]
conn.close() except mdb.Error as e:
except sqlite3.Error as e: self.log.error("database error during module registered check")
conn.close() self.log.exception(e)
self.log.error("sqlite error:" + str(e)) raise
finally: cur.close()
return version return version
@ -214,14 +212,16 @@ class Module(object):
db = self.get_db() db = self.get_db()
try: try:
db.execute('INSERT OR REPLACE INTO drbotzo_modules (version, module) VALUES (?, ?)', (version, modulename)) cur = db.cursor(mdb.cursors.DictCursor)
cur.execute('INSERT IGNORE INTO drbotzo_modules (version, module) VALUES (%s, %s)',
(version, modulename))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error during register module version")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def db_init(self): def db_init(self):
""" """

View File

@ -7,10 +7,13 @@ usermode = -x
debug = true debug = true
admin_userhost = bss@ayu.incorporeal.org admin_userhost = bss@ayu.incorporeal.org
module_list = IrcAdmin module_list = IrcAdmin
database = dr.botzo.data dbhost = localhost
dbuser = dr_botzo
dbpass = password
dbname = dr_botzo
[IrcAdmin] [IrcAdmin]
autojoin = #bss autojoin = #bss
[Karma] [Karma]
meta.pubmsg_needs_bot_prefix = false meta.pubmsg_needs_bot_prefix = false

View File

@ -21,7 +21,8 @@ import logging
import logging.config import logging.config
import os import os
import sys import sys
import sqlite3
import MySQLdb as mdb
import DrBotIRC import DrBotIRC
from extlib import irclib from extlib import irclib
@ -53,28 +54,31 @@ logging.config.fileConfig('logging.cfg')
log = logging.getLogger('drbotzo') log = logging.getLogger('drbotzo')
try: try:
# make sure we can initialize the database, if such a thing is dbhost = config.get('dr.botzo', 'dbhost')
# called for in the config file dbuser = config.get('dr.botzo', 'dbuser')
dbfile = config.get('dr.botzo', 'database') dbpass = config.get('dr.botzo', 'dbpass')
conn = sqlite3.connect(dbfile, isolation_level=None) dbname = config.get('dr.botzo', 'dbname')
db = mdb.connect(dbhost, dbuser, dbpass, dbname, use_unicode=True)
try: try:
cur = db.cursor()
# need to create the drbotzo_modules table if it doesn't exist
query = """ query = """
SELECT COUNT(*) SELECT COUNT(*) FROM information_schema.tables
FROM sqlite_master WHERE table_schema = %s
WHERE type = 'table' AND name = 'drbotzo_modules' AND table_name = %s
""" """
row = conn.execute(query).fetchone() cur.execute(query, (dbname, 'drbotzo_modules'))
row = cur.fetchone()
if row[0] == 0: if row[0] == 0:
# need to create the drbotzo_modules table
query = """ query = """
CREATE TABLE drbotzo_modules ( CREATE TABLE IF NOT EXISTS drbotzo_modules (
module TEXT PRIMARY KEY, module VARCHAR(64) PRIMARY KEY,
version INTEGER version INTEGER
) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
""" """
conn.execute(query) cur.execute(query)
conn.commit() db.commit()
finally: conn.close() finally: cur.close()
except NoOptionError as e: except NoOptionError as e:
sys.exit("Aborted due to error with necessary configuration: " + str(e)) sys.exit("Aborted due to error with necessary configuration: " + str(e))

View File

@ -17,10 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import re import re
import sqlite3
import thread import thread
import time import time
import MySQLdb as mdb
from Module import Module from Module import Module
from extlib import irclib from extlib import irclib
@ -73,89 +74,73 @@ class Achievements(Module):
db = self.get_db() db = self.get_db()
try: try:
version = 1 version = 1
db.execute(''' cur = db.cursor(mdb.cursors.DictCursor)
cur.execute('''
CREATE TABLE achievements_player ( CREATE TABLE achievements_player (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
nick TEXT NOT NULL UNIQUE, nick VARCHAR(64) NOT NULL UNIQUE,
userhost TEXT NOT NULL DEFAULT '', userhost VARCHAR(256) NOT NULL DEFAULT '',
is_playing INTEGER NOT NULL DEFAULT 0, is_playing INTEGER NOT NULL DEFAULT 0,
last_seen_time TEXT DEFAULT CURRENT_TIMESTAMP last_seen_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE TABLE achievements_event ( CREATE TABLE achievements_event (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
player_id INTEGER NOT NULL, player_id BIGINT(20) UNSIGNED NOT NULL,
event TEXT NOT NULL, event VARCHAR(64) NOT NULL,
target TEXT, target VARCHAR(64),
msg_len INTEGER, msg_len INTEGER,
event_time TEXT DEFAULT CURRENT_TIMESTAMP, event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(player_id) REFERENCES achievements_player(id) FOREIGN KEY(player_id) REFERENCES achievements_player(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE TABLE achievements_achievement ( CREATE TABLE achievements_achievement (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
name TEXT NOT NULL, name VARCHAR(256) NOT NULL,
desc TEXT NOT NULL, description VARCHAR(256) NOT NULL,
query TEXT NOT NULL query VARCHAR(1024) NOT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE TABLE achievements_log ( CREATE TABLE achievements_log (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
player_id INTEGER NOT NULL, player_id BIGINT(20) UNSIGNED NOT NULL,
achievement_id INTEGER NOT NULL, achievement_id BIGINT(20) UNSIGNED NOT NULL,
event_time TEXT DEFAULT CURRENT_TIMESTAMP, event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(player_id) REFERENCES achievements_player(id), FOREIGN KEY(player_id) REFERENCES achievements_player(id),
FOREIGN KEY(achievement_id) REFERENCES achievements_achievement(id) FOREIGN KEY(achievement_id) REFERENCES achievements_achievement(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.commit() ''')
db.close() cur.execute('''
self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e:
db.rollback()
db.close()
self.log.error("sqlite error: " + str(e))
raise
if (version < 2):
db = self.get_db()
try:
version = 2
db.execute('''
CREATE TABLE achievements_config ( CREATE TABLE achievements_config (
channel TEXT NOT NULL channel TEXT NOT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.commit() ''')
db.close() cur.execute('''
self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e:
db.rollback()
db.close()
self.log.error("sqlite error: " + str(e))
raise
if (version < 3):
db = self.get_db()
try:
version = 3
db.execute('''
CREATE TABLE achievements_filter ( CREATE TABLE achievements_filter (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
filter TEXT NOT NULL filter VARCHAR(256) NOT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE TABLE achievements_filter_log ( CREATE TABLE achievements_filter_log (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
filter_id INTEGER NOT NULL, filter_id BIGINT(20) UNSIGNED NOT NULL,
event_id INTEGER NOT NULL, event_id BIGINT(20) UNSIGNED NOT NULL,
FOREIGN KEY(filter_id) REFERENCES achievements_filter(id), FOREIGN KEY(filter_id) REFERENCES achievements_filter(id),
FOREIGN KEY(event_id) REFERENCES achievements_event(id) FOREIGN KEY(event_id) REFERENCES achievements_event(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
db.commit() db.commit()
db.close()
self.db_register_module_version(self.__class__.__name__, version) self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def register_handlers(self): def register_handlers(self):
"""Handle all sorts of things to track.""" """Handle all sorts of things to track."""
@ -247,37 +232,37 @@ class Achievements(Module):
def _get_or_add_player(self, nick, userhost): def _get_or_add_player(self, nick, userhost):
"""Add a player to the database, or update the existing one, and return the id.""" """Add a player to the database, or update the existing one, and return the id."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
INSERT OR IGNORE INTO achievements_player (nick) VALUES (?)''' INSERT IGNORE INTO achievements_player (nick) VALUES (%s)'''
cur.execute(statement, (nick,)) cur.execute(statement, (nick,))
statement = ''' statement = '''
UPDATE achievements_player SET userhost = ?, last_seen_time = CURRENT_TIMESTAMP UPDATE achievements_player SET userhost = %s, last_seen_time = CURRENT_TIMESTAMP
WHERE nick = ?''' WHERE nick = %s'''
cur.execute(statement, (userhost, nick)) cur.execute(statement, (userhost, nick))
db.commit() db.commit()
statement = '''SELECT id FROM achievements_player WHERE nick = ?''' statement = '''SELECT id FROM achievements_player WHERE nick = %s'''
cur = db.execute(statement, (nick,)) cur.execute(statement, (nick,))
result = cur.fetchone() result = cur.fetchone()
db.close()
return result['id'] return result['id']
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error getting or adding player")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _add_event(self, player_id, event, target, msg, msg_len): def _add_event(self, player_id, event, target, msg, msg_len):
"""Add an event to the log.""" """Add an event to the log."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
INSERT INTO achievements_event ( INSERT INTO achievements_event (
player_id, event, target, msg_len player_id, event, target, msg_len
) VALUES (?, ?, ?, ?) ) VALUES (%s, %s, %s, %s)
''' '''
cur.execute(statement, (player_id, event, target, msg_len)) cur.execute(statement, (player_id, event, target, msg_len))
db.commit() db.commit()
@ -285,135 +270,143 @@ class Achievements(Module):
# now see if the event matched any filters # now see if the event matched any filters
query = ''' query = '''
SELECT id FROM achievements_filter WHERE ? REGEXP filter SELECT id FROM achievements_filter WHERE %s REGEXP filter
''' '''
cursor = db.execute(query, (msg.decode('utf-8', 'replace'),)) cur.execute(query, (msg.decode('utf-8', 'replace'),))
results = cursor.fetchall() results = cur.fetchall()
for result in results: for result in results:
cur = db.cursor() cur = db.cursor(mdb.cursors.DictCursor)
statement = ''' statement = '''
INSERT INTO achievements_filter_log (filter_id, event_id) INSERT INTO achievements_filter_log (filter_id, event_id)
VALUES (?, ?) VALUES (%s, %s)
''' '''
cur.execute(statement, (result['id'], event_id)) cur.execute(statement, (result['id'], event_id))
db.commit() db.commit()
db.close()
return event_id return event_id
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error adding event")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_achievements_settings(self): def _get_achievements_settings(self):
"""Get the report settings.""" """Get the report settings."""
db = self.get_db()
try: try:
# get the settings # get the settings
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT channel FROM achievements_config' query = 'SELECT channel FROM achievements_config'
cursor = db.execute(query) cur.execute(query)
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
settings = self.AchievementsSettings() settings = self.AchievementsSettings()
settings.channel = result['channel'] settings.channel = result['channel']
return settings return settings
except sqlite3.Error as e: else:
db.close() return None
self.log.error('sqlite error: ' + str(e)) except mdb.Error as e:
self.log.error("database error getting settings")
self.log.exception(e)
raise raise
except AttributeError as e:
self.log.error("could not get channel settings, probably unset")
self.log.exception(e)
return None
finally: cur.close()
def _join_system(self, nick): def _join_system(self, nick):
"""Add the appropriate nick to the game.""" """Add the appropriate nick to the system."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = 'UPDATE achievements_player SET is_playing = 1 WHERE nick = %s'
statement = 'UPDATE achievements_player SET is_playing = 1 WHERE nick = ?'
cur.execute(statement, (nick,)) cur.execute(statement, (nick,))
db.commit() db.commit()
db.close()
return nick + ' joined.' return nick + ' joined.'
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error joining the system")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _leave_system(self, nick): def _leave_system(self, nick):
"""Remove the appropriate nick from the game.""" """Remove the appropriate nick from the system."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = 'UPDATE achievements_player SET is_playing = 0 WHERE nick = %s'
statement = 'UPDATE achievements_player SET is_playing = 0 WHERE nick = ?'
cur.execute(statement, (nick,)) cur.execute(statement, (nick,))
db.commit() db.commit()
db.close()
return nick + ' left.' return nick + ' left.'
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error leaving the system")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _add_player_to_achievement_log(self, player_id, achievement_id): def _add_player_to_achievement_log(self, player_id, achievement_id):
"""Log the success of a player.""" """Log the success of a player."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = 'INSERT INTO achievements_log (player_id, achievement_id) VALUES (%s, %s)'
statement = 'INSERT INTO achievements_log (player_id, achievement_id) VALUES (?, ?)'
cur.execute(statement, (player_id, achievement_id)) cur.execute(statement, (player_id, achievement_id))
db.commit() db.commit()
db.close()
return return
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error adding player to achievement log")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_achievement_info(self, achievement): def _get_achievement_info(self, achievement):
"""Return the description of a given achievement.""" """Return the description of a given achievement."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT desc FROM achievements_achievement WHERE name = ?' query = 'SELECT description FROM achievements_achievement WHERE name = %s'
cursor = db.execute(query, (achievement,)) cur.execute(query, (achievement,))
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
return result['desc'] return result['description']
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error getting achievement info")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_player_achievements(self, nick): def _get_player_achievements(self, nick):
"""Return the achievements the nick has.""" """Return the achievements the nick has."""
achievements = [] achievements = []
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT a.name FROM achievements_achievement a SELECT a.name FROM achievements_achievement a
INNER JOIN achievements_log l ON l.achievement_id = a.id INNER JOIN achievements_log l ON l.achievement_id = a.id
INNER JOIN achievements_player p ON p.id = l.player_id INNER JOIN achievements_player p ON p.id = l.player_id
WHERE p.nick = ? WHERE p.nick = %s
''' '''
cursor = db.execute(query, (nick,)) cur.execute(query, (nick,))
results = cursor.fetchall() results = cur.fetchall()
db.close()
for result in results: for result in results:
achievements.append(result['name']) achievements.append(result['name'])
return achievements return achievements
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error getting player achievements")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _do_achievement_scan(self): def _do_achievement_scan(self):
"""Run the queries in the database, seeing if anyone new has an achievement.""" """Run the queries in the database, seeing if anyone new has an achievement."""
@ -428,22 +421,26 @@ class Achievements(Module):
if self.connection is None: if self.connection is None:
return return
self.log.debug('in achievement scan')
settings = self._get_achievements_settings() settings = self._get_achievements_settings()
channel = settings.channel if settings is not None:
achievers = self._query_for_new_achievers() channel = settings.channel
for achiever in achievers: achievers = self._query_for_new_achievers()
self.sendmsg(self.connection, channel, achiever[0] + ' achieved ' + achiever[1] + '!') for achiever in achievers:
self.sendmsg(self.connection, channel, achiever[0] + ' achieved ' + achiever[1] + '!')
def _query_for_new_achievers(self): def _query_for_new_achievers(self):
"""Get new achievement earners for each achievement.""" """Get new achievement earners for each achievement."""
achievers = [] achievers = []
self.log.debug('checking achievements')
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT id, name, query FROM achievements_achievement' query = 'SELECT id, name, query FROM achievements_achievement'
cursor = db.execute(query) cur.execute(query)
achievements = cursor.fetchall() achievements = cur.fetchall()
for achievement in achievements: for achievement in achievements:
self.log.debug('checking achievement:[' + achievement['name'] + ']') self.log.debug('checking achievement:[' + achievement['name'] + ']')
@ -458,22 +455,22 @@ class Achievements(Module):
SELECT player_id FROM achievements_log l SELECT player_id FROM achievements_log l
INNER JOIN achievements_achievement a INNER JOIN achievements_achievement a
ON a.id = l.achievement_id ON a.id = l.achievement_id
WHERE a.name = ? WHERE a.name = %s
) )
''' '''
cursor = db.execute(query, (achievement['name'],)) cur.execute(query, (achievement['name'],))
ach_achievers = cursor.fetchall() ach_achievers = cur.fetchall()
for ach_achiever in ach_achievers: for ach_achiever in ach_achievers:
self.log.debug('name:[' + ach_achiever['nick'] + '] achievement:[' + achievement['name'] + ']') self.log.debug('name:[' + ach_achiever['nick'] + '] achievement:[' + achievement['name'] + ']')
self._add_player_to_achievement_log(ach_achiever['id'], achievement['id']) self._add_player_to_achievement_log(ach_achiever['id'], achievement['id'])
achievers.append((ach_achiever['nick'], achievement['name'])) achievers.append((ach_achiever['nick'], achievement['name']))
db.close()
return achievers return achievers
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error scanning new achievers")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent

View File

@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import random import random
import re import re
import sqlite3
import thread import thread
import time import time

View File

@ -18,7 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import random import random
import re import re
import sqlite3
import MySQLdb as mdb
from extlib import irclib from extlib import irclib
@ -46,38 +47,40 @@ class Facts(Module):
if version == None: if version == None:
db = self.get_db() db = self.get_db()
try: try:
db.execute(''' version = 1
cur = db.cursor(mdb.cursors.DictCursor)
cur.execute('''
CREATE TABLE facts_facts ( CREATE TABLE facts_facts (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
category TEXT NOT NULL, category VARCHAR(64) NOT NULL,
fact TEXT NOT NULL, fact LONGTEXT NOT NULL,
who TEXT NOT NULL, who VARCHAR(64) NOT NULL,
userhost TEXT NOT NULL, userhost VARCHAR(256) NOT NULL,
time TEXT DEFAULT CURRENT_TIMESTAMP time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''') ''')
db.execute('INSERT INTO drbotzo_modules VALUES (?,?)', (self.__class__.__name__, 1))
db.commit() db.commit()
db.close() self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Add or retrieve a fact from the database.""" """Add or retrieve a fact from the database."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
match = re.search('^!facts\s+add\s+(\S+)\s+(.*)$', what) match = re.search('^!facts\s+add\s+(\S+)\s+(.*)$', what)
if match: if match:
category = match.group(1) category = match.group(1)
fact = match.group(2) fact = match.group(2)
cur.execute('''INSERT INTO facts_facts (category, fact, who, userhost) cur.execute('''INSERT INTO facts_facts (category, fact, who, userhost)
VALUES (?, ?, ?, ?)''', (category, fact, nick, userhost)) VALUES (%s, %s, %s, %s)''', (category, fact, nick, userhost))
db.commit() db.commit()
return self.reply(connection, event, category + ' added.') return self.reply(connection, event, category + ' added.')
@ -91,10 +94,12 @@ class Facts(Module):
if match: if match:
category = match.group(1) category = match.group(1)
return self.reply(connection, event, self._get_fact(category)) return self.reply(connection, event, self._get_fact(category))
db.close() except mdb.Error as e:
except sqlite3.Error as e: db.rollback()
db.close() self.log.error("database error during add/retrieve")
return self.reply(connection, event, "sqlite error: " + str(e)) self.log.exception(e)
return self.reply(connection, event, "database error during add/retrieve fact")
finally: cur.close()
def _get_fact(self, category, search=""): def _get_fact(self, category, search=""):
""" """
@ -105,26 +110,27 @@ class Facts(Module):
search - the optional regex to match against within that category search - the optional regex to match against within that category
""" """
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
if search == "": if search == "":
category_facts = cur.execute("SELECT * FROM facts_facts WHERE category=?", (category,)) cur.execute("SELECT * FROM facts_facts WHERE category = %s",
facts = category_facts.fetchall() (category,))
db.close() facts = cur.fetchall()
else: else:
category_facts = cur.execute("SELECT * FROM facts_facts WHERE category=? AND fact REGEXP ?", cur.execute("SELECT * FROM facts_facts WHERE category = %s AND fact REGEXP %s",
(category, search)) (category, search))
facts = category_facts.fetchall() facts = cur.fetchall()
db.close()
if len(facts) > 0: if len(facts) > 0:
fact = facts[random.randint(1,len(facts))-1] fact = facts[random.randint(1,len(facts))-1]
return fact['fact'].rstrip().encode('utf-8', 'ignore') return fact['fact'].rstrip().encode('utf-8', 'ignore')
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _get_fact")
return self.reply(connection, event, "sqlite error in _get_fact: " + str(e)) self.log.exception(e)
return self.reply(connection, event, "database error in _get_fact")
finally: cur.close()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -17,7 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import re import re
import sqlite3
from Module import Module from Module import Module

View File

@ -16,10 +16,12 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from math import floor
import re import re
import sqlite3
import string import string
import MySQLdb as mdb
from Module import Module from Module import Module
__author__ = "Mike Bloy <mike@bloy.org>" __author__ = "Mike Bloy <mike@bloy.org>"
@ -50,67 +52,40 @@ class Karma(Module):
version = self.db_module_registered(self.__class__.__name__) version = self.db_module_registered(self.__class__.__name__)
if (version == None): if (version == None):
# have to create the database tables # have to create the database tables
conn = self.get_db() db = self.get_db()
try: 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()
conn.close()
version = 1 version = 1
except sqlite3.Error as e: cur = db.cursor(mdb.cursors.DictCursor)
conn.rollback() cur.execute('''
conn.close() CREATE TABLE karma_log (
self.log.error("sqlite error: " + str(e)) id SERIAL,
raise karma_key VARCHAR(128) NOT NULL,
if (version < 2): delta INTEGER NOT NULL,
conn = self.get_db() who VARCHAR(64) NOT NULL,
try: userhost VARCHAR(256) NOT NULL,
conn.execute(''' karmatime TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
cur.execute('CREATE INDEX karma_log_key_ix ON karma_log (karma_key)')
cur.execute('CREATE INDEX karma_log_who_ix ON karma_log (who)')
cur.execute('''
CREATE VIEW karma_values AS
SELECT karma_key, SUM(delta) AS value
FROM karma_log
GROUP BY karma_key''')
cur.execute('''
CREATE VIEW karma_users AS CREATE VIEW karma_users AS
SELECT who, COUNT(NULLIF(delta, -1)) AS pos, SELECT who, COUNT(NULLIF(delta, -1)) AS pos,
COUNT(NULLIF(delta, 1)) AS neg COUNT(NULLIF(delta, 1)) AS neg
FROM karma_log GROUP BY who''') FROM karma_log GROUP BY who''')
sql = 'UPDATE drbotzo_modules SET version = ? WHERE module = ?' db.commit()
conn.execute(sql, (2, self.__class__.__name__))
conn.commit()
conn.close()
version = 2
except sqlite3.Error as e:
conn.rollback()
conn.close()
self.log.error("sqlite error: " + str(e))
raise
if (version < 3):
conn = self.get_db()
try:
version = 3
conn.execute('''
UPDATE karma_log SET key = LOWER(key)''')
conn.commit()
conn.close()
self.db_register_module_version(self.__class__.__name__, version) self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
conn.rollback() db.rollback()
conn.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""look for karma strings at the start of messages""" """look for karma strings at the start of messages"""
@ -147,19 +122,21 @@ class Karma(Module):
Go out to the database and update the karma value. Go out to the database and update the karma value.
""" """
conn = self.get_db() db = self.get_db()
try: try:
cur = db.cursor(mdb.cursors.DictCursor)
sql = ''' sql = '''
INSERT INTO karma_log (key, delta, who, userhost) INSERT INTO karma_log (karma_key, delta, who, userhost)
VALUES (?, ?, ?, ?) VALUES (%s, %s, %s, %s)
''' '''
conn.execute(sql, (key.decode('utf-8', 'ignore').lower(), value, nick, userhost)) cur.execute(sql, (key.decode('utf-8', 'ignore').lower(), value, nick, userhost))
conn.commit() db.commit()
conn.close() except mdb.Error as e:
except sqlite3.Error as e: db.rollback()
conn.rollback() self.log.error("database error modifying karma")
conn.close() self.log.exception(e)
return "sqlite error: " + str(e) raise
finally: cur.close()
def handle_report_query(self, connection, nick, userhost, what): def handle_report_query(self, connection, nick, userhost, what):
match = self.reportre.search(what) match = self.reportre.search(what)
@ -169,61 +146,66 @@ class Karma(Module):
query = None query = None
header = None header = None
if (report == 'highest'): if (report == 'highest'):
query = 'SELECT key, value FROM karma_values ORDER BY value DESC LIMIT 5' query = 'SELECT karma_key AS who, value FROM karma_values ORDER BY value DESC LIMIT 5'
header = 'Top 5 karma recipients:' header = 'Top 5 karma recipients:'
elif (report == 'lowest'): elif (report == 'lowest'):
query = 'SELECT key, value FROM karma_values ORDER BY value ASC LIMIT 5' query = 'SELECT karma_key AS who, value FROM karma_values ORDER BY value ASC LIMIT 5'
header = 'Bottom 5 karma recipients:' header = 'Bottom 5 karma recipients:'
elif (report == 'positive'): elif (report == 'positive'):
query = 'SELECT who, pos FROM karma_users ORDER BY pos DESC LIMIT 5' query = 'SELECT who, pos AS value FROM karma_users ORDER BY pos DESC LIMIT 5'
header = 'Top 5 Optimists:' header = 'Top 5 Optimists:'
elif (report == 'negative'): elif (report == 'negative'):
query = 'SELECT who, neg FROM karma_users ORDER BY neg DESC LIMIT 5' query = 'SELECT who, neg AS value FROM karma_users ORDER BY neg DESC LIMIT 5'
header = 'Top 5 Pessimists:' header = 'Top 5 Pessimists:'
elif (report == 'top'): elif (report == 'top'):
query = 'SELECT who, pos+neg AS total FROM karma_users ORDER BY total DESC LIMIT 5' query = 'SELECT who, pos+neg AS value FROM karma_users ORDER BY value DESC LIMIT 5'
header = 'Top 5 Total Karma Givers:' header = 'Top 5 Total Karma Givers:'
if (query != None): if (query != None):
conn = self.get_db() db = self.get_db()
list = [] list = []
try: try:
cursor = conn.execute(query) cur = db.cursor(mdb.cursors.DictCursor)
result = cursor.fetchone() cur.execute(query)
result = cur.fetchone()
while (result != None): while (result != None):
list.append("{key} ({value})".format(key=result[0], value=result[1])) list.append("{key} ({value})".format(key=result['who'], value=result['value']))
result = cursor.fetchone() result = cur.fetchone()
list = ', '.join(list) list = ', '.join(list)
message = '{header} {list}'.format(header=header, list=list) message = '{header} {list}'.format(header=header, list=list)
conn.close() except mdb.Error as e:
except sqlite3.Error as e: self.log.error("database error during report query")
conn.rollback() self.log.exception(e)
conn.close() raise
return "sqlite error: " + str(e) finally: cur.close()
return message return message
def handle_stat_query(self, connection, nick, userhost, what): def handle_stat_query(self, connection, nick, userhost, what):
match = self.statre.search(what) match = self.statre.search(what)
statnick = match.group(1) statnick = match.group(1)
conn = self.get_db() db = self.get_db()
reply = '{nick}: {statnick} has never given karma'.format(nick=nick, statnick=statnick) reply = '{nick}: {statnick} has never given karma'.format(nick=nick, statnick=statnick)
try: try:
cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT pos, neg SELECT pos, neg
FROM karma_users FROM karma_users
WHERE who = :who WHERE who = :who
''' '''
value = conn.execute(query, {'who': statnick}).fetchone() cur.execute(query, {'who': statnick})
value = cur.fetchone()
if (value != None): if (value != None):
pos = value[0] pos = value[0]
neg = value[1] neg = value[1]
total = pos+neg; 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) 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)
conn.close() except mdb.Error as e:
except sqlite3.Error as e: self.log.error("database error during handle stat query")
conn.close() self.log.exception(e)
return "sqlite error: " + str(e) raise
finally: cur.close()
return reply return reply
@ -231,29 +213,33 @@ class Karma(Module):
match = self.queryre.search(what) match = self.queryre.search(what)
key = match.group(1) key = match.group(1)
conn = self.get_db() db = self.get_db()
reply = '{nick}: {key} has no karma'.format(nick=nick, key=key) reply = '{nick}: {key} has no karma'.format(nick=nick, key=key)
try: try:
cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT value SELECT value
FROM karma_values FROM karma_values
WHERE key = :key WHERE karma_key = %s
''' '''
value = conn.execute(query, {'key': key.decode('utf-8', 'ignore').lower()}).fetchone() cur.execute(query, (key.decode('utf-8', 'ignore').lower(),))
value = cur.fetchone()
if (value != None): if (value != None):
query = ''' query = '''
SELECT count(*) FROM karma_values WHERE value > :value SELECT count(*) FROM karma_values WHERE value > %s
''' '''
rank = conn.execute(query, {'value': value[0]}).fetchone() cur.execute(query, (value['value'],))
rank = rank[0] + 1; rank = cur.fetchone()
rank = rank['count(*)'] + 1;
reply = '{nick}: {key} has {value[0]!s} points of karma (rank {rank})'.format( reply = '{0:s}: {1:s} has {2:d} points of karma (rank {3:d})'.format(
nick=nick, key=key, value=value, rank=rank) nick, key, int(floor(value['value'])), rank)
conn.close() except mdb.Error as e:
except sqlite3.Error as e: self.log.error("database error during handle karma query")
conn.close() self.log.exception(e)
return "sqlite error: " + str(e) raise
finally: cur.close()
return reply return reply

View File

@ -21,11 +21,12 @@ from datetime import datetime
import os import os
import random import random
import re import re
import sqlite3
import sys import sys
import thread import thread
import time import time
import MySQLdb as mdb
from dateutil.parser import * from dateutil.parser import *
from dateutil.relativedelta import * from dateutil.relativedelta import *
from extlib import irclib from extlib import irclib
@ -76,67 +77,58 @@ class Markov(Module):
"""Create the markov chain table.""" """Create the markov chain table."""
version = self.db_module_registered(self.__class__.__name__) version = self.db_module_registered(self.__class__.__name__)
if (version == None or version < 9): if version == None:
db = self.get_db() db = self.get_db()
try: try:
version = 9 version = 1
cur = db.cursor(mdb.cursors.DictCursor)
# recreating the tables, since i need to add some foreign key constraints cur.execute('''
db.execute('''DROP INDEX IF EXISTS markov_chain_keys_and_context_index''')
db.execute('''DROP INDEX IF EXISTS markov_chain_keys_index''')
db.execute('''DROP INDEX IF EXISTS markov_chain_value_and_context_index''')
db.execute('''DROP TABLE IF EXISTS markov_chain''')
db.execute('''DROP TABLE IF EXISTS markov_target_to_context_map''')
db.execute('''DROP TABLE IF EXISTS markov_chatter_target''')
db.execute('''DROP TABLE IF EXISTS markov_context''')
db.execute('''
CREATE TABLE markov_chatter_target ( CREATE TABLE markov_chatter_target (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
target TEXT NOT NULL, target VARCHAR(256) NOT NULL,
chance INTEGER NOT NULL DEFAULT 99999 chance INTEGER NOT NULL DEFAULT 99999
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
db.execute(''' cur.execute('''
CREATE TABLE markov_context ( CREATE TABLE markov_context (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
context TEXT NOT NULL context VARCHAR(256) NOT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
db.execute(''' cur.execute('''
CREATE TABLE markov_target_to_context_map ( CREATE TABLE markov_target_to_context_map (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
target TEXT NOT NULL, target VARCHAR(256) NOT NULL,
context_id INTEGER NOT NULL, context_id BIGINT(20) UNSIGNED NOT NULL,
FOREIGN KEY(context_id) REFERENCES markov_context(id) FOREIGN KEY(context_id) REFERENCES markov_context(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
db.execute(''' cur.execute('''
CREATE TABLE markov_chain ( CREATE TABLE markov_chain (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
k1 TEXT NOT NULL, k1 VARCHAR(128) NOT NULL,
k2 TEXT NOT NULL, k2 VARCHAR(128) NOT NULL,
v TEXT NOT NULL, v VARCHAR(128) NOT NULL,
context_id INTEGER DEFAULT NULL, context_id BIGINT(20) UNSIGNED NOT NULL,
FOREIGN KEY(context_id) REFERENCES markov_context(id) FOREIGN KEY(context_id) REFERENCES markov_context(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
db.execute(''' cur.execute('''
CREATE INDEX markov_chain_keys_and_context_id_index CREATE INDEX markov_chain_keys_and_context_id_index
ON markov_chain (k1, k2, context_id)''') ON markov_chain (k1, k2, context_id)''')
db.execute(''' cur.execute('''
CREATE INDEX markov_chain_value_and_context_id_index CREATE INDEX markov_chain_value_and_context_id_index
ON markov_chain (v, context_id)''') ON markov_chain (v, context_id)''')
db.commit() db.commit()
db.close()
self.db_register_module_version(self.__class__.__name__, version) self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def register_handlers(self): def register_handlers(self):
"""Handle pubmsg/privmsg, to learn and/or reply to IRC events.""" """Handle pubmsg/privmsg, to learn and/or reply to IRC events."""
@ -303,10 +295,10 @@ class Markov(Module):
if len(words) <= 0: if len(words) <= 0:
return line return line
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = 'INSERT INTO markov_chain (k1, k2, v, context_id) VALUES (%s, %s, %s, %s)'
statement = 'INSERT INTO markov_chain (k1, k2, v, context_id) VALUES (?, ?, ?, ?)'
for word in words: for word in words:
cur.execute(statement, (k1.decode('utf-8', 'replace'), cur.execute(statement, (k1.decode('utf-8', 'replace'),
k2.decode('utf-8', 'replace'), word.decode('utf-8', 'replace'), context_id)) k2.decode('utf-8', 'replace'), word.decode('utf-8', 'replace'), context_id))
@ -315,12 +307,12 @@ class Markov(Module):
k2.decode('utf-8', 'replace'), self.stop, context_id)) k2.decode('utf-8', 'replace'), self.stop, context_id))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error learning line")
self.log.error("sqlite error in Markov._learn_line: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _generate_line(self, target, line='', min_size=15, max_size=100): def _generate_line(self, target, line='', min_size=15, max_size=100):
""" """
@ -412,69 +404,73 @@ class Markov(Module):
"""Get the value(s) for a given key (a pair of strings).""" """Get the value(s) for a given key (a pair of strings)."""
values = [] values = []
db = self.get_db()
try: try:
db = self.get_db()
query = '' query = ''
if k1 == self.start1 and k2 == self.start2: if k1 == self.start1 and k2 == self.start2:
# hack. get a quasi-random start from the database, in # hack. get a quasi-random start from the database, in
# a faster fashion than selecting all starts # a faster fashion than selecting all starts
max_id = self._get_max_chain_id() max_id = self._get_max_chain_id()
rand_id = random.randint(1,max_id) rand_id = random.randint(1,max_id)
query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND ' query = ('SELECT v FROM markov_chain WHERE k1 = %s AND k2 = %s AND '
'(context_id = ?) AND id >= {0:d} LIMIT 1'.format(rand_id)) '(context_id = %s) AND id >= {0:d} LIMIT 1'.format(rand_id))
else: else:
query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND ' query = ('SELECT v FROM markov_chain WHERE k1 = %s AND k2 = %s AND '
'(context_id = ?)') '(context_id = %s)')
cursor = db.execute(query, (k1.decode('utf-8', 'replace'), cur = db.cursor(mdb.cursors.DictCursor)
k2.decode('utf-8', 'replace'), cur.execute(query, (k1.decode('utf-8', 'replace'),
context_id)) k2.decode('utf-8', 'replace'),
results = cursor.fetchall() context_id))
results = cur.fetchall()
for result in results: for result in results:
values.append(result['v'].encode('utf-8', 'replace')) values.append(result['v'].encode('utf-8', 'replace'))
db.close()
return values return values
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _retrieve_chains_for_key")
self.log.error('sqlite error in Markov._retrieve_chains_for_key: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _retrieve_k2_for_value(self, v, context_id): def _retrieve_k2_for_value(self, v, context_id):
"""Get the value(s) for a given key (a pair of strings).""" """Get the value(s) for a given key (a pair of strings)."""
values = [] values = []
db = self.get_db()
try: try:
db = self.get_db() query = 'SELECT k2 FROM markov_chain WHERE v = %s AND context_id = %s'
query = 'SELECT k2 FROM markov_chain WHERE v = ? AND (context_id = ?)' cur = db.cursor(mdb.cursors.DictCursor)
cursor = db.execute(query, (v.decode('utf-8', 'replace'), context_id)) cur.execute(query, (v.decode('utf-8', 'replace'), context_id))
results = cursor.fetchall() results = cur.fetchall()
for result in results: for result in results:
values.append(result['k2'].encode('utf-8', 'replace')) values.append(result['k2'].encode('utf-8', 'replace'))
db.close()
return values return values
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _retrieve_k2_for_value")
self.log.error('sqlite error in Markov._retrieve_k2_for_value: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_chatter_targets(self): def _get_chatter_targets(self):
"""Get all possible chatter targets.""" """Get all possible chatter targets."""
values = [] values = []
db = self.get_db()
try: try:
# need to create our own db object, since this is likely going to be in a new thread # need to create our own db object, since this is likely going to be in a new thread
db = self.get_db()
query = 'SELECT target, chance FROM markov_chatter_target' query = 'SELECT target, chance FROM markov_chatter_target'
cursor = db.execute(query) cur = db.cursor(mdb.cursors.DictCursor)
results = cursor.fetchall() cur.execute(query)
results = cur.fetchall()
return results return results
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _get_chatter_targets")
self.log.error('sqlite error in Markov._get_chatter_targets: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_one_chatter_target(self): def _get_one_chatter_target(self):
"""Select one random chatter target.""" """Select one random chatter target."""
@ -486,37 +482,39 @@ class Markov(Module):
def _get_max_chain_id(self): def _get_max_chain_id(self):
"""Get the highest id in the chain table.""" """Get the highest id in the chain table."""
db = self.get_db()
try: try:
db = self.get_db()
query = ''' query = '''
SELECT id FROM markov_chain ORDER BY id DESC LIMIT 1 SELECT id FROM markov_chain ORDER BY id DESC LIMIT 1
''' '''
cursor = db.execute(query) cur = db.cursor(mdb.cursors.DictCursor)
result = cursor.fetchone() cur.execute(query)
db.close() result = cur.fetchone()
if result: if result:
return result['id'] return result['id']
else: else:
return None return None
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _get_max_chain_id")
self.log.error('sqlite error in Markov._get_max_chain_id: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_context_id_for_target(self, target): def _get_context_id_for_target(self, target):
"""Get the context ID for the desired/input target.""" """Get the context ID for the desired/input target."""
db = self.get_db()
try: try:
db = self.get_db()
query = ''' query = '''
SELECT mc.id FROM markov_context mc SELECT mc.id FROM markov_context mc
INNER JOIN markov_target_to_context_map mt INNER JOIN markov_target_to_context_map mt
ON mt.context_id = mc.id ON mt.context_id = mc.id
WHERE mt.target = ? WHERE mt.target = %s
''' '''
cursor = db.execute(query, (target,)) cur = db.cursor(mdb.cursors.DictCursor)
result = cursor.fetchone() cur.execute(query, (target,))
result = cur.fetchone()
db.close() db.close()
if result: if result:
return result['id'] return result['id']
@ -524,53 +522,55 @@ class Markov(Module):
# auto-generate a context to keep things private # auto-generate a context to keep things private
self._add_context_for_target(target) self._add_context_for_target(target)
return self._get_context_id_for_target(target) return self._get_context_id_for_target(target)
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _get_context_id_for_target")
self.log.error('sqlite error in Markov._get_context_id_for_target: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _add_context_for_target(self, target): def _add_context_for_target(self, target):
"""Create a new context for the desired/input target.""" """Create a new context for the desired/input target."""
db = self.get_db()
try: try:
db = self.get_db() statement = 'INSERT INTO markov_context (context) VALUES (%s)'
cur = db.cursor() cur = db.cursor(mdb.cursors.DictCursor)
statement = 'INSERT INTO markov_context (context) VALUES (?)'
cur.execute(statement, (target,)) cur.execute(statement, (target,))
statement = ''' statement = '''
INSERT INTO markov_target_to_context_map (target, context_id) INSERT INTO markov_target_to_context_map (target, context_id)
VALUES (?, (SELECT id FROM markov_context WHERE context = ?)) VALUES (%s, (SELECT id FROM markov_context WHERE context = %s))
''' '''
cur.execute(statement, (target,target)) cur.execute(statement, (target,target))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error in _add_context_for_target")
self.log.error("sqlite error in Markov._add_context_for_target: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
try: try:
db = self.get_db()
query = ''' query = '''
SELECT mc.id FROM markov_context mc SELECT mc.id FROM markov_context mc
INNER JOIN markov_target_to_context_map mt INNER JOIN markov_target_to_context_map mt
ON mt.context_id = mc.id ON mt.context_id = mc.id
WHERE mt.target = ? WHERE mt.target = %s
''' '''
cursor = db.execute(query, (target,)) cur = db.cursor(mdb.cursors.DictCursor)
result = cursor.fetchone() cur.execute(query, (target,))
db.close() result = cur.fetchone()
if result: if result:
return result['id'] return result['id']
else: else:
# auto-generate a context to keep things private # auto-generate a context to keep things private
self._add_context_for_target(target) self._add_context_for_target(target)
return self._get_context_id_for_target(target) return self._get_context_id_for_target(target)
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error in _get_context_id_for_target")
self.log.error('sqlite error in Markov._get_context_id_for_target: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -19,7 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import math import math
import random import random
import re import re
import sqlite3
import MySQLdb as mdb
from extlib import irclib from extlib import irclib
@ -46,37 +47,39 @@ class Pi(Module):
# create tables # create tables
db = self.get_db() db = self.get_db()
try: try:
db.execute(''' version = 1
cur = db.cursor(mdb.cursors.DictCursor)
cur.execute('''
CREATE TABLE pi_log ( CREATE TABLE pi_log (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
count_inside INTEGER NOT NULL, count_inside INTEGER NOT NULL,
count_total INTEGER NOT NULL, count_total INTEGER NOT NULL,
time TEXT DEFAULT CURRENT_TIMESTAMP time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''') ''')
db.execute(''' cur.execute('''
CREATE VIEW pi_latest_pi AS CREATE VIEW pi_latest_pi AS
SELECT count_inside, count_total SELECT count_inside, count_total
FROM pi_log FROM pi_log
ORDER BY id DESC ORDER BY id DESC
''') ''')
db.execute('INSERT INTO drbotzo_modules VALUES (?,?)', (self.__class__.__name__, 1))
db.commit() db.commit()
db.close() self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
match = re.search('^!pi$', what) match = re.search('^!pi$', what)
if match: if match:
db = self.get_db() db = self.get_db()
try: try:
cur = db.cursor() cur = db.cursor(mdb.cursors.DictCursor)
pi_data = cur.execute('SELECT * FROM pi_latest_pi') cur.execute('SELECT * FROM pi_latest_pi')
datum = pi_data.fetchone() datum = cur.fetchone()
if datum == None: if datum == None:
count_inside = 0 count_inside = 0
@ -96,13 +99,15 @@ class Pi(Module):
count += 1 count += 1
pi = 4.0 * count_inside / count pi = 4.0 * count_inside / count
cur.execute('INSERT INTO pi_log (count_inside, count_total) VALUES (?,?)', (count_inside, count)) cur.execute('INSERT INTO pi_log (count_inside, count_total) VALUES (%s,%s)',
(count_inside, count))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error doing pi stuff")
return self.reply(connection, event, "sqlite error: " + str(e)) self.log.exception(e)
return self.reply(connection, event, "database error doing pi stuff")
finally: cur.close()
return self.reply(connection, event, "({0:.10f}, {1:.10f}) is {2}within the circle. pi is {5:.10f}. (i:{3:d} p:{4:d})".format(x, y, "" if inside else "not ", count_inside, count, pi)) return self.reply(connection, event, "({0:.10f}, {1:.10f}) is {2}within the circle. pi is {5:.10f}. (i:{3:d} p:{4:d})".format(x, y, "" if inside else "not ", count_inside, count, pi))

View File

@ -17,7 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import re import re
import sqlite3
import MySQLdb as mdb
from datetime import datetime from datetime import datetime
from dateutil.tz import * from dateutil.tz import *
@ -36,89 +37,72 @@ class Seen(Module):
if version == None: if version == None:
db = self.get_db() db = self.get_db()
try: try:
db.execute('''
CREATE TABLE seen_nicks (
nick TEXT NOT NULL PRIMARY KEY,
host TEXT NOT NULL,
time TEXT DEFAULT CURRENT_TIMESTAMP,
what TEXT NOT NULL
)''')
sql = 'INSERT INTO drbotzo_modules VALUES (?,?)'
db.execute(sql, (self.__class__.__name__, 1))
db.commit()
db.close()
version = 1 version = 1
except sqlite3.Error as e: cur = db.cursor(mdb.cursors.DictCursor)
db.rollback() cur.execute('''
db.close()
self.log.error("sqlite error: " + str(e))
raise
if version < 2:
db = self.get_db()
try:
version = 2
db.execute('''DROP TABLE seen_nicks''')
db.execute('''
CREATE TABLE seen_nicks ( CREATE TABLE seen_nicks (
nick TEXT NOT NULL, nick VARCHAR(64) NOT NULL PRIMARY KEY,
location TEXT NOT NULL, location VARCHAR(64) NOT NULL,
host TEXT NOT NULL, host VARCHAR(256) NOT NULL,
time TEXT DEFAULT CURRENT_TIMESTAMP, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
what TEXT NOT NULL what LONGTEXT NOT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE UNIQUE INDEX seen_nicks_nick_and_location_index CREATE UNIQUE INDEX seen_nicks_nick_and_location_index
ON seen_nicks (nick, location)''') ON seen_nicks (nick, location)
''')
db.commit() db.commit()
db.close()
self.db_register_module_version(self.__class__.__name__, version) self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Track pubmsg/privmsg events, and if asked, report on someone.""" """Track pubmsg/privmsg events, and if asked, report on someone."""
where = event.target() where = event.target()
db = self.get_db()
# whatever it is, store it # whatever it is, store it
try: try:
# if there's no where, this is probably a sub-command. don't learn it # if there's no where, this is probably a sub-command. don't learn it
if where: if where:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = 'REPLACE INTO seen_nicks (nick, location, host, what) VALUES (%s, %s, %s, %s)'
statement = 'REPLACE INTO seen_nicks (nick, location, host, what) VALUES (?, ?, ?, ?)'
cur.execute(statement, (nick, where, userhost, what.decode('utf-8', 'replace'))) cur.execute(statement, (nick, where, userhost, what.decode('utf-8', 'replace')))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error storing seen data")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
match = re.search('^!seen\s+(\S+)$', what) match = re.search('^!seen\s+(\S+)$', what)
if match: if match:
nick = match.group(1) nick = match.group(1)
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT * FROM seen_nicks WHERE nick = ? AND location = ?' query = 'SELECT * FROM seen_nicks WHERE nick = %s AND location = %s'
cursor = db.execute(query, (nick,where)) cur.execute(query, (nick,where))
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
seentime = datetime.strptime(result['time'], '%Y-%m-%d %H:%M:%S').replace(tzinfo=tzutc()) seentime = result['time'].replace(tzinfo=tzlocal())
replystr = 'last saw {0:s} in {3:s} at {1:s} saying \'{2:s}\'.'.format(result['nick'], seentime.astimezone(tzlocal()).strftime('%Y/%m/%d %H:%M:%S %Z'), result['what'].encode('utf-8', 'ignore'), result['location'].encode('utf-8', 'ignore')) replystr = 'last saw {0:s} in {3:s} at {1:s} saying \'{2:s}\'.'.format(result['nick'], seentime.astimezone(tzlocal()).strftime('%Y/%m/%d %H:%M:%S %Z'), result['what'].encode('utf-8', 'ignore'), result['location'].encode('utf-8', 'ignore'))
return self.reply(connection, event, replystr) return self.reply(connection, event, replystr)
else: else:
return self.reply(connection, event, 'i have not seen {0:s} in {1:s}.'.format(nick, where)) return self.reply(connection, event, 'i have not seen {0:s} in {1:s}.'.format(nick, where))
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error retrieving seen data")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -18,9 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import random import random
import re import re
import sqlite3
import time import time
import MySQLdb as mdb
from Module import Module from Module import Module
__author__ = "Brian S. Stephan" __author__ = "Brian S. Stephan"
@ -101,66 +102,70 @@ class Storycraft(Module):
# have to create the database tables # have to create the database tables
db = self.get_db() db = self.get_db()
try: try:
db.execute(''' version = 1
cur = db.cursor(mdb.cursors.DictCursor)
cur.execute('''
CREATE TABLE storycraft_config ( CREATE TABLE storycraft_config (
master_channel TEXT NOT NULL, master_channel VARCHAR(64) NOT NULL,
concurrent_games INTEGER NOT NULL, concurrent_games INTEGER NOT NULL,
default_round_mode INTEGER NOT NULL, default_round_mode INTEGER NOT NULL,
default_game_length INTEGER NOT NULL, default_game_length INTEGER NOT NULL,
default_line_length INTEGER NOT NULL, default_line_length INTEGER NOT NULL,
default_random_method INTEGER NOT NULL, default_random_method INTEGER NOT NULL,
default_lines_per_turn INTEGER NOT NULL default_lines_per_turn INTEGER NOT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
INSERT INTO storycraft_config INSERT INTO storycraft_config
(master_channel, concurrent_games, default_round_mode, (master_channel, concurrent_games, default_round_mode,
default_game_length, default_line_length, default_game_length, default_line_length,
default_random_method, default_lines_per_turn) default_random_method, default_lines_per_turn)
VALUES ('#drbotzo', 10, 1, 20, 140, 1, 2) VALUES ('#dr.botzo', 10, 1, 20, 140, 1, 2)
''') ''')
db.execute(''' cur.execute('''
CREATE TABLE storycraft_game ( CREATE TABLE storycraft_game (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
round_mode INTEGER NOT NULL, round_mode INTEGER NOT NULL,
game_length INTEGER NOT NULL, game_length INTEGER NOT NULL,
line_length INTEGER NOT NULL, line_length INTEGER NOT NULL,
random_method INTEGER NOT NULL, random_method INTEGER NOT NULL,
lines_per_turn INTEGER NOT NULL, lines_per_turn INTEGER NOT NULL,
status TEXT NOT NULL, status VARCHAR(16) NOT NULL,
owner_nick TEXT NOT NULL, owner_nick VARCHAR(64) NOT NULL,
owner_userhost TEXT NOT NULL, owner_userhost VARCHAR(256) NOT NULL,
start_time TEXT DEFAULT CURRENT_TIMESTAMP, start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
end_time TEXT DEFAULT NULL end_time TIMESTAMP NULL DEFAULT NULL
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE TABLE storycraft_player ( CREATE TABLE storycraft_player (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
game_id INTEGER NOT NULL, game_id BIGINT(20) UNSIGNED NOT NULL,
nick TEXT NOT NULL, nick VARCHAR(64) NOT NULL,
userhost TEXT NOT NULL, userhost VARCHAR(256) NOT NULL,
FOREIGN KEY(game_id) REFERENCES storycraft_game(id) FOREIGN KEY(game_id) REFERENCES storycraft_game(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
db.execute(''' ''')
cur.execute('''
CREATE TABLE storycraft_line ( CREATE TABLE storycraft_line (
id INTEGER PRIMARY KEY AUTOINCREMENT, id SERIAL,
game_id INTEGER NOT NULL, game_id BIGINT(20) UNSIGNED NOT NULL,
player_id INTEGER NOT NULL, player_id BIGINT(20) UNSIGNED NOT NULL,
line TEXT NOT NULL, line LONGTEXT NOT NULL,
time TEXT DEFAULT CURRENT_TIMESTAMP, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(game_id) REFERENCES storycraft_game(id) FOREIGN KEY(game_id) REFERENCES storycraft_game(id),
FOREIGN KEY(player_id) REFERENCES storycraft_player(id) FOREIGN KEY(player_id) REFERENCES storycraft_player(id)
)''') ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
sql = 'INSERT INTO drbotzo_modules VALUES (?,?)'
db.execute(sql, (self.__class__.__name__, 1))
db.commit() db.commit()
db.close() self.db_register_module_version(self.__class__.__name__, version)
version = 1 except mdb.Error as e:
except sqlite3.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Pass storycraft control commands to the appropriate method based on input.""" """Pass storycraft control commands to the appropriate method based on input."""
@ -525,18 +530,18 @@ class Storycraft(Module):
def _get_game_details(self, game_id): def _get_game_details(self, game_id):
"""Get the details of one game.""" """Get the details of one game."""
db = self.get_db()
try: try:
cur = db.cursor(mdb.cursors.DictCursor)
# get the specified game and populate a StorycraftGame # get the specified game and populate a StorycraftGame
db = self.get_db()
query = ''' query = '''
SELECT id, round_mode, game_length, line_length, random_method, SELECT id, round_mode, game_length, line_length, random_method,
lines_per_turn, status, owner_nick, owner_userhost, start_time, lines_per_turn, status, owner_nick, owner_userhost, start_time,
end_time end_time
FROM storycraft_game WHERE id = ? FROM storycraft_game WHERE id = %s
''' '''
cursor = db.execute(query, (game_id,)) cur.execute(query, (game_id,))
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
game = self.StorycraftGame() game = self.StorycraftGame()
@ -553,10 +558,11 @@ class Storycraft(Module):
game.end_time = result['end_time'] game.end_time = result['end_time']
return game return game
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get game details")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_game_summary(self, game): def _get_game_summary(self, game):
"""Display game info for a general summary.""" """Display game info for a general summary."""
@ -601,35 +607,37 @@ class Storycraft(Module):
def _add_new_game(self, round_mode, game_length, line_length, random_method, lines_per_turn, nick, userhost): def _add_new_game(self, round_mode, game_length, line_length, random_method, lines_per_turn, nick, userhost):
"""Add a new game to the system.""" """Add a new game to the system."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
INSERT INTO storycraft_game ( INSERT INTO storycraft_game (
round_mode, game_length, line_length, random_method, round_mode, game_length, line_length, random_method,
lines_per_turn, status, owner_nick, owner_userhost lines_per_turn, status, owner_nick, owner_userhost
) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
''' '''
cur.execute(statement, (round_mode, game_length, line_length, random_method, lines_per_turn, 'OPEN', nick, userhost)) cur.execute(statement, (round_mode, game_length, line_length,
random_method, lines_per_turn, 'OPEN', nick, userhost))
db.commit() db.commit()
db.close()
return cur.lastrowid return cur.lastrowid
except sqlite3.Error as e: except mdb.Error as e:
db.close() db.rollback()
self.log.error('sqlite error: ' + str(e)) self.log.error("database error during add new game")
self.log.exception(e)
raise raise
finally: cur.close()
def _get_player_list_for_game(self, game_id): def _get_player_list_for_game(self, game_id):
"""Get the list of players in one game.""" """Get the list of players in one game."""
players = [] players = []
db = self.get_db()
try: try:
# get the players for specified game and populate a list # get the players for specified game and populate a list
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = ?' query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = %s'
cursor = db.execute(query, (game_id,)) cur.execute(query, (game_id,))
results = cursor.fetchall() results = cur.fetchall()
db.close()
for result in results: for result in results:
player = self.StorycraftPlayer() player = self.StorycraftPlayer()
@ -641,10 +649,11 @@ class Storycraft(Module):
players.append(player) players.append(player)
return players return players
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during getting player list for game")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_game_exists(self, game_id): def _get_game_exists(self, game_id):
"""Return the existence of a game.""" """Return the existence of a game."""
@ -654,20 +663,21 @@ class Storycraft(Module):
def _start_game(self, game_id): def _start_game(self, game_id):
"""Start a game, if it's currently open.""" """Start a game, if it's currently open."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
UPDATE storycraft_game SET status = 'IN PROGRESS' WHERE status = 'OPEN' AND id = ? UPDATE storycraft_game SET status = 'IN PROGRESS' WHERE status = 'OPEN' AND id = %s
''' '''
cur.execute(statement, (game_id,)) cur.execute(statement, (game_id,))
db.commit() db.commit()
db.close()
return game_id return game_id
except sqlite3.Error as e: except mdb.Error as e:
db.close() db.rollback()
self.log.error('sqlite error: ' + str(e)) self.log.error("database error during start game")
self.log.exception(e)
raise raise
finally: cur.close()
def _pick_next_player(self, game_id): def _pick_next_player(self, game_id):
"""Based on the game's settings and state, set who will be replying next.""" """Based on the game's settings and state, set who will be replying next."""
@ -717,51 +727,53 @@ class Storycraft(Module):
def _assign_game_to_player(self, game_id, player_id): def _assign_game_to_player(self, game_id, player_id):
"""Assign the game to a player, prompting them for responses.""" """Assign the game to a player, prompting them for responses."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
INSERT INTO storycraft_line (game_id, player_id, line) INSERT INTO storycraft_line (game_id, player_id, line)
VALUES (?, ?, ?) VALUES (%s, %s, %s)
''' '''
cur.execute(statement, (game_id, player_id, '')) cur.execute(statement, (game_id, player_id, ''))
db.commit() db.commit()
db.close()
return cur.lastrowid return cur.lastrowid
except sqlite3.Error as e: except mdb.Error as e:
db.close() db.rollback()
self.log.error('sqlite error: ' + str(e)) self.log.error("database error during assign game to player")
self.log.exception(e)
raise raise
finally: cur.close()
def _end_game(self, game_id): def _end_game(self, game_id):
"""End the given game, disallowing adding lines.""" """End the given game, disallowing adding lines."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
UPDATE storycraft_game SET status = 'COMPLETED', end_time = CURRENT_TIMESTAMP UPDATE storycraft_game SET status = 'COMPLETED', end_time = CURRENT_TIMESTAMP
WHERE status = 'IN PROGRESS' AND id = ? WHERE status = 'IN PROGRESS' AND id = %s
''' '''
cur.execute(statement, (game_id,)) cur.execute(statement, (game_id,))
db.commit() db.commit()
db.close()
return game_id return game_id
except sqlite3.Error as e: except mdb.Error as e:
db.close() db.rollback()
self.log.error('sqlite error: ' + str(e)) self.log.error("database error during end game")
self.log.exception(e)
raise raise
finally: cur.close()
def _get_player_by_id(self, player_id): def _get_player_by_id(self, player_id):
"""Get the player details based on id.""" """Get the player details based on id."""
db = self.get_db()
try: try:
# get the specified player and populate a StorycraftPlayer # get the specified player and populate a StorycraftPlayer
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE id = ?' query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE id = %s'
cursor = db.execute(query, (player_id,)) cur.execute(query, (player_id,))
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
player = self.StorycraftPlayer() player = self.StorycraftPlayer()
@ -771,21 +783,22 @@ class Storycraft(Module):
player.userhost = result['userhost'] player.userhost = result['userhost']
return player return player
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get player by id")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_player_by_userhost_in_game(self, game_id, userhost): def _get_player_by_userhost_in_game(self, game_id, userhost):
"""Get the player details if they exist in the given game.""" """Get the player details if they exist in the given game."""
db = self.get_db()
try: try:
# get the specified player if they exist in the game and populate a StorycraftPlayer # get the specified player if they exist in the game and populate a StorycraftPlayer
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = ? AND userhost = ?' query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = %s AND userhost = %s'
cursor = db.execute(query, (game_id,userhost)) cur.execute(query, (game_id,userhost))
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
player = self.StorycraftPlayer() player = self.StorycraftPlayer()
@ -795,10 +808,11 @@ class Storycraft(Module):
player.userhost = result['userhost'] player.userhost = result['userhost']
return player return player
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get player by userhost")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_completed_games(self): def _get_completed_games(self):
"""Get the games with COMPLETED status.""" """Get the games with COMPLETED status."""
@ -819,20 +833,20 @@ class Storycraft(Module):
"""Return the in progress/open games that include the player nick.""" """Return the in progress/open games that include the player nick."""
games = [] games = []
db = self.get_db()
try: try:
# get the games of specified type and populate a list # get the games of specified type and populate a list
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT game.id, game.round_mode, game.game_length, game.line_length, SELECT game.id, game.round_mode, game.game_length, game.line_length,
game.random_method, game.lines_per_turn, game.status, game.owner_nick, game.random_method, game.lines_per_turn, game.status, game.owner_nick,
game.owner_userhost, game.start_time, game.end_time game.owner_userhost, game.start_time, game.end_time
FROM storycraft_game game FROM storycraft_game game
INNER JOIN storycraft_player player ON player.game_id = game.id INNER JOIN storycraft_player player ON player.game_id = game.id
WHERE player.nick = ? AND (game.status = 'OPEN' OR game.status = 'IN PROGRESS') WHERE player.nick = %s AND (game.status = 'OPEN' OR game.status = 'IN PROGRESS')
''' '''
cursor = db.execute(query, (player_nick,)) cur.execute(query, (player_nick,))
results = cursor.fetchall() results = cur.fetchall()
db.close()
for result in results: for result in results:
game = self.StorycraftGame() game = self.StorycraftGame()
@ -851,10 +865,11 @@ class Storycraft(Module):
games.append(game) games.append(game)
return games return games
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get active games with player")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_games_waiting_on_player(self, player_nick): def _get_games_waiting_on_player(self, player_nick):
"""Return the games where the player nick is the owner of a pending line. """Return the games where the player nick is the owner of a pending line.
@ -864,9 +879,10 @@ class Storycraft(Module):
""" """
games = [] games = []
db = self.get_db()
try: try:
# get the games of specified type and populate a list # get the games of specified type and populate a list
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT game.id, game.round_mode, game.game_length, game.line_length, SELECT game.id, game.round_mode, game.game_length, game.line_length,
game.random_method, game.lines_per_turn, game.status, game.owner_nick, game.random_method, game.lines_per_turn, game.status, game.owner_nick,
@ -874,56 +890,16 @@ class Storycraft(Module):
FROM storycraft_game game FROM storycraft_game game
INNER JOIN storycraft_player player ON player.game_id = game.id INNER JOIN storycraft_player player ON player.game_id = game.id
INNER JOIN storycraft_line line ON line.player_id = player.id INNER JOIN storycraft_line line ON line.player_id = player.id
WHERE player.nick = ? AND game.status = 'IN PROGRESS' AND line.line = '' WHERE player.nick = %s AND game.status = 'IN PROGRESS' AND line.line = ''
UNION UNION
SELECT game.id, game.round_mode, game.game_length, game.line_length, SELECT game.id, game.round_mode, game.game_length, game.line_length,
game.random_method, game.lines_per_turn, game.status, game.owner_nick, game.random_method, game.lines_per_turn, game.status, game.owner_nick,
game.owner_userhost, game.start_time, game.end_time game.owner_userhost, game.start_time, game.end_time
FROM storycraft_game game FROM storycraft_game game
WHERE game.owner_nick = ? AND game.status = 'OPEN' WHERE game.owner_nick = %s AND game.status = 'OPEN'
''' '''
cursor = db.execute(query, (player_nick, player_nick)) cur.execute(query, (player_nick, player_nick))
results = cursor.fetchall() results = cur.fetchall()
db.close()
for result in results:
game = self.StorycraftGame()
game.id = int(result['game.id'])
game.round_mode = int(result['game.round_mode'])
game.game_length = int(result['game.game_length'])
game.line_length = int(result['game.line_length'])
game.random_method = int(result['game.random_method'])
game.lines_per_turn = int(result['game.lines_per_turn'])
game.status = result['game.status']
game.owner_nick = result['game.owner_nick']
game.owner_userhost = result['game.owner_userhost']
game.start_time = result['game.start_time']
game.end_time = result['game.end_time']
games.append(game)
return games
except sqlite3.Error as e:
db.close()
self.log.error('sqlite error: ' + str(e))
raise
def _get_games_of_type(self, game_type):
"""Return the games of the specified type."""
games = []
try:
# get the games of specified type and populate a list
db = self.get_db()
query = '''
SELECT id, round_mode, game_length, line_length, random_method,
lines_per_turn, status, owner_nick, owner_userhost, start_time,
end_time
FROM storycraft_game WHERE status = ?
'''
cursor = db.execute(query, (game_type,))
results = cursor.fetchall()
db.close()
for result in results: for result in results:
game = self.StorycraftGame() game = self.StorycraftGame()
@ -942,29 +918,71 @@ class Storycraft(Module):
games.append(game) games.append(game)
return games return games
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get games waiting on player")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_games_of_type(self, game_type):
"""Return the games of the specified type."""
games = []
db = self.get_db()
try:
# get the games of specified type and populate a list
cur = db.cursor(mdb.cursors.DictCursor)
query = '''
SELECT id, round_mode, game_length, line_length, random_method,
lines_per_turn, status, owner_nick, owner_userhost, start_time,
end_time
FROM storycraft_game WHERE status = %s
'''
cur.execute(query, (game_type,))
results = cur.fetchall()
for result in results:
game = self.StorycraftGame()
game.id = int(result['id'])
game.round_mode = int(result['round_mode'])
game.game_length = int(result['game_length'])
game.line_length = int(result['line_length'])
game.random_method = int(result['random_method'])
game.lines_per_turn = int(result['lines_per_turn'])
game.status = result['status']
game.owner_nick = result['owner_nick']
game.owner_userhost = result['owner_userhost']
game.start_time = result['start_time']
game.end_time = result['end_time']
games.append(game)
return games
except mdb.Error as e:
self.log.error("database error during get games of type")
self.log.exception(e)
raise
finally: cur.close()
def _add_player_to_game(self, game_id, nick, userhost): def _add_player_to_game(self, game_id, nick, userhost):
"""Add a player to a game, so that they may eventually play.""" """Add a player to a game, so that they may eventually play."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
INSERT INTO storycraft_player (game_id, nick, userhost) INSERT INTO storycraft_player (game_id, nick, userhost)
VALUES (?, ?, ?) VALUES (%s, %s, %s)
''' '''
cur.execute(statement, (game_id, nick, userhost)) cur.execute(statement, (game_id, nick, userhost))
db.commit() db.commit()
db.close()
return cur.lastrowid return cur.lastrowid
except sqlite3.Error as e: except mdb.Error as e:
db.close() db.rollback()
self.log.error('sqlite error: ' + str(e)) self.log.error("database error during add player to game")
self.log.exception(e)
raise raise
finally: cur.close()
def _get_player_exists_in_game(self, game_id, userhost): def _get_player_exists_in_game(self, game_id, userhost):
"""Return the existence of a player in a game.""" """Return the existence of a player in a game."""
@ -998,19 +1016,20 @@ class Storycraft(Module):
"""Return the number of games of the specified type.""" """Return the number of games of the specified type."""
count = 0 count = 0
db = self.get_db()
try: try:
# get count of game_type games # get count of game_type games
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT COUNT(*) FROM storycraft_game WHERE status = ?' query = 'SELECT COUNT(*) FROM storycraft_game WHERE status = %s'
cursor = db.execute(query, (game_type,)) cur.execute(query, (game_type,))
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
count = result['COUNT(*)'] count = result['COUNT(*)']
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get game type count")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
return count return count
@ -1018,19 +1037,20 @@ class Storycraft(Module):
"""Return the current game server concurrency.""" """Return the current game server concurrency."""
concurrency = 0 concurrency = 0
db = self.get_db()
try: try:
# get the concurrency value from config table # get the concurrency value from config table
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT concurrent_games FROM storycraft_config' query = 'SELECT concurrent_games FROM storycraft_config'
cursor = db.execute(query) cur.execute(query)
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
concurrency = result['concurrent_games'] concurrency = result['concurrent_games']
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get concurrent game count")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
return concurrency return concurrency
@ -1038,17 +1058,17 @@ class Storycraft(Module):
"""Get the lines for the specified game_id.""" """Get the lines for the specified game_id."""
lines = [] lines = []
db = self.get_db()
try: try:
# get the games of specified type and populate a list # get the games of specified type and populate a list
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT id, game_id, player_id, line, time SELECT id, game_id, player_id, line, time
FROM storycraft_line WHERE game_id = ? FROM storycraft_line WHERE game_id = %s
ORDER BY time DESC, id DESC ORDER BY time DESC, id DESC
''' '''
cursor = db.execute(query, (game_id,)) cur.execute(query, (game_id,))
results = cursor.fetchall() results = cur.fetchall()
db.close()
for result in results: for result in results:
line = self.StorycraftLine() line = self.StorycraftLine()
@ -1061,28 +1081,30 @@ class Storycraft(Module):
lines.append(line) lines.append(line)
return lines return lines
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get lines for game")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _update_line(self, line_id, input_line): def _update_line(self, line_id, input_line):
"""Update the specified line with the given text.""" """Update the specified line with the given text."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor()
statement = ''' statement = '''
UPDATE storycraft_line SET line = ?, time = CURRENT_TIMESTAMP WHERE id = ? UPDATE storycraft_line SET line = %s, time = CURRENT_TIMESTAMP WHERE id = %s
''' '''
cur.execute(statement, (input_line.decode('utf-8', 'replace'), line_id)) cur.execute(statement, (input_line.decode('utf-8', 'replace'), line_id))
db.commit() db.commit()
db.close()
return line_id return line_id
except sqlite3.Error as e: except mdb.Error as e:
db.close() db.rollback()
self.log.error('sqlite error: ' + str(e)) self.log.error("database error during update line")
self.log.exception(e)
raise raise
finally: cur.close()
def _export_game_to_disk(self, game, lines): def _export_game_to_disk(self, game, lines):
"""Write a game to disk.""" """Write a game to disk."""
@ -1118,18 +1140,18 @@ class Storycraft(Module):
def _get_storycraft_settings(self): def _get_storycraft_settings(self):
"""Get the server settings.""" """Get the server settings."""
db = self.get_db()
try: try:
# get the settings and return in StorycraftSettings # get the settings and return in StorycraftSettings
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = ''' query = '''
SELECT master_channel, concurrent_games, default_round_mode, SELECT master_channel, concurrent_games, default_round_mode,
default_game_length, default_line_length, default_random_method, default_game_length, default_line_length, default_random_method,
default_lines_per_turn default_lines_per_turn
FROM storycraft_config FROM storycraft_config
''' '''
cursor = db.execute(query) cur.execute(query)
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
settings = self.StorycraftSettings() settings = self.StorycraftSettings()
@ -1142,9 +1164,10 @@ class Storycraft(Module):
settings.default_lines_per_turn = int(result['default_lines_per_turn']) settings.default_lines_per_turn = int(result['default_lines_per_turn'])
return settings return settings
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error during get storycraft settings")
self.log.error('sqlite error: ' + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent

View File

@ -19,11 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from ConfigParser import NoSectionError, NoOptionError from ConfigParser import NoSectionError, NoOptionError
import oauth2 as oauth import oauth2 as oauth
import re import re
import sqlite3
import thread import thread
import time import time
import urlparse import urlparse
import MySQLdb as mdb
from extlib import irclib from extlib import irclib
from extlib import twitter from extlib import twitter
@ -96,41 +97,28 @@ class Twitter(Module):
# init the table if it doesn't exist # init the table if it doesn't exist
version = self.db_module_registered(self.__class__.__name__) version = self.db_module_registered(self.__class__.__name__)
if version == None or version < 1: if version == None or version < 1:
# create tables
db = self.get_db() db = self.get_db()
# create tables
try: try:
version = 1 version = 1
cur = db.cursor(mdb.cursors.DictCursor)
db.execute(""" cur.execute("""
CREATE TABLE twitter_settings ( CREATE TABLE twitter_settings (
since_id INTEGER NOT NULL, since_id SERIAL,
output_channel TEXT NOT NULL output_channel VARCHAR(64) NOT NULL,
)""") oauth_token VARCHAR(256) DEFAULT NULL,
db.execute("""INSERT INTO twitter_settings (since_id, output_channel) VALUES (0, '#drbotzo')""") oauth_token_secret VARCHAR(256) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
""")
cur.execute("""INSERT INTO twitter_settings (since_id, output_channel) VALUES (0, '#drbotzo')""")
db.commit() db.commit()
db.close()
self.db_register_module_version(self.__class__.__name__, version) self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e: except mdb.Error as e:
db.rollback() db.rollback()
db.close() self.log.error("database error trying to create tables")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise
if version < 2:
db = self.get_db()
try:
version = 2
db.execute("""ALTER TABLE twitter_settings ADD COLUMN oauth_token TEXT DEFAULT NULL""")
db.execute("""ALTER TABLE twitter_settings ADD COLUMN oauth_token_secret TEXT DEFAULT NULL""")
db.commit()
db.close()
self.db_register_module_version(self.__class__.__name__, version)
except sqlite3.Error as e:
db.rollback()
db.close()
self.log.error("sqlite error: " + str(e))
raise raise
finally: cur.close()
def shutdown(self): def shutdown(self):
"""Deauth, and make the twitter API item inoperable.""" """Deauth, and make the twitter API item inoperable."""
@ -395,49 +383,51 @@ class Twitter(Module):
def _get_last_since_id(self): def _get_last_since_id(self):
"""Get the since_id out of the database.""" """Get the since_id out of the database."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = "SELECT since_id FROM twitter_settings" query = "SELECT since_id FROM twitter_settings"
cursor = db.execute(query) cur.execute(query)
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
return result['since_id'] return result['since_id']
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error getting last since ID")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _get_output_channel(self): def _get_output_channel(self):
"""Get the output_channel out of the database.""" """Get the output_channel out of the database."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = "SELECT output_channel FROM twitter_settings" query = "SELECT output_channel FROM twitter_settings"
cursor = db.execute(query) cur.execute(query)
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
return result['output_channel'] return result['output_channel']
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error getting output channel")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
def _set_last_since_id(self, since_id): def _set_last_since_id(self, since_id):
"""Set the since_id.""" """Set the since_id."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = "UPDATE twitter_settings SET since_id = %s"
statement = "UPDATE twitter_settings SET since_id = ?"
cur.execute(statement, (since_id,)) cur.execute(statement, (since_id,))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e: self.log.error("database error saving last since ID")
db.close() self.log.exception(e)
self.log.error("sqlite error: " + str(e))
raise raise
finally: cur.close()
def _get_latest_tweet_id(self, tweets, since_id): def _get_latest_tweet_id(self, tweets, since_id):
"""Find the latest tweet id in the provided list, or the given since_id.""" """Find the latest tweet id in the provided list, or the given since_id."""
@ -452,34 +442,34 @@ class Twitter(Module):
def _persist_auth_tokens(self, oauth_token, oauth_token_secret): def _persist_auth_tokens(self, oauth_token, oauth_token_secret):
"""Save the auth tokens to the database, with the intent of reusing them.""" """Save the auth tokens to the database, with the intent of reusing them."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
cur = db.cursor() statement = "UPDATE twitter_settings SET oauth_token = %s, oauth_token_secret = %s"
statement = "UPDATE twitter_settings SET oauth_token = ?, oauth_token_secret = ?"
cur.execute(statement, (oauth_token, oauth_token_secret)) cur.execute(statement, (oauth_token, oauth_token_secret))
db.commit() db.commit()
db.close() except mdb.Error as e:
except sqlite3.Error as e: self.log.error("database error saving auth tokens")
db.close() self.log.exception(e)
self.log.error("sqlite error: " + str(e))
raise raise
finally: cur.close()
def _retrieve_stored_auth_tokens(self): def _retrieve_stored_auth_tokens(self):
"""Check the database for existing auth tokens, try reusing them.""" """Check the database for existing auth tokens, try reusing them."""
db = self.get_db()
try: try:
db = self.get_db() cur = db.cursor(mdb.cursors.DictCursor)
query = "SELECT oauth_token, oauth_token_secret FROM twitter_settings" query = "SELECT oauth_token, oauth_token_secret FROM twitter_settings"
cursor = db.execute(query) cur.execute(query)
result = cursor.fetchone() result = cur.fetchone()
db.close()
if result: if result:
return (result['oauth_token'], result['oauth_token_secret']) return (result['oauth_token'], result['oauth_token_secret'])
except sqlite3.Error as e: except mdb.Error as e:
db.close() self.log.error("database error retrieving auth tokens")
self.log.error("sqlite error: " + str(e)) self.log.exception(e)
raise raise
finally: cur.close()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -1,3 +1,4 @@
MySQL-python==1.2.3
httplib2==0.7.4 httplib2==0.7.4
oauth2==1.5.211 oauth2==1.5.211
ply==3.4 ply==3.4