File Coverage

blib/lib/Mojo/YR.pm
Criterion Covered Total %
statement 6 49 12.2
branch 0 18 0.0
condition 0 10 0.0
subroutine 2 8 25.0
pod 4 4 100.0
total 12 89 13.4


line stmt bran cond sub pod time code
1             package Mojo::YR;
2              
3             =head1 NAME
4              
5             Mojo::YR - Get weather information from yr.no
6              
7             =head1 DESCRIPTION
8              
9             L is an (a)synchronous weather data fetcher for the L
10             framework. The backend for weather data is L.
11              
12             Look at the resources below for mere information about the API:
13              
14             =over 4
15              
16             =item * L
17              
18             =item * L
19              
20             =item * L
21              
22             =item * L
23              
24             =back
25              
26             =head1 SYNOPSIS
27              
28             use Mojo::YR;
29             my $yr = Mojo::YR->new;
30              
31             # Fetch location_forecast ==========================================
32             my $now = $yr->location_forecast([59, 10])->find('pointData > time')->first;
33             my $temp = $now->at('temperature');
34              
35             warn "$temp->{value} $temp->{unit}";
36              
37             # Fetch text_forecast ==============================================
38             my $today = $yr->text_forecast->children('time')->first;
39             my $hordaland = $today->at('area[name="Hordaland"]');
40              
41             warn $hordaland->at('header')->text;
42             warn $hordaland->at('in')->text; # "in" holds the forecast text
43              
44             =cut
45              
46 4     4   82835 use Mojo::Base -base;
  4         20  
  4         28  
47 4     4   2398 use Mojo::UserAgent;
  4         657654  
  4         36  
