diff --git a/Module.py b/Module.py
index 94cb111..fd3156b 100644
--- a/Module.py
+++ b/Module.py
@@ -21,9 +21,10 @@ from ConfigParser import NoSectionError, NoOptionError
import logging
import re
import sys
-import sqlite3
from threading import Timer
+import MySQLdb as mdb
+
from extlib import irclib
class Module(object):
@@ -165,7 +166,7 @@ class Module(object):
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
test for and create (or, eventually, alter) required table structure
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.
"""
- dbfile = self.config.get('dr.botzo', 'database')
- conn = sqlite3.connect(dbfile, isolation_level=None)
- conn.row_factory = sqlite3.Row
+ dbhost = self.config.get('dr.botzo', 'dbhost')
+ dbuser = self.config.get('dr.botzo', 'dbuser')
+ 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
- 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
+ return db
def db_module_registered(self, modulename):
"""
@@ -193,19 +190,20 @@ class Module(object):
number if the module has registered, or None if not
"""
- conn = self.get_db()
+ db = self.get_db()
version = None
try:
- cur = conn.cursor()
- cur.execute("SELECT version FROM drbotzo_modules WHERE module = :name",
- {'name': modulename})
+ cur = db.cursor()
+ cur.execute("SELECT version FROM drbotzo_modules WHERE module = %s",
+ (modulename,))
version = cur.fetchone()
if (version != None):
version = version[0]
- conn.close()
- except sqlite3.Error as e:
- conn.close()
- self.log.error("sqlite error:" + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during module registered check")
+ self.log.exception(e)
+ raise
+ finally: cur.close()
return version
@@ -214,14 +212,16 @@ class Module(object):
db = self.get_db()
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.close()
- except sqlite3.Error as e:
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error during register module version")
+ self.log.exception(e)
raise
+ finally: cur.close()
def db_init(self):
"""
diff --git a/dr.botzo.cfg.example b/dr.botzo.cfg.example
index efa4417..d9ade37 100644
--- a/dr.botzo.cfg.example
+++ b/dr.botzo.cfg.example
@@ -7,10 +7,13 @@ usermode = -x
debug = true
admin_userhost = bss@ayu.incorporeal.org
module_list = IrcAdmin
-database = dr.botzo.data
+dbhost = localhost
+dbuser = dr_botzo
+dbpass = password
+dbname = dr_botzo
[IrcAdmin]
autojoin = #bss
[Karma]
-meta.pubmsg_needs_bot_prefix = false
\ No newline at end of file
+meta.pubmsg_needs_bot_prefix = false
diff --git a/dr.botzo.py b/dr.botzo.py
index 2560ad9..01572da 100644
--- a/dr.botzo.py
+++ b/dr.botzo.py
@@ -21,7 +21,8 @@ import logging
import logging.config
import os
import sys
-import sqlite3
+
+import MySQLdb as mdb
import DrBotIRC
from extlib import irclib
@@ -53,28 +54,31 @@ logging.config.fileConfig('logging.cfg')
log = logging.getLogger('drbotzo')
try:
- # make sure we can initialize the database, if such a thing is
- # called for in the config file
- dbfile = config.get('dr.botzo', 'database')
- conn = sqlite3.connect(dbfile, isolation_level=None)
+ dbhost = config.get('dr.botzo', 'dbhost')
+ dbuser = config.get('dr.botzo', 'dbuser')
+ dbpass = config.get('dr.botzo', 'dbpass')
+ dbname = config.get('dr.botzo', 'dbname')
+ db = mdb.connect(dbhost, dbuser, dbpass, dbname, use_unicode=True)
try:
+ cur = db.cursor()
+ # need to create the drbotzo_modules table if it doesn't exist
query = """
- SELECT COUNT(*)
- FROM sqlite_master
- WHERE type = 'table' AND name = 'drbotzo_modules'
+ SELECT COUNT(*) FROM information_schema.tables
+ WHERE table_schema = %s
+ AND table_name = %s
"""
- row = conn.execute(query).fetchone()
+ cur.execute(query, (dbname, 'drbotzo_modules'))
+ row = cur.fetchone()
if row[0] == 0:
- # need to create the drbotzo_modules table
query = """
- CREATE TABLE drbotzo_modules (
- module TEXT PRIMARY KEY,
- version INTEGER
- )
+ CREATE TABLE IF NOT EXISTS drbotzo_modules (
+ module VARCHAR(64) PRIMARY KEY,
+ version INTEGER
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
"""
- conn.execute(query)
- conn.commit()
- finally: conn.close()
+ cur.execute(query)
+ db.commit()
+ finally: cur.close()
except NoOptionError as e:
sys.exit("Aborted due to error with necessary configuration: " + str(e))
diff --git a/modules/Achievements.py b/modules/Achievements.py
index 8298a54..70fafc8 100644
--- a/modules/Achievements.py
+++ b/modules/Achievements.py
@@ -17,10 +17,11 @@ along with this program. If not, see .
"""
import re
-import sqlite3
import thread
import time
+import MySQLdb as mdb
+
from Module import Module
from extlib import irclib
@@ -73,89 +74,73 @@ class Achievements(Module):
db = self.get_db()
try:
version = 1
- db.execute('''
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
CREATE TABLE achievements_player (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- nick TEXT NOT NULL UNIQUE,
- userhost TEXT NOT NULL DEFAULT '',
+ id SERIAL,
+ nick VARCHAR(64) NOT NULL UNIQUE,
+ userhost VARCHAR(256) NOT NULL DEFAULT '',
is_playing INTEGER NOT NULL DEFAULT 0,
- last_seen_time TEXT DEFAULT CURRENT_TIMESTAMP
- )''')
- db.execute('''
+ last_seen_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE achievements_event (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- player_id INTEGER NOT NULL,
- event TEXT NOT NULL,
- target TEXT,
+ id SERIAL,
+ player_id BIGINT(20) UNSIGNED NOT NULL,
+ event VARCHAR(64) NOT NULL,
+ target VARCHAR(64),
msg_len INTEGER,
- event_time TEXT DEFAULT CURRENT_TIMESTAMP,
+ event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(player_id) REFERENCES achievements_player(id)
- )''')
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE achievements_achievement (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- name TEXT NOT NULL,
- desc TEXT NOT NULL,
- query TEXT NOT NULL
- )''')
- db.execute('''
+ id SERIAL,
+ name VARCHAR(256) NOT NULL,
+ description VARCHAR(256) NOT NULL,
+ query VARCHAR(1024) NOT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE achievements_log (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- player_id INTEGER NOT NULL,
- achievement_id INTEGER NOT NULL,
- event_time TEXT DEFAULT CURRENT_TIMESTAMP,
+ id SERIAL,
+ player_id BIGINT(20) UNSIGNED NOT NULL,
+ achievement_id BIGINT(20) UNSIGNED NOT NULL,
+ event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(player_id) REFERENCES achievements_player(id),
FOREIGN KEY(achievement_id) REFERENCES achievements_achievement(id)
- )''')
- 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
- if (version < 2):
- db = self.get_db()
- try:
- version = 2
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE achievements_config (
channel TEXT NOT 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
- if (version < 3):
- db = self.get_db()
- try:
- version = 3
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE achievements_filter (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- filter TEXT NOT NULL
- )''')
- db.execute('''
+ id SERIAL,
+ filter VARCHAR(256) NOT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE achievements_filter_log (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- filter_id INTEGER NOT NULL,
- event_id INTEGER NOT NULL,
+ id SERIAL,
+ filter_id BIGINT(20) UNSIGNED NOT NULL,
+ event_id BIGINT(20) UNSIGNED NOT NULL,
FOREIGN KEY(filter_id) REFERENCES achievements_filter(id),
FOREIGN KEY(event_id) REFERENCES achievements_event(id)
- )''')
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
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.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def register_handlers(self):
"""Handle all sorts of things to track."""
@@ -247,37 +232,37 @@ class Achievements(Module):
def _get_or_add_player(self, nick, userhost):
"""Add a player to the database, or update the existing one, and return the id."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
- INSERT OR IGNORE INTO achievements_player (nick) VALUES (?)'''
+ INSERT IGNORE INTO achievements_player (nick) VALUES (%s)'''
cur.execute(statement, (nick,))
statement = '''
- UPDATE achievements_player SET userhost = ?, last_seen_time = CURRENT_TIMESTAMP
- WHERE nick = ?'''
+ UPDATE achievements_player SET userhost = %s, last_seen_time = CURRENT_TIMESTAMP
+ WHERE nick = %s'''
cur.execute(statement, (userhost, nick))
db.commit()
- statement = '''SELECT id FROM achievements_player WHERE nick = ?'''
- cur = db.execute(statement, (nick,))
+ statement = '''SELECT id FROM achievements_player WHERE nick = %s'''
+ cur.execute(statement, (nick,))
result = cur.fetchone()
- db.close()
return result['id']
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error getting or adding player")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _add_event(self, player_id, event, target, msg, msg_len):
"""Add an event to the log."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
INSERT INTO achievements_event (
player_id, event, target, msg_len
- ) VALUES (?, ?, ?, ?)
+ ) VALUES (%s, %s, %s, %s)
'''
cur.execute(statement, (player_id, event, target, msg_len))
db.commit()
@@ -285,135 +270,143 @@ class Achievements(Module):
# now see if the event matched any filters
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'),))
- results = cursor.fetchall()
+ cur.execute(query, (msg.decode('utf-8', 'replace'),))
+ results = cur.fetchall()
for result in results:
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
INSERT INTO achievements_filter_log (filter_id, event_id)
- VALUES (?, ?)
+ VALUES (%s, %s)
'''
cur.execute(statement, (result['id'], event_id))
db.commit()
- db.close()
-
return event_id
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error adding event")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_achievements_settings(self):
"""Get the report settings."""
+ db = self.get_db()
try:
# get the settings
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT channel FROM achievements_config'
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur.execute(query)
+ result = cur.fetchone()
if result:
settings = self.AchievementsSettings()
settings.channel = result['channel']
return settings
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ else:
+ return None
+ except mdb.Error as e:
+ self.log.error("database error getting settings")
+ self.log.exception(e)
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):
- """Add the appropriate nick to the game."""
+ """Add the appropriate nick to the system."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = 'UPDATE achievements_player SET is_playing = 1 WHERE nick = ?'
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = 'UPDATE achievements_player SET is_playing = 1 WHERE nick = %s'
cur.execute(statement, (nick,))
db.commit()
- db.close()
return nick + ' joined.'
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error joining the system")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _leave_system(self, nick):
- """Remove the appropriate nick from the game."""
+ """Remove the appropriate nick from the system."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = 'UPDATE achievements_player SET is_playing = 0 WHERE nick = ?'
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = 'UPDATE achievements_player SET is_playing = 0 WHERE nick = %s'
cur.execute(statement, (nick,))
db.commit()
- db.close()
return nick + ' left.'
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error leaving the system")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _add_player_to_achievement_log(self, player_id, achievement_id):
"""Log the success of a player."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = 'INSERT INTO achievements_log (player_id, achievement_id) VALUES (?, ?)'
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = 'INSERT INTO achievements_log (player_id, achievement_id) VALUES (%s, %s)'
cur.execute(statement, (player_id, achievement_id))
db.commit()
- db.close()
return
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error adding player to achievement log")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_achievement_info(self, achievement):
"""Return the description of a given achievement."""
+ db = self.get_db()
try:
- db = self.get_db()
- query = 'SELECT desc FROM achievements_achievement WHERE name = ?'
- cursor = db.execute(query, (achievement,))
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ query = 'SELECT description FROM achievements_achievement WHERE name = %s'
+ cur.execute(query, (achievement,))
+ result = cur.fetchone()
if result:
- return result['desc']
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ return result['description']
+ except mdb.Error as e:
+ self.log.error("database error getting achievement info")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_player_achievements(self, nick):
"""Return the achievements the nick has."""
achievements = []
+ db = self.get_db()
try:
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
SELECT a.name FROM achievements_achievement a
INNER JOIN achievements_log l ON l.achievement_id = a.id
INNER JOIN achievements_player p ON p.id = l.player_id
- WHERE p.nick = ?
+ WHERE p.nick = %s
'''
- cursor = db.execute(query, (nick,))
- results = cursor.fetchall()
- db.close()
+ cur.execute(query, (nick,))
+ results = cur.fetchall()
for result in results:
achievements.append(result['name'])
return achievements
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error getting player achievements")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _do_achievement_scan(self):
"""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:
return
+ self.log.debug('in achievement scan')
settings = self._get_achievements_settings()
- channel = settings.channel
- achievers = self._query_for_new_achievers()
- for achiever in achievers:
- self.sendmsg(self.connection, channel, achiever[0] + ' achieved ' + achiever[1] + '!')
+ if settings is not None:
+ channel = settings.channel
+ achievers = self._query_for_new_achievers()
+ for achiever in achievers:
+ self.sendmsg(self.connection, channel, achiever[0] + ' achieved ' + achiever[1] + '!')
def _query_for_new_achievers(self):
"""Get new achievement earners for each achievement."""
achievers = []
+ self.log.debug('checking achievements')
+ db = self.get_db()
try:
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT id, name, query FROM achievements_achievement'
- cursor = db.execute(query)
- achievements = cursor.fetchall()
+ cur.execute(query)
+ achievements = cur.fetchall()
for achievement in achievements:
self.log.debug('checking achievement:[' + achievement['name'] + ']')
@@ -458,22 +455,22 @@ class Achievements(Module):
SELECT player_id FROM achievements_log l
INNER JOIN achievements_achievement a
ON a.id = l.achievement_id
- WHERE a.name = ?
+ WHERE a.name = %s
)
'''
- cursor = db.execute(query, (achievement['name'],))
- ach_achievers = cursor.fetchall()
+ cur.execute(query, (achievement['name'],))
+ ach_achievers = cur.fetchall()
for ach_achiever in ach_achievers:
self.log.debug('name:[' + ach_achiever['nick'] + '] achievement:[' + achievement['name'] + ']')
self._add_player_to_achievement_log(ach_achiever['id'], achievement['id'])
achievers.append((ach_achiever['nick'], achievement['name']))
- db.close()
return achievers
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error scanning new achievers")
+ self.log.exception(e)
raise
+ finally: cur.close()
# vi:tabstop=4:expandtab:autoindent
diff --git a/modules/Acro.py b/modules/Acro.py
index 00b21a5..2243095 100644
--- a/modules/Acro.py
+++ b/modules/Acro.py
@@ -18,7 +18,6 @@ along with this program. If not, see .
import random
import re
-import sqlite3
import thread
import time
diff --git a/modules/Facts.py b/modules/Facts.py
index b16ab8f..f4bb95b 100644
--- a/modules/Facts.py
+++ b/modules/Facts.py
@@ -18,7 +18,8 @@ along with this program. If not, see .
import random
import re
-import sqlite3
+
+import MySQLdb as mdb
from extlib import irclib
@@ -46,38 +47,40 @@ class Facts(Module):
if version == None:
db = self.get_db()
try:
- db.execute('''
+ version = 1
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
CREATE TABLE facts_facts (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- category TEXT NOT NULL,
- fact TEXT NOT NULL,
- who TEXT NOT NULL,
- userhost TEXT NOT NULL,
- time TEXT DEFAULT CURRENT_TIMESTAMP
- )
+ id SERIAL,
+ category VARCHAR(64) NOT NULL,
+ fact LONGTEXT NOT NULL,
+ who VARCHAR(64) NOT NULL,
+ userhost VARCHAR(256) NOT NULL,
+ time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
''')
- db.execute('INSERT INTO drbotzo_modules VALUES (?,?)', (self.__class__.__name__, 1))
db.commit()
- db.close()
- except sqlite3.Error as e:
+ self.db_register_module_version(self.__class__.__name__, version)
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Add or retrieve a fact from the database."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
match = re.search('^!facts\s+add\s+(\S+)\s+(.*)$', what)
if match:
category = match.group(1)
fact = match.group(2)
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()
return self.reply(connection, event, category + ' added.')
@@ -91,10 +94,12 @@ class Facts(Module):
if match:
category = match.group(1)
return self.reply(connection, event, self._get_fact(category))
- db.close()
- except sqlite3.Error as e:
- db.close()
- return self.reply(connection, event, "sqlite error: " + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during add/retrieve")
+ self.log.exception(e)
+ return self.reply(connection, event, "database error during add/retrieve fact")
+ finally: cur.close()
def _get_fact(self, category, search=""):
"""
@@ -105,26 +110,27 @@ class Facts(Module):
search - the optional regex to match against within that category
"""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
if search == "":
- category_facts = cur.execute("SELECT * FROM facts_facts WHERE category=?", (category,))
- facts = category_facts.fetchall()
- db.close()
+ cur.execute("SELECT * FROM facts_facts WHERE category = %s",
+ (category,))
+ facts = cur.fetchall()
else:
- category_facts = cur.execute("SELECT * FROM facts_facts WHERE category=? AND fact REGEXP ?",
- (category, search))
- facts = category_facts.fetchall()
- db.close()
+ cur.execute("SELECT * FROM facts_facts WHERE category = %s AND fact REGEXP %s",
+ (category, search))
+ facts = cur.fetchall()
if len(facts) > 0:
fact = facts[random.randint(1,len(facts))-1]
return fact['fact'].rstrip().encode('utf-8', 'ignore')
- except sqlite3.Error as e:
- db.close()
- return self.reply(connection, event, "sqlite error in _get_fact: " + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _get_fact")
+ self.log.exception(e)
+ return self.reply(connection, event, "database error in _get_fact")
+ finally: cur.close()
# vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on;
diff --git a/modules/Help.py b/modules/Help.py
index eabbf1c..77c1b62 100644
--- a/modules/Help.py
+++ b/modules/Help.py
@@ -17,7 +17,6 @@ along with this program. If not, see .
"""
import re
-import sqlite3
from Module import Module
diff --git a/modules/Karma.py b/modules/Karma.py
index f7e2f9a..467d263 100644
--- a/modules/Karma.py
+++ b/modules/Karma.py
@@ -16,10 +16,12 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+from math import floor
import re
-import sqlite3
import string
+import MySQLdb as mdb
+
from Module import Module
__author__ = "Mike Bloy "
@@ -50,67 +52,40 @@ class Karma(Module):
version = self.db_module_registered(self.__class__.__name__)
if (version == None):
# have to create the database tables
- conn = self.get_db()
+ db = self.get_db()
try:
- conn.execute('''
- CREATE TABLE karma_log (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- key TEXT NOT NULL,
- delta INTEGER NOT NULL,
- who TEXT NOT NULL,
- userhost TEXT NOT NULL,
- karmatime TEXT DEFAULT CURRENT_TIMESTAMP
- )''')
- conn.execute('CREATE INDEX karma_log_key_ix ON karma_log (key)')
- conn.execute('CREATE INDEX karma_log_who_ix ON karma_log (who)')
- conn.execute('''
- CREATE VIEW karma_values AS
- SELECT key, SUM(delta) AS value
- FROM karma_log
- GROUP BY key''')
-
- sql = 'INSERT INTO drbotzo_modules VALUES (?,?)'
- conn.execute(sql, (self.__class__.__name__, 1))
- conn.commit()
- conn.close()
version = 1
- except sqlite3.Error as e:
- conn.rollback()
- conn.close()
- self.log.error("sqlite error: " + str(e))
- raise
- if (version < 2):
- conn = self.get_db()
- try:
- conn.execute('''
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
+ CREATE TABLE karma_log (
+ id SERIAL,
+ karma_key VARCHAR(128) NOT NULL,
+ delta INTEGER NOT NULL,
+ who VARCHAR(64) NOT NULL,
+ userhost VARCHAR(256) NOT NULL,
+ 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
SELECT who, COUNT(NULLIF(delta, -1)) AS pos,
COUNT(NULLIF(delta, 1)) AS neg
FROM karma_log GROUP BY who''')
- sql = 'UPDATE drbotzo_modules SET version = ? WHERE module = ?'
- conn.execute(sql, (2, self.__class__.__name__))
- conn.commit()
- 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()
+ db.commit()
self.db_register_module_version(self.__class__.__name__, version)
- except sqlite3.Error as e:
- conn.rollback()
- conn.close()
- self.log.error("sqlite error: " + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""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.
"""
- conn = self.get_db()
+ db = self.get_db()
try:
+ cur = db.cursor(mdb.cursors.DictCursor)
sql = '''
- INSERT INTO karma_log (key, delta, who, userhost)
- VALUES (?, ?, ?, ?)
+ INSERT INTO karma_log (karma_key, delta, who, userhost)
+ VALUES (%s, %s, %s, %s)
'''
- conn.execute(sql, (key.decode('utf-8', 'ignore').lower(), value, nick, userhost))
- conn.commit()
- conn.close()
- except sqlite3.Error as e:
- conn.rollback()
- conn.close()
- return "sqlite error: " + str(e)
+ cur.execute(sql, (key.decode('utf-8', 'ignore').lower(), value, nick, userhost))
+ db.commit()
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error modifying karma")
+ self.log.exception(e)
+ raise
+ finally: cur.close()
def handle_report_query(self, connection, nick, userhost, what):
match = self.reportre.search(what)
@@ -169,61 +146,66 @@ class Karma(Module):
query = None
header = None
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:'
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:'
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:'
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:'
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:'
if (query != None):
- conn = self.get_db()
+ db = self.get_db()
list = []
try:
- cursor = conn.execute(query)
- result = cursor.fetchone()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query)
+ result = cur.fetchone()
while (result != None):
- list.append("{key} ({value})".format(key=result[0], value=result[1]))
- result = cursor.fetchone()
+ list.append("{key} ({value})".format(key=result['who'], value=result['value']))
+ result = cur.fetchone()
list = ', '.join(list)
message = '{header} {list}'.format(header=header, list=list)
- conn.close()
- except sqlite3.Error as e:
- conn.rollback()
- conn.close()
- return "sqlite error: " + str(e)
+ except mdb.Error as e:
+ self.log.error("database error during report query")
+ self.log.exception(e)
+ raise
+ finally: cur.close()
+
return message
def handle_stat_query(self, connection, nick, userhost, what):
match = self.statre.search(what)
statnick = match.group(1)
- conn = self.get_db()
+ db = self.get_db()
reply = '{nick}: {statnick} has never given karma'.format(nick=nick, statnick=statnick)
try:
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
SELECT pos, neg
FROM karma_users
WHERE who = :who
'''
- value = conn.execute(query, {'who': statnick}).fetchone()
+ cur.execute(query, {'who': statnick})
+ value = cur.fetchone()
if (value != None):
pos = value[0]
neg = value[1]
total = pos+neg;
reply = '{nick}: {statnick} has given {pos} postive karma and {neg} negative karma, for a total of {total} karma'.format(nick=nick, statnick=statnick, pos=pos, neg=neg, total=total)
- conn.close()
- except sqlite3.Error as e:
- conn.close()
- return "sqlite error: " + str(e)
+ except mdb.Error as e:
+ self.log.error("database error during handle stat query")
+ self.log.exception(e)
+ raise
+ finally: cur.close()
return reply
@@ -231,29 +213,33 @@ class Karma(Module):
match = self.queryre.search(what)
key = match.group(1)
- conn = self.get_db()
+ db = self.get_db()
reply = '{nick}: {key} has no karma'.format(nick=nick, key=key)
try:
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
SELECT value
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):
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()
- rank = rank[0] + 1;
+ cur.execute(query, (value['value'],))
+ rank = cur.fetchone()
+ rank = rank['count(*)'] + 1;
- reply = '{nick}: {key} has {value[0]!s} points of karma (rank {rank})'.format(
- nick=nick, key=key, value=value, rank=rank)
- conn.close()
- except sqlite3.Error as e:
- conn.close()
- return "sqlite error: " + str(e)
+ reply = '{0:s}: {1:s} has {2:d} points of karma (rank {3:d})'.format(
+ nick, key, int(floor(value['value'])), rank)
+ except mdb.Error as e:
+ self.log.error("database error during handle karma query")
+ self.log.exception(e)
+ raise
+ finally: cur.close()
return reply
diff --git a/modules/Markov.py b/modules/Markov.py
index 60e02e6..ffa68f8 100644
--- a/modules/Markov.py
+++ b/modules/Markov.py
@@ -21,11 +21,12 @@ from datetime import datetime
import os
import random
import re
-import sqlite3
import sys
import thread
import time
+import MySQLdb as mdb
+
from dateutil.parser import *
from dateutil.relativedelta import *
from extlib import irclib
@@ -76,67 +77,58 @@ class Markov(Module):
"""Create the markov chain table."""
version = self.db_module_registered(self.__class__.__name__)
- if (version == None or version < 9):
+ if version == None:
db = self.get_db()
try:
- version = 9
-
- # recreating the tables, since i need to add some foreign key constraints
- 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('''
+ version = 1
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
CREATE TABLE markov_chatter_target (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- target TEXT NOT NULL,
+ id SERIAL,
+ target VARCHAR(256) NOT NULL,
chance INTEGER NOT NULL DEFAULT 99999
- )''')
-
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE markov_context (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- context TEXT NOT NULL
- )''')
-
- db.execute('''
+ id SERIAL,
+ context VARCHAR(256) NOT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE markov_target_to_context_map (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- target TEXT NOT NULL,
- context_id INTEGER NOT NULL,
+ id SERIAL,
+ target VARCHAR(256) NOT NULL,
+ context_id BIGINT(20) UNSIGNED NOT NULL,
FOREIGN KEY(context_id) REFERENCES markov_context(id)
- )''')
-
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE markov_chain (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- k1 TEXT NOT NULL,
- k2 TEXT NOT NULL,
- v TEXT NOT NULL,
- context_id INTEGER DEFAULT NULL,
+ id SERIAL,
+ k1 VARCHAR(128) NOT NULL,
+ k2 VARCHAR(128) NOT NULL,
+ v VARCHAR(128) NOT NULL,
+ context_id BIGINT(20) UNSIGNED NOT NULL,
FOREIGN KEY(context_id) REFERENCES markov_context(id)
- )''')
-
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE INDEX markov_chain_keys_and_context_id_index
ON markov_chain (k1, k2, context_id)''')
- db.execute('''
+ cur.execute('''
CREATE INDEX markov_chain_value_and_context_id_index
ON markov_chain (v, context_id)''')
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.close()
- self.log.error('sqlite error: ' + str(e))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def register_handlers(self):
"""Handle pubmsg/privmsg, to learn and/or reply to IRC events."""
@@ -303,10 +295,10 @@ class Markov(Module):
if len(words) <= 0:
return line
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = 'INSERT INTO markov_chain (k1, k2, v, context_id) VALUES (?, ?, ?, ?)'
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = 'INSERT INTO markov_chain (k1, k2, v, context_id) VALUES (%s, %s, %s, %s)'
for word in words:
cur.execute(statement, (k1.decode('utf-8', 'replace'),
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))
db.commit()
- db.close()
- except sqlite3.Error as e:
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error in Markov._learn_line: " + str(e))
+ self.log.error("database error learning line")
+ self.log.exception(e)
raise
+ finally: cur.close()
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)."""
values = []
+ db = self.get_db()
try:
- db = self.get_db()
query = ''
if k1 == self.start1 and k2 == self.start2:
# hack. get a quasi-random start from the database, in
# a faster fashion than selecting all starts
max_id = self._get_max_chain_id()
rand_id = random.randint(1,max_id)
- query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND '
- '(context_id = ?) AND id >= {0:d} LIMIT 1'.format(rand_id))
+ query = ('SELECT v FROM markov_chain WHERE k1 = %s AND k2 = %s AND '
+ '(context_id = %s) AND id >= {0:d} LIMIT 1'.format(rand_id))
else:
- query = ('SELECT v FROM markov_chain WHERE k1 = ? AND k2 = ? AND '
- '(context_id = ?)')
- cursor = db.execute(query, (k1.decode('utf-8', 'replace'),
- k2.decode('utf-8', 'replace'),
- context_id))
- results = cursor.fetchall()
+ query = ('SELECT v FROM markov_chain WHERE k1 = %s AND k2 = %s AND '
+ '(context_id = %s)')
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query, (k1.decode('utf-8', 'replace'),
+ k2.decode('utf-8', 'replace'),
+ context_id))
+ results = cur.fetchall()
for result in results:
values.append(result['v'].encode('utf-8', 'replace'))
- db.close()
return values
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error in Markov._retrieve_chains_for_key: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _retrieve_chains_for_key")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _retrieve_k2_for_value(self, v, context_id):
"""Get the value(s) for a given key (a pair of strings)."""
values = []
+ db = self.get_db()
try:
- db = self.get_db()
- query = 'SELECT k2 FROM markov_chain WHERE v = ? AND (context_id = ?)'
- cursor = db.execute(query, (v.decode('utf-8', 'replace'), context_id))
- results = cursor.fetchall()
+ query = 'SELECT k2 FROM markov_chain WHERE v = %s AND context_id = %s'
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query, (v.decode('utf-8', 'replace'), context_id))
+ results = cur.fetchall()
for result in results:
values.append(result['k2'].encode('utf-8', 'replace'))
- db.close()
return values
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error in Markov._retrieve_k2_for_value: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _retrieve_k2_for_value")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_chatter_targets(self):
"""Get all possible chatter targets."""
values = []
+ db = self.get_db()
try:
# 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'
- cursor = db.execute(query)
- results = cursor.fetchall()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query)
+ results = cur.fetchall()
return results
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error in Markov._get_chatter_targets: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _get_chatter_targets")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_one_chatter_target(self):
"""Select one random chatter target."""
@@ -486,37 +482,39 @@ class Markov(Module):
def _get_max_chain_id(self):
"""Get the highest id in the chain table."""
+ db = self.get_db()
try:
- db = self.get_db()
query = '''
SELECT id FROM markov_chain ORDER BY id DESC LIMIT 1
'''
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query)
+ result = cur.fetchone()
if result:
return result['id']
else:
return None
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error in Markov._get_max_chain_id: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _get_max_chain_id")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_context_id_for_target(self, target):
"""Get the context ID for the desired/input target."""
+ db = self.get_db()
try:
- db = self.get_db()
query = '''
SELECT mc.id FROM markov_context mc
INNER JOIN markov_target_to_context_map mt
ON mt.context_id = mc.id
- WHERE mt.target = ?
+ WHERE mt.target = %s
'''
- cursor = db.execute(query, (target,))
- result = cursor.fetchone()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query, (target,))
+ result = cur.fetchone()
db.close()
if result:
return result['id']
@@ -524,53 +522,55 @@ class Markov(Module):
# auto-generate a context to keep things private
self._add_context_for_target(target)
return self._get_context_id_for_target(target)
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error in Markov._get_context_id_for_target: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _get_context_id_for_target")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _add_context_for_target(self, target):
"""Create a new context for the desired/input target."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = 'INSERT INTO markov_context (context) VALUES (?)'
+ statement = 'INSERT INTO markov_context (context) VALUES (%s)'
+ cur = db.cursor(mdb.cursors.DictCursor)
cur.execute(statement, (target,))
statement = '''
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))
db.commit()
- db.close()
- except sqlite3.Error as e:
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error in Markov._add_context_for_target: " + str(e))
+ self.log.error("database error in _add_context_for_target")
+ self.log.exception(e)
raise
+ finally: cur.close()
+
try:
- db = self.get_db()
query = '''
SELECT mc.id FROM markov_context mc
INNER JOIN markov_target_to_context_map mt
ON mt.context_id = mc.id
- WHERE mt.target = ?
+ WHERE mt.target = %s
'''
- cursor = db.execute(query, (target,))
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute(query, (target,))
+ result = cur.fetchone()
if result:
return result['id']
else:
# auto-generate a context to keep things private
self._add_context_for_target(target)
return self._get_context_id_for_target(target)
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error in Markov._get_context_id_for_target: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error in _get_context_id_for_target")
+ self.log.exception(e)
raise
+ finally: cur.close()
# vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on;
diff --git a/modules/Pi.py b/modules/Pi.py
index 1f1af2e..04e400e 100644
--- a/modules/Pi.py
+++ b/modules/Pi.py
@@ -19,7 +19,8 @@ along with this program. If not, see .
import math
import random
import re
-import sqlite3
+
+import MySQLdb as mdb
from extlib import irclib
@@ -46,37 +47,39 @@ class Pi(Module):
# create tables
db = self.get_db()
try:
- db.execute('''
+ version = 1
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
CREATE TABLE pi_log (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
+ id SERIAL,
count_inside 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
SELECT count_inside, count_total
FROM pi_log
ORDER BY id DESC
''')
- db.execute('INSERT INTO drbotzo_modules VALUES (?,?)', (self.__class__.__name__, 1))
db.commit()
- db.close()
- except sqlite3.Error as e:
+ self.db_register_module_version(self.__class__.__name__, version)
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked):
match = re.search('^!pi$', what)
if match:
db = self.get_db()
try:
- cur = db.cursor()
- pi_data = cur.execute('SELECT * FROM pi_latest_pi')
- datum = pi_data.fetchone()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('SELECT * FROM pi_latest_pi')
+ datum = cur.fetchone()
if datum == None:
count_inside = 0
@@ -96,13 +99,15 @@ class Pi(Module):
count += 1
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.close()
- except sqlite3.Error as e:
+ except mdb.Error as e:
db.rollback()
- db.close()
- return self.reply(connection, event, "sqlite error: " + str(e))
+ self.log.error("database error doing pi stuff")
+ 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))
diff --git a/modules/Seen.py b/modules/Seen.py
index 7442a19..ea06c3e 100644
--- a/modules/Seen.py
+++ b/modules/Seen.py
@@ -17,7 +17,8 @@ along with this program. If not, see .
"""
import re
-import sqlite3
+
+import MySQLdb as mdb
from datetime import datetime
from dateutil.tz import *
@@ -36,89 +37,72 @@ class Seen(Module):
if version == None:
db = self.get_db()
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
- 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('''DROP TABLE seen_nicks''')
- db.execute('''
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
CREATE TABLE seen_nicks (
- nick TEXT NOT NULL,
- location TEXT NOT NULL,
- host TEXT NOT NULL,
- time TEXT DEFAULT CURRENT_TIMESTAMP,
- what TEXT NOT NULL
- )''')
- db.execute('''
+ nick VARCHAR(64) NOT NULL PRIMARY KEY,
+ location VARCHAR(64) NOT NULL,
+ host VARCHAR(256) NOT NULL,
+ time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ what LONGTEXT NOT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE UNIQUE INDEX seen_nicks_nick_and_location_index
- ON seen_nicks (nick, location)''')
+ ON seen_nicks (nick, location)
+ ''')
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.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Track pubmsg/privmsg events, and if asked, report on someone."""
where = event.target()
+ db = self.get_db()
# whatever it is, store it
try:
# if there's no where, this is probably a sub-command. don't learn it
if where:
- db = self.get_db()
- cur = db.cursor()
- statement = 'REPLACE INTO seen_nicks (nick, location, host, what) VALUES (?, ?, ?, ?)'
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = 'REPLACE INTO seen_nicks (nick, location, host, what) VALUES (%s, %s, %s, %s)'
cur.execute(statement, (nick, where, userhost, what.decode('utf-8', 'replace')))
db.commit()
- db.close()
- except sqlite3.Error as e:
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error storing seen data")
+ self.log.exception(e)
raise
+ finally: cur.close()
match = re.search('^!seen\s+(\S+)$', what)
if match:
nick = match.group(1)
+ db = self.get_db()
try:
- db = self.get_db()
- query = 'SELECT * FROM seen_nicks WHERE nick = ? AND location = ?'
- cursor = db.execute(query, (nick,where))
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ query = 'SELECT * FROM seen_nicks WHERE nick = %s AND location = %s'
+ cur.execute(query, (nick,where))
+ result = cur.fetchone()
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'))
return self.reply(connection, event, replystr)
else:
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.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error retrieving seen data")
+ self.log.exception(e)
raise
+ finally: cur.close()
# vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on;
diff --git a/modules/Storycraft.py b/modules/Storycraft.py
index 3e3f171..b7fa362 100644
--- a/modules/Storycraft.py
+++ b/modules/Storycraft.py
@@ -18,9 +18,10 @@ along with this program. If not, see .
import random
import re
-import sqlite3
import time
+import MySQLdb as mdb
+
from Module import Module
__author__ = "Brian S. Stephan"
@@ -101,66 +102,70 @@ class Storycraft(Module):
# have to create the database tables
db = self.get_db()
try:
- db.execute('''
+ version = 1
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute('''
CREATE TABLE storycraft_config (
- master_channel TEXT NOT NULL,
+ master_channel VARCHAR(64) NOT NULL,
concurrent_games INTEGER NOT NULL,
default_round_mode INTEGER NOT NULL,
default_game_length INTEGER NOT NULL,
default_line_length INTEGER NOT NULL,
default_random_method INTEGER NOT NULL,
default_lines_per_turn INTEGER NOT NULL
- )''')
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
INSERT INTO storycraft_config
(master_channel, concurrent_games, default_round_mode,
default_game_length, default_line_length,
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 (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
+ id SERIAL,
round_mode INTEGER NOT NULL,
game_length INTEGER NOT NULL,
line_length INTEGER NOT NULL,
random_method INTEGER NOT NULL,
lines_per_turn INTEGER NOT NULL,
- status TEXT NOT NULL,
- owner_nick TEXT NOT NULL,
- owner_userhost TEXT NOT NULL,
- start_time TEXT DEFAULT CURRENT_TIMESTAMP,
- end_time TEXT DEFAULT NULL
- )''')
- db.execute('''
+ status VARCHAR(16) NOT NULL,
+ owner_nick VARCHAR(64) NOT NULL,
+ owner_userhost VARCHAR(256) NOT NULL,
+ start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ end_time TIMESTAMP NULL DEFAULT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE storycraft_player (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- game_id INTEGER NOT NULL,
- nick TEXT NOT NULL,
- userhost TEXT NOT NULL,
+ id SERIAL,
+ game_id BIGINT(20) UNSIGNED NOT NULL,
+ nick VARCHAR(64) NOT NULL,
+ userhost VARCHAR(256) NOT NULL,
FOREIGN KEY(game_id) REFERENCES storycraft_game(id)
- )''')
- db.execute('''
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+ ''')
+ cur.execute('''
CREATE TABLE storycraft_line (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- game_id INTEGER NOT NULL,
- player_id INTEGER NOT NULL,
- line TEXT NOT NULL,
- time TEXT DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY(game_id) REFERENCES storycraft_game(id)
+ id SERIAL,
+ game_id BIGINT(20) UNSIGNED NOT NULL,
+ player_id BIGINT(20) UNSIGNED NOT NULL,
+ line LONGTEXT NOT NULL,
+ time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY(game_id) REFERENCES storycraft_game(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.close()
- version = 1
- except sqlite3.Error as e:
+ self.db_register_module_version(self.__class__.__name__, version)
+ except mdb.Error as e:
db.rollback()
- db.close()
- self.log.error("sqlite error: " + str(e))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""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):
"""Get the details of one game."""
+ db = self.get_db()
try:
+ cur = db.cursor(mdb.cursors.DictCursor)
# get the specified game and populate a StorycraftGame
- 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 id = ?
+ FROM storycraft_game WHERE id = %s
'''
- cursor = db.execute(query, (game_id,))
- result = cursor.fetchone()
- db.close()
+ cur.execute(query, (game_id,))
+ result = cur.fetchone()
if result:
game = self.StorycraftGame()
@@ -553,10 +558,11 @@ class Storycraft(Module):
game.end_time = result['end_time']
return game
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get game details")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_game_summary(self, game):
"""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):
"""Add a new game to the system."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
INSERT INTO storycraft_game (
round_mode, game_length, line_length, random_method,
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.close()
return cur.lastrowid
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during add new game")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_player_list_for_game(self, game_id):
"""Get the list of players in one game."""
players = []
+ db = self.get_db()
try:
# get the players for specified game and populate a list
- db = self.get_db()
- query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = ?'
- cursor = db.execute(query, (game_id,))
- results = cursor.fetchall()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = %s'
+ cur.execute(query, (game_id,))
+ results = cur.fetchall()
for result in results:
player = self.StorycraftPlayer()
@@ -641,10 +649,11 @@ class Storycraft(Module):
players.append(player)
return players
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during getting player list for game")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_game_exists(self, game_id):
"""Return the existence of a game."""
@@ -654,20 +663,21 @@ class Storycraft(Module):
def _start_game(self, game_id):
"""Start a game, if it's currently open."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
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,))
db.commit()
- db.close()
return game_id
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during start game")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _pick_next_player(self, game_id):
"""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):
"""Assign the game to a player, prompting them for responses."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
INSERT INTO storycraft_line (game_id, player_id, line)
- VALUES (?, ?, ?)
+ VALUES (%s, %s, %s)
'''
cur.execute(statement, (game_id, player_id, ''))
db.commit()
- db.close()
return cur.lastrowid
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during assign game to player")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _end_game(self, game_id):
"""End the given game, disallowing adding lines."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
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,))
db.commit()
- db.close()
return game_id
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during end game")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_player_by_id(self, player_id):
"""Get the player details based on id."""
+ db = self.get_db()
try:
# get the specified player and populate a StorycraftPlayer
- db = self.get_db()
- query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE id = ?'
- cursor = db.execute(query, (player_id,))
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE id = %s'
+ cur.execute(query, (player_id,))
+ result = cur.fetchone()
if result:
player = self.StorycraftPlayer()
@@ -771,21 +783,22 @@ class Storycraft(Module):
player.userhost = result['userhost']
return player
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get player by id")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_player_by_userhost_in_game(self, game_id, userhost):
"""Get the player details if they exist in the given game."""
+ db = self.get_db()
try:
# get the specified player if they exist in the game and populate a StorycraftPlayer
- db = self.get_db()
- query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = ? AND userhost = ?'
- cursor = db.execute(query, (game_id,userhost))
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ query = 'SELECT id, game_id, nick, userhost FROM storycraft_player WHERE game_id = %s AND userhost = %s'
+ cur.execute(query, (game_id,userhost))
+ result = cur.fetchone()
if result:
player = self.StorycraftPlayer()
@@ -795,10 +808,11 @@ class Storycraft(Module):
player.userhost = result['userhost']
return player
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get player by userhost")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_completed_games(self):
"""Get the games with COMPLETED status."""
@@ -819,20 +833,20 @@ class Storycraft(Module):
"""Return the in progress/open games that include the player nick."""
games = []
+ db = self.get_db()
try:
# get the games of specified type and populate a list
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
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.owner_userhost, game.start_time, game.end_time
FROM storycraft_game game
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,))
- results = cursor.fetchall()
- db.close()
+ cur.execute(query, (player_nick,))
+ results = cur.fetchall()
for result in results:
game = self.StorycraftGame()
@@ -851,10 +865,11 @@ class Storycraft(Module):
games.append(game)
return games
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get active games with player")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_games_waiting_on_player(self, player_nick):
"""Return the games where the player nick is the owner of a pending line.
@@ -864,9 +879,10 @@ class Storycraft(Module):
"""
games = []
+ db = self.get_db()
try:
# get the games of specified type and populate a list
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
SELECT game.id, game.round_mode, game.game_length, game.line_length,
game.random_method, game.lines_per_turn, game.status, game.owner_nick,
@@ -874,56 +890,16 @@ class Storycraft(Module):
FROM storycraft_game game
INNER JOIN storycraft_player player ON player.game_id = game.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
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.owner_userhost, game.start_time, game.end_time
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))
- results = cursor.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()
+ cur.execute(query, (player_nick, player_nick))
+ results = cur.fetchall()
for result in results:
game = self.StorycraftGame()
@@ -942,29 +918,71 @@ class Storycraft(Module):
games.append(game)
return games
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get games waiting on player")
+ self.log.exception(e)
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):
"""Add a player to a game, so that they may eventually play."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
statement = '''
INSERT INTO storycraft_player (game_id, nick, userhost)
- VALUES (?, ?, ?)
+ VALUES (%s, %s, %s)
'''
cur.execute(statement, (game_id, nick, userhost))
db.commit()
- db.close()
return cur.lastrowid
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during add player to game")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_player_exists_in_game(self, game_id, userhost):
"""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."""
count = 0
+ db = self.get_db()
try:
# get count of game_type games
- db = self.get_db()
- query = 'SELECT COUNT(*) FROM storycraft_game WHERE status = ?'
- cursor = db.execute(query, (game_type,))
- result = cursor.fetchone()
- db.close()
+ cur = db.cursor(mdb.cursors.DictCursor)
+ query = 'SELECT COUNT(*) FROM storycraft_game WHERE status = %s'
+ cur.execute(query, (game_type,))
+ result = cur.fetchone()
if result:
count = result['COUNT(*)']
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get game type count")
+ self.log.exception(e)
raise
+ finally: cur.close()
return count
@@ -1018,19 +1037,20 @@ class Storycraft(Module):
"""Return the current game server concurrency."""
concurrency = 0
+ db = self.get_db()
try:
# get the concurrency value from config table
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = 'SELECT concurrent_games FROM storycraft_config'
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur.execute(query)
+ result = cur.fetchone()
if result:
concurrency = result['concurrent_games']
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get concurrent game count")
+ self.log.exception(e)
raise
+ finally: cur.close()
return concurrency
@@ -1038,17 +1058,17 @@ class Storycraft(Module):
"""Get the lines for the specified game_id."""
lines = []
+ db = self.get_db()
try:
# get the games of specified type and populate a list
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
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
'''
- cursor = db.execute(query, (game_id,))
- results = cursor.fetchall()
- db.close()
+ cur.execute(query, (game_id,))
+ results = cur.fetchall()
for result in results:
line = self.StorycraftLine()
@@ -1061,28 +1081,30 @@ class Storycraft(Module):
lines.append(line)
return lines
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get lines for game")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _update_line(self, line_id, input_line):
"""Update the specified line with the given text."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
+ cur = db.cursor(mdb.cursors.DictCursor)
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))
db.commit()
- db.close()
return line_id
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ db.rollback()
+ self.log.error("database error during update line")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _export_game_to_disk(self, game, lines):
"""Write a game to disk."""
@@ -1118,18 +1140,18 @@ class Storycraft(Module):
def _get_storycraft_settings(self):
"""Get the server settings."""
+ db = self.get_db()
try:
# get the settings and return in StorycraftSettings
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = '''
SELECT master_channel, concurrent_games, default_round_mode,
default_game_length, default_line_length, default_random_method,
default_lines_per_turn
FROM storycraft_config
'''
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur.execute(query)
+ result = cur.fetchone()
if result:
settings = self.StorycraftSettings()
@@ -1142,9 +1164,10 @@ class Storycraft(Module):
settings.default_lines_per_turn = int(result['default_lines_per_turn'])
return settings
- except sqlite3.Error as e:
- db.close()
- self.log.error('sqlite error: ' + str(e))
+ except mdb.Error as e:
+ self.log.error("database error during get storycraft settings")
+ self.log.exception(e)
raise
+ finally: cur.close()
# vi:tabstop=4:expandtab:autoindent
diff --git a/modules/Twitter.py b/modules/Twitter.py
index d26b98f..0686eed 100644
--- a/modules/Twitter.py
+++ b/modules/Twitter.py
@@ -19,11 +19,12 @@ along with this program. If not, see .
from ConfigParser import NoSectionError, NoOptionError
import oauth2 as oauth
import re
-import sqlite3
import thread
import time
import urlparse
+import MySQLdb as mdb
+
from extlib import irclib
from extlib import twitter
@@ -96,41 +97,28 @@ class Twitter(Module):
# init the table if it doesn't exist
version = self.db_module_registered(self.__class__.__name__)
if version == None or version < 1:
- # create tables
db = self.get_db()
+ # create tables
try:
version = 1
-
- db.execute("""
+ cur = db.cursor(mdb.cursors.DictCursor)
+ cur.execute("""
CREATE TABLE twitter_settings (
- since_id INTEGER NOT NULL,
- output_channel TEXT NOT NULL
- )""")
- db.execute("""INSERT INTO twitter_settings (since_id, output_channel) VALUES (0, '#drbotzo')""")
+ since_id SERIAL,
+ output_channel VARCHAR(64) NOT NULL,
+ oauth_token VARCHAR(256) DEFAULT NULL,
+ 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.close()
self.db_register_module_version(self.__class__.__name__, version)
- except sqlite3.Error as e:
+ except mdb.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("""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))
+ self.log.error("database error trying to create tables")
+ self.log.exception(e)
raise
+ finally: cur.close()
def shutdown(self):
"""Deauth, and make the twitter API item inoperable."""
@@ -395,49 +383,51 @@ class Twitter(Module):
def _get_last_since_id(self):
"""Get the since_id out of the database."""
+ db = self.get_db()
try:
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = "SELECT since_id FROM twitter_settings"
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur.execute(query)
+ result = cur.fetchone()
if result:
return result['since_id']
- except sqlite3.Error as e:
- db.close()
- self.log.error("sqlite error: " + str(e))
+ except mdb.Error as e:
+ self.log.error("database error getting last since ID")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_output_channel(self):
"""Get the output_channel out of the database."""
+ db = self.get_db()
try:
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = "SELECT output_channel FROM twitter_settings"
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur.execute(query)
+ result = cur.fetchone()
if result:
return result['output_channel']
- except sqlite3.Error as e:
- db.close()
- self.log.error("sqlite error: " + str(e))
+ except mdb.Error as e:
+ self.log.error("database error getting output channel")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _set_last_since_id(self, since_id):
"""Set the since_id."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = "UPDATE twitter_settings SET since_id = ?"
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = "UPDATE twitter_settings SET since_id = %s"
cur.execute(statement, (since_id,))
db.commit()
- db.close()
- except sqlite3.Error as e:
- db.close()
- self.log.error("sqlite error: " + str(e))
+ except mdb.Error as e:
+ self.log.error("database error saving last since ID")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _get_latest_tweet_id(self, tweets, 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):
"""Save the auth tokens to the database, with the intent of reusing them."""
+ db = self.get_db()
try:
- db = self.get_db()
- cur = db.cursor()
- statement = "UPDATE twitter_settings SET oauth_token = ?, oauth_token_secret = ?"
+ cur = db.cursor(mdb.cursors.DictCursor)
+ statement = "UPDATE twitter_settings SET oauth_token = %s, oauth_token_secret = %s"
cur.execute(statement, (oauth_token, oauth_token_secret))
db.commit()
- db.close()
- except sqlite3.Error as e:
- db.close()
- self.log.error("sqlite error: " + str(e))
+ except mdb.Error as e:
+ self.log.error("database error saving auth tokens")
+ self.log.exception(e)
raise
+ finally: cur.close()
def _retrieve_stored_auth_tokens(self):
"""Check the database for existing auth tokens, try reusing them."""
+ db = self.get_db()
try:
- db = self.get_db()
+ cur = db.cursor(mdb.cursors.DictCursor)
query = "SELECT oauth_token, oauth_token_secret FROM twitter_settings"
- cursor = db.execute(query)
- result = cursor.fetchone()
- db.close()
+ cur.execute(query)
+ result = cur.fetchone()
if result:
return (result['oauth_token'], result['oauth_token_secret'])
- except sqlite3.Error as e:
- db.close()
- self.log.error("sqlite error: " + str(e))
+ except mdb.Error as e:
+ self.log.error("database error retrieving auth tokens")
+ self.log.exception(e)
raise
-
+ finally: cur.close()
# vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on;
diff --git a/requirements.txt b/requirements.txt
index a64a319..f8d2f37 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+MySQL-python==1.2.3
httplib2==0.7.4
oauth2==1.5.211
ply==3.4