Searching Twitter for Tweets

To complete this section of the tutorial, you should have completed the previous two sections Getting Started and Authenticating With Twitter.

In this section we will search Twitter for tweets and display them on the screen. Start with the source code that resulted from the end of the Authenticating With Twitter part of the tutorial.

1. Searching Twitter for Tweets

We are now going ask Twitter to give us back some tweets based upon a search query. Before we do this we are going to add a couple of lines at the top of our program. Firstly, at the top of our sketch, just after creating the Twitter object, create a String to contain our search query (we have gone for “digital art”):

String searchString = "digital art";

Next, we need a List of Status objects to hold the tweets we get back from Twitter. Directly after our search string, add the following:

List<Status> tweets;

Now we are going to create a function called getNewTweets() that will ask Twitter to give us some tweets based on the search query. Start with an empty function, after the draw() function:

void getNewTweets()
{

}

The Internet Always Works, Right?

Now, before writing code to ask Twitter for tweets, consider the fact that we are trying to use the internet here, and that sadly the internet isn’t always reliable for a number of reasons. What happens if we ask for tweets and our connection is down? Or Twitter’s servers are too busy? We need to handle this problematic case, or ‘exception’, by using a try { ... } catch { ... } block. Specifically, we will try to ask Twitter for tweets and then attempt to handle (or catch) something called a TwitterException. Let’s add the try/catch block to our getNewTweets() function (we will add the code to ask for tweets next):

try
{
    // try to get tweets here
}
catch (TwitterException te)
{
    // deal with the case where we can't get them here
}

The try block

Right, let’s ask Twitter for some tweets. In the try block, first create a new Query object using our search string:

Query query = new Query(searchString);

Next, let’s ask Twitter to provide tweets based on the search string, and store the results in a QueryResult object:

QueryResult result = twitter.search(query);

And finally, store the tweets from the QueryResult object in our list of tweets that we created earlier:

tweets = result.getTweets();

Exception Handling, the catch block

So what if it goes wrong? Rather than having the computer freeze/explode, it would be better if it could simply tell us that it didn’t work. In the catch block, add the following:

System.out.println("Failed to search tweets: " + te.getMessage());
System.exit(-1);

This will print out to the console a simple message, with any relevant information that was included with the exception, and then quit the program gracefully.

Calling the getNewTweets() Function

To make sure we ask Twitter for tweets, add a call to the getNewTweets() function to the end of our setup() function. Your full sketch should now look like:

import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;

Twitter twitter;
String searchString = "digital art";
List<Status> tweets;

void setup()
{
    size(800,600);

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setOAuthConsumerKey("*****YOUR-KEY-HERE******");
    cb.setOAuthConsumerSecret("*************YOUR-KEY-HERE*************");
    cb.setOAuthAccessToken("*************YOUR-KEY-HERE***************");
    cb.setOAuthAccessTokenSecret("**********YOUR-KEY-HERE***************");

    TwitterFactory tf = new TwitterFactory(cb.build());

    twitter = tf.getInstance();

    getNewTweets();
}

void draw()
{

}

void getNewTweets()
{
    try
    {
        Query query = new Query(searchString);

        QueryResult result = twitter.search(query);

        tweets = result.getTweets();
    }
    catch (TwitterException te)
    {
        System.out.println("Failed to search tweets: " + te.getMessage());
        System.exit(-1);
    }
}

2. Displaying the Tweets Using Processing

