#!/usr/bin/perl use strict; use Flickr::API; use Data::Dumper; use LWP::UserAgent; use Tk; use Tk::ProgressBar; use Tk::ROText; use Tk::Balloon; use Tk::DialogBox; # Put your Flickr key here: use constant API_KEY => 'xxx'; use constant PER_PAGE => 500; use constant PAGE => 1; use constant DEBUG => 0; my $flickrId; my $percent_done; printf "Starting application...\n"; my $mainWindow = MainWindow->new(-title => 'KodeGeek.com: Download Flickr public pictures'); $mainWindow->geometry('+500+300'); # Create a simple menu my $menu = $mainWindow->Frame()->pack(-side => 'top', -fill => 'x'); my $filemenu = $menu->Menubutton( -text => 'File', -underline => 0 )->pack(-side => 'left'); $filemenu->command( -label => 'Quit', -underline => 0, -accelerator => 'Meta+Q', -command => \&quit ); my $frame = $mainWindow->Frame()->pack(-side => 'bottom', -fill => 'both'); # Create the main window contents. Use more frames to align the components my $topFrame = $frame->Frame()->pack(-side => 'top', -fill => 'both'); my $label = $topFrame->Label( -text => 'Flickr user ID' )->pack(-side => "left")->pack(); my $text = $topFrame->Entry( -textvariable => \$flickrId )->pack(-side => "right", -fill => "x", -expand => 'x')->pack(); my $bText = $mainWindow->Balloon(); $bText->attach($text,-balloonmsg => "Please, type the Flickr ID with public photos"); my $textArea = $frame->Scrolled( 'ROText', -width => 60, -height => 30 )->pack(-side => "bottom", -fill => "y")->pack(); my $download = $frame->Button( -text => 'Download pictures', -command => [\&getPhotos, \$flickrId, $mainWindow, $textArea, $text] )->pack(-side => "bottom", -fill => "x")->pack(-padx=>15, -pady=>15); my $dBaloom = $mainWindow->Balloon(); $dBaloom->attach($download,-balloonmsg => "Click here to download the photos!"); MainLoop(); # Quit the app sub quit() { $mainWindow->destroy(); printf "Exiting application...\n"; exit; } # Get the public photos from Flickr sub getPhotos { my $id = ${$_[0]}; my $mainWindow = $_[1]; my $textArea = $_[2]; $mainWindow->update(); my $api = new Flickr::API({ 'key' => API_KEY} ); my $ua = LWP::UserAgent->new; # Get the user NSID first my $response = $api->execute_method( 'flickr.people.findByUsername', { 'username' => $id }); if (! $response->{success}) { $textArea->insert('end', sprintf "[ERROR]: %s (%s)\n", $response->{error_message}, $id); return; } $download->configure(-state => 'disabled'); $filemenu->configure(-state => 'disabled'); $text->configure(-state => 'disabled'); $text->delete('1.0', 'end'); # Parse the tree and get the NSID my %tree = %{$response->{tree}}; # Cheat with 'print Dumper($tree);' to get the value I want right away my $id = $tree{children}->[1]->{attributes}->{nsid}; if (DEBUG) { printf "%s\n", $id; } # Get now the list of public photos $response = $api->execute_method( 'flickr.photos.search', { 'user_id' => $id }); %tree = %{$response->{tree}}; # Get the photo information. For that we get a more manageable structure my @subtree = @{$tree{children}->[1]->{children}}; if (DEBUG) { print Dumper(\@subtree); } my $position = 0; # Collect the real list of URL to download: my %urlList = (); # Get the list of photos $textArea->insert('end', "Getting list of photos from Flickr\n"); $mainWindow->update(); foreach my $ref (@subtree) { my $attributes = $$ref{attributes}; next if $attributes == undef; # Construct the URL like this: # http://photos{server-id}.flickr.com/{id}_{secret}_o.(jpg|gif|png) my $url = "http://photos" . $$attributes{'server'} . ".flickr.com/" . $$attributes{'id'} . "_" . $$attributes{'secret'} . "_o.jpg"; $urlList{$url}->{DEST} = $$attributes{'id'} . "_" . $$attributes{'secret'} . "_o.jpg"; $urlList{$url}->{TITLE} = $$attributes{'title'}; } # end for-each $textArea->insert('end', sprintf "Preparing to download %d photos.\n",scalar(keys %urlList)); $mainWindow->update(); for my $url (keys %urlList) { $textArea->insert('end', sprintf "%s -> %s...", $urlList{$url}->{TITLE}, $url); $ua->mirror($url, $urlList{$url}->{DEST}); if ($response->is_success) { $textArea->insert('end', sprintf "OK\n"); } else { $textArea->insert('end', sprintf "ERROR\n"); } $mainWindow->update(); } $filemenu->configure(-state => 'normal'); $download->configure(-state => 'normal'); $text->configure(-state => 'normal'); } __END__ =head1 NAME flickr_download_public_pic.pl - A program that downloads all the public pictures for a given user, from Flickr.com =head1 DESCRIPTION This program uses the API as described in 'http://www.flickr.com/services/api/', and uses the Perl module Flickr::API (http://search.cpan.org/~iamcal/Flickr-API/). =head1 AUTHOR Jose Vicente Nunez Zuleta =head1 BLOG KodeGeek - http://kodegeek.com =head1 LICENSE GPL =cut