use strict; use warnings; use LWP::Simple; use HTML::TableExtract; use Sort::Versions; use MIME::Lite; # A few configuration variables... my $datafile = 'gpsdata.dat'; my $website = 'http://www.garmin.com/support/download.jsp'; my $mailfrom = 'your@return.address'; my $email_notify = 'Yes'; my $mailto = 'notification@email.address'; my $mailhost = 'smtp.host.net'; my @devices = ( 'GPSMAP 76', 'MapSource' ); my %found_device; { # Pull in the webpage... my $raw_html = get( $website ); # For testing, save the webpage as 'garmin.htm', comment out the # preceeding line, and uncomment the following six lines. This # will test against the saved version rather than hitting # the remote site. # my $raw_html = do { # open my $in, '<', 'garmin.htm' # or die "Can't open infile: $!\n"; # local $/ = undef; # <$in>; # }; # Define which tables to search. my $te = new HTML::TableExtract( headers => [ 'Product\s+Name', 'Software\s+Version', 'Compatible\s+with\s+Versions', 'Date' ] ); $te->parse($raw_html); # Find and keep track of the applicable entries. my $find_devices = join '|', @devices; my $re_devices = qr/$find_devices/; foreach my $ts ( $te->table_states ) { foreach my $row ( $ts->rows ) { s/^\s+// foreach @{$row}; s/\s+$// foreach @{$row}; $found_device{ $row->[0] } = [ @$row ] if $row->[0] =~ /^(?:$re_devices)$/i; } } } # Check for and pull in previous-run data. my %prev_device = (); if ( -e $datafile ) { open my $dat, '<', $datafile or die "Couldn't open input file: $!\n"; while ( my $line = <$dat> ) { chomp $line; my @row = split /\s*\|\s*/, $line; $prev_device{ $row[0] } = [ @row ]; } close $dat; } # Compare site data with stored data. my @changed; foreach my $key ( keys %found_device ) { push @changed, $key if ( ( not defined $prev_device{$key} ) or versioncmp( $prev_device{$key}[1], $found_device{$key}[1] ) == -1 ); } # We're done if there are no updates available. unless ( @changed ) { print "No updates available at $website.\n"; exit; } # If updates, print results and, send an email message. my $out_text = "Download from $website:\n"; foreach ( @changed ) { $out_text .= "Upgrade available for $_: " . " version $found_device{$_}[1], " . "$found_device{$_}[3]\n"; } print $out_text; # Email stuff. if ( $email_notify =~ /^y/i ) { my $msg = MIME::Lite->new( 'From' => $mailfrom, 'To' => $mailto, 'Subject' => "[Upgrade] Updates available for " . do { local $" = ', '; "@changed"; } . ".", 'Data' => $out_text ); # This line is for us Windows folks. MIME::Lite->send( 'smtp', $mailhost, 'Timeout' => 60 ); $msg->send(); } # Save updates to data file. open my $fh, '>', $datafile or die "Can't write update to $datafile: $!\n"; foreach my $key ( keys %found_device ) { local $" = '|'; print $fh "@{$found_device{$key}}\n"; } close $fh or die "Can't close $datafile after update: $!\n";