inicio mail me! sindicaci;ón

2S

Techie. Writer. Photographer.

wikibday: Playing with the Twitter API

Statutory warning: if thou ain’t geeky, adios already.

Taggy’s cricket update bot, which is out yesterday, inspired me to look at the Twitter APIs. I mean, what better way to spend a Sunday morning juggling a India-Pak test match, and trying out some some new API, with yesterday’s pizza leftovers to keep me company?

Firstly, for those who are new to Twitter, here’s a quick Ctrl+C / Ctrl+V from their website:

Twitter is a community of friends and strangers from around the world sending updates about moments in their lives. Friends near or far can use Twitter to remain somewhat close while far away. Curious people can make friends. Bloggers can use it as a mini-blogging tool. Developers can use the API to make Twitter tools of their own. Possibilities are endless!

To make a long story short, Mr. X twitters and Mr. Y follows him. When Mr. X updates his status, his followers (which include Y) will get a notification. That simple? Yep. No kidding.

Now, the Twitter API itself allows you to build remote applications that talk to Twitter, for retrieving updates/friends/followers or to simply update your status.

Yours truly is pretty much at home with Java, so a quick Google for a Java Twitter API revealed ThinkTank’s open-source interface to Twitter. The package, jTwtiter, is oh-so-simple to use, and comes with good documentation, like most Java libs.

To start with, I thought of building a Twitter bot that is scheduled to run every day in the morning, pick up a list of Indians who are born on the day and update the bot’s status. In which case, whoever follows the bot would get notified of the update. Just a random use-case to get a comfort level. Of course, it’s pretty lightweight and hardly any code, but here is what a crude design of the app would look like.

There are two classes, CelebBirthdayUpdate and WikiBirthdayAdapter. CelebBirthdayUpdate instantiates a new WikiBirthdayAdapter and transmits two arguments, a date and a nationality. WikiBirthdayAdapter internally connects to Wikipedia over HTTP (using the Apache Commons HttpClient API), gets a dump of the HTML output and scrapes it using simple string/regex functions to retrieve a Vector of Strings, which contains each birthday for the day. I initialled picked XPath - am a big fan of X-technologies - but string parsing here seemed simpler and faster, especially as the Wikis are structured decently enough.

CelebBirthdayUpdate simply iterates through this list, and for each item it finds, invokes the Twitter.updateStatus() method to set the remote status of the bot.

Here is what the code looks like:

CelebBirthdayUpdate.java

package com.sslabs.twitter.playground;

import java.util.Date;
import thinktank.twitter.Twitter;

public class CelebBirthdayUpdate {

	public static void main(String[] args) {

		WikiBirthdayAdapter wba = new WikiBirthdayAdapter();
		Date today = new Date();
		if (wba.execute(today, "India")) {
			if (wba.getBirthdays().size() > 0) {
				Twitter twitter = new Twitter("wikibday", "******");
				for (String status : wba.getBirthdays()) {
					System.out.println(status);
					twitter.updateStatus(status);
				}
			} else {
				System.err.println("No birthdays to update.");
			}
		}

	}

}

WikiBirthdayAdapter.java

package com.sslabs.twitter.playground;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class WikiBirthdayAdapter {

	private List birthdays = new Vector();

	public List getBirthdays() {
		return birthdays;
	}

	public boolean execute(Date date, String nationality) {

		boolean result = true;

		SimpleDateFormat wikiFormat = new SimpleDateFormat(”MMMM_dd”);
		SimpleDateFormat outFormat = new SimpleDateFormat(”dd/MM/”);
		String disp = outFormat.format(date);

		// Create a HTTP Client
		HttpClient client = new HttpClient();

		String url = “http://en.wikipedia.org/wiki/” + wikiFormat.format(date);
		System.out.println(”Looking for ” + nationality + ” birthdays at ”
				+ url);

		// Create a method instance
		GetMethod method = new GetMethod(url);

		// Build a retry handler
		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
				new DefaultHttpMethodRetryHandler(3, false));

		try {

			// Execute the method.
			int statusCode = client.executeMethod(method);
			System.out.println(”Status response: ” + statusCode);

			if (statusCode != HttpStatus.SC_OK) {
				System.err.println(”Method failed: ” + method.getStatusLine());
				result = false;
			}

			// Read the response body.
			System.out.println(”Connected. Retrieving response …”);
			byte[] responseBody = method.getResponseBody();
			System.out.println(”Response retrieved.”);

			System.out.println(”Parsing content …”);
			String body = new String(responseBody);
			int start = body.indexOf(”<a name=\”Births\”");
			int end = body.indexOf(”<a name=\”Deaths\”");
			body = body.substring(start, end);
			String births = body.replaceAll(”\\<.*?>”, “”);
			String entries[] = births.split(”\n”);
			for (int i = 0; i < entries.length; i++) {
				if (entries[i].contains(”, ” + nationality)) {
					birthdays.add(disp + entries[i]);
				}
			}
			System.out.println(”Parsed: found ” + birthdays.size()
					+ ” birthday(s)”);
			System.out.println(”Method invocation complete.”);

		} catch (HttpException e) {
			System.err.println(”Fatal protocol violation: ” + e.getMessage());
			e.printStackTrace();
			result = false;
		} catch (IOException e) {
			System.err.println(”Fatal transport error: ” + e.getMessage());
			e.printStackTrace();
			result = false;
		} finally {
			// Release the connection.
			method.releaseConnection();
			return result;
		}
	}
}

The sample output for today (25/11) looks like this:

Looking for India birthdays at http://en.wikipedia.org/wiki/November_25
Status response: 200
Connected. Retrieving response ...
Response retrieved.
Parsing content ...
Parsed: found 0 birthday(s)
No birthdays to update.
Method invocation complete.

Apparently, Wikipedia isn’t aware of any celeb Indians born today, so let’s see what happens tmorrow. Astonishingly simple, innit? So if the idea of working with a microblogging API turns you on, go for it.

And, wikibday?

Here is what the notification would look like …

For all those of you who are already on Twitter, follow wikibday for these random, useless updates at 09.00 AM IST every morning (cronned locally), although taggy’s bot - meninblue - is a more useful one to look at.

3 Comments »

  taggy wrote @ November 25th, 2007 at 5:24 pm

i was wishing if there is anyway i can track my friends birthday in to this :)
no idea how one can do this actually .
may be i will leave for u to figure it out

  2S wrote @ November 25th, 2007 at 5:25 pm

Maybe an orkut / facebook plugin …

  amreen wrote @ November 27th, 2007 at 4:30 pm

yep cool stuff … as u know i am following… twits :)

Your comment

HTML-Tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>