#!/usr/bin/perl -w # Copyright © 2005 Jay R. Wren . # Copyright © 2001, 2002, 2003, 2004 Jamie Zawinski . # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation. No representations are made about the suitability of this # software for any purpose. It is provided "as is" without express or # implied warranty. # # This started off ax xscreensaver-getimage-file by JWZ. # # Modified by JRW to be a flickr client # # This program attempts to locate a random image from the specified flickr user, group, or just a public flickr image. # # vim :set foldmethod=indent # # Created 20-Feb-05 require 5; use diagnostics; use strict; use Flickr::API; use LWP::UserAgent; use File::Temp (); my $FLICKRKEY = 'PUTKEYHERE'; my $progname = $0; $progname =~ s@.*/@@g; my $version = q{ $Revision: 1.15 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/; my $verbose = 0; # These are programs that can be used to put an image file on the root # window (including virtual root windows.) The first one of these programs # that exists on $PATH will be used (with the file name as the last arg.) # # If you add other programs to this list, please let me know! # my @programs = ( "chbg -once -xscreensaver -max_grow 4 -max_size 100", "xv -root -quit -viewonly -maxpect +noresetroot -quick24 -rmode 5" . " -rfg black -rbg black", "xli -quiet -fullscreen -onroot -center -border black", "xloadimage -quiet -fullscreen -onroot -center -border black", # this lame program wasn't built with vroot.h: # "xsri -scale -keep-aspect -center-horizontal -center-vertical", ); # http://www.flickr.com/services/api/misc.urls.html # Photo URLs # You can construct the url of a photo once you know it's id, server id and secret, as returned by many api methods. # The url takes the following format: # http://photos{server-id}.flickr.com/{id}_{secret}.jpg # or # http://photos{server-id}.flickr.com/{id}_{secret}_[mstb].jpg # or # http://photos{server-id}.flickr.com/{id}_{secret}_o.(jpg|gif|png) # Size Suffixes # The letter suffixes are as follows: # s small square 75x75 # t thumbnail, 100 on longest side # m small, 240 on longest side # - medium, 500 on longest side # b large, 1024 on longest side (only exists for very large original images) # o original image, either a jpg, gif or png, depending on source format # Example # http://photos2.flickr.com/1418878_1e92283336_m.jpg # server-id: 2 # photo-id: 1418878 # secret: 1e92283336 # size: m sub pick_displayer { my @names = (); foreach my $cmd (@programs) { $_ = $cmd; my ($name) = m/^([^ ]+)/; push @names, "\"$name\""; print STDERR "$progname: looking for $name...\n" if ($verbose > 2); foreach my $dir (split (/:/, $ENV{PATH})) { print STDERR "$progname: checking $dir/$name\n" if ($verbose > 3); return $cmd if (-x "$dir/$name"); } } $names[$#names] = "or " . $names[$#names]; printf STDERR "$progname: none of: " . join (", ", @names) . " were found on \$PATH.\n"; exit 1; } my @urls; sub find_all_images { my ($user) = @_; my $flickrapi = new Flickr::API({'key' => $FLICKRKEY}); my $response = $flickrapi->execute_method('flickr.people.findByUsername', { 'username' => $user, }); my $nsid = $response->{tree}->{children}->[1]->{attributes}->{nsid}; $response = $flickrapi->execute_method('flickr.people.getPublicPhotos', { 'user_id' => $nsid, }); foreach my $element (@{$response->{tree}->{children}->[1]->{children}}) { next if( ($element->{type}) eq 'data'); my $photo = $element->{attributes}; #foreach my $attr (qw{owner title server secret id}) #{ # print $photo->{$attr}."\t"; #} #implement size options for mstb push @urls, "http://photos".$photo->{server}.".flickr.com/".$photo->{id}."_".$photo->{secret}.".jpg"; } } sub get_temp_image { my ($url) = @_; my $ua = LWP::UserAgent->new; $ua->agent("xscreensaver-getimage-flickr/0.1"); my $req = HTTP::Request->new(GET=>$url); my $res = $ua->request($req); if ( $res->is_success ) { my $fh = new File::Temp(UNLINK=>0, SUFFIX=>'.jpg'); print $fh $res->content; return $fh->filename; } else { print STDERR "could not GET $url\n"; exit 2; } } sub find_random_image { my ($user) = @_; find_all_images ($user); #@urls = sort(@urls); if ($#urls < 0) { print STDERR "$progname: no photos for $user\n"; exit 1; } my $n = int (rand ($#urls + 1)); my $url = $urls[$n]; print STDERR "$progname: chose image $n: $url\n" if ($verbose > 1); my $file = get_temp_image($url); return $file; } sub display_file { my ($file, $displayer) = @_; if (!defined($displayer)) { print STDOUT "$file\n"; } else { my @cmd = split (/ +/, $displayer); push @cmd, $file; # do it this way to allow file names with spaces. print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n" if ($verbose); exec (@cmd) || die; } } sub find_and_display { my ($user, $displayer) = @_; my $file = find_random_image ($user); display_file ($file, $displayer); } sub usage { print STDERR "usage: $progname [--verbose] [--name] flickr-username\n\n" . " Puts the given image file from a randomly selected image from the\n" . " flickr photo on the root window. If --name is specified,\n" . " just prints the selected filename to stdout instead.\n\n"; exit 1; } sub main { my $user = undef; my $do_name = 0; while ($_ = $ARGV[0]) { shift @ARGV; if ($_ eq "--verbose") { $verbose++; } elsif (m/^-v+$/) { $verbose += length($_)-1; } elsif ($_ eq "--name") { $do_name++; } elsif (m/^-./) { usage; } elsif (!defined($user)) { $user = $_; } else { usage; } } usage unless (defined($user)); my $displayer = undef; $displayer = pick_displayer() unless $do_name; find_and_display ($user, $displayer); } main; exit 0;