How-to: using the new Facebook stream API in a desktop app

Facebook recently launched a new set of APIs that allow third-party …

Facebook launched a new set of APIs on Monday that allow third-party software to interact with the Facebook activity stream. Developers can use these new APIs to build sophisticated Facebook client applications that give users direct access to the stream from their desktop.

Courtesy of these APIs, rich support for Facebook could soon arrive in your favorite Twitter client and other social networking programs. In this article, I'll give you an inside look at how I used the new APIs to add full support for the Facebook stream in Gwibber, my own open source microblogging client for Linux.

The activity stream includes several kinds of content, including status updates, images, links, videos, and content that is imported from other services, such as Delicious bookmarks and Google Reader shared items. Users can post comments on stream items and can also indicate that they "like" a specific stream item. Facebook now provides programmatic access to all of this data through several different mechanisms. Developers can use a conventional REST method, a FQL query, or an Atom-based feed.

Atom Activity Extensions

The Atom-based feed is, perhaps, the most intriguing aspect of the new open streams system. Atom is a standardized XML-based format for simple syndication that is similar to RSS but is more robust and extensible. Rather than completely inventing its own dialect, Facebook wisely chose to put its weight behind Atom Activity Extensions, an emerging effort to build a standardized set of activity tags that can be used in Atom feeds.

Atom Activity Extensions is still in the draft stage and is not yet a formal standard. The draft is authored by David Recordon and Martin Atkins of Six Apart under the aegis of the DiSo project, a collaborative effort to build open standards for data portability and social networking.

Facebook has become one of the first major adopters of Atom Activity Extensions, a move that will significantly boost the visibility of the nascent standard and help it gain traction. MySpace is also committed to the format and working on an implementation, so it now has the backing of two of the most popular social networking websites. This is a major win for interoperability and it could eventually facilitate development of universal activity stream clients that function in much the same way that desktop news feed readers work today.

Chris Messina, a leading figure in DiSo who is well-known for his work with OAuth and is closely involved with Atom Activity Streams, is enthusiastic about Facebook's adoption of the format. He commented on the implications in a message posted to DiSo's Activity Streams mailing list on Monday following Facebook's announcement.

"This is indeed good news for Facebook and for this community effort," he wrote. "At the very least, I'm excited to see how similar we can get the feeds coming out of MySpace and Facebook and I'm also eager to start looking at how we can replace the current activities API in OpenSocial with the Activity Streams format."

Facebook makes the stream available to third-party software through a URL. In order to access the feed, the program will need to be authenticated and will have to provide as parameters a session key and signature checksum. The following is the URL format:

The significance of each of those attributes is described in greater detail in the official documentation, but those values should all be relatively familiar to developers who have worked with the Facebook API.

Although the Atom-based feed will be very useful for developers who are building generalized stream clients, Facebook's native APIs are more practical for client applications that will integrate tightly with the service. In Gwibber, I chose to use the new activity stream REST API methods.

Implementing Facebook activity streams in Gwibber

I originally created Gwibber in 2007 with the goal of building a social networking application for the GNOME desktop environment. It brings together comprehensive support for several popular microblogging services in a single program with a unified message stream. It is written in the Python programming language and is distributed under the terms of the General Public License (GPL). The actual content stream is drawn with an embedded WebKit HTML renderer and the rest of the user interface is built the GTK+ toolkit.

Gwibber's current Facebook functionality is built on top of PyFacebook, a lightweight open source Python library that wraps the Facebook APIs. PyFacebook mitigates a lot of the pain of Facebook client development because it handles all of the authentication, session, and signature hash stuff. It hides those idiosyncrasies under a simple object-oriented interface that is easy for developers to use.

PyFacebook is also very easy to extend when new Facebook API methods are introduced. Each Facebook API method is described in the PyFacebook library using a simple data structure that specifies the method's name and parameter types. PyFacebook does not appear to have been updated to work with the new stream API methods yet, but it was trivially easy for me to do it myself. You can see my simple PyFacebook modifications here. Note that I did not add all of the new methods, just the ones that I'm using in Gwibber.

Each service that is supported in Gwibber is implemented in its own module which exposes its functionality through a set of methods and properties that is consistent across all of the service modules. This makes it possible to wrap the services with a generalized abstraction layer so that the rest of the client application doesn't have to understand the differences between the various services. This abstraction layer is what makes it possible for Gwibber to display a combined stream of the messages from all of the services. To implement support for the activity stream, I rewrote most of Gwibber's Facebook service module.

Obtaining stream data

To add the full Facebook stream to Gwibber, I had to process the stream and extract the values into standard Gwibber message classes. I started by adding support for reading the stream. With my modified version of PyFacebook, this is very easy. I call the stream.get method on a PyFacebook instance. When called, the stream.get method will return the contents of the stream in either XML or JSON, depending on what you have requested.

The only parameter that is required by stream.get (besides the session key and others that are handled automatically by PyFacebook) is the UID of your application's user. There are several optional parameters that you can provide to customize the output. For example, you can provide start_time and end_time parameters which will display stream content that was published between the specified times. This is sort of Facebook's equivalent of Twitter's since_id and max_id values.

There is also a limit parameter (similar to Twitter's count) which allows you to specify how many messages you would like to download. The default if no limit value is explicitly specified is 30 posts. The maximum number that can be retrieved at once isn't documented, so I did some experimentation to see if I could figure it out.

I tried pulling down 400 but only got 312, with the oldest messages dating back seven days. This leads me to believe that there is probably not a numerical maximum but that it will only give you access to a week of messages. Unlike Twitter, Facebook's stream API doesn't support the concept of paging, so you can't go back any further than that or iteratively download your entire history.