#!/usr/bin/perl -w use Cache::Memcached; use CGI qw(escape); use DateTime; use DateTime::Format::Mail; use Date::Parse; use File::Slurp qw( slurp ) ; use Getopt::Long; use JSON::XS; use LWP; use Text::CSV; use strict; my $USERNAME='dmarti'; my $PASSWORD=slurp('/home/dmarti/.twitter-password'); my $AGE = 24 * 60 * 60; my $EXPIRE = 4 * 60 * 60; my $VERBOSE = 0; my $HEADER = 1; my $DT = DateTime->now; my $NOW = $DT->epoch(); my $NAUGHTY = 0; my @users = (); my @searches = (); my %me = (); my $name = ''; GetOptions ("user=s" => \@users, "search=s" => \@searches, "name=s" => \$name, "header!" => \$HEADER, "verbose|v" => \$VERBOSE); my $ua = new LWP::UserAgent; $ua->credentials( 'twitter.com:80', 'Twitter API', $USERNAME => $PASSWORD); my $memd = new Cache::Memcached { 'servers' => [ "127.0.0.1:11211" ], 'debug' => 0, 'namespace' => 'twitter_stuff' }; my $page = 1; my $total = 0; my $my_followers; my $earliest = $NOW; my $at_res; my %users = map {escape($_) => 1} @users; foreach my $user(@users) { $me{$user} = 1; push (@searches, '@' . $user); $name = $user if !$name; } foreach my $search (@searches) { $earliest = $NOW; $page = 1; my $s = escape($search); SEARCHPAGES: while ($earliest + $AGE > $NOW) { my $results = get("http://search.twitter.com/search.json?q=$s&page=$page"); last SEARCHPAGES if !@{$results->{results}}; foreach my $result (@{$results->{results}}) { my $when = str2time($result->{created_at}); if ($when < $earliest) { $earliest = $when; } if ($when + $AGE > $NOW) { $users{$result->{from_user}} = 1; print $result->{from_user}, " said ", $result->{text}, "\n" if $VERBOSE; } } $page++; } } foreach my $user (keys(%users)) { print "checking $user..." if $VERBOSE; my $ui = get("http://twitter.com/users/show.json?screen_name=$user"); next if !defined($ui) or !$ui; my $count = $ui->{followers_count}; print "$count\n" if $VERBOSE; $total += $count; $my_followers += $count if $me{$user}; } print "total $total\n" if $VERBOSE; my $smif; if ($total > 0) { $smif = (int(log($total) * 10))/10; } else { $smif = "NAN"; } my $csv = Text::CSV->new(); if ($HEADER) { $csv->combine("Date", "Name", "Impact Factor", "Own Followers", "Total Followers", "Searches Performed"); print $csv->string, "\n"; } $csv->combine(DateTime::Format::Mail->format_datetime($DT), $name, $smif, $my_followers, $total, @searches); print $csv->string, "\n"; sub get { my $url = shift; my $content; unless ($NAUGHTY or $content = $memd->get('NEW' . $url)) { my $res = $ua->get($url); if ($res->is_success()) { $content = decode_json($res->content); $memd->set('NEW' . $url, $content, $EXPIRE); $memd->set('OLD' . $url, $content, 7 * $EXPIRE); } elsif ($res->code == 400) { $NAUGHTY = 1; $content = $memd->get('OLD' . $url) } else { print STDERR $res->code . ' ' . $res->message . " getting $url\n"; $content = $memd->get('OLD' . $url) } } return $content; }