We now have retrieved some tweets but so far we can’t see anything. Let’s print them out one by one at random locations on the screen. To do this, at the top of our program, create a new integer variable called `currentTweet’:

int currentTweet;

and initialise it at the end of our setup() function to 0:

currentTweet = 0;

In the draw() function, we will first set the background colour to black:

background(0);

Next, we are going to add some code to increase the currentTweet integer by one each frame:

currentTweet = currentTweet + 1;

and then some code to reset it to zero when it becomes larger than the number of tweets:

if (currentTweet >= tweets.size())
{
    currentTweet = 0;
}

Then we retrieve the current tweet from our list of tweets and store it in a Status object:

Status status = tweets.get(currentTweet);

Finally, we will set the fill colour to a light grey, draw the text at a random location and ask the program to wait for 250ms:

fill(200);
text(status.getText(), random(width), random(height), 300, 200);
delay(250);

Try running the program and you should see the latest tweets displayed on the screen

3. Making it look (a bit) nicer

We will add a couple of lines of code to make the tweets fade away, rather than instantly disappear. Replace the setting of the background colour in the draw() function with the following two lines:

fill(0, 40);
rect(0, 0, width, height);

4. Full Source So Far

The full sketch should now look like:

import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;

Twitter twitter;
String searchString = "digital art";
List<Status> tweets;

int currentTweet;

void setup()
{
    size(800,600);

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setOAuthConsumerKey("*****YOUR-KEY-HERE******");
    cb.setOAuthConsumerSecret("*************YOUR-KEY-HERE*************");
    cb.setOAuthAccessToken("*************YOUR-KEY-HERE***************");
    cb.setOAuthAccessTokenSecret("**********YOUR-KEY-HERE***************");

    TwitterFactory tf = new TwitterFactory(cb.build());

    twitter = tf.getInstance();

    getNewTweets();

    currentTweet = 0;
}

void draw()
{
    fill(0, 40);
    rect(0, 0, width, height);

    currentTweet = currentTweet + 1;

    if (currentTweet >= tweets.size())
    {
        currentTweet = 0;
    }

    Status status = tweets.get(currentTweet);

    fill(200);
    text(status.getText(), random(width), random(height), 300, 200);

    delay(250);
}

void getNewTweets()
{
    try
    {
        Query query = new Query(searchString);

        QueryResult result = twitter.search(query);

        tweets = result.getTweets();
    }
    catch (TwitterException te)
    {
        System.out.println("Failed to search tweets: " + te.getMessage());
        System.exit(-1);
    }
}

5. Updating the Tweets at Regular Intervals

So far, our program only asks for tweets at the beginning of the program and then displays them on the screen. It would be great if we have the program automatically update itself.

In order to achieve this, we need to use something called a “thread”. This is essentially a process that will happen in parallel to our program. First, we need to create a function called refreshTweets() that will ask for the list of tweets to be updated at regular intervals. Create a new empty function to do this as follows:

void refreshTweets()
{

}

Next, inside this function we are going to create a while loop that will run indefinitely, calling getNewTweets(), printing to the console that it has updated the tweets and then waiting for 30 seconds (30,000 milliseconds):

void refreshTweets()
{
    while (true)
    {
        getNewTweets();

        println("Updated Tweets");

        delay(30000);
    }
}

Finally, we need to tell Processing to request new tweets on a different thread. At the bottom of the setup() function, simply add the following line:

thread("refreshTweets");

6. Final Source Code

import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;

Twitter twitter;
String searchString = "digital art";
List<Status> tweets;

int currentTweet;

void setup()
{
    size(800,600);

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setOAuthConsumerKey("*****YOUR-KEY-HERE******");
    cb.setOAuthConsumerSecret("*************YOUR-KEY-HERE*************");
    cb.setOAuthAccessToken("*************YOUR-KEY-HERE***************");
    cb.setOAuthAccessTokenSecret("**********YOUR-KEY-HERE***************");

    TwitterFactory tf = new TwitterFactory(cb.build());

    twitter = tf.getInstance();

    getNewTweets();

    currentTweet = 0;

    thread("refreshTweets");
}

void draw()
{
    fill(0, 40);
    rect(0, 0, width, height);

    currentTweet = currentTweet + 1;

    if (currentTweet >= tweets.size())
    {
        currentTweet = 0;
    }

    Status status = tweets.get(currentTweet);

    fill(200);
    text(status.getText(), random(width), random(height), 300, 200);

    delay(250);
}

void getNewTweets()
{
    try
    {
        Query query = new Query(searchString);

        QueryResult result = twitter.search(query);

        tweets = result.getTweets();
    }
    catch (TwitterException te)
    {
        System.out.println("Failed to search tweets: " + te.getMessage());
        System.exit(-1);
    }
}

void refreshTweets()
{
    while (true)
    {
        getNewTweets();

        println("Updated Tweets");

        delay(30000);
    }
}