diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2019-06-30 09:11:34 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-06-30 09:11:34 +0100 |
| commit | 6805b5f91bb1f110a9037990dbf1c13dbb60d8d0 (patch) | |
| tree | 428605d908afcb12a69a6c4e58acce59c4d62c08 | |
| parent | 6a24a097a6e3c06a6b3acfe93a0a2158a90925d9 (diff) | |
| parent | 923471af31e396031329be4fcf6cec904b97bd1a (diff) | |
| download | perlweeklychallenge-club-6805b5f91bb1f110a9037990dbf1c13dbb60d8d0.tar.gz perlweeklychallenge-club-6805b5f91bb1f110a9037990dbf1c13dbb60d8d0.tar.bz2 perlweeklychallenge-club-6805b5f91bb1f110a9037990dbf1c13dbb60d8d0.zip | |
Merge pull request #316 from jmaslak/joelle-14-3-1
Solve 14.3 in P6 and P5
| -rwxr-xr-x | challenge-014/joelle-maslak/perl5/ch-3.pl | 149 | ||||
| -rwxr-xr-x | challenge-014/joelle-maslak/perl6/ch-3.p6 | 129 |
2 files changed, 278 insertions, 0 deletions
diff --git a/challenge-014/joelle-maslak/perl5/ch-3.pl b/challenge-014/joelle-maslak/perl5/ch-3.pl new file mode 100755 index 0000000000..43951a61dd --- /dev/null +++ b/challenge-014/joelle-maslak/perl5/ch-3.pl @@ -0,0 +1,149 @@ +#!/usr/bin/env perl +use v5.26; +use strict; +use warnings; + +# Turn on method signatures +use feature 'signatures'; +no warnings 'experimental::signatures'; + +use autodie; +use Getopt::Long; +use JSON::PP; +use Mojo::Util qw(url_escape); +use Mojo::UserAgent; +use Path::Tiny; +use Perl6::Slurp; +use Term::Choose qw(choose); + +MAIN: { + my $configfile = path( $ENV{HOME} // "", ".rapidapi" )->stringify(); + my $url_time = 'https://wft-geo-db.p.rapidapi.com/v1/geo/cities/_CITY_/time'; + my $url_lookup = 'https://wft-geo-db.p.rapidapi.com/v1/geo/cities?namePrefix=_CITY_'; + GetOptions( + "url-time=s" => \$url_time, + "url-lookup=s" => \$url_lookup, + "config-file=s" => \$configfile, + ); + + if ( @ARGV != 1 ) { die("Must specify one city to look up"); } + my $city = $ARGV[0]; + + my $apikey = get_api_key($configfile); + + if ($city =~ m/^ [0-9]+ \z/msxx) { + display_time($city, $apikey, $url_time); + } else { + my ($info) = get_city( + apikey => $apikey, + urlbase => $url_lookup, + city => $ARGV[0], + ); + + if (scalar($info) == 0) { + say "No results"; + } elsif (scalar($info) == 1) { + display_time($info->[0]{id}, $apikey, $url_time); + } else { + my %tableinfo; + my (@table); + for my $row ($info->@*) { + my $line = "(" . $row->{id} . ") " . $row->{city} . ", " . + $row->{regionCode} . ", " . $row->{countryCode}; + push @table, $line; + $tableinfo{$line} = $row->{id}; + } + my $selected = choose( \@table ); + if (! defined $selected ) { + say "No city selected"; + exit; + } + display_time($tableinfo{$selected}, $apikey, $url_time); + } + } +} + +sub display_time($city_id, $apikey, $url) { + my $time = get_time( + apikey => $apikey, + urlbase => $url, + city_id => $city_id, + ); + if (defined $time) { + say "Current time: $time"; + } else { + say "No results"; + } +} + +sub get_api_key($configfile) { + my (@lines) = grep { length($_) } slurp($configfile); + die "Config-file ($configfile) must consist of one line" if @lines != 1; + chomp $lines[0]; + return $lines[0]; +} + +# Usage: +# apikey = Your API key +# urlbase = Base URL +# city = City ID to look up +# +sub get_city(%args) { + my $url = $args{urlbase}; + $url =~ s/_CITY_/url_escape( $args{city} )/eg; + + my $ua = Mojo::UserAgent->new(); + $ua->max_redirects(16); + $ua->once( + start => sub ( $ua, $tx ) { + $tx->req->headers->header( 'X-Mashape-Key' => $args{apikey} ); + } + ); + + my $tx = $ua->get($url); + if ( ( $tx->result->code >= 200 ) && ( $tx->result->code <= 299 ) ) { + my $json = $tx->result->json; + if ( exists( $json->{data} ) ) { + return $json->{data}; + } else { + say "Could not fetch info from API"; + } + return; + } + + my $body = $tx->result->json; + die "Error from API endpoint: " . $body->{errors}[0]{message}; +} + +# Usage: +# apikey = Your API key +# urlbase = Base URL +# city_id = City ID to look up +# +sub get_time(%args) { + my $url = $args{urlbase}; + $url =~ s/_CITY_/url_escape( $args{city_id} )/eg; + + my $ua = Mojo::UserAgent->new(); + $ua->max_redirects(16); + $ua->once( + start => sub ( $ua, $tx ) { + $tx->req->headers->header( 'X-Mashape-Key' => $args{apikey} ); + } + ); + + my $tx = $ua->get($url); + if ( ( $tx->result->code >= 200 ) && ( $tx->result->code <= 299 ) ) { + my $json = $tx->result->json; + if ( exists( $json->{data} ) ) { + return $json->{data}; + } else { + say "Could not fetch info from API"; + } + return; + } + + my $body = $tx->result->json; + die "Error from API endpoint: " . $body->{errors}[0]{message}; +} + diff --git a/challenge-014/joelle-maslak/perl6/ch-3.p6 b/challenge-014/joelle-maslak/perl6/ch-3.p6 new file mode 100755 index 0000000000..f6ad7790f3 --- /dev/null +++ b/challenge-014/joelle-maslak/perl6/ch-3.p6 @@ -0,0 +1,129 @@ +#!/usr/bin/env perl6 +use v6; + +use Cro::HTTP::Client; +use Terminal::Table; +use URI::Encode; + +multi sub MAIN( + Int $city-id, + Str:D :$config-file? = $*HOME.add(".rapidapi").Str, + Str:D :$url-time = 'https://wft-geo-db.p.rapidapi.com/v1/geo/cities/_CITY_/time', +) { + my $info = get-time(:$city-id, :url($url-time), :$config-file); + if $info.defined { + say "Current time: $info"; + } else { + say "No results"; + } +} + +multi sub MAIN( + Str:D $city, + Str:D :$config-file? = $*HOME.add(".rapidapi").Str, + Str:D :$url-time = 'https://wft-geo-db.p.rapidapi.com/v1/geo/cities/_CITY_/time', + Str:D :$url-lookup = 'https://wft-geo-db.p.rapidapi.com/v1/geo/cities?namePrefix=_CITY_', +) { + my $lookup = get-city(:$city, :url($url-lookup), :$config-file); + if $lookup<data>.elems == 0 { + die("City not found"); + } elsif $lookup<data>.elems == 1 { + MAIN($lookup<data>[0]<id>, :$config-file, :$url-time); + } else { + say "There is more than one city that matches. Please use the City ID"; + say ""; + + my @table; + @table.push: ["City ID", "City", "Region", "Country"]; + for @($lookup<data>) -> $row { + @table.push: [ + $row<id>.Str, + $row<city>, + $row<regionCode>, + $row<countryCode>, + ]; + } + print-table(@table); + } +} + +sub get-api-key(Str:D $config-file -->Str:D) { + my @lines = $config-file.IO.lines().grep( *.chars > 0 ); + die "Config-file ($config-file) must consist of one line" if @lines.elems ≠ 1; + + return @lines.first; +} + +# Usage: +# :$city-id = City ID to look up +# :$url = base URL +# :$config-file = Name of config file to use +# +sub get-city ( + Str:D :$city, + Str:D :$url, + Str:D :$config-file, +) { + my $api-key = get-api-key($config-file); + + my $client = Cro::HTTP::Client.new( + base-uri => $url, + headers => [ X-Mashape-Key => $api-key ], + ); + + my $fetch-url = S:g/_CITY_/{uri_encode_component($city)}/ given $url; + + my $resp = await $client.get($fetch-url); + my $json = await $resp.body; + + if $json<data>:exists { + return $json<data>; + } else { + return; + } + + CATCH { + when X::Cro::HTTP::Error { + my $body = await .response.body; + die "Error from API endpoint: $body<message>"; + } + } +} + +# Usage: +# :$city-id = City ID to look up +# :$url = base URL +# :$config-file = Name of config file to use +# +sub get-time ( + Int:D() :$city-id, + Str:D :$url, + Str:D :$config-file, +) { + my $api-key = get-api-key($config-file); + + my $client = Cro::HTTP::Client.new( + base-uri => $url, + headers => [ X-Mashape-Key => $api-key ], + ); + + my $fetch-url = S:g/_CITY_/{uri_encode_component($city-id.Str)}/ given $url; + + my $resp = await $client.get($fetch-url); + my $json = await $resp.body; + + if $json<data>:exists { + return $json<data>; + } else { + return; + } + + CATCH { + when X::Cro::HTTP::Error { + my $body = await .response.body; + $*ERR.say("Error from API endpoint: $body<errors>[0]<message>"); + exit; + } + } +} + |
