]> jfr.im git - z_archive/twitter.git/blobdiff - twitter/ircbot.py
More stuff in gitignore.
[z_archive/twitter.git] / twitter / ircbot.py
index 1ea68237946caa973157813ad6926f491188f0bc..c1bae0814a851c7f2b78dd9bbdc5d229ecb4999e 100644 (file)
@@ -18,6 +18,7 @@ server: <irc_server>
 port: <irc_port>
 nick: <irc_nickname>
 channel: <irc_channels_to_join>
+prefixes: <prefix_type>
 
 [twitter]
 oauth_token_file: <oauth_token_filename>
@@ -29,6 +30,8 @@ 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)"
@@ -43,7 +46,8 @@ IRC_REGULAR = chr(0x0f)
 
 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
@@ -55,6 +59,22 @@ from oauth import OAuth, read_token_file
 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:
@@ -100,7 +120,7 @@ class Scheduler(object):
         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:
@@ -112,6 +132,9 @@ class TwitterBot(object):
         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)
@@ -131,21 +154,22 @@ class TwitterBot(object):
         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'))
@@ -155,17 +179,17 @@ class TwitterBot(object):
                 #   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):
@@ -181,9 +205,10 @@ class TwitterBot(object):
             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)
 
@@ -214,21 +239,23 @@ class TwitterBot(object):
         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]
@@ -237,15 +264,16 @@ class TwitterBot(object):
         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(
@@ -262,14 +290,21 @@ class TwitterBot(object):
             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