summaryrefslogtreecommitdiff
path: root/lib/WebService/ForecastIo.pm
blob: a2ef8ecdb16426318eb03d278df52c221cdec405 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package WebService::ForecastIo; 
use Moose;
use MooseX::Types::URI 'Uri';
use MooseX::Types::DateTime;
use MooseX::Params::Validate;
use Moose::Util::TypeConstraints;
use DateTime::Format::ISO8601;
use WebService::ForecastIo::Response;
 
has base_uri => (
    is => 'ro',
    isa => Uri,
    coerce => 1,
    default => 'https://api.forecast.io/forecast',
);
 
has api_key => (
    is => 'ro',
    isa => 'Str',
    required => 1,
);
 
has user_agent => (
    is => 'ro',
    isa => duck_type(['get']),
    lazy_build => 1,
);
sub _build_user_agent {
    require LWP::UserAgent;
    my $agent = LWP::UserAgent->new(
        agent => __PACKAGE__ . ' version ' . ($WebService::ForecastIo::VERSION // 'devel' ),
        env_proxy => 1,
        keep_alive => 1,
    );
    $agent->default_header( 'Accept-Encoding' => 'gzip' );
    return $agent;
}
 
sub _make_request_uri {
    my ($self,%opts) = @_;
 
    my ($lat,$lon,$time) = delete @opts{qw(latitude longitude time)};
 
    my $req_uri = $self->base_uri->clone;
 
    my $time_str;
    if ($time) {
        $time_str = $time->iso8601;
        my $tz = $time->time_zone;
        if ($tz->is_utc) { $time_str .= 'Z' }
        elsif (not $tz->is_floating) {
            $time_str .= DateTime::TimeZone->offset_as_string(
                $tz->offset_for_datetime($time)
            );
        }
    }
 
    $req_uri->path_segments(
        grep { length($_) }
            $req_uri->path_segments,
            $self->api_key,
            "$lat,$lon",
            $time_str,
        );
 
    if ($opts{exclude}) {
        $opts{exclude} = join ',',@{$opts{exclude}};
    }
 
    $req_uri->query_form(\%opts);
 
    return $req_uri;
}
 
enum my $units_type=__PACKAGE__.'::units',
    [qw(us si ca uk auto)];
enum my $block_type=__PACKAGE__.'::block',
    [qw(currently minutely hourly daily alerts flags)];
 
coerce 'DateTime', from 'Str',
    via {
        s{([+-])(\d\d)(\d\d)\z}{$1$2:$3};
        DateTime::Format::ISO8601->new->parse_datetime($_)
      };
 
sub request {
    my ($self,%opts) = validated_hash(
        \@_,
        latitude => { isa => 'Num' },
        longitude => { isa => 'Num' },
        time => { isa => 'DateTime'optional => 1, coerce => 1 },
        units => { isa => $units_typedefault => 'si' },
        exclude => { isa => "ArrayRef[$block_type]"default => sub { [] } },
    );
 
    my $uri = $self->_make_request_uri(%opts);
 
    my $response = $self->user_agent->get($uri);
    if ($response->is_success) {
        return WebService::ForecastIo::Response->new(
            $response->decoded_content,
        );
    }
    else {
        die $response->status_line
    }
}
 
1;