package WebService::ForecastIo;
use Moo;
use 5.10.0;
use Types::Standard -types,'slurpy';
use Types::URI 'Uri';
use Types::DateTime -all;
use Type::Params;
use Future::AsyncAwait;
use WebService::ForecastIo::Response;
use DateTime::TimeZone;
use namespace::clean;
has base_uri => (
is => 'ro',
isa => Uri,
default => 'https://api.pirateweather.net/forecast',
coerce => Uri->coercion,
);
has api_key => (
is => 'ro',
isa => Str,
required => 1,
);
has user_agent => (
is => 'ro',
isa => HasMethods['do_request'],
required => 1,
);
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)];
async sub request {
state $argcheck = compile(
Object, Dict[
latitude => Num,
longitude => Num,
time => Optional[DateTimeUTC],
units => Optional[$units_type],
exclude => Optional[ArrayRef[$block_type]],
],
);
my ($self,$opts) = $argcheck->(@_);
$opts->{units} //= 'si';
$opts->{exclude} //= [];
my $uri = $self->_make_request_uri({%$opts});
my $response = await $self->user_agent->do_request(uri => $uri);
if ($response->is_success) {
my $json = $response->decoded_content;
return WebService::ForecastIo::Response->new($json);
}
else {
die $response->status_line;
}
}
1;