#!/usr/bin/perl -w # # A perl script which chooses a random image from the internet to display in your X background. # The image is sourced by using a google query consisting random selection of keywords , # choosing a suitable page from the results and choosing an image from the page. # # This works well with the image stretched and with transparent terminal windows , maybe add a cronjob. # You should need no other setup than to make the /tmp/goggle directory writeable to the current user # and X user. # # I got the idea from a script called blink by someone called dave which did the same kind of thing # way back when altavista was a search engine worth using . so props to dave , google , London.pm , # all the perlmongers who monged the modules and anyone who ever wrote a silly program. # # Copyright (C) 2004 Amias channer # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # # Please send feedback , patches and offers of well paid Perl programming work but no pie. # ########################## # OPTIONS ########################## # DEBUG #my $DEBUG = 0; # silent #my $DEBUG = 1; # spew keywords only #my $DEBUG = 2; # spew urls #my $DEBUG = 3; # spew image urls #my $DEBUG = 4; # tell you everything that is happening # set the default debug level when no value is supplied my $DEBUG = 3; # GOOGLE # # your google api key , get a free one from www.google.com/apis my $key = 'get your own !'; # the maximum amount of results to fetch , keep this high to increase your chances of a good image. my $result_count = 30; # prepend this to the search terms to remove certain formats with out image links my $crank = '-pdf -pdf -doc -ppt -words -xls -lyx -tex -txt'; # AGENT # # make your goggle pretend to be another browser , you should use a known browser string or some # sites may refuse to serve you webpages with images ) my $agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020"; # WORD LIST # # the location of a file containing a list of words to choose randomly my $word_list ='/usr/share/dict/words'; #'/home/amias/.xchat/xchatlogs/#london.pm.xchatlog'; # the amount of random words to use my $word_count = 2; # IMAGE DISPLAY # # This command line will be run to set the background image and will have a filename appended in quotes. my $command_line = "gconftool-2 -t string -s /desktop/gnome/background/picture_filename"; # GNOME #my $command_line = "xsetroot "; # Looping # # How often in seconds to loop the program or 0 not too loop at all , override with -l seconds my $LOOP = 0; ######################### # CODE STARTS HERE ######################### if ($DEBUG == 4) { print "Loading Modules:" }; use strict; use DBI; use Data::Dumper; use Data::Random::WordList; use Net::Google::Search; use LWP::UserAgent; use HTML::LinkExtor; use URI::URL; use File::Temp qw/ tempdir tempfile /; if ($DEBUG == 4) { print " Done \n" }; my @rand_words; print "Before overrides : D=$DEBUG \t L=$LOOP \n"; # override with command line vars foreach my $value (@ARGV) { if ($value =~ m/^\-d/) { $DEBUG = substr($value,2) }; if ($value =~ m/^\-l/) { $LOOP = substr($value,2) }; if ($value !~ m/^\-/ ) { unshift @rand_words , $value }; } print "After overrides : D=$DEBUG \t L=$LOOP \t ".join(',',@rand_words)."\n"; my (@imgs,@uniq_images); my $filename; my ($wl,$search,$ua); my $quit = 'no'; while ($quit eq 'no') { # get random words if needed if ( $#rand_words < 0 ){ $wl = new Data::Random::WordList( wordlist => $word_list ); @rand_words = $wl->get_words($word_count); $wl->close(); } print "Using ".join(' , ',@rand_words)."\n" if ($DEBUG > 0); # apply hacks to force html pages unshift @rand_words,$crank; if ($DEBUG == 4) { print "Querying Google:" }; # look them up via google $search = Net::Google::Search->new( { key => $key, max_results => $result_count,} ) or die('error creating search object'); $search->query(@rand_words); if ($DEBUG == 4) { print "Done \n" }; if ($DEBUG == 4) { print "Loading LWP:" }; # create LWP agent $ua = LWP::UserAgent->new; $ua->agent($agent); if ($DEBUG == 4) { print "Done \n" }; # loop through the results foreach my $result (@{$search->results()}) { # get the url for the current result my $url = $result->URL() || 'null'; # allow only a few known html docs or / if ( $url =~ m/(html|htm|asp|pl|cgi)/ || $url =~ m/\/$/ ) { print "Got URL: $url \n" if ($DEBUG > 1); # declare storage for images and callback routine sub callback { my($tag, %attr) = @_; return if $tag ne 'img'; # we only look closer at push(@imgs, values %attr); } if ($DEBUG == 4) { print "Parsing Url:$url" }; # Make the parser. my $p = HTML::LinkExtor->new(\&callback); # Request document and parse it as it arrives my $res = $ua->request(HTTP::Request->new(GET => $url), sub {$p->parse($_[0])} ); # get url base my $base = $res->base; if ($DEBUG == 4) { print "Done \n" }; print "Got images $#imgs:\n" if ($DEBUG >2); # list , dedupe and expand urls images my %seen; foreach my $image (@imgs) { $seen{$image}++; print "scanning \t $image (".$seen{$image}.") " if ($DEBUG >2); unless ($seen{$image} > 2 || $image =~ m/( spacer|clear|icon|arrow|banner|pixel|symbol|1x1|htm| mast|\?|brand|trans|logo|nav|shim|menu|line|top| bottom|button|\#|dot|zip|xml|w3c|adgo )/ix ) { push(@uniq_images, url($image,$base)->abs); print "\t passed" if ($DEBUG >2); } print "\n" if ($DEBUG >2); } if ($#imgs ne -1) { last; }; } else { print "$url doesn't look like HTML - skipping\n" if ($DEBUG >1); } } # randomize the order of the image array for (my $i = @uniq_images; --$i;) { my $j = int rand ($i+1); next if ($i == $j || $i < 0); my $temp = $uniq_images[$i]; $uniq_images[$i] = $uniq_images[$j]; $uniq_images[$j] = $temp; } my $image_file; # try downloading an image , if not do the next foreach my $image (@uniq_images) { print "using $image \n" if ($DEBUG > 1); # download image to temp location my $getimage = $ua->request(HTTP::Request->new(GET => $image)); if ($getimage->content) { my ($fh,$filename) = tempfile( DIR=>'/tmp/goggle'); # make the tempfile configurable print $fh $getimage->content or (next); close $fh or (next); print "wrote to ".$filename."\n" if ($DEBUG > 0); $image_file = $filename; last; } } # now load image on to x background system "$command_line \"$image_file\""; if ($LOOP > 0) { print "sleeping for $LOOP \n"; # null the random words in preperation for next loop $#rand_words = 0; # undef the google object to keep it fresh $search = undef; sleep ($LOOP); } else { $quit= 'yes'; } }