Markov: some minor formatting/pylint cleanups
This commit is contained in:
parent
9ea3e9d688
commit
60ac4d25bd
@ -14,6 +14,7 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
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 datetime import datetime
|
from datetime import datetime
|
||||||
@ -22,7 +23,7 @@ import re
|
|||||||
import thread
|
import thread
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dateutil.relativedelta import *
|
from dateutil.relativedelta import relativedelta
|
||||||
import MySQLdb as mdb
|
import MySQLdb as mdb
|
||||||
|
|
||||||
from extlib import irclib
|
from extlib import irclib
|
||||||
@ -31,18 +32,21 @@ from Module import Module
|
|||||||
|
|
||||||
class Markov(Module):
|
class Markov(Module):
|
||||||
|
|
||||||
"""
|
"""Create a chatterbot very similar to a MegaHAL, but simpler and
|
||||||
Create a chatterbot very similar to a MegaHAL, but simpler and
|
|
||||||
implemented in pure Python. Proof of concept code from Ape.
|
implemented in pure Python. Proof of concept code from Ape.
|
||||||
|
|
||||||
Ape wrote: based on this:
|
Ape wrote: based on this:
|
||||||
http://uswaretech.com/blog/2009/06/pseudo-random-text-markov-chains-python/
|
http://uswaretech.com/blog/2009/06/pseudo-random-text-markov-chains-python/
|
||||||
and this:
|
and this:
|
||||||
http://code.activestate.com/recipes/194364-the-markov-chain-algorithm/
|
http://code.activestate.com/recipes/194364-the-markov-chain-algorithm/
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, irc, config):
|
def __init__(self, irc, config):
|
||||||
"""Create the Markov chainer, and learn text from a file if available."""
|
"""Create the Markov chainer, and learn text from a file if
|
||||||
|
available.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
# set up some keywords for use in the chains --- don't change these
|
# set up some keywords for use in the chains --- don't change these
|
||||||
# once you've created a brain
|
# once you've created a brain
|
||||||
@ -67,7 +71,8 @@ class Markov(Module):
|
|||||||
self.connection = None
|
self.connection = None
|
||||||
thread.start_new_thread(self.thread_do, ())
|
thread.start_new_thread(self.thread_do, ())
|
||||||
|
|
||||||
irc.xmlrpc_register_function(self._generate_line, "markov_generate_line")
|
irc.xmlrpc_register_function(self._generate_line,
|
||||||
|
"markov_generate_line")
|
||||||
|
|
||||||
def db_init(self):
|
def db_init(self):
|
||||||
"""Create the markov chain table."""
|
"""Create the markov chain table."""
|
||||||
@ -118,7 +123,8 @@ class Markov(Module):
|
|||||||
ON markov_chain (v, context_id)''')
|
ON markov_chain (v, context_id)''')
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
self.db_register_module_version(self.__class__.__name__, version)
|
self.db_register_module_version(self.__class__.__name__,
|
||||||
|
version)
|
||||||
except mdb.Error as e:
|
except mdb.Error as e:
|
||||||
db.rollback()
|
db.rollback()
|
||||||
self.log.error("database error trying to create tables")
|
self.log.error("database error trying to create tables")
|
||||||
@ -129,16 +135,24 @@ class Markov(Module):
|
|||||||
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."""
|
||||||
|
|
||||||
self.irc.server.add_global_handler('pubmsg', self.on_pub_or_privmsg, self.priority())
|
self.irc.server.add_global_handler('pubmsg', self.on_pub_or_privmsg,
|
||||||
self.irc.server.add_global_handler('privmsg', self.on_pub_or_privmsg, self.priority())
|
self.priority())
|
||||||
self.irc.server.add_global_handler('pubmsg', self.learn_from_irc_event)
|
self.irc.server.add_global_handler('privmsg', self.on_pub_or_privmsg,
|
||||||
self.irc.server.add_global_handler('privmsg', self.learn_from_irc_event)
|
self.priority())
|
||||||
|
self.irc.server.add_global_handler('pubmsg',
|
||||||
|
self.learn_from_irc_event)
|
||||||
|
self.irc.server.add_global_handler('privmsg',
|
||||||
|
self.learn_from_irc_event)
|
||||||
|
|
||||||
def unregister_handlers(self):
|
def unregister_handlers(self):
|
||||||
self.irc.server.remove_global_handler('pubmsg', self.on_pub_or_privmsg)
|
self.irc.server.remove_global_handler('pubmsg',
|
||||||
self.irc.server.remove_global_handler('privmsg', self.on_pub_or_privmsg)
|
self.on_pub_or_privmsg)
|
||||||
self.irc.server.remove_global_handler('pubmsg', self.learn_from_irc_event)
|
self.irc.server.remove_global_handler('privmsg',
|
||||||
self.irc.server.remove_global_handler('privmsg', self.learn_from_irc_event)
|
self.on_pub_or_privmsg)
|
||||||
|
self.irc.server.remove_global_handler('pubmsg',
|
||||||
|
self.learn_from_irc_event)
|
||||||
|
self.irc.server.remove_global_handler('privmsg',
|
||||||
|
self.learn_from_irc_event)
|
||||||
|
|
||||||
def learn_from_irc_event(self, connection, event):
|
def learn_from_irc_event(self, connection, event):
|
||||||
"""Learn from IRC events."""
|
"""Learn from IRC events."""
|
||||||
@ -167,11 +181,11 @@ class Markov(Module):
|
|||||||
target = event.target()
|
target = event.target()
|
||||||
|
|
||||||
if self.learnre.search(what):
|
if self.learnre.search(what):
|
||||||
return self.irc.reply(event, self.markov_learn(connection, event, nick,
|
return self.irc.reply(event, self.markov_learn(connection, event,
|
||||||
userhost, what, admin_unlocked))
|
nick, userhost, what, admin_unlocked))
|
||||||
elif self.replyre.search(what) and not self.shut_up:
|
elif self.replyre.search(what) and not self.shut_up:
|
||||||
return self.irc.reply(event, self.markov_reply(connection, event, nick,
|
return self.irc.reply(event, self.markov_reply(connection, event,
|
||||||
userhost, what, admin_unlocked))
|
nick, userhost, what, admin_unlocked))
|
||||||
|
|
||||||
if not self.shut_up:
|
if not self.shut_up:
|
||||||
# not a command, so see if i'm being mentioned
|
# not a command, so see if i'm being mentioned
|
||||||
@ -179,7 +193,8 @@ class Markov(Module):
|
|||||||
addressed_pattern = '^' + connection.get_nickname() + '[:,]\s+(.*)'
|
addressed_pattern = '^' + connection.get_nickname() + '[:,]\s+(.*)'
|
||||||
addressed_re = re.compile(addressed_pattern)
|
addressed_re = re.compile(addressed_pattern)
|
||||||
if addressed_re.match(what):
|
if addressed_re.match(what):
|
||||||
# i was addressed directly, so respond, addressing the speaker
|
# i was addressed directly, so respond, addressing
|
||||||
|
# the speaker
|
||||||
self.lines_seen.append(('.self.said.', datetime.now()))
|
self.lines_seen.append(('.self.said.', datetime.now()))
|
||||||
return self.irc.reply(event, '{0:s}: {1:s}'.format(nick,
|
return self.irc.reply(event, '{0:s}: {1:s}'.format(nick,
|
||||||
self._generate_line(target, line=addressed_re.match(what).group(1))))
|
self._generate_line(target, line=addressed_re.match(what).group(1))))
|
||||||
@ -261,14 +276,14 @@ class Markov(Module):
|
|||||||
|
|
||||||
last_30_sec_lines = []
|
last_30_sec_lines = []
|
||||||
|
|
||||||
for (nick,then) in self.lines_seen:
|
for (nick, then) in self.lines_seen:
|
||||||
rdelta = relativedelta(datetime.now(), then)
|
rdelta = relativedelta(datetime.now(), then)
|
||||||
if (rdelta.years == 0 and rdelta.months == 0 and rdelta.days == 0 and
|
if (rdelta.years == 0 and rdelta.months == 0 and rdelta.days == 0 and
|
||||||
rdelta.hours == 0 and rdelta.minutes == 0 and rdelta.seconds <= 29):
|
rdelta.hours == 0 and rdelta.minutes == 0 and rdelta.seconds <= 29):
|
||||||
last_30_sec_lines.append((nick,then))
|
last_30_sec_lines.append((nick, then))
|
||||||
|
|
||||||
if len(last_30_sec_lines) >= 8:
|
if len(last_30_sec_lines) >= 8:
|
||||||
lines_i_said = len(filter(lambda (a,b): a == '.self.said.', last_30_sec_lines))
|
lines_i_said = len(filter(lambda (a, b): a == '.self.said.', last_30_sec_lines))
|
||||||
if lines_i_said >= 8:
|
if lines_i_said >= 8:
|
||||||
self.shut_up = True
|
self.shut_up = True
|
||||||
targets = self._get_chatter_targets()
|
targets = self._get_chatter_targets()
|
||||||
@ -309,14 +324,15 @@ class Markov(Module):
|
|||||||
finally: cur.close()
|
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):
|
||||||
"""
|
"""Create a line, optionally using some text in a seed as a point in
|
||||||
Create a line, optionally using some text in a seed as a point in the chain.
|
the chain.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
target - the target to retrieve the context for (i.e. a channel or nick)
|
target - the target to retrieve the context for (i.e. a channel or nick)
|
||||||
line - the line to reply to, by picking a random word and seeding with it
|
line - the line to reply to, by picking a random word and seeding with it
|
||||||
min_size - the minimum desired size in words. not guaranteed
|
min_size - the minimum desired size in words. not guaranteed
|
||||||
max_size - the maximum desired size in words. not guaranteed
|
max_size - the maximum desired size in words. not guaranteed
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# if the limit is too low, there's nothing to do
|
# if the limit is too low, there's nothing to do
|
||||||
@ -496,7 +512,7 @@ class Markov(Module):
|
|||||||
# 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 = %s AND k2 = %s AND '
|
query = ('SELECT v FROM markov_chain WHERE k1 = %s AND k2 = %s AND '
|
||||||
'(context_id = %s) AND id >= {0:d} LIMIT 1'.format(rand_id))
|
'(context_id = %s) AND id >= {0:d} LIMIT 1'.format(rand_id))
|
||||||
else:
|
else:
|
||||||
@ -583,7 +599,6 @@ class Markov(Module):
|
|||||||
finally: cur.close()
|
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()
|
db = self.get_db()
|
||||||
@ -611,7 +626,6 @@ class Markov(Module):
|
|||||||
finally: cur.close()
|
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()
|
db = self.get_db()
|
||||||
@ -623,7 +637,7 @@ class Markov(Module):
|
|||||||
INSERT INTO markov_target_to_context_map (target, context_id)
|
INSERT INTO markov_target_to_context_map (target, context_id)
|
||||||
VALUES (%s, (SELECT id FROM markov_context WHERE context = %s))
|
VALUES (%s, (SELECT id FROM markov_context WHERE context = %s))
|
||||||
'''
|
'''
|
||||||
cur.execute(statement, (target,target))
|
cur.execute(statement, (target, target))
|
||||||
db.commit()
|
db.commit()
|
||||||
except mdb.Error as e:
|
except mdb.Error as e:
|
||||||
db.rollback()
|
db.rollback()
|
||||||
|
Loading…
Reference in New Issue
Block a user