File Coverage

blib/lib/WebService/Livedoor/Weather.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package WebService::Livedoor::Weather;
2              
3 3     3   119219 use strict;
  3         7  
  3         106  
4 3     3   18 use warnings;
  3         4  
  3         73  
5 3     3   1064 use utf8;
  3         17  
  3         17  
6 3     3   68 use Carp;
  3         4  
  3         256  
7 3     3   1844 use Encode;
  3         29083  
  3         304  
8 3     3   3000 use URI::Fetch;
  3         429004  
  3         109  
9 3     3   4235 use XML::Simple;
  0            
  0            
10             use JSON 2;
11             our $VERSION = '0.10';
12              
13             use constant BASE_URI => $ENV{LDWEATHER_BASE_URI} || 'http://weather.livedoor.com';
14             use constant ENDPOINT_URI => $ENV{LDWEATHER_ENDPOINT_URI} || BASE_URI. '/forecast/webservice/json/v1';
15             use constant FORECASTMAP_URI => $ENV{LDWEATHER_FORECASTMAP_URI} || BASE_URI. '/forecast/rss/primary_area.xml';
16              
17             sub new {
18             my ( $class, %args ) = @_;
19             $args{fetch} ||= {};
20             $args{fetch} = {
21             %{$args{fetch}},
22             UserAgent => LWP::UserAgent->new( agent => __PACKAGE__.'/'.$VERSION )
23             };
24             bless \%args,$class;
25             }
26              
27             sub get {
28             my ($self, $city) = @_;
29             croak('city is required') unless $city;
30             my $cityid = $self->__get_cityid($city);
31              
32             my $res = URI::Fetch->fetch(ENDPOINT_URI. "?city=$cityid", %{$self->{fetch}});
33             croak("Cannot get weather information : " . URI::Fetch->errstr) unless $res;
34              
35             return $self->__parse_forecast($res->content);
36             }
37              
38             sub __parse_forecast {
39             my ($self, $json) = @_;
40             my $ref;
41             eval{$ref = decode_json($json)};
42             croak('Oops! failed reading weather information : ' . $@) if $@;
43              
44             ### temperature fixing for null case
45             for ( @{$ref->{forecasts}} ) {
46             ref $_->{temperature}{max}{celsius} and $_->{temperature}{max}{celsius} = undef;
47             ref $_->{temperature}{min}{celsius} and $_->{temperature}{min}{celsius} = undef;
48             ref $_->{temperature}{max}{fahrenheit} and $_->{temperature}{max}{fahrenheit} = undef;
49             ref $_->{temperature}{min}{fahrenheit} and $_->{temperature}{min}{fahrenheit} = undef;
50             }
51              
52             return $ref;
53             }
54              
55             sub __get_cityid {
56             my ($self,$city) = @_;
57             $city =~ /^\d+$/ ? $city : $self->__forecastmap->{$city} or croak('Invalid city name. cannot find city id with '. $city);
58             }
59              
60             sub __forecastmap {
61             my $self = shift;
62             unless ($self->{forecastmap}) {
63             my $res = URI::Fetch->fetch(FORECASTMAP_URI, %{$self->{fetch}});
64             croak("Couldn't get forecastmap: " . URI::Fetch->errstr) unless $res;
65             $self->{forecastmap} = $self->__parse_forecastmap($res->content);
66             }
67             return $self->{forecastmap};
68             }
69              
70             sub __parse_forecastmap {
71             my ($self, $str) = @_;
72              
73             my $ref = eval {
74             local $XML::Simple::PREFERRED_PARSER = 'XML::Parser';
75             XMLin($str, ForceArray => [qw[pref area city]]);
76             };
77             if ($@) {
78             local $Carp::CarpLevel = 1;
79             croak('Oops! failed reading forecastmap: '. $@);
80             }
81             my %forecastmap;
82             foreach my $pref ( @{$ref->{channel}{'ldWeather:source'}{pref}} ){
83             $forecastmap{$pref->{city}{$_}{title}} = $_ for keys %{$pref->{city}};
84             }
85             return \%forecastmap;
86             }
87              
88             1;
89             __END__