Module: remove the timer stuff, since individual modules can do this better themselves

Markov, Twitter: switch to forking a thread ourselves, and check every
second whether or not to quit. this is the "better" part above, as
now we can instantly quit the thread rather than waiting for all
the timers to fire and expire
This commit is contained in:
Brian S. Stephan 2011-06-20 21:18:55 -05:00
parent c7846e415a
commit 152ef2a1ad
3 changed files with 58 additions and 77 deletions

View File

@ -32,11 +32,6 @@ class Module(object):
def priority(self):
return 50
def timer_interval(self):
"""Run a timer-based event every N seconds (0 to disable)."""
return 0
def __init__(self, irc, config, server):
"""Construct a feature module. Inheritors can do special things here, but
should be sure to call Module.__init__.
@ -62,10 +57,6 @@ class Module(object):
# set up database for this module
self.db_init()
# register the timer, if the implementing module has one
if self.timer_interval() > 0:
Timer(self.timer_interval(), self.timer_bootstrap, ()).start()
# print what was loaded, for debugging
print("loaded " + self.__class__.__name__)
@ -242,26 +233,6 @@ class Module(object):
print("looks like someone forgot to implement do!")
def timer_bootstrap(self):
"""Run a thread that does something periodically.
This only has real functionality if timer_interval() is
defined to return non-zero.
"""
# don't actually do stuff if, since the last timer registration,
# the interval was set to 0
if self.timer_interval() > 0 and self.is_shutdown == False:
self.timer_do()
if self.timer_interval() > 0 and self.is_shutdown == False:
Timer(self.timer_interval(), self.timer_bootstrap, ()).start()
def timer_do(self):
"""If we're invoking the timer, do something (that you should implement)."""
print("looks like someone forgot to implement timer_do!")
def help_description(self):
"""Return a quick list of commands or other summary, should be
less than two lines. If you want the module hidden from "!help",

View File

@ -23,6 +23,8 @@ import random
import re
import sqlite3
import sys
import thread
import time
from dateutil.parser import *
from dateutil.relativedelta import *
@ -42,10 +44,6 @@ class Markov(Module):
http://code.activestate.com/recipes/194364-the-markov-chain-algorithm/
"""
def timer_interval(self):
"""Do various conversation scoring and infinite reply checks."""
return 30
def __init__(self, irc, config, server):
"""Create the Markov chainer, and learn text from a file if available."""
@ -69,6 +67,9 @@ class Markov(Module):
Module.__init__(self, irc, config, server)
self.next_shut_up_check = 0
thread.start_new_thread(self.thread_do, ())
def db_init(self):
"""Create the markov chain table."""
@ -280,30 +281,34 @@ class Markov(Module):
self.lines_seen.append(('.self.said.', datetime.now()))
return self._generate_line(target, min_size=min_size, max_size=max_size)
def timer_do(self):
def thread_do(self):
"""Do various things."""
self._do_shut_up_checks()
while not self.is_shutdown:
self._do_shut_up_checks()
time.sleep(1)
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
if self.next_shut_up_check < time.time():
self.shut_up = False
self.next_shut_up_check = time.time() + 30
last_30_sec_lines = []
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))
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) >= 15:
lines_i_said = len(filter(lambda (a,b): a == '.self.said.', last_30_sec_lines))
if lines_i_said >= 8:
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')
if len(last_30_sec_lines) >= 15:
lines_i_said = len(filter(lambda (a,b): a == '.self.said.', last_30_sec_lines))
if lines_i_said >= 8:
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):
"""Create Markov chains from the provided line."""

View File

@ -20,7 +20,8 @@ from ConfigParser import NoSectionError, NoOptionError
import oauth2 as oauth
import re
import sqlite3
from threading import Timer
import thread
import time
import urlparse
from extlib import irclib
@ -32,11 +33,6 @@ class Twitter(Module):
"""Access Twitter via the bot as an authenticated client."""
def timer_interval(self):
"""Check for twitter updates every 300 seconds."""
return 300
def __init__(self, irc, config, server):
"""Prepare for oauth stuff (but don't execute it yet)."""
@ -72,6 +68,9 @@ class Twitter(Module):
self.twit = twitter.Api()
self.authed = False
self.next_timeline_check = 0
thread.start_new_thread(self.thread_do, ())
def db_init(self):
"""Set up the settings table."""
@ -239,39 +238,45 @@ class Twitter(Module):
return 'The bot is now logged in.'
def timer_do(self):
def thread_do(self):
"""Check the timeline."""
self._check_self_timeline()
while not self.is_shutdown:
self._check_self_timeline()
time.sleep(1)
def _check_self_timeline(self):
"""Check my timeline, and if there are entries, print them to the channel."""
if self.authed:
# get the id of the last check we made
since_id = self._get_last_since_id()
output_channel = self._get_output_channel()
if self.next_timeline_check < time.time():
self.next_timeline_check = time.time() + 300
if since_id is not None and output_channel != '':
tweets = self.twit.GetFriendsTimeline(since_id=since_id)
tweets.reverse()
for tweet in tweets:
tweet_text = self._return_tweet_or_retweet_text(tweet=tweet, print_source=True)
self.sendmsg(self.connection, output_channel.encode('utf-8', 'ignore'), tweet_text)
if self.authed:
# get the id of the last check we made
since_id = self._get_last_since_id()
output_channel = self._get_output_channel()
# friends timeline printed, find the latest id
new_since_id = self._get_latest_tweet_id(tweets, since_id)
if since_id is not None and output_channel != '':
tweets = self.twit.GetFriendsTimeline(since_id=since_id)
tweets.reverse()
for tweet in tweets:
tweet_text = self._return_tweet_or_retweet_text(tweet=tweet, print_source=True)
self.sendmsg(self.connection, output_channel.encode('utf-8', 'ignore'), tweet_text)
tweets = self.twit.GetMentions(since_id=since_id)
tweets.reverse()
for tweet in tweets:
tweet_text = self._return_tweet_or_retweet_text(tweet=tweet, print_source=True)
self.sendmsg(self.connection, output_channel.encode('utf-8', 'ignore'), tweet_text)
# friends timeline printed, find the latest id
new_since_id = self._get_latest_tweet_id(tweets, since_id)
# mentions printed, find the latest id
new_since_id = self._get_latest_tweet_id(tweets, new_since_id)
tweets = self.twit.GetMentions(since_id=since_id)
tweets.reverse()
for tweet in tweets:
tweet_text = self._return_tweet_or_retweet_text(tweet=tweet, print_source=True)
self.sendmsg(self.connection, output_channel.encode('utf-8', 'ignore'), tweet_text)
# set since_id
self._set_last_since_id(new_since_id)
# mentions printed, find the latest id
new_since_id = self._get_latest_tweet_id(tweets, new_since_id)
# set since_id
self._set_last_since_id(new_since_id)
def _return_tweet_or_retweet_text(self, tweet, print_source=False):
"""