Twitter API From C#: Getting a User’s Time Line

Twitter API C#: Getting Time Line From Twitter API Documentation page:

User Timeline:

Returns the 20 most recent statuses posted from the authenticating user:

http://twitter.com/statuses/user_timeline.xml

It's also possible to request another user's timeline. For example:

http://twitter.com/statuses/user_timeline/bursteg.xml

Making an HTTP Request

Since all the API is expressed in REST, I figured out that I need a simple reusable method to perform HTTP requests. This method takes the URL and the method (GET or POST), gets the credentials from the configuration file and makes the request.

private string PerformRequest(string method, string url)

{

    string user = ConfigurationManager.AppSettings["user"];

    string password = ConfigurationManager.AppSettings["password"];

 

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);

    request.Method = method;

    request.Credentials = new NetworkCredential(user, password);

    WebResponse response = request.GetResponse();

    StreamReader reader = new StreamReader(response.GetResponseStream());

    string responseString = reader.ReadToEnd();

    reader.Close();

    return responseString;

}

Just for the simplicity, I also added the following methods:

private string Post(string url)

{

    return PerformRequest("POST", url);

}

 

private string Get(string url)

{

    return PerformRequest("GET", url);

}

Getting a User’s Time Line from Twitter

Using the following code, you can get a user’s timeline from twitter in xml  format:

string url = string.Format("http://twitter.com/statuses/friends/{0}.xml", user);

string response = Get(url);

This call returns the following piece of xml:

<?xml version="1.0" encoding="UTF-8"?>

<statuses type="array">

  <status>

    <created_at>Sat Nov 15 10:08:15 +0000 2008</created_at>

    <id>1006846483</id>

    <text>Testing &quot;posts&quot; #devacademy3</text>

    <source>web</source>

    <truncated>false</truncated>

    <in_reply_to_status_id></in_reply_to_status_id>

    <in_reply_to_user_id></in_reply_to_user_id>

    <favorited>false</favorited>

    <user>

      <id>6849932</id>

      <name>Guy Burstein</name>

      <screen_name>bursteg</screen_name>

      <location></location>

      <description></description>

      <profile_image_url>http://.../Guy_Burstein_Small_normal.jpg</profile_image_url>

      <url>http://blogs.microsoft.co.il/blogs/bursteg</url>

      <protected>false</protected>

      <followers_count>42</followers_count>

    </user>

  </status>

 

  <status>

    ...

  </status>

</statuses>

As we can see, this response is an array of statuses, each contains the details about the user who posted it.

Extracting the Data

With my favor to LINQ to XML, I used it to extract the data that I was interested in, and construct CLR objects that I can easily work with.

XDocument document = XDocument.Parse(response, LoadOptions.None);

 

var query = from e in document.Root.Descendants("status")

            select new UserStatus

            {

                UserName = e.Element("user").Element("name").Value,

                ProfileImage = e.Element("user").Element("profile_image_url").Value,

                Status = HttpUtility.HtmlDecode(e.Element("text").Value),

                StatusDate = (e.Element("created_at").Value.ParseDateTime())

            };

First, I parsed an xml document from the response string. Then, I created a list of UserStatus objects from the contents of the response xml.

public class UserStatus

{

    public string UserName { get; set; }

    public string ProfileImage { get; set; }

    public string Status { get; set; }

    public DateTime StatusDate { get; set; }

}

Few things to note about the above code:

1. HttpUtility.HtmlDecode is being used in order to get a readable text. The response contained text like “Testing &quot;posts&quot; #devacademy3” and this method (in System.Web) converts it to “Testing posts #devacademy3”.

2. The ParseDateTime() method on the element’s value is an extension method I created in order to parse a DateTime from the special string representation of the time the status was posted:

Sat Nov 15 10:08:15 +0000 2008

This method looks like:

public static class StringExtensions

{

    public static DateTime ParseDateTime(this string date)

    {

        string dayOfWeek = date.Substring(0, 3).Trim();

        string month = date.Substring(4, 3).Trim();

        string dayInMonth = date.Substring(8, 2).Trim();

        string time = date.Substring(11, 9).Trim();

        string offset = date.Substring(20, 5).Trim();

        string year = date.Substring(25, 5).Trim();

        string dateTime = string.Format("{0}-{1}-{2} {3}", dayInMonth, month, year, time);

        DateTime ret = DateTime.Parse(dateTime);

        return ret;

    }

}

 

If you come up with another idea of how to parse this string into a DateTime object, please let me know.

Wrapping it up...

The final version of the GetUserTimeLine method looks like this:

public List<UserStatus> GetUserTimeLine(string user)

{

    string url = string.Format("http://twitter.com/statuses/user_timeline/{0}.xml", user);

    string response = Get(url);

 

    XDocument document = XDocument.Parse(response, LoadOptions.None);

 

    var query = from e in document.Root.Descendants("status")

                select new UserStatus

                {

                    UserName = e.Element("user").Element("name").Value,

                    ProfileImage = e.Element("user").Element("profile_image_url").Value,

                    Status = HttpUtility.HtmlDecode(e.Element("text").Value),

                    StatusDate = (e.Element("created_at").Value.ParseDateTime())

                };

 

    List<UserStatus> users = (from u in query

                              where u.Status != ""

                              orderby u.StatusDate descending

                              select u).ToList();

 

    return users;

}

The techniques I’ve used here can be used in almost all the “get” methods of the REST API of Twitter.

Enjoy!