#!/usr/bin/perl # vi:sw=4:ts=4:ai:cindent # $Id: bbc-weather-forecast,v 1.2 2009-08-05 08:15:09 dave Exp $ # Dave Holland use warnings; use strict; use utf8; use XML::RSS; use HTML::Entities qw(:DEFAULT encode_entities_numeric); use LWP::UserAgent; use Gtk2; use Glib qw(:constants); my $debug=1; # Cambridge = 1413 my $feed='http://feeds.bbc.co.uk/weather/feeds/rss/5day/id/1413.xml'; my $freq=60; # minutes between RSS fetches # http://backstage.bbc.co.uk/data/WeatherFeeds?v=151i says: # "Forecast data is fully updated at least twice a day, at # approximately 08:00 and 20:00 GMT. Minor updates can be made # throughout the day." Gtk2->init; my $window = Gtk2::Window->new ('toplevel'); $window->signal_connect (delete_event => sub { Gtk2->main_quit; 1; }); $window->set_title ('Weather Forecast'); # this is what to catch if # you use gnome-swallow-applet # FIXME it would be nice to be able to force an update by clicking somewhere my $hbox = Gtk2::HBox->new; $window->add($hbox); my $image = Gtk2::Image->new; $image->set_from_file("/usr/share/icons/gnome/24x24/stock/generic/stock_unknown.png"); $hbox->add($image); $window->show_all; Glib::Timeout->add($freq * 60 * 1000, \&update); update(); Gtk2->main; exit(0); ########################################## sub update { debug('updating at', scalar localtime); my $ua=LWP::UserAgent->new(timeout=>30, env_proxy=>1); my $response=$ua->get($feed); if(!$response->is_success) { # FIXME display this as a tooltip to an icon print STDERR "problem fetching $feed: ".$response->status_line." \n"; return TRUE; } my $rss=XML::RSS->new; eval { $rss->parse(encode_entities_numeric($response->content, "\200-\377")); }; if($@) { # FIXME display this as a tooltip to an icon print STDERR "problem parsing $feed: $@\n"; return TRUE; } # empty the window (hbox) and repopulate it based on the RSS feed $hbox->foreach( sub { $_[0]->destroy(); } ); my @items=@{$rss->{'items'}}; foreach my $item (@items) { my $ititle = decode_entities($item->{'title'} || "(untitled)"); $ititle =~ s/^\s+//; $ititle =~ s/\s+/ /g; my $f='stock_dialog-question'; # FIXME more parsing needed... these are not tested... # there's no documentation on what words/phrases are in use. if($ititle=~/fog/i) { $f='weather-fog'; } if($ititle=~/snow/i) { $f='weather-snow'; } if($ititle=~/storm/i) { $f='weather-storm'; } # these are tested and so override the above... if($ititle=~/light (rain|showers)/i) { $f='weather-showers-scattered'; } if($ititle=~/heavy (rain|showers)/i) { $f='weather-showers'; } if($ititle=~/sun/i) { $f='weather-clear'; } if($ititle=~/sunny interval/i) { $f='weather-few-clouds'; } if($ititle=~/cloudy/i) { $f='weather-overcast'; } my $file='/usr/share/icons/gnome/24x24/status/' . $f . '.png'; debug($ititle, "->", $f); my $image = Gtk2::Image->new; $image->set_from_file($file); my $ttip = Gtk2::Tooltips->new; $ttip->set_tip($image,$ititle); $hbox->add($image); } $window->show_all; # this is what we've got to choose from in "standard" Gnome... # the Debian package is "gnome-icon-theme" # /usr/share/icons/gnome/24x24/status/weather- * .png # clear-night # clear # few-clouds-night # few-clouds # fog # overcast # severe-alert # showers # showers-scattered # snow # storm } sub debug { return unless $debug; print STDERR join(" ",@_), "\n"; }