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:
parent
deedf330e3
commit
1a36becead
50
Module.py
50
Module.py
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
||||||
|
38
dr.botzo.py
38
dr.botzo.py
@ -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))
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
180
modules/Karma.py
180
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 <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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user