port: <irc_port>
nick: <irc_nickname>
channel: <irc_channels_to_join>
+prefixes: <prefix_type>
[twitter]
oauth_token_file: <oauth_token_filename>
The default token file is ~/.twitterbot_oauth.
+ The default prefix type is 'cats'. You can also use 'none'.
+
"""
BOT_VERSION = "TwitterBot 1.4 (http://mike.verdone.ca/twitter)"
import sys
import time
-from dateutil.parser import parse
+from datetime import datetime, timedelta
+from email.utils import parsedate
from ConfigParser import SafeConfigParser
from heapq import heappop, heappush
import traceback
from oauth_dance import oauth_dance
from util import htmlentitydecode
+PREFIXES = dict(
+ cats=dict(
+ new_tweet="=^_^= ",
+ error="=O_o= ",
+ inform="=o_o= "
+ ),
+ none=dict(
+ new_tweet=""
+ ),
+ )
+ACTIVE_PREFIXES=dict()
+
+def get_prefix(prefix_typ=None):
+ return ACTIVE_PREFIXES.get(prefix_typ, ACTIVE_PREFIXES.get('new_tweet', ''))
+
+
try:
import irclib
except:
if (wait > 0):
time.sleep(wait)
task()
- debug("tasks: " + str(self.task_heap))
+ #debug("tasks: " + str(self.task_heap))
def run_forever(self):
while True:
self.configFilename = configFilename
self.config = load_config(self.configFilename)
+ global ACTIVE_PREFIXES
+ ACTIVE_PREFIXES = PREFIXES[self.config.get('irc', 'prefixes')]
+
oauth_file = self.config.get('twitter', 'oauth_token_file')
if not os.path.exists(oauth_file):
oauth_dance("IRC Bot", CONSUMER_KEY, CONSUMER_SECRET, oauth_file)
self.sched = Scheduler(
(SchedTask(self.process_events, 1),
SchedTask(self.check_statuses, 120)))
- self.lastUpdate = time.gmtime()
+ self.lastUpdate = (datetime.utcnow() - timedelta(minutes=10)).utctimetuple()
def check_statuses(self):
debug("In check_statuses")
try:
- updates = self.twitter.statuses.friends_timeline()
+ updates = reversed(self.twitter.statuses.friends_timeline())
except Exception, e:
print >> sys.stderr, "Exception while querying twitter:"
traceback.print_exc(file=sys.stderr)
return
nextLastUpdate = self.lastUpdate
+ debug("self.lastUpdate is %s" % self.lastUpdate)
for update in updates:
- crt = parse(update['created_at']).utctimetuple()
- if (crt > self.lastUpdate):
+ crt = parsedate(update['created_at'])
+ if (crt > nextLastUpdate):
text = (htmlentitydecode(
update['text'].replace('\n', ' '))
.encode('utf-8', 'replace'))
# to people who are not on our following list.
if not text.startswith("@"):
self.privmsg_channels(
- u"=^_^= %s%s%s %s" %(
+ u"%s %s%s%s %s" %(
+ get_prefix(),
IRC_BOLD, update['user']['screen_name'],
IRC_BOLD, text.decode('utf-8')))
nextLastUpdate = crt
- else:
- break
+
+ debug("setting self.lastUpdate to %s" % nextLastUpdate)
self.lastUpdate = nextLastUpdate
def process_events(self):
- debug("In process_events")
self.irc.process_once()
def handle_privmsg(self, conn, evt):
else:
conn.privmsg(
evt.source().split('!')[0],
- "=^_^= Hi! I'm Twitterbot! you can (follow "
- + "<twitter_name>) to make me follow a user or "
- + "(unfollow <twitter_name>) to make me stop.")
+ "%sHi! I'm Twitterbot! you can (follow "
+ "<twitter_name>) to make me follow a user or "
+ "(unfollow <twitter_name>) to make me stop." %
+ get_prefix())
except Exception:
traceback.print_exc(file=sys.stderr)
if (name in friends):
conn.privmsg(
userNick,
- "=O_o= I'm already following %s." %(name))
+ "%sI'm already following %s." %(get_prefix('error'), name))
else:
try:
self.twitter.friendships.create(id=name)
except TwitterError:
conn.privmsg(
userNick,
- "=O_o= I can't follow that user. Are you sure the name is correct?")
+ "%sI can't follow that user. Are you sure the name is correct?" %(
+ get_prefix('error')
+ ))
return
conn.privmsg(
userNick,
- "=^_^= Okay! I'm now following %s." %(name))
+ "%sOkay! I'm now following %s." %(get_prefix('followed'), name))
self.privmsg_channels(
- "=o_o= %s has asked me to start following %s" %(
- userNick, name))
+ "%s%s has asked me to start following %s" %(
+ get_prefix('inform'), userNick, name))
def unfollow(self, conn, evt, name):
userNick = evt.source().split('!')[0]
if (name not in friends):
conn.privmsg(
userNick,
- "=O_o= I'm not following %s." %(name))
+ "%sI'm not following %s." %(get_prefix('error'), name))
else:
self.twitter.friendships.destroy(id=name)
conn.privmsg(
userNick,
- "=^_^= Okay! I've stopped following %s." %(name))
+ "%sOkay! I've stopped following %s." %(
+ get_prefix('stop_follow'), name))
self.privmsg_channels(
- "=o_o= %s has asked me to stop following %s" %(
- userNick, name))
+ "%s%s has asked me to stop following %s" %(
+ get_prefix('inform'), userNick, name))
def run(self):
self.ircServer.connect(
except KeyboardInterrupt:
break
except TwitterError:
- # twitter.com is probably down because it sucks. ignore the fault and keep going
+ # twitter.com is probably down because it
+ # sucks. ignore the fault and keep going
pass
def load_config(filename):
- defaults = dict(
- server=dict(port=6667, nick="twitterbot"),
- twitter=dict(oauth_token_file=OAUTH_FILE))
- cp = SafeConfigParser(defaults)
+ # Note: Python ConfigParser module has the worst interface in the
+ # world. Mega gross.
+ cp = SafeConfigParser()
+ cp.add_section('irc')
+ cp.set('irc', 'port', '6667')
+ cp.set('irc', 'nick', 'twitterbot')
+ cp.set('irc', 'prefixes', 'cats')
+ cp.add_section('twitter')
+ cp.set('twitter', 'oauth_token_file', OAUTH_FILE)
+
cp.read((filename,))
# attempt to read these properties-- they are required