#!/usr/bin/env python # -*- encoding: utf-8 -*- username = "" password = "" interval = 52 from datetime import datetime, timedelta import os import sys import re import time import types from threading import Thread import urllib import urllib2 import webbrowser from xml.dom.minidom import parse import thread import warnings warnings.filterwarnings("ignore") try: import readline except ImportError: sys.stderr.write('INFO: For better line editing capability, ' 'install "readline" module.\n') auth_handler = urllib2.HTTPBasicAuthHandler() auth_handler.add_password( 'Twitter API', 'http://twitter.com/', username, password) opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener) tagText = lambda node, tagName: \ node.getElementsByTagName(tagName)[0].firstChild.nodeValue class TwitterReader(Thread): target_url ='http://twitter.com/statuses/friends_timeline.xml' def __init__(self): Thread.__init__(self) self.last_id = 0 def run(self): while not TwitterWriter.already_exit: req = urllib2.Request(self.target_url) req.add_data("since_id=" + str(self.last_id)) e = None try: e = parse(file=urllib2.urlopen(req)) except Exception, ex: # HTTPError or ExpatError sys.stderr.write(str(ex) + " will retry after %s sec\n" % interval) if type(e) != types.NoneType: for status in reversed(e.getElementsByTagName("status")): if self.last_id < int(tagText(status, "id")): screen_name = tagText(status, "screen_name") text = tagText(status, "text") source = tagText(status,"source") icon_url = tagText(status,"profile_image_url") if source[0] == "<": source = source[source.find(">")+1:source.rfind("<")] print_status(screen_name, text, source, time_created_at(tagText(status, "created_at"))) self.last_id = int(tagText(status, "id")) for i in range(interval): if TwitterWriter.already_exit: break time.sleep(1) def print_status(screen_name, text, source, (rel_time, created_at)): #print "%s %s %s %s from %s" % (created_at, screen_name, text, rel_time, source) print "%s %s %s from %s" % (screen_name, text, rel_time, source) plural = lambda n: n > 1 and "s" or "" def time_created_at(s): """ recieving text element of 'created_at' in the response of Twitter API, returns relative time string from now. """ try: date = time.strptime(s, "%a %b %d %H:%M:%S +0000 %Y")[:-2] except ValueError: return "", "" created_at = datetime(*date) - timedelta(seconds=time.timezone) d = datetime.now() - created_at if d.days: rel_time = "%s days ago" % d.days elif d.seconds > 3600: hours = d.seconds / 3600 rel_time = "%s hour%s ago" % (hours, plural(hours)) elif 60 <= d.seconds < 3600: minutes = d.seconds / 60 rel_time = "%s minute%s ago" % (minutes, plural(minutes)) elif 30 < d.seconds < 60: rel_time = "less than a minute ago" else: rel_time = "less than %s second%s ago" % (d.seconds, plural(d.seconds)) return rel_time, created_at.strftime("%H:%M:%S") class TwitterWriter(Thread): target_url = "http://twitter.com/statuses/update.xml" already_exit = False def __init__(self): Thread.__init__(self) def run(self): while 1: try: update_text = raw_input().strip() if hasattr(sys, "winver"): update_text = update_text.decode("shift_jis", "replace").encode("utf-8") except EOFError: # EOFError TwitterWriter.already_exit = True break if len(update_text): r = urllib2.Request(self.target_url) r.add_header("User-Agent", "TwitTerm http://yanbe.org/twitterm/") r.add_header("X-Twitter-Client", "TwitTerm") r.add_header("X-Twitter-Client-URL", "http://yanbe.org/twitterm/") r.add_header("X-Twitter-Client-Version", "0.1") r.add_data("source=twitterm&status="+update_text) status = parse(file=urllib2.urlopen(r)) print_status( "(updated) " + tagText(status, "screen_name"), tagText(status, "text"), "TwitTerm", time_created_at(tagText(status, "created_at"))) TwitterWriter.already_exit = True def main(): if username == "" or password == "": print "Error: Please specify your twitter account info in", sys.argv[0] sys.exit(1) print "Note: CTRL-D (or CTRL-C) to exit" reader = TwitterReader() writer = TwitterWriter() reader.start() writer.start() reader.join() writer.join() if __name__ == '__main__': main() # /* vim: set filetype=python : */