aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2019-06-30 09:11:34 +0100
committerGitHub <noreply@github.com>2019-06-30 09:11:34 +0100
commit6805b5f91bb1f110a9037990dbf1c13dbb60d8d0 (patch)
tree428605d908afcb12a69a6c4e58acce59c4d62c08
parent6a24a097a6e3c06a6b3acfe93a0a2158a90925d9 (diff)
parent923471af31e396031329be4fcf6cec904b97bd1a (diff)
downloadperlweeklychallenge-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-xchallenge-014/joelle-maslak/perl5/ch-3.pl149
-rwxr-xr-xchallenge-014/joelle-maslak/perl6/ch-3.p6129
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;
+ }
+ }
+}
+