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__


From:
Anonymous( )Anonymous This account has disabled anonymous posting.
OpenID( )OpenID You can comment on this post while signed in with an account from many other sites, once you have confirmed your email address. Sign in using OpenID.
User
Account name:
Password:
If you don't have an account you can create one now.
Subject:
HTML doesn't work in the subject.

Message:

 
Notice: This account is set to log the IP addresses of everyone who comments.
Links will be displayed as unclickable URLs to help prevent spam.

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:40 am
Powered by Dreamwidth Studios