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