Quantcast

Showing Twitter Status On Your Group Blog

First a bit of meta discussion: I changed the left sidebar of TikiRobot to show the five most recent status updates from the fellow robots! It was kind of silly to display tweets from people who haven’t updated since last year. If you want your status to show up in the sidebar, and it isn’t there for some reason, lemme know!

Twitter has an API for showing for retrieving the most recent status updates from your friends, so I created a new twitter user to follow the tikirobot posters. Then, I used this python script to fetch the friends timeline and spit out html for the blog. I wanted to do this all in javascript, but the the friends timeline api needs authentication, and I didn’t want to publicize the twitter account password. Plus, this way I can cache the data on our server, so it doesn’t hit twitter so often.

PYTHON:
  1. #!/usr/bin/python2.5
  2. #Copyright(c)2008 TikiRobot.net - Software license GPL version 3.
  3.  
  4. import time
  5. import datetime
  6. import os
  7. import fcntl
  8. import sys
  9. import codecs
  10. import re
  11.  
  12. # CalculateRelativeTime()
  13. #_______________________________________________________________________________
  14. def CalculateRelativeTime(str):
  15.     dt = datetime.datetime.strptime(str, ‘%a %b %d %H:%M:%S +0000 %Y’)
  16.     now = datetime.datetime.utcnow()
  17.     delta = now - dt
  18.     secs  = delta.seconds
  19.     if (delta.days> 0):
  20.         return “%d days ago”%(delta.days)
  21.     elif (secs <60):
  22.         return “%s seconds ago”%(int(secs))
  23.     elif (secs <3600):
  24.         return “%s minutes ago”%(int(secs/60))
  25.     else:
  26.         return “%s hours ago”%(int(secs/3600))
  27.  
  28. # main()
  29. #_______________________________________________________________________________
  30. print “”“Content-type: text/javascript; charset=UTF-8\n“”
  31.  
  32. useCachedRss = True
  33. cacheFile    = ‘cache/twitter.json’
  34. sys.stdout = codecs.getwriter(‘utf8′)(sys.stdout)
  35.  
  36. try:
  37.     stats = os.stat(cacheFile)
  38.     if (time.time() - stats.st_mtime)> 300:
  39.         #cache expired
  40.         useCachedRss = False
  41. except OSError:
  42.     #cache file not found
  43.     useCachedRss = False
  44.  
  45. if useCachedRss:
  46.     try:
  47.         #print "reading cached json"
  48.         fh = open(cacheFile, ‘r’)
  49.         fcntl.lockf(fh, fcntl.LOCK_SH)
  50.         contents = fh.read()
  51.         fcntl.lockf(fh, fcntl.LOCK_UN)
  52.         fh.close()   
  53.     except:
  54.         print “got some kind of error when reading cached json. quitting”
  55.         sys.exit()
  56. else:
  57.     try:
  58.         #print "fetching new json"
  59.         import urllib2
  60.         apiurl = ‘http://twitter.com/statuses/friends_timeline.json?count=5′
  61.         auth_handler = urllib2.HTTPBasicAuthHandler()
  62.         auth_handler.add_password(
  63.             realm=‘Twitter API’,
  64.             uri=apiurl,
  65.             user=‘username’,
  66.             passwd=‘password’
  67.         )
  68.         opener = urllib2.build_opener(auth_handler)           
  69.         urllib2.install_opener(opener)
  70.         urlfh = urllib2.urlopen(apiurl)
  71.         contents = urlfh.read()
  72.         urlfh.close()
  73.         fh = open(cacheFile, ‘w’)
  74.         fcntl.lockf(fh, fcntl.LOCK_EX)
  75.         fh.write(contents)
  76.         fcntl.lockf(fh, fcntl.LOCK_UN)
  77.         fh.close()
  78.     except:
  79.         print “got some kind of error when fetching twitter timeline. quitting”
  80.         sys.exit()
  81.  
  82.  
  83. import json
  84. timeline = json.read(contents)
  85. htmlstr = “”
  86. for i in range(5):
  87.     name = timeline[i][‘user’][’screen_name’]
  88.     imgurl = re.sub(r‘_normal.(jpg|png)$’, r‘_mini.\1, timeline[i][‘user’][‘profile_image_url’])
  89.     twit   = re.sub(r\’, ‘&#39;’, timeline[i][‘text’])
  90.     twit   = re.sub(r\n, ‘ ‘, twit)
  91.     twit   = re.sub(r‘http://tinyurl.com/(\S+)’, r‘<a href="http://tinyurl.com/\1">tinyurl.com/\1</a>’, twit)
  92.     when   = CalculateRelativeTime(timeline[i][‘created_at’])
  93.     htmlstr += “”“<div class=”twitter“>”“”
  94.     htmlstr += “”“<img src=”%s“/>”“”%(imgurl)
  95.     htmlstr += “”“<div class=”twitterRight“>”“”
  96.     htmlstr += “”“<a href=”http://twitter.com/%s“><strong>%s</strong></a>: ““”%(name, name)
  97.     htmlstr += twit
  98.     htmlstr += “”“<span class=”twitterMeta“>- ““” + when + “</span>”
  99.     htmlstr += “”“</div>”“”
  100.     htmlstr += “”“<div class=”clear“></div>”“”
  101.     htmlstr += “”“</div>”“”
  102.    
  103. print “”“var tikiTwits = ‘”“”+htmlstr+“‘;”
  104. print “”“document.write(tikiTwits);”“”

It’s fun to see that Twitter still uses the Javascript API that I proposed to them over the phone a couple years ago.

Also, dear lazyweb: please send my a python function that converts a UTC date string to PST. Thanks!

WiiMe

wiime1.jpg
They sent me 9 consecutive text messages this morning, alternating between “Wiis are in stock at Amazon! Grab one!” and “No Wiis available :-( they were up for 8 seconds.

I’d pretty much given up until the 9th msg came through and I got one! yay! I can’t believe that it’s been a year already and it’s *STILL* so hard to get a Wii on Amazon. Yes, I know it’s possible to get one at a store if you live in Missouri (or just not in the Bay Area)…or if you wait in line at Best Buy at the crack of dawn, but I really didn’t want to do that (cause I’m lazy). I just wanted to get one online for the office and WiiMe came through!