Markov: shut up if we've been too chatty in too short a period of time.

track all lines seen and all lines said by Markov. every 30 seconds,
if there have been more than 20 such lines, and Markov is responsible
for roughly half of them, then shut up for 30 seconds, because the
bot probably got stuck talking to another bot.

this should mean that such a reply infinite loop can't happen for
more than a minute.

i'm not entirely sure on the 30 sec/20 lines ratio. this may need
tuning.
This commit is contained in:
Brian S. Stephan 2011-05-01 10:31:20 -05:00
parent 7692d295f6
commit 03d0d6bc2d
1 changed files with 33 additions and 4 deletions

View File

@ -17,12 +17,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import cPickle
from datetime import datetime
import os
import random
import re
import sqlite3
import sys
from dateutil.parser import *
from dateutil.relativedelta import *
from extlib import irclib
from Module import Module
@ -62,6 +65,7 @@ class Markov(Module):
self.replyre = re.compile(replypattern)
self.shut_up = False
self.lines_seen = []
Module.__init__(self, irc, config, server)
@ -180,6 +184,10 @@ class Markov(Module):
my_nick = connection.get_nickname()
what = re.sub('^' + my_nick + '[:,]\s+', '', what)
target = event.target()
nick = irclib.nm_to_n(event.source())
self.lines_seen.append((nick, datetime.now()))
self.connection = connection
# don't learn from commands
if self.trainre.search(what) or self.learnre.search(what) or self.replyre.search(what):
@ -204,9 +212,11 @@ class Markov(Module):
addressed_re = re.compile(addressed_pattern)
if addressed_re.match(what):
# i was addressed directly, so respond, addressing the speaker
self.lines_seen.append(('.self.said.', datetime.now()))
return self.reply(connection, event, '{0:s}: {1:s}'.format(nick, self._generate_line(line=addressed_re.match(what).group(1))))
else:
# i wasn't addressed directly, so just respond
self.lines_seen.append(('.self.said.', datetime.now()))
return self.reply(connection, event, '{0:s}'.format(self._generate_line(line=what)))
def markov_train(self, connection, event, nick, userhost, what, admin_unlocked):
@ -251,17 +261,36 @@ class Markov(Module):
if match.group(5) != '':
line = match.group(6)
self.lines_seen.append(('.self.said.', datetime.now()))
return self._generate_line(line=line, min_size=min_size, max_size=max_size)
else:
self.lines_seen.append(('.self.said.', datetime.now()))
return self._generate_line(min_size=min_size, max_size=max_size)
def timer_do(self):
"""Do various things.
"""Do various things."""
* Check to see if we've been talking too much, and shut up if so.
"""
self._do_shut_up_checks()
self.shut_up = True
def _do_shut_up_checks(self):
"""Check to see if we've been talking too much, and shut up if so."""
self.shut_up = False
last_30_sec_lines = []
for (nick,then) in self.lines_seen:
rdelta = relativedelta(datetime.now(), then)
if rdelta.years == 0 and rdelta.months == 0 and rdelta.days == 0 and rdelta.hours == 0 and rdelta.minutes == 0 and rdelta.seconds <= 29:
last_30_sec_lines.append((nick,then))
if len(last_30_sec_lines) >= 20:
lines_i_said = len(filter(lambda (a,b): a == '.self.said.', last_30_sec_lines))
if lines_i_said * 100 / len(last_30_sec_lines) >= 45:
self.shut_up = True
targets = self._get_chatter_targets()
for t in targets:
self.sendmsg(self.connection, t, 'shutting up for 30 seconds due to last 30 seconds of activity')
def _learn_line(self, line, target=None):
"""Create Markov chains from the provided line."""