#!/usr/bin/perl ########################################################################### # google_rss.cgi: # Render a Google search as RSS # # Maintained by l.m.orchard http://www.decafbad.com # # 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, published at # http://www.gnu.org/copyleft/gpl.html ########################################################################### use strict; use lib qw( /home/deusx/lib/perl /home/deusx/lib/perl/i386-linux ); use Data::Dumper qw(Dumper); use Net::Google; use XML::RSS; use LWP::Simple; use CGI; use MD5; use vars qw( $google_key ); ### Global config my $HOME = "/www/www.decafbad.com/data"; #my $HOME = "/Users/deus_x/Sites"; my $cache_dir = "$HOME/services_cache"; require "$HOME/google_key.pl"; # Sorry, you don't get my Google API key. :) ### Initialize my $q = new CGI(); ### Get parameters from URL query my %params; my @query = $q->param("query") || (qw(google apis)); $params{query} = \@query; $params{key} = $q->param("key") || $google_key; $params{title} = $q->param("title") || "Google APIs"; $params{link} = $q->param("link") || "http://www.google.com/apis"; $params{description} = $q->param("description") || "Top 10 Google hits for Google APIs"; $params{pubDate} = $q->param("pubdate") || scalar(localtime()); $params{webmaster} = $q->param("webmaster") || "deus_x\@pobox.com"; $params{rss_version} = $q->param("rss_version") || "1.0"; $params{cache_age} = $q->param("cache_age") || "3600"; ### Come up with a cache filename which changes based on changes in ### supplied options. This is a big ugly hack. Suggestions welcome. my $cache_signature = join (":", ($params{key}, (join(" ", @{$params{query}})), $params{title}, $params{link}, $params{description}, $params{webmaster}) ); ### Perform & display the results my $out = perform_with_cache(\%params, \&google_to_rss, $cache_dir, $cache_signature); print $q->header("-content-type", "text/xml"); print $out; exit (0); ########################################################################### sub google_to_rss { my $params = shift; my $google = Net::Google->new(key=>$params->{key}); my $search = $google->search(); $search->query(@{$params->{query}}); $search->lr(qw(en)); $search->ie("utf8"); $search->oe("utf8"); my $rss = new XML::RSS (version => $params->{rss_version}); $rss->channel ( title => $params->{title}, link => $params->{link}, description => $params->{description}, ); foreach my $result (@{$search->results()}) { $rss->add_item ( title => $q->escapeHTML($result->title()), link => $q->escapeHTML($result->URL()), description => $q->escapeHTML($result->snippet()) ); } return $rss->as_string(); } ########################################################################### sub perform_with_cache { my ($params, $sub_to_perform, $cache_dir, $cache_signature) = @_; my $cache_fn = "$cache_dir/".MD5->hexhash($cache_signature); #my $cache_fn = "$cache_dir/".CGI::escape($cache_signature); my $cache_modtime = (stat($cache_fn))[9]; ### If the cached file is too old, re-render my $out; if ( (time() - $cache_modtime) > $params->{cache_age} ) { $cache_modtime = time(); $out = $sub_to_perform->($params); unlink($cache_fn); open(FOUT, ">$cache_fn"); print FOUT $out; close(FOUT); } ### If cache not too old, just use the cached rendering else { local $/ = undef; open(FIN, "$cache_fn"); $out = ; close(FIN); } return $out; }