package WebService::ForecastIo; use Moo; use 5.10.0; use Types::Standard -types,'slurpy'; use Type::Utils -all; use Types::URI 'Uri'; use Types::DateTime 'DateTimeT'; use Type::Params; use WebService::ForecastIo::Response; use DateTime::TimeZone; use namespace::autoclean; has base_uri => ( is => 'ro', isa => Uri, default => 'https://api.forecast.io/forecast', coerce => Uri->coercion, ); has api_key => ( is => 'ro', isa => Str, required => 1, ); has user_agent => ( is => 'lazy', isa => duck_type(['get']), ); 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; } my $units_type = enum [qw(us si ca uk auto)]; my $block_type = enum [qw(currently minutely hourly daily alerts flags sources)]; sub request { state $argcheck = compile( Object, Dict[ latitude => Num, longitude => Num, time => Optional[DateTimeT], units => Optional[$units_type], exclude => Optional[ArrayRef[$block_type]], raw => Optional[Bool], ], ); my ($self,$opts) = $argcheck->(@_); $opts->{units} //= 'si'; $opts->{exclude} //= []; $opts->{raw} //= 0; my $uri = $self->_make_request_uri({%$opts}); my $response = $self->user_agent->get($uri); if ($response->is_success) { my $json = $response->decoded_content; return $json if $opts->{raw}; my $res = WebService::ForecastIo::Response->new($json); return wantarray ? ($res,$json) : $res } else { die $response->status_line } } 1;