Tuesday, July 14, 2009

Following a Topic on Twitter with Net::Twitter

Last week I was keeping up to date with Triple J's Hottest 100 of All Time for 2009 and the hashtag to follow was #hottest100, so that's what I typed into search.twitter.com and kept refreshing every few minutes to see the latest thoughts as the countdown progressed. However, it very quickly became annoying to constantly refresh the search page to view the latest tweets. So I threw together this quick Perl script to display Growl notifications for the latest updates:

#!/usr/bin/env perl

use warnings;
use strict;

use Config::ApacheFormat;
use Encode qw/encode/;
use HTML::Entities;
use Mac::Growl;
use Net::Twitter;

use constant {
    TWEETRC             => "$ENV{HOME}/.tweetrc",
    MAX_RESULTS_DISPLAY => 5,
    POLL_FREQUENCY      => 30
};

die "usage: tweet-follow \n" unless @ARGV > 0;

Mac::Growl::RegisterNotifications(
    'tweet-follow',
    ['tweet'],
    ['tweet']
);

my $num_results_display = MAX_RESULTS_DISPLAY;
my $poll_frequency      = POLL_FREQUENCY;

if ( -e TWEETRC ) { 
    my $config = new Config::ApacheFormat;
    $config->read(TWEETRC);
    my $block = $config->block('follow');
    $num_results_display = $block->get('max_display_results');
    $poll_frequency      = $block->get('poll_frequency');
}

my ($query) = @ARGV;
my $twitter = Net::Twitter->new( traits => [qw/API::Search/] );

my $since_id = 0;
my $max_id   = 0;
while (1) {
    my $response = $twitter->search(
        {   q   => $query,
            rpp => $num_results_display,
            $since_id ? ( since_id => $since_id ) : ()
        }   
    );  

    unless ( defined $response ) { 
        printf "error while following: %s\n",
            $twitter->get_error->{error};
        exit 1;
    }   

    for my $tweet ( @{ $response->{results} } ) { 
        next unless $tweet->{id} > $since_id;

        $max_id = $tweet->{id} if $tweet->{id} > $max_id;

        Mac::Growl::PostNotification(
            'tweet-follow',
            'tweet',
            decode_entities( $tweet->{from_user} ),
            encode( 'UTF-8', decode_entities( $tweet->{text} ) ) 
        );  
    }   

    $since_id = $max_id;
    sleep $poll_frequency;
}

Usage is simple:
tweet-follow hottest100

Add something like this to your ~/.tweetrc to tweak some basic settings:

<follow>
    max_display_results 7
    poll_frequency 30
</follow>

The options are pretty self-explanatory:
  • max_display_results controls how many tweets to post Growl notifications for.
  • poll_frequency configures how often, in seconds, to poll for, and display, new tweets.

If only I could get Unicode characters to display properly in the Growl boxes. At the moment they just display as question marks for me.

I made a design decision to only display the latest N tweets, rather than displaying the next N tweets since the last poll, otherwise if you are displaying 5 tweets every 30 seconds for a topic that receives 50 new tweets every 10 seconds (think #iranelection or celebrity deaths), the script will get far behind very quickly.

No comments:

Post a Comment