randomfox: (Default)
[personal profile] randomfox
This Perl script outputs a list of users that a Twitter List is following. Use this script to save your Twitter Lists in case you need to recreate those one day.


#!perl -w
#
# twlist.pl - Output members of a Twitter List.
#
# Usage: twlist.pl [-p proxyhost:proxyport] [-P proxyuser:proxypass] 
# 		user:password user list
#
# proxyserver:proxyport - Optional. HTTP proxy server and port.
# proxyuser:proxypass   - Optional. HTTP proxy login.
# username:password     - Required. Twitter login. 
# user			- Required. User who owns the List. Need not be the
# 			  same as login user.
# list			- Required. The id or slug of the List.
#
# Login information can be specified in Base64 format. If it is, it will be
# placed directly in the HTTP headers.
#
use strict;
use XML::Simple;
use LWP::UserAgent; 
use Getopt::Std;
use MIME::Base64;
use Data::Dumper;

my $count = 0;

# Parse XML and output List members.
sub process_xml {
    my $xmlstr = shift;

    my $xml = XMLin($xmlstr, ForceArray => ['user'], KeyAttr => []);

#     print Dumper($xml);

    for my $user (@{$xml->{users}{user}}) {
	++$count;
	print "$count: $user->{id} $user->{name}\n";
    }

    return $xml->{next_cursor};
}

# Encode in Base64 if login string is in user:pass format. Otherwise,
# assume it is already in Base64.
sub base64login {
    my $login = shift;
    $login =~ /:/ ? encode_base64($login) : $login;
}

my $MAXRETRY = 5;

# Download Twitter list members through Twitter API.
sub twitter_api {
    my $user = shift;
    my $list = shift;
    my $login = shift;
    my $proxy = shift;
    my $proxylogin = shift;
    my $cursor = shift;

    my $retrycount = 0;
    while (1) {
	my $ua = new LWP::UserAgent;
	$proxy ne '' and $ua->proxy('http', "http://$proxy");

	$proxylogin ne '' and
	    $ua->default_header('Proxy-Authorization' => 
		"Basic ".base64login($proxylogin));
	$login ne '' and
	    $ua->default_header('Authorization' =>
		"Basic ".base64login($login));

	my $response = $ua->get("http://api.twitter.com/1/$user/$list/" .
	    "members.xml?cursor=$cursor");
	$response->is_success and return $response->content;

	++$retrycount;
	$retrycount > $MAXRETRY and die $response->as_string;

	warn "Retrying...\n";
	sleep 3;
    }
}

# Get all pages of Twitter list members.
sub get_pages {
    my $user = shift;
    my $list = shift;
    my $login = shift;
    my $proxy = shift;
    my $proxylogin = shift;

    my $cursor = -1;
    my $page = 0;

    do {
	++$page;
	warn "Getting $user/$list list members page $page...\n";

	my $xmlstr;
	eval {
	    $xmlstr = twitter_api($user, $list, $login, 
		$proxy, $proxylogin, $cursor);
	};
	return if $@;

	$cursor = process_xml($xmlstr);
	sleep 1;
    } until $cursor == 0;
}

sub usage {
    die "Usage: $0 [-p proxyhost:proxyport] [-P proxyuser:proxypass] "
    	."user:password user list\n";
}

sub main {
    binmode STDOUT, ":utf8";

    my $proxy = '';
    my $login = '';
    my $proxylogin = '';

    my %opts;
    getopts('p:P:', \%opts) or usage;
    defined $opts{p} and $proxy = $opts{p};
    defined $opts{P} and $proxylogin = $opts{P};

    @ARGV < 3 and usage;
    $login = shift @ARGV;

    my $user = shift @ARGV;
    my $list = shift @ARGV;

    get_pages($user, $list, $login, $proxy, $proxylogin);
}

main;

__END__


Profile

randomfox: (Default)
randomfox

November 2012

S M T W T F S
    123
45678910
11121314151617
18192021222324
25262728 2930 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 23rd, 2017 10:50 am
Powered by Dreamwidth Studios