Scripts archive: Weather script

#
# weather.pl v0.1
# Fetch weather information for given city from FMI (Finnish Meteorological Institute).
# Returns always weather information for Helsinki if given city not found.
# Works ONLY with cities in Finland. Usage: !saa <city> (eg. !saa Turku).
# by Teemu Ikonen 4/2010 - http://iconen.org - teemu@iconen.org
#

use LWP::Simple;
use HTML::Entities;

OerPerl::add_command_handler("saa", "oer_weather_cmd");

sub oer_weather_cmd
{
    my($command, $target, $nick, $userhost, $args) = @_;
    my $tochan = OerPerl::is_valid_channel($target) ? 1 : 0;
    my $target_type = $tochan ? OerPerl::CHANNEL : OerPerl::USER;
    my($temp, $place, $details);

    $temp = get "http://www.fmi.fi/saa/paikalli.html?place=" . ucfirst $args;

    if(defined $temp) {
	# Decode html entities to plain characters.
        $_ = decode_entities($temp);
        chomp;
        
	# Trying to find city's measure point from <option> element (= given city has several measure points).
	m/\<option value=\"\d+\" selected=\"selected\"\>(([a-z\xE4\xF6]+)\s([a-z\xE4\xF6\.\s\W]+))\<\/option\>/i;
	
	if (!defined $2) {
		# Not found - only one measure point for given city, so grab it's name.
		m/\<p class=\"station-description\"\>(([a-z\xE4\xF6]+)\s([a-z\xE4\xF6\.\s\W]+))\</i;
		# Set city and measure point name to variable.
		$place = trim(encode_entities($2)) . " (" . trim(encode_entities($3)) . ")";
	} else {
		# Several measure points found, set city and first measure point name to variable.
		$place = trim(encode_entities($2)) . " (" . trim(encode_entities($3)) . ")";
	}

	# Trying to find weather information.
	m/\<p class=\"observation-text\"\>(.*)\<\/p\>/;

	if (defined $1) {
		# Weather information found, clean html tags etc.
		$details = $1;
		$details =~ s/Tuorein/tuorein/;
		$details =~ s/Suomen aikaa//;
		$details =~ s/\<[^\<]+\>//g;
	} else {
		# Not found, grab text for missing data and clean html tags etc.
		m/\<p class=\"missing-data\"\>([a-z\.\s\W]*)\<\/p\>/i;
		$details = $1;
		$details =~ s/Havainnot/havainnot/;
		$details =~ s/\<[^\<]+\>//g;
	}

	# We're finished, send weather information to user/channel if we have something to return.
	OerPerl::sendto($tochan ? $target : $nick, $target_type, "$place $details") if defined $place && $details;
    }
}

sub trim($)
{
	my $str = shift;
	$str =~ s/^(\s|\&nbsp;)+//;
	$str =~ s/(\s|\&nbsp;)+$//;
	return decode_entities($str);
}