Wednesday, June 20, 2012

Searching for the nth Tweet in a Hashtag

My girlfriend works for a media company. Last June 12, they had an Independence day promo wherein you tweet your #onesmallactforPH and if you are the 114th person to tweet you get a prize. It made me think how my girlfriend would count the 114th tweet from 800+ tweets because it seems too difficult to count them manually via the search page of twitter. So, I thought of doing a program that would count the tweets for her. However, since my work schedule didn't really permit me to develop the code, she ended up counting them manually. During the weekend, I finally had the time to write the code and I was able to verify the result of the promo! :)

I utilized Twitter's search API for this. Just a word of caution, the search API has limitations and the results are not that accurate. Visit the Twitter Search API to see the limitations.

If you have questions about my implementation don't hesitate to comment! Enjoy!

The first thing I did was to create the HTML file.
<html>
 <head>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <style>
   //insert css here
  </style>
  <script type="text/javascript">
   //insert javascript here
   function submitQuery() {
    //insert logic here
   }
  </script>
 </head>
 <body>  
  <h1>Tweet Counter</h1>
  
  <form action="#" method="POST" onsubmit="submitQuery(); return false;">
   Tweet number: <input type="text" id="n" name="n" value="114" /><br />
   Search: <input type="text" id="q" name="q" value="#onesmallactforPH" /><br />
   Since(yyyy-mm-dd): <input type="text" id="since" name="since" value="2012-06-12" /><br />
   Except user: <input type="text" id="except_user" name="except_user" value="TALKtvPhil" /><br />
   <input type="submit" name="submit" value="Go!" />
  </form>
  <div id="total-count">Total count: </div>
  <div id="invocations"></div>
  <div id="tweets"></div>
 </body>
</html>

Then I wrote the javascript code:
var endpoint = 'http://search.twitter.com/search.json';
var callback = '&callback=?';
var totalCount = 0;
var pageIndex = 0;
var count = 0;
var dataCollection = new Array();
var results = new Array();

function getTweets(url)
{
 $.getJSON(url, function(data)
  {
   dataCollection[pageIndex] = data;
   if(data != '' && data.results.length !=0) {
    getNextPage(data.next_page, data.results.length);
   }
  }
 );
}

function getNextPage(nextPage, count)
{
 totalCount += count;
 pageIndex += 1;
 $('#total-count').html('Total count: ' + totalCount);
 if (typeof nextPage != 'undefined')
 {
  var url = endpoint + nextPage + callback;
  getTweets(url);    
 }
 else
 {
  showTweets();
 }
}
function showTweets()
{
 var n = $('#n').val();
 for (var i = dataCollection.length -1; i >= 0; i--)
 {
  for (var t = dataCollection[i].results.length -1; t >= 0; t--)
  {
   results.push(dataCollection[i].results[t])
  }
 }
 for(var t=n-1; t >= 0; t--) {
  $('#tweets').append('<div class="tweet">' + (t+1) + '<div class="tweet-user"><img class="tweet-img" src="' + results[t].profile_image_url + '" />' + results[t].from_user + '</div><div class="tweet-text">' + results[t].text + '"</div><div class="tweet-date">' + results[t].created_at + '</div></div>');
 }
}

function submitQuery()
{
 totalCount = 0;
 pageIndex = 0;
 dataCollection = new Array();
 count =0;
 results = new Array();
 $('#tweets').html('');
 $('#total-count').html('Total count: ' + totalCount);
 var query = escape($('#q').val());
 var since = escape(' since:' + $('#since').val());
 var except_user = escape(' -from:' + $('#except_user').val());
 var nextPage = '?q='+ query + since + except_user + '&page=1&rpp=100';
 var url = endpoint + nextPage + callback;
 getTweets(url);
}

Finally, I added some styling;
.tweet 
{
 margin: 10px;
 padding: 10px;
 border: 1px solid black;
 width: 300px;
}
.tweet, .tweet-user, .tweet-date, tweet-text
{
 display:block;
}

Here's the full code. Copy the code, paste in a Text editor (notepad), save as filename.html, open the file in a browser and have fun. Important reminder: there are no validation checks in this code so you might encounter errors if you decide to place garbage in your input.
<html>
 <head>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <style>
   .tweet 
   {
    margin: 10px;
    padding: 10px;
    border: 1px solid black;
    width: 300px;
   }
   .tweet, .tweet-user, .tweet-date, tweet-text
   {
    display:block;
   }
  </style>
  <script type="text/javascript">
   var endpoint = 'http://search.twitter.com/search.json';
   var callback = '&callback=?';
   var totalCount = 0;
   var pageIndex = 0;
   var count = 0;
   var dataCollection = new Array();
   var results = new Array();
   
   function getTweets(url)
   {
    $.getJSON(url, function(data)
     {
      dataCollection[pageIndex] = data;
      if(data != '' && data.results.length !=0) {
       getNextPage(data.next_page, data.results.length);
      }
     }
    );
   }
   
   function getNextPage(nextPage, count)
   {
    totalCount += count;
    pageIndex += 1;
    $('#total-count').html('Total count: ' + totalCount);
    if (typeof nextPage != 'undefined')
    {
     var url = endpoint + nextPage + callback;
     getTweets(url);    
    }
    else
    {
     showTweets();
    }
   }
   function showTweets()
   {
    var n = $('#n').val();
    for (var i = dataCollection.length -1; i >= 0; i--)
    {
     for (var t = dataCollection[i].results.length -1; t >= 0; t--)
     {
      results.push(dataCollection[i].results[t])
     }
    }
    for(var t=n-1; t >= 0; t--) {
     $('#tweets').append('<div class="tweet">' + (t+1) + '<div class="tweet-user"><img class="tweet-img" src="' + results[t].profile_image_url + '" />' + results[t].from_user + '</div><div class="tweet-text">' + results[t].text + '"</div><div class="tweet-date">' + results[t].created_at + '</div></div>');
    }
   }
   
   function submitQuery()
   {
    totalCount = 0;
    pageIndex = 0;
    dataCollection = new Array();
    count =0;
    results = new Array();
    $('#tweets').html('');
    $('#total-count').html('Total count: ' + totalCount);
    var query = escape($('#q').val());
    var since = escape(' since:' + $('#since').val());
    var except_user = escape(' -from:' + $('#except_user').val());
    var nextPage = '?q='+ query + since + except_user + '&page=1&rpp=100';
    var url = endpoint + nextPage + callback;
    getTweets(url);
   }
  </script>
 </head>
 <body>  
  <h1>Tweet Counter</h1>
  
  <form action="#" method="POST" onsubmit="submitQuery(); return false;">
   Tweet number: <input type="text" id="n" name="n" value="114" /><br />
   Search: <input type="text" id="q" name="q" value="#onesmallactforPH" /><br />
   Since(yyyy-mm-dd): <input type="text" id="since" name="since" value="2012-06-12" /><br />
   Except user: <input type="text" id="except_user" name="except_user" value="TALKtvPhil" /><br />
   <input type="submit" name="submit" value="Go!" />
  </form>
  <div id="total-count">Total count: </div>
  <div id="invocations"></div>
  <div id="tweets"></div>
 </body>
</html>

No comments: