mirror of
				https://github.com/pragma-/pbot.git
				synced 2025-10-31 06:37:35 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # File: Weather.pm
 | |
| # Author: pragma-
 | |
| #
 | |
| # Purpose: Weather command.
 | |
| 
 | |
| # This Source Code Form is subject to the terms of the Mozilla Public
 | |
| # License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
| # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | |
| 
 | |
| package Plugins::Weather;
 | |
| 
 | |
| use warnings;
 | |
| use strict;
 | |
| 
 | |
| use feature 'unicode_strings';
 | |
| 
 | |
| use PBot::Utils::LWPUserAgentCached;
 | |
| use XML::LibXML;
 | |
| use Getopt::Long qw(GetOptionsFromString);
 | |
| use Carp ();
 | |
| 
 | |
| sub new {
 | |
|   Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH';
 | |
|   my ($class, %conf) = @_;
 | |
|   my $self = bless {}, $class;
 | |
|   $self->initialize(%conf);
 | |
|   return $self;
 | |
| }
 | |
| 
 | |
| sub initialize {
 | |
|   my ($self, %conf) = @_;
 | |
|   $self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
 | |
|   $self->{pbot}->{commands}->register(sub { $self->weathercmd(@_) },  "weather", 0);
 | |
| }
 | |
| 
 | |
| sub unload {
 | |
|   my $self = shift;
 | |
|   $self->{pbot}->{commands}->unregister("weather");
 | |
| }
 | |
| 
 | |
| sub weathercmd {
 | |
|   my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_;
 | |
| 
 | |
|   my $usage = "Usage: weather [-u <user account>] [location]";
 | |
|   Getopt::Long::Configure("bundling");
 | |
| 
 | |
|   my $getopt_error;
 | |
|   local $SIG{__WARN__} = sub {
 | |
|     $getopt_error = shift;
 | |
|     chomp $getopt_error;
 | |
|   };
 | |
| 
 | |
|   my ($user_override, $show_usage);
 | |
|   my ($ret, $args) = GetOptionsFromString($arguments,
 | |
|     'u=s' => \$user_override,
 | |
|     'h' => \$show_usage
 | |
|   );
 | |
| 
 | |
|   return $usage if $show_usage;
 | |
|   return "/say $getopt_error -- $usage" if defined $getopt_error;
 | |
|   $arguments = "@$args";
 | |
| 
 | |
|   my $hostmask = defined $user_override ? $user_override : "$nick!$user\@$host";
 | |
|   my $location_override = $self->{pbot}->{users}->get_loggedin_user_metadata($from, $hostmask, 'location') // '';
 | |
|   $arguments = $location_override if not length $arguments;
 | |
| 
 | |
|   if (defined $user_override and not length $location_override) {
 | |
|     return "No location set or user account does not exist.";
 | |
|   }
 | |
| 
 | |
|   if (not length $arguments) {
 | |
|     return $usage;
 | |
|   }
 | |
| 
 | |
|   return $self->get_weather($arguments);
 | |
| }
 | |
| 
 | |
| sub get_weather {
 | |
|   my ($self, $location) = @_;
 | |
| 
 | |
|   my %cache_opt = (
 | |
|     'namespace' => 'accuweather',
 | |
|     'default_expires_in' => 3600
 | |
|   );
 | |
| 
 | |
|   my $ua = PBot::Utils::LWPUserAgentCached->new(\%cache_opt, timeout => 10);
 | |
|   my $response = $ua->get("http://rss.accuweather.com/rss/liveweather_rss.asp?metric=0&locCode=$location");
 | |
| 
 | |
|   my $xml;
 | |
|   if ($response->is_success) {
 | |
|     $xml = $response->decoded_content;
 | |
|   } else {
 | |
|     return "Failed to fetch weather data: " . $response->status_line;
 | |
|   }
 | |
| 
 | |
|   my $dom = XML::LibXML->load_xml(string => $xml);
 | |
| 
 | |
|   my $result = '';
 | |
| 
 | |
|   foreach my $channel ($dom->findnodes('//channel')) {
 | |
|     my $title = $channel->findvalue('./title');
 | |
|     my $description = $channel->findvalue('./description');
 | |
| 
 | |
|     if ($description eq 'Invalid Location') {
 | |
|       return "Location $location not found. Use \"<city>, <country abbrev>\" (e.g. \"paris, fr\") or a US Zip Code or \"<city>, <state abbrev>, US\" (e.g., \"austin, tx, us\").";
 | |
|     }
 | |
| 
 | |
|     $title =~ s/ - AccuW.*$//;
 | |
|     $result .= "Weather for $title: ";
 | |
|   }
 | |
| 
 | |
|   foreach my $item ($dom->findnodes('//item')) {
 | |
|     my $title = $item->findvalue('./title');
 | |
|     my $description = $item->findvalue('./description');
 | |
| 
 | |
|     if ($title =~ m/^Currently:/) {
 | |
|       $title = $self->fix_temps($title);
 | |
|       $result .= "$title; ";
 | |
|     }
 | |
| 
 | |
|     if ($title =~ m/Forecast$/) {
 | |
|       $description =~ s/ <img.*$//;
 | |
|       $description = $self->fix_temps($description);
 | |
|       $result .= "Forecast: $description";
 | |
|       last;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return $result;
 | |
| }
 | |
| 
 | |
| sub fix_temps {
 | |
|   my ($self, $text) = @_;
 | |
|   $text =~ s|(-?\d+)\s*F|my $f = $1; my $c = ($f - 32 ) * 5 / 9; $c = sprintf("%.1d", $c); "${f}F/${c}C"|eg;
 | |
|   return $text;
 | |
| }
 | |
| 
 | |
| 1;
 | 
