#!/usr/bin/env perl
use strict;
use warnings;
# Take your LJ username and password as arguments;
# print to stdout an HTML page containing the userpics
# of all your friends.
use RPC::XML;
use RPC::XML::Client;
use LWP::Simple;
use HTML::TokeParser;
my $client = RPC::XML::Client->new(
'/interface/xmlrpc'
);
my $username = shift @ARGV or die("Need username");
my $password = shift @ARGV or die("Need password");
my $logindata = {
username => $username,
password => $password,
ver => 1,
};
# Set @friends to contain LJ usernames of all your friends.
my @friends = get_friends_list($logindata);
print STDERR "Fetching friends userpics...\n";
# Read their userpics into a hash.
my %info = %{get_friendspics(@friends)};
# Print a summary page to stdout.
<!DOCTYPE html
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd"
>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" >
<title></title>
</head>
<body bgcolor="white" text="black" link="blue" vlink="purple" alink="red">
HTML
for my $friend (keys %info) {
<br clear="all">
<h3><a href="/users/$friend">$friend</a></h3>
<br clear="all">
HTML
for my $url (@{$info{$friend}}) {
print "<img src=\"$url\">\n";
}
}
</body>
</html>
HTML
# Done.
# Take a hashref of login data, return an array of friends usernames.
sub get_friends_list {
my $response = $client->send_request(
RPC::XML::request->new('LJ.XMLRPC.getfriends',$logindata));
die_if_rpc_fault($response);
my @friends = map { $_->{'username'} }
@{$response->value->{'friends'}};
}
# Take an RPC::XML response, and check if it contains a fault.
# If so, print some diagnostics and die.
sub die_if_rpc_fault {
if ($response->is_fault) {
die("Unable to login:\n".
"faultString=\"". $response->value->{'faultString'} ."\"\n".
"faultCode=\"". $response->value->{'faultCode'} ."\"\n");
}
}
# Take an LJ username; fetch their userpics page,
# screenscrape it for their userpics.
# Return an array containing userpic URLs.
sub get_userpics {
my $picsurl = "/allpics.bml?user=$username";
my $picspage = get
($picsurl) or die("Unable to fetch $picsurl");
my $stream = HTML::TokeParser->new(\$picspage);
my $class='';
my @urls = ();
# Find <span class="heading">.
while ( ($class ne 'heading') &&
(my $nexttag = $stream->get_tag("span"))) {
my ($tag,$attr,$attrseq,$text) = @$nexttag;
$class = $attr->{'class'} || '';
}
}
# Now find all img tags.
while ( my $nexttag = $stream->get_tag("img")) {
my ($tag,$attr,$attrseq,$text) = @$nexttag;
if (defined(my $url = $attr->{'src'})) {
if ($url =~ /userpic/) {
}
}
}
}
}
# Take a list of Lj usernames.
# Return a reference to a hash, each key of which is an LJ username.
# Each value is a reference to an array containing the URLs
# of their userpics.
sub get_friendspics {
my %info = ();
print STDERR "Fetching $_ ...\n";
$info{$_} = [ get_userpics($_) ] } @_;
}