File Coverage

blib/lib/Bot/Cobalt/Plugin/Weather.pm
Criterion Covered Total %
statement 16 114 14.0
branch 0 26 0.0
condition 0 4 0.0
subroutine 6 14 42.8
pod 0 8 0.0
total 22 166 13.2


line stmt bran cond sub pod time code
1             package Bot::Cobalt::Plugin::Weather;
2             $Bot::Cobalt::Plugin::Weather::VERSION = '0.002001';
3 1     1   21203 use List::Objects::WithUtils;
  1         3399  
  1         7  
4              
5 1     1   99873 use Bot::Cobalt;
  1         3163  
  1         6  
6 1     1   1906 use Bot::Cobalt::Common;
  1         235077  
  1         8  
7              
8 1     1   9598 use POE;
  1         138306  
  1         6  
9 1     1   75254 use POEx::Weather::OpenWeatherMap;
  1         4630127  
  1         2104  
10              
11 1     1 0 71 sub new { bless +{}, shift }
12              
13 0 0   0 0   sub pwx { $_[1] ? $_[0]->{pwx} = $_[1] : $_[0]->{pwx} }
14              
15             sub Cobalt_register {
16 0     0 0   my ($self, $core) = splice @_, 0, 2;
17              
18 0           POE::Session->create(
19             object_states => [
20             $self => [ qw/
21             _start
22              
23             pwx_error
24             pwx_weather
25             pwx_forecast
26             / ],
27             ],
28             );
29              
30 0           register( $self, SERVER =>
31             'public_cmd_wx',
32             );
33              
34 0           logger->info("Loaded: wx");
35              
36 0           PLUGIN_EAT_NONE
37             }
38              
39              
40             sub Cobalt_unregister {
41 0     0 0   my ($self, $core) = splice @_, 0, 2;
42 0           logger->info("Shutting down POEx::Weather::OpenWeatherMap ...");
43 0 0         $self->pwx->stop if $self->pwx;
44 0           logger->info("wx unloaded");
45 0           PLUGIN_EAT_NONE
46             }
47              
48              
49             sub _start {
50 0     0     my $self = $_[OBJECT];
51              
52 0           my $pcfg = core->get_plugin_cfg($self);
53 0           my $api_key = $pcfg->{API_Key};
54              
55 0 0         unless (defined $api_key) {
56 0           logger->warn(
57             "No 'API_Key' found in plugin configuration, continuing without"
58             )
59             }
60              
61             $self->pwx(
62 0 0         POEx::Weather::OpenWeatherMap->new(
63             ( defined $api_key ? (api_key => $api_key) : () ),
64             event_prefix => 'pwx_',
65             )
66             );
67              
68 0           $self->pwx->start;
69             }
70              
71             sub pwx_error {
72 0     0 0   my $self = $_[OBJECT];
73 0           my $err = $_[ARG0];
74 0           my $tag = $err->request->tag;
75              
76 0           logger->warn("POEx::Weather::OpenWeatherMap failure: $err");
77 0           broadcast(
78             message => $tag->context => $tag->channel =>
79             "wx: error: $err"
80             );
81             }
82              
83             sub pwx_weather {
84 0     0 0   my $self = $_[OBJECT];
85 0           my $res = $_[ARG0];
86 0           my $tag = $res->request->tag;
87              
88 0           my $place = $res->name;
89              
90 0           my $tempf = $res->temp_f;
91 0           my $tempc = $res->temp_c;
92 0           my $humid = $res->humidity;
93              
94 0           my $wind = $res->wind_speed_mph;
95 0           my $gust = $res->wind_gust_mph;
96 0           my $winddir = $res->wind_direction;
97              
98 0           my $terse = $res->conditions_terse;
99 0           my $verbose = $res->conditions_verbose;
100              
101 0           my $hms = $res->dt->hms;
102              
103 0           my $str = "$place at ${hms}UTC: ${tempf}F/${tempc}C";
104 0           $str .= " and ${humid}% humidity;";
105 0           $str .= " wind is ${wind}mph $winddir";
106 0 0         $str .= " gusting to ${gust}mph" if $gust;
107 0           $str .= ". Current conditions: ${terse}: $verbose";
108              
109 0           broadcast( message => $tag->context => $tag->channel => $str );
110             }
111              
112             sub pwx_forecast {
113 0     0 0   my $self = $_[OBJECT];
114 0           my $res = $_[ARG0];
115 0           my $tag = $res->request->tag;
116 0           my $place = $res->name;
117              
118 0           broadcast(
119             message => $tag->context => $tag->channel =>
120             "Forecast for $place ->"
121             );
122              
123 0 0         if ($res->hourly) {
124 0           my $itr = $res->iter(3);
125 0           for my $hr ($itr->()) {
126 0           my $date = $hr->dt->hms;
127 0           my $temp = $hr->temp;
128 0           my $temp_c = $hr->temp_c;
129              
130 0           my $terse = $hr->conditions_terse;
131 0           my $verbose = $hr->conditions_verbose;
132              
133 0           my $wind = $hr->wind_speed_mph;
134 0           my $winddir = $hr->wind_direction;
135              
136 0           my $rain = $hr->rain;
137 0           my $snow = $hr->snow;
138              
139 0           my $str = "${date}UTC: ${temp}F/${temp_c}C";
140 0           $str .= ", wind $winddir at ${wind}mph";
141 0           $str .= ", ${terse}: $verbose";
142 0 0         $str .= ", rain ${rain}in" if $rain;
143 0 0         $str .= ", snow ${snow}in" if $snow;
144 0           broadcast( message => $tag->context => $tag->channel => $str );
145             }
146             } else {
147 0           my $itr = $res->iter;
148 0           while (my $day = $itr->()) {
149 0           my $date = $day->dt->day_name;
150              
151 0           my $temp_hi_f = $day->temp_max_f;
152 0           my $temp_lo_f = $day->temp_min_f;
153 0           my $temp_hi_c = $day->temp_max_c;
154 0           my $temp_lo_c = $day->temp_min_c;
155              
156 0           my $terse = $day->conditions_terse;
157 0           my $verbose = $day->conditions_verbose;
158              
159 0           my $wind = $day->wind_speed_mph;
160 0           my $winddir = $day->wind_direction;
161              
162 0           my $str = "${date}: High of ${temp_hi_f}F/${temp_hi_c}C";
163 0           $str .= ", low of ${temp_lo_f}F/${temp_lo_c}C";
164 0           $str .= ", wind $winddir at ${wind}mph";
165 0           $str .= "; $terse: $verbose";
166              
167 0           broadcast( message => $tag->context => $tag->channel => $str );
168             }
169             }
170             }
171              
172              
173             sub Bot_public_cmd_wx {
174 0     0 0   my ($self, $core) = splice @_, 0, 2;
175 0           my $msg = ${ $_[0] };
  0            
176              
177 0           my ($location, $fcast, $hourly);
178 0           my @parts = @{ $msg->message_array };
  0            
179 0 0 0       if ( ($parts[0] || '') eq 'forecast' ) {
    0 0        
    0          
180 0           $location = join ' ', @parts[1 .. $#parts];
181 0           $fcast++
182             } elsif ( ($parts[0] || '') eq 'hourly' ) {
183 0           $location = join ' ', @parts[1 .. $#parts];
184 0           $hourly++;
185             } elsif (!@parts) {
186 0           broadcast( message => $msg->context => $msg->channel =>
187             $msg->src_nick . ": no location specified"
188             );
189 0           return PLUGIN_EAT_NONE
190             } else {
191 0           $location = join ' ', @parts
192             }
193              
194 0           my $tag = hash(
195             context => $msg->context,
196             channel => $msg->channel,
197             )->inflate;
198              
199 0 0         $self->pwx->get_weather(
    0          
200             location => $location,
201             tag => $tag,
202             ( $fcast ? (forecast => 1, days => 3) : () ),
203             ( $hourly ? (forecast => 1, hourly => 1, days => 1) : () ),
204             );
205              
206 0           PLUGIN_EAT_NONE
207             }
208              
209             1;
210              
211             =pod
212              
213             =head1 NAME
214              
215             Bot::Cobalt::Plugin::Weather - Weather retrieval plugin for Bot::Cobalt
216              
217             =head1 SYNOPSIS
218              
219             # In your plugins.conf:
220             WX:
221             Module: Bot::Cobalt::Plugin::Weather
222             Opts:
223             API_Key: "my OpenWeatherMap API key here"
224              
225             # On IRC:
226             > !wx Boston, MA
227             > !wx forecast Toronto, Canada
228             > !wx hourly Moscow, Russia
229              
230             =head1 DESCRIPTION
231              
232             A weather conditions/forecast retrieval plugin for L<Bot::Cobalt>.
233              
234             Uses L<http://www.openweathermap.org/> via L<POEx::Weather::OpenWeatherMap> /
235             L<Weather::OpenWeatherMap> for retrieval.
236              
237             =head1 AUTHOR
238              
239             Jon Portnoy <avenj@cobaltirc.org>
240              
241             =cut