|
Write Your Own Linux Twitter Client In Less Time Than It Takes To Find One!
A command-line Twitter client in about 20 lines
I know, I know. All the cool kids have been doing it for months now. I'm way behind. But a couple of weeks ago, I finally took the plunge and signed up for Twitter. I was skeptical, but it's actually pretty interesting. It didn't take me long to build up a list of people to follow. But I didn't want to keep a tab open in my browser all day every day just to check on them. I investigated the available Linux clients, but none was quite what I was looking for. Either they required that I install some big piece of infrastructure like Mono or Adobe Air, or they had nasty bugs. And then I found out about Python-Twitter. It provides Python bindings for Twitter's public API, and it's super easy to use. Turns out you can write your own Twitter client in less time than it takes to read about the existing ones! Install python-twitterThe first step is installing Python-Twitter. Cutting-edge distros like Ubuntu 9.04 have it as a package; install python-twitter and you're done. On older distros, you might have to get it from the source. First, you'll need a package called SimpleJSON. Your distro may have it already (it might, even if it doesn't have python-twitter. But if not, get it from cheeseshop.python.org/pypi/simplejson. Then go to code.google.com/p/python-twitter, click on Downloads and grab the latest tarball. Expand it, build and install: tar xvf python-twitter-0.6.tar.gz cd python-twitter-0.6/ python setup.py build sudo python setup.py install Once it's installed, you're ready to start programming. A command-line Twitter client in about 20 linesTo do anything with Twitter, you need to log in with a username and password. That looks like this: import twitter username = "your_username" password = "your_password" api = twitter.Api(username=username, password=password) Once you're logged in, you can get your "friends timeline" -- the list of tweets you'd see if you went to twitter.com and logged in -- like this: statuses = api.GetFriendsTimeline(username) statuses is a list of the Python-Twitter status object. A status represents one tweet, and has properties like user (the author), text (the contents) and created_at_in_seconds (the time when it was posted). user is an object representing a Twitter user. It has properties like name, screen_name and profile_image_url.
So you can print that list of tweets like this:
for s in statuses :
print s.user.name, "(", s.user.screen_name, ") :"
print s.text
print
Well, almost. There's one more thing you need to do. Tweets come in as unicode, and Python's print can't handle unicode characters unless you tell it how to encode them. If you're not sure, UTF-8 is a good choice:
for s in statuses :
print s.user.name.encode("utf-8"), "(", s.user.screen_name, ") :"
print s.text.encode("utf-8")
print
Run it, and you'll see output something like this: /var/lib/python-support/python2.6/twitter.py:10: DeprecationWarning: the md5 module is deprecated; use hashlib instead import md5 donttrythis ( donttrythis ) : I'm playing with a Canon 5D Mark II if you must know @el_es_gato. The footage it shoots is UNBELIEVABLE! I'm gonna make me a film. Tim O'Reilly ( timoreilly ) : Chevron patents on NiMH batteries holding back future of plug-in hybrid cars. http://bit.ly/awwJ3 Learned about in conversation at #aif09 PZ Myers ( pzmyers ) : I have now been traveling for a full 24 hours...and still 2 hours from home. Wall Street Journal ( WSJ ) : Companies, Workers Tangle Over Law http://bit.ly/kya1p Science News ( SciNewsBlog ) : China's Internet Users Force Government to Back Down on Censorship: China's Internet Users Force Government to B.. http://tinyurl.com/qmorz9 Voilà! Your very own customizable Twitter client. Add a loop and a time.sleep(300) to make it update every five minutes (300 seconds). Don't worry too much if you see that DeprecationWarning at the beginning. That's a minor bug in python-twitter, but it doesn't hurt anything; hopefully they'll fix it soon.
A Twitter WindowThat's all very well, you say, but if you use a commandline client, your friends will laugh at you and won't let you play in their reindeer games? No problem -- Python, as you've seen in previous articles, is fully capable of doing graphics. I'll use Tkinter here. Let's pick a simple design: each tweet will have a label showing the author and a text area showing the contents of the tweet. Start with an object representing the window. You'll need a few variables, including the username, password, and how many entries you want to show.
#! /usr/bin/env python
import twitter, Tkinter
class TwitWindow :
""" Display Twitter output in a TkInter window."""
def __init__(self, _name, _location) :
self.username = "your_username"
self.password = "your_password"
self.num_entries = 11
You'll also want lists where you can store the label and text area for each tweet. Still inside __init__:
# Lists to hold the labels and text areas
self.labels = []
self.texts = []
Next, write a function to create the main window:
def CreateWindow(self) :
# Create the main window
self.tkroot = Tkinter.Tk()
self.tkroot.title("Twit")
Now you're ready to create the labels and text areas:
# Create all the labels and text widgets:
for i in range(0, self.num_entries) :
self.labels.append(Tkinter.Label(self.tkroot))
self.labels[i].pack(expand=False, fill=Tkinter.X)
self.texts.append(Tkinter.Text())
self.texts[i].config(width=55, height=3)
self.texts[i].config(wrap=Tkinter.WORD)
self.texts[i].pack(expand=True)
For each tweet, append a Tkinter label and text to the appropriate list, then use TkInter's pack manager to arrange the widgets in a vertical stack. expand=False means the label won't get any bigger than one line even if you resize the window; expand=True on the text areas mean they'll take up the extra space. fill=Tkinter.X on the label makes it take up the full width of the window. The text widget is configured to be 55 characters wide and 3 lines high. Of course, you can adjust all of these to your liking. Of course you need to initialize the Twitter API and show the window:
self.api = twitter.Api(username=self.username, password=self.passwd)
self.tkroot.mainloop()
You can test the program now by adding a few lines at the end of your program to create the window (Figure 1): # main win = TwitWindow() win.CreateWindow() Ew, ugly colors! Fortunately, you can adjust the colors to your preference (Figure 2):
self.labels[i].config(bg="#07c", fg="white")
self.texts[i].config(bg="#eff", fg="black")
Next, you need a function to get new tweets and update the window. That works a lot like in the command-line twitter, except that when looping over the list of statuses it should update the labels and text widgets instead of printing. One minor difference is that you have to clear each text widget first before adding the new text.
def UpdateWindow(self) :
statuses = self.api.GetFriendsTimeline(self.username)
for i in range(0, self.num_entries) :
self.texts[i].delete(1.0, Tkinter.END) # Clear the old text
if i < len(statuses) :
# Update the label with the user's name and screen name
user = statuses[i].user
labeltext = user.name + " (" + user.screen_name + ")"
self.labels[i].config(text=labeltext)
# Display the text of the tweet
self.texts[i].insert(Tkinter.END, statuses[i].text)
Notice anything missing? Right -- the program never calls UpdateWindow(). You can call it just before calling self.tkroot.mainloop() ... but you'll need to set a timer to call it again in five minutes. Do that from the end of UpdateWindow(), and remember, Tkinter timers are in milliseconds, not seconds, so multiply by 1000:
# Run this again five minutes from now:
self.timer = self.tkroot.after(300000, self.UpdateWindow)
Be careful on the indentation of that timer line -- you don't want it And there you have it -- your very own, fully customizable Twitter client. Happy tweeting! ReferencesAkkana Peck is a freelance programmer and writer and the author of Beginning GIMP: From Novice to Professional. Her website includes a more fully featured version of the Python Twit client, and you can follow her tweets here.
|