Fluent twitter search API
The other day I was working on a application at work that needed to use the twitter search api. I Figured I might just as well build a small wrapper for the api as I will probably use it in other applications as well. I decided to make a fluent interface, as I think that is the most readable way of cunstructing a query like the one I need for the api.
I started by creating a model of two classes. One class to represent a "tweet" and one to represent a author. They look like this:
public class Tweet
{
public virtual string Id { get; set; }
public virtual DateTime Published { get; set; }
public virtual string Link { get; set; }
public virtual string Title { get; set; }
public virtual string ImageUrl { get; set; }
public virtual Author Author { get; set; }
}
public class Author
{
public virtual string Name { get; set; }
public virtual string Uri { get; set; }
}
I the devided the search options I needed in different logical groups. Here is, for example, the user part of the query:
public interface IPersonQuery : ISubQuery
{
IPersonQuery From(string name);
IPersonQuery To(string name);
IPersonQuery Referencing(string name);
}
Then I have a "main class" that handels the query. This class looks like this:
public class TwitterQuery : IQuery
{
private readonly StringBuilder _querySb = new StringBuilder();
internal TwitterQuery()
{
Users = new PersonQuery(this);
Words = new WordQuery(this);
Paging = new PagingQuery(this);
Places = new PlacesQuery(this);
Date = new DateQuery(this);
}
internal StringBuilder QuerySb
{
get { return _querySb; }
}
public static IQuery BuildQuery()
{
return new TwitterQuery();
}
public virtual IPersonQuery Users { get; private set; }
public virtual IWordQuery Words { get; private set; }
public virtual IPagingQuery Paging { get; private set; }
public virtual IPlacesQuery Places { get; private set; }
public virtual IDateQuery Date { get; private set; }
public virtual IEnumerable<Tweet> ExecuteQuery()
{
return new SearchEngine(QuerySb.ToString()).RunQuery();
}
}
I use this class to execute the query:
internal class SearchEngine
{
private readonly string _searchString;
private const string UrlTemplate = "http://search.twitter.com/search.atom?q={0}";
private static readonly XNamespace AtomNS = "http://www.w3.org/2005/Atom";
internal SearchEngine(string searchString)
{
_searchString = searchString;
}
internal IEnumerable<Tweet> RunQuery()
{
var xDoc = XDocument.Load(string.Format(UrlTemplate, _searchString));
var tweets =
(from tweet in xDoc.Descendants(AtomNS + "entry")
select new Tweet
{
Title = (string)tweet.Element(AtomNS + "title"),
Published =
DateTime.Parse((string)tweet.Element(AtomNS + "published")),
Id = (string)tweet.Element(AtomNS + "id"),
Link = tweet.Elements(AtomNS + "link")
.Where(link => (string)link.Attribute("rel") == "alternate")
.Select(link => (string)link.Attribute("href"))
.First(),
ImageUrl = tweet.Elements(AtomNS + "link")
.Where(link => (string)link.Attribute("rel") == "image")
.Select(link => (string)link.Attribute("href"))
.First(),
Author = (from author in tweet.Descendants(AtomNS + "author")
select new Author
{
Name = (string)author.Element(AtomNS + "name"),
Uri = (string)author.Element(AtomNS + "uri"),
}).First(),
});
return tweets.ToList();
}
}
Those are pretty much all the parts of this API. And I can use it like this to get all "tweets" by the user Jakobsson (me):
var tweets = TwitterQuery.BuildQuery().Users.From("Jakobsson").End().ExecuteQuery();
Pretty simple and readable in my opinion. I have plans to extend this with the rest of the twitter API as well when I find the time. But for now, this will have to do.
You can download the whole source from my svn repository at: https://87.237.213.147:8443/svn/Mattias_TwitterAPI and log in with username: "User" and no password.