How To: Add a Caching Twitter Badge to CS2007

A few months ago I started playing around with Twitter. In case you are not familiar with it, Twitter is a blog of short messages. Think about all the times you want to say something, or tell people where you are, but you don’t think the idea warrants an entire blog post. Those are the times you use Twitter. People can subscribe to your Twitter status and get those updates where ever they are. They can get them via IM, or SMS, or some 3rd party applications. Since I live in Europe, I subscribe to a few people’s status via SMS (SMS in Europe is cheap, unlike the US where no one uses it since it is so expensive).

When I was thinking about what I wanted on this website, I thought some sort of Twitter status update would be cool. Not an entire history, just the latest item. If you go to Twitter’s badge page, you can see a number of options for grabbing your current Twitter status. I tried the Javascript one first. It seemed to work, but I was annoyed at the fact that it polled Twitter on every refresh. Chances are I am not going to update my Twitter status that often, so I want to cache the information locally. But I don’t want to cache the entire block of text, because the time since I made the update will change as time goes by. So I wanted to cache just the text and the time I made the update.

First I check the CSCache for my Twitter information:

string TwitterText = CSCache.Get("TwitterText") as string;
string TwitterTime = CSCache.Get("TwitterTime") as string;

 

If TwitterTime is null, then I grab the latest one status item from Twitter:

string TwitterPath = 
"http://www.twitter.com/statuses/user_timeline/2449901.xml?count=1";
WebClient webClient = new WebClient();
string TwitterXML = Encoding.ASCII.GetString(wClient.DownloadData(TwitterPath));

 

Once I have the TwitterXML string, I can parse it to get my text and time and I add that to the cache. From there I just converted the Javascript relative time code from Twitter’s code to C#. Here is the full TwitterStatus.ascx:

<%@ Import namespace="System.Xml.XPath"%>
<%@ Import namespace="System.Net"%>
<%@ Import namespace="CommunityServer.Components"%>
<%@ Control Language="C#" ClassName="TwitterStatus" %>
<script runat=server language="C#">

protected int cacheTime;
public int CacheTime
{
get
{
return cacheTime;
}
set
{
cacheTime = value;
}
}
protected override void OnInit(EventArgs e)
{
string TwitterPath =
"http://www.twitter.com/statuses/user_timeline/2449901.xml?count=1";
string TwitterText = CSCache.Get(
"TwitterText") as string;
string TwitterTime = CSCache.Get(
"TwitterTime") as string;
string TwitterString =
" ";

if (string.IsNullOrEmpty(TwitterTime))
{
string returnXML =
" ";
WebClient wClient = new WebClient();
returnXML = Encoding.ASCII.GetString(wClient.DownloadData(TwitterPath));

XPathDocument doc = new XPathDocument(new System.IO.StringReader(returnXML));
XPathNavigator nav = doc.CreateNavigator();

//Get Twitter Time
XPathNodeIterator nodes = nav.Select(@
"/statuses/status/created_at");
nodes.MoveNext();
TwitterTime = nodes.Current.Value;
//Get Twitter Text
nodes = nav.Select(@
"/statuses/status/text");
nodes.MoveNext();
TwitterText = nodes.Current.Value;
string[] TimeValues = TwitterTime.Split(' ');
TwitterTime = TimeValues[1] +
" " + TimeValues[2]
+ " " + TimeValues[5] + " " + TimeValues[3] + " GMT";

CSCache.Insert(
"TwitterText",TwitterText, cacheTime);
CSCache.Insert(
"TwitterTime", TwitterTime, cacheTime);
}

DateTime twDate = Convert.ToDateTime(TwitterTime);

int secondsago = Convert.ToInt32(DateTime.Now.Subtract(twDate).TotalSeconds);
if (secondsago < 60)
TwitterString = "less than a minute ago";
else if (secondsago < 120)
TwitterString = "about a minute ago";
else if (secondsago < (45 * 60))
TwitterString = (secondsago / 60).ToString() + " minutes ago";
else if (secondsago < (90 * 60))
TwitterString = "about an hour ago";
else if (secondsago < (24 * 60 * 60))
TwitterString = "about " + (secondsago / 3600).ToString() + " hours ago";
else if (secondsago < (48 * 60 * 60))
TwitterString = "1 day ago";
else
TwitterString = (secondsago / 86400).ToString() +
" days ago";

TwitterTextLiteral.Text = TwitterText;
TwitterSinceLiteral.Text = TwitterString;

base.OnInit(e);
}

</script>

<div id=TwitterStatus>
According to <a href="http://twitter.com/Technovangelist" target=_blank>Twitter</a>
I am: <asp:Literal ID=TwitterTextLiteral runat=server></asp:Literal> as of
<asp:Literal ID=TwitterSinceLiteral runat=server></asp:Literal>
</div>

 

To use this I add the following at the top of my aspx page:

 

And then add this where I want the TwitterStatus to go:

<MW:TwitterStatus runat=server CacheTime=300 />

This seems to be working for me for now. Let me know if you end up using it on your site. Or if you have any suggestions on improving this, I would love to hear that too.