48              
49             our $VERSION = '0.06';
50              
51             =head1 ATTRIBUTES
52              
53             =head2 url_map
54              
55             $hash_ref = $self->url_map;
56              
57             Returns the URL used to fetch data.
58              
59             Note: These will always be pointers to the current version. If you require a
60             specific version, set it manually. Note: YR have short deprecation cycles.
61              
62             Default:
63              
64             {
65             location_forecast => 'http://api.yr.no/weatherapi/locationforecast/1.9/',
66             text_forecast => 'http://api.yr.no/weatherapi/textforecast/1.6/',
67             };
68              
69             =cut
70              
71             has url_map => sub {
72             my $self = shift;
73              
74             return {
75             location_forecast => 'http://api.met.no/weatherapi/locationforecast/1.9/',
76             text_forecast => 'http://api.met.no/weatherapi/textforecast/1.6/',
77             text_location_forecast => 'http://api.met.no/weatherapi/textlocation/1.0/',
78             sunrise => 'http://api.met.no/weatherapi/sunrise/1.1/',
79             };
80             };
81              
82             has _ua => sub {
83             Mojo::UserAgent->new;
84             };
85              
86             =head1 METHODS
87              
88             =head2 location_forecast
89              
90             $self = $self->location_forecast([$latitude, $longitude], sub { my($self, $err, $dom) = @_; ... });
91             $self = $self->location_forecast(\%args, sub { my($self, $err, $dom) = @_; ... });
92             $dom = $self->location_forecast([$latitude, $longitude]);
93             $dom = $self->location_forecast(\%args);
94              
95             Used to fetch
96             L.
97              
98             C<%args> is required (unless C<[$latitude,$longitude]> is given):
99              
100             {
101             latitude => $num,
102             longitude => $num,
103             }
104              
105             C<$dom> is a L object you can use to query the result.
106             See L for example.
107              
108             =cut
109              
110             sub location_forecast {
111 0     0 1   my ($self, $args, $cb) = @_;
112 0           my $url = Mojo::URL->new($self->url_map->{location_forecast});
113              
114 0 0         if (ref $args eq 'ARRAY') {
115 0           $args = {latitude => $args->[0], longitude => $args->[1]};
116             }
117 0 0         if (2 != grep { defined $args->{$_} } qw( latitude longitude )) {
  0            
118 0           return $self->$cb('latitude and/or longitude is missing', undef);
119             }
120              
121 0           $url->query([lon => $args->{longitude}, lat => $args->{latitude},]);
122              
123 0           $self->_run_request($url, $cb);
124             }
125              
126             =head2 text_location_forecast
127              
128             $self = $self->text_location_forecast([$latitude, $longitude], sub { my($self, $err, $dom) = @_; ... });
129             $self = $self->text_location_forecast(\%args, sub { my($self, $err, $dom) = @_; ... });
130             $dom = $self->text_location_forecast([$latitude, $longitude]);
131             $dom = $self->text_location_forecast(\%args);
132              
133             Used to fetch
134             L.
135              
136             C<%args> is required (unless C<[$latitude,$longitude]> is given):
137              
138             {
139             latitude => $num,
140             longitude => $num,
141             language => 'nb', # default
142             }
143              
144             C<$dom> is a L object you can use to query the result.
145             See L for example.
146              
147             =cut
148              
149             sub text_location_forecast {
150 0     0 1   my ($self, $args, $cb) = @_;
151 0           my $url = Mojo::URL->new($self->url_map->{text_location_forecast});
152              
153 0 0         if (ref $args eq 'ARRAY') {
154 0           $args = {latitude => $args->[0], longitude => $args->[1]};
155             }
156 0 0         if (2 != grep { defined $args->{$_} } qw( latitude longitude )) {
  0            
157 0           return $self->$cb('latitude and/or longitude is missing', undef);
158             }
159 0   0       $args->{language} ||= 'nb';
160              
161 0           $url->query($args);
162              
163 0           $self->_run_request($url, $cb);
164             }
165              
166              
167             =head2 text_forecast
168              
169             $dom = $self->text_forecast(\%args);
170             $self = $self->text_forecast(\%args, sub { my($self, $err, $dom) = @_; ... });
171              
172             Used to fetch
173             L.
174              
175             C<%args> is optional and has these default values:
176              
177             {
178             forecast => 'land',
179             language => 'nb',
180             }
181              
182             C<$dom> is a L object you can use to query the result.
183             See L for example.
184              
185             =cut
186              
187             sub text_forecast {
188 0 0   0 1   my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
189 0           my $self = shift;
190 0   0       my $args = shift || {};
191 0           my $url = Mojo::URL->new($self->url_map->{text_forecast});
192              
193             $url->query(
194             [
195             forecast => $args->{forecast} || 'land',
196 0   0       language => $args->{language} || 'nb',
      0        
197             ]
198             );
199              
200 0           $self->_run_request($url, $cb);
201             }
202              
203             =head2 sunrise
204              
205             $dom = $self->sunrise(\%args);
206             $self = $self->sunrise(\%args, sub { my($self, $err, $dom) = @_; ... });
207              
208             Used to fetch
209             L
210              
211             C<%args> is required
212              
213             {
214             lat => $num,
215             lon => $num,
216             date => 'YYYY-MM-DD', # OR
217             from => 'YYYY-MM-DD',
218             to => 'YYYY-MM-DD',
219             }
220              
221             C<$dom> is a L object you can use to query the result.
222             See L for example.
223              
224             =cut
225              
226             sub sunrise {
227 0 0   0 1   my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
228 0           my $self = shift;
229 0   0       my $args = shift || {};
230 0           my $url = Mojo::URL->new($self->url_map->{sunrise});
231              
232 0           $url->query($args);
233              
234 0           $self->_run_request($url, $cb);
235             }
236              
237             sub _run_request {
238 0     0     my ($self, $url, $cb) = @_;
239              
240 0 0         if (!$cb) {
241 0           my $tx = $self->_ua->get($url);
242 0 0         die scalar $tx->error if $tx->error;
243 0           return $tx->res->dom->children->first;
244             }
245              
246 0           Scalar::Util::weaken($self);
247             $self->_ua->get(
248             $url,
249             sub {
250 0     0     my ($ua, $tx) = @_;
251 0           my $err = $tx->error;
252              
253 0 0         return $self->$cb($err, undef) if $err;
254 0           return $self->$cb('', $tx->res->dom->children->first)
255             ; # is the first element. don't want that
256             },
257 0           );
258              
259 0           return $self;
260             }
261              
262             =head1 COPYRIGHT AND LICENSE
263              
264             Copyright (C) 2014 Jan Henning Thorsen
265              
266             This program is free software, you can redistribute it and/or modify it under
267             the terms of the Artistic License version 2.0.
268              
269             =head1 AUTHOR
270              
271             Jan Henning Thorsen - C
272             Marcus Ramberg - C
273              
274             =cut
275              
276             1;