diff --git a/cpanfile b/cpanfile index 279950b..8b61669 100644 --- a/cpanfile +++ b/cpanfile @@ -1,5 +1,8 @@ requires 'Carp'; +requires 'CHI'; +requires 'CHI::Driver::BerkeleyDB'; requires 'Cwd::utf8'; +requires 'DateTime'; requires 'DB_File'; requires 'SQLite_File'; requires 'Digest::HMAC_SHA1'; @@ -10,7 +13,6 @@ requires 'File::Basename'; requires 'File::Path'; requires 'Hailo'; requires 'HTML::TokeParser'; -requires 'HTTP::Tiny'; requires 'IO::Socket::SSL'; requires 'JSON'; requires 'JSON::XS'; @@ -23,6 +25,7 @@ requires 'Math::Random::Secure'; requires 'Mojo::Base'; requires 'Mojo::IOLoop'; requires 'Mojo::UserAgent'; +requires 'Mojo::UserAgent::Cached'; requires 'Text::Fuzzy'; requires 'URI::Encode::XS'; requires 'URI::URL'; diff --git a/lib/buni.pm b/lib/buni.pm index 0b06b15..37352af 100644 --- a/lib/buni.pm +++ b/lib/buni.pm @@ -7,8 +7,8 @@ use utf8; use open qw (:std :utf8); use English qw ( -no_match_vars ); use Carp qw (cluck); -use HTTP::Tiny; use HTML::TokeParser; +use Mojo::UserAgent; use version; our $VERSION = qw (1.0); use Exporter qw (import); @@ -19,18 +19,18 @@ sub buni { my $ret = 'Нету Buni'; for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ('http://www.bunicomic.com/?random&nocache=1'); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + $r = $ua->get ('http://www.bunicomic.com/?random&nocache=1')->result; - if ($r->{success}) { + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { - my $p = HTML::TokeParser->new(\$r->{content}); + if ($r->is_success) { + my $p = HTML::TokeParser->new(\$r->body); my @a; # additional {} required in order "last" to work properly :) @@ -47,7 +47,7 @@ sub buni { } while ($#{$a[0]} > 1); } } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; } return $ret; diff --git a/lib/drink.pm b/lib/drink.pm index 734d749..f106810 100644 --- a/lib/drink.pm +++ b/lib/drink.pm @@ -5,11 +5,16 @@ use strict; use warnings; use utf8; use open qw (:std :utf8); +use CHI; +use CHI::Driver::BerkeleyDB; +use DateTime; use English qw ( -no_match_vars ); use Encode; use Carp qw (cluck); -use HTTP::Tiny; use HTML::TokeParser; +use Mojo::Log; +use Mojo::UserAgent::Cached; +use POSIX qw (strftime); use version; our $VERSION = qw (1.0); use Exporter qw (import); @@ -23,19 +28,56 @@ sub drink { my ($dayNum, $monthNum) = (localtime ())[3, 4]; my $url = sprintf 'https://kakoysegodnyaprazdnik.ru/baza/%s/%s', $MONTH[$monthNum], $dayNum; - for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ($url, {'Accept-Charset' => 'utf-8', 'Accept-Language' => 'ru-RU'}); + # Those POSIX assholes just forgot to add unix timestamps without TZ offset, so... + my ($mday, $mon, $year) = (gmtime ())[3, 4, 5]; + my $offset = strftime ('%z', gmtime ()); + my $offsetMinutes = (substr $offset, -2) * 60; + my $offsetHours = (substr $offset, 1, 2) * 60 * 60; + my $offsetSign; - if ($r->{success}) { + if ((substr $offset, 0, 1) eq '+') { + $offsetSign = 1; + } + + my $expirationDate = DateTime->new ( + year => $year + 1900, + month => $mon + 1, + day => $mday, + hour => 0, + minute => 0, + second => 0 + )->add (days => 1)->strftime ('%s'); + + if ((substr $offset, 0, 1) eq '+') { + $expirationDate = $expirationDate - $offsetHours - $offsetMinutes; + } else { + $expirationDate = $expirationDate + $offsetHours + $offsetMinutes; + } + + for (1..3) { + my $ua = Mojo::UserAgent::Cached->new->connect_timeout (3); + $ua->cache_agent( + CHI->new ( + driver => 'BerkeleyDB', + root_dir => 'data/cache', + namespace => __PACKAGE__, + expires_at => $expirationDate, + expires_on_backend => 1, + ) + ); + # just to make Mojo::UserAgent::Cached happy + $ua->logger (Mojo::Log->new (path => '/dev/null', level => 'error')); + $r = $ua->get ($url => {'Accept-Language' => 'ru-RU', 'Accept-Charset' => 'utf-8'})->result; + + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { - my $p = HTML::TokeParser->new(\$r->{content}); + if ($r->is_success) { + my $p = HTML::TokeParser->new(\$r->body); my @a; my @holyday; @@ -58,7 +100,7 @@ sub drink { $ret = join "\n", @holyday; } } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; } return $ret; diff --git a/lib/flickr.pm b/lib/flickr.pm index d38a99d..9212a17 100644 --- a/lib/flickr.pm +++ b/lib/flickr.pm @@ -9,10 +9,9 @@ use English qw ( -no_match_vars ); use Carp qw (cluck); use Digest::HMAC_SHA1 qw (hmac_sha1); use File::Path qw (make_path); -use JSON::XS; -use HTTP::Tiny; use Math::Random::Secure qw (irand); use MIME::Base64; +use Mojo::UserAgent; use SQLite_File; use URI::Encode::XS qw (uri_encode); @@ -120,15 +119,15 @@ sub flickrRequestToken { uri_encode ($flickr_callback_url) ); - my $http = HTTP::Tiny->new (timeout => 5); - my $r = $http->get ($url); + my $ua = Mojo::UserAgent->new->connect_timeout (5); + my $r = $ua->get ($url)->result; my %params; - if ($r->{success}) { + if ($r->is_success) { # they ignore format=json, so... - %params = map {split /=/} split /&/, $r->{content}; + %params = map {split /=/} split /&/, $r->body; } else { - say "Something bad returns from flickr api: $r->{status} $r->{content}"; ## no critic (InputOutput::RequireCheckedSyscalls) + say "Something bad returns from flickr api: $r->code $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls) } return %params; @@ -161,15 +160,15 @@ sub flickrAccessToken { uri_encode ($oauth_signature) ); - my $http = HTTP::Tiny->new (timeout => 5); - my $r = $http->get ($url); + my $ua = Mojo::UserAgent->new->connect_timeout (5); + my $r = $ua->get ($url)->result; my %params; - if ($r->{success}) { + if ($r->is_success) { # they ignore format=json - %params = map {split /=/} split /&/, $r->{content}; + %params = map {split /=/} split /&/, $r->body; } else { - say "Something bad returns from flickr api: $r->{status} $r->{content}"; ## no critic (InputOutput::RequireCheckedSyscalls) + say "Something bad returns from flickr api: $r->code $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls) } return %params; @@ -183,13 +182,13 @@ sub flickrAuthorization { $flickr_request_token, ); - my $http = HTTP::Tiny->new (timeout => 5); - my $r = $http->get ($url); + my $ua = Mojo::UserAgent->new->connect_timeout (5); + my $r = $ua->get ($url)->result; - if ($r->{success}) { - return $r->{url}; + if ($r->is_success) { + return $r->url; } else { - say "Something went wrong: $r->{status} $r->{content}"; ## no critic (InputOutput::RequireCheckedSyscalls) + say "Something went wrong: $r->code $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls) return; } } @@ -224,24 +223,23 @@ sub flickrTestLogin { uri_encode ($oauth_signature) ); - my $http = HTTP::Tiny->new (timeout => 5); - my $r = $http->get ($url); + my $ua = Mojo::UserAgent->new->connect_timeout (5); + my $r = $ua->get ($url)->result; - if ($r->{success}) { + if ($r->is_success) { my $response = eval { - my $j = JSON::XS->new->utf8->relaxed; - return $j->decode ($r->{content}); + return $r->json; }; if (defined $response) { say Dumper $response; ## no critic (InputOutput::RequireCheckedSyscalls) return 1; } else { - say "Flickr api returns incorrect json: $r->{content}"; ## no critic (InputOutput::RequireCheckedSyscalls) + say "Flickr api returns incorrect json: $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls) return 0; } } else { - say "HTTP status code not 200: $r->{status}, $r>{contenr}"; ## no critic (InputOutput::RequireCheckedSyscalls) + say "HTTP status code not 200: $r->code, $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls) return 0; } } @@ -282,13 +280,12 @@ sub flickrSearchByText { uri_encode ($text) ); - my $http = HTTP::Tiny->new (timeout => 5); - my $r = $http->get ($url); + my $ua = Mojo::UserAgent->new->connect_timeout (5); + my $r = $ua->get ($url)->result; - if ($r->{success}) { + if ($r->is_success) { my $response = eval { - my $j = JSON::XS->new->utf8->relaxed; - return $j->decode ($r->{content}); + return $r->json; }; if (defined $response) { @@ -326,31 +323,31 @@ sub flickrSearchByText { uri_encode ($text) ); - $http = HTTP::Tiny->new (timeout => 5); - $r = $http->get ($url); + $ua = Mojo::UserAgent->new->connect_timeout (5); + $r = $ua->get ($url)->result; - if ($r->{success}) { + + if ($r->is_success) { $response = eval { - my $j = JSON::XS->new->utf8->relaxed; - return $j->decode ($r->{content}); + return $r->json; }; if (defined $response) { return $response; } else { - cluck "Flickr api returns incorrect json: $r->{content}"; + cluck "Flickr api returns incorrect json: $r->message"; return undef; } } else { - cluck "Flickr api returns incorrect json: $r->{content}"; + cluck "Flickr api returns incorrect json: $r->message"; return undef; } } else { - cluck "Flickr api returns incorrect json: $r->{content}"; + cluck "Flickr api returns incorrect json: $r->message"; return undef; } } else { - cluck "HTTP status code not 200: $r->{status}, $r->{content}"; + cluck "HTTP status code not 200: $r->code, $r->message"; return undef; } } @@ -391,13 +388,12 @@ sub flickrSearchByTags { uri_encode ($tags) ); - my $http = HTTP::Tiny->new (timeout => 5); - my $r = $http->get ($url); + my $ua = Mojo::UserAgent->new->connect_timeout (5); + my $r = $ua->get ($url)->result; - if ($r->{success}) { + if ($r->is_success) { my $response = eval { - my $j = JSON::XS->new->utf8->relaxed; - return $j->decode ($r->{content}); + return $r->json; }; if (defined $response) { @@ -435,31 +431,30 @@ sub flickrSearchByTags { uri_encode ($tags) ); - $http = HTTP::Tiny->new (timeout => 5); - $r = $http->get ($url); + $ua = Mojo::UserAgent->new->connect_timeout (5); + $r = $ua->get ($url)->result; - if ($r->{success}) { + if ($r->is_success) { $response = eval { - my $j = JSON::XS->new->utf8->relaxed; - return $j->decode ($r->{content}); + return $r->json; }; if (defined $response) { return $response; } else { - cluck "Flickr api returns incorrect json: $r->{content}"; + cluck "Flickr api returns incorrect json: $r->message"; return undef; } } else { - cluck "Flickr api returns incorrect json: $r->{content}"; + cluck "Flickr api returns incorrect json: $r->message"; return undef; } } else { - cluck "Flickr api returns incorrect json: $r->{content}"; + cluck "Flickr api returns incorrect json: $r->message"; return undef; } } else { - cluck "HTTP status code not 200: $r->{status}, $r>{contenr}"; + cluck "HTTP status code not 200: $r->code, $r->message"; return undef; } } @@ -484,8 +479,8 @@ sub flickr_init { my $flickr_request_token_secret = $secret{flickr_request_token_secret}; unless (defined $flickr_request_token || defined $flickr_request_token_secret) { - say "Looks like there is no request token or request token secret in $backingfile"; - say "Please remove verifier settings from config.json and run this script again"; + say "Looks like there is no request token or request token secret in $backingfile"; ## no critic (InputOutput::RequireCheckedSyscalls) + say 'Please remove verifier settings from config.json and run this script again'; ## no critic (InputOutput::RequireCheckedSyscalls) untie %secret; return 0; } diff --git a/lib/image.pm b/lib/image.pm index 345825e..56fcdd1 100644 --- a/lib/image.pm +++ b/lib/image.pm @@ -8,9 +8,8 @@ use open qw (:std :utf8); use English qw ( -no_match_vars ); use Carp qw (cluck); use File::Path qw (make_path); -use JSON::XS; -use HTTP::Tiny; use Math::Random::Secure qw (irand); +use Mojo::UserAgent; use SQLite_File; use conf qw (loadConf); use flickr qw (flickr_by_tags); @@ -29,19 +28,19 @@ sub kitty { my $ret = 'Нету кошечек, все разбежались.'; for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ('https://api.thecatapi.com/v1/images/search'); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + $r = $ua->get ('https://api.thecatapi.com/v1/images/search')->result; - if ($r->{success}) { + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { + if ($r->is_success) { my $jcat = eval { - decode_json ($r->{content}) + return $r->json; }; unless (defined $jcat) { @@ -53,7 +52,7 @@ sub kitty { } } } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; } return $ret; @@ -64,19 +63,19 @@ sub fox { my $ret = 'Нету лисичек, все разбежались.'; for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ('https://randomfox.ca/floof/'); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + $r = $ua->get ('https://randomfox.ca/floof/')->result; - if ($r->{success}) { + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { + if ($r->is_success) { my $jfox = eval { - decode_json ($r->{content}) + return $r->json; }; unless (defined $jfox) { @@ -88,7 +87,7 @@ sub fox { } } } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; } return $ret; @@ -99,19 +98,19 @@ sub oboobs { my $ret = 'Нету cисичек, все разбежались.'; for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ('http://api.oboobs.ru/boobs/0/1/random'); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + $r = $ua->get ('http://api.oboobs.ru/boobs/0/1/random')->result; - if ($r->{success}) { + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { + if ($r->is_success) { my $joboobs = eval { - decode_json ($r->{content}) + return $r->json; }; unless (defined $joboobs) { @@ -123,7 +122,7 @@ sub oboobs { } } } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; } return $ret; @@ -134,19 +133,19 @@ sub obutts { my $ret = 'Нету попок, все разбежались.'; for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ('http://api.obutts.ru/butts/0/1/random'); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + $r = $ua->get ('http://api.obutts.ru/butts/0/1/random')->result; - if ($r->{success}) { + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { + if ($r->is_success) { my $jobutts = eval { - decode_json ($r->{content}) + return $r->json; }; unless (defined $jobutts) { @@ -158,7 +157,7 @@ sub obutts { } } } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; } return $ret; diff --git a/lib/imgur.pm b/lib/imgur.pm index 5739bdf..929639f 100644 --- a/lib/imgur.pm +++ b/lib/imgur.pm @@ -8,9 +8,8 @@ use open qw (:std :utf8); use English qw ( -no_match_vars ); use Carp qw (cluck); use File::Path qw (make_path); -use JSON::XS; -use HTTP::Tiny; use Math::Random::Secure qw (irand); +use Mojo::UserAgent; use SQLite_File; use conf qw (loadConf); @@ -30,7 +29,6 @@ sub imgur { my $refresh_url = 'https://api.imgur.com/oauth2/token'; my $search_url = 'https://api.imgur.com/3/gallery/search/'; - my $http = HTTP::Tiny->new (timeout => 5); # load all tokens from api secrets db my $backingfile = sprintf '%s/secrets.sqlite', $dir; @@ -62,20 +60,13 @@ sub imgur { } # query api - my $r = $http->get ( - $search_url . $tag, - { - headers => { - Authorization => "Bearer $imgur_access_token" - } - } - ); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + my $r = $ua->get ($search_url . $tag => {Authorization => "Bearer $imgur_access_token"})->result; # looks like we need to refresh token - if (($r->{status} == 401) || ($r->{status} == 403)) { - $r = $http->post_form ( - $refresh_url, - { + if (($r->code == 401) || ($r->code == 403)) { + $ua->post ( + $refresh_url => form { refresh_token => $imgur_refresh_token, client_id => $imgur_client_id, clinent_secret => $imgur_client_secret, @@ -83,13 +74,13 @@ sub imgur { } ); - unless ($r->{success}) { - cluck "Unable to refresh imgur token, please re-authorise app! or imgur experiencing api outage: $r->{status} $r->{content}"; + unless ($r->is_success) { + cluck "Unable to refresh imgur token, please re-authorise app! or imgur experiencing api outage: $r->code $r->message"; untie %secret; return undef; } - my $refresh = eval { decode_json $r->{content} }; + my $refresh = eval { return $r->json; }; if (defined $refresh) { $imgur_refresh_token = $refresh->{refresh_token}; @@ -103,20 +94,13 @@ sub imgur { } # query api again - $r = $http->get ( - $search_url . $tag, - { - headers => { - Authorization => "Bearer $imgur_access_token" - } - } - ); + $r = $ua->get ($search_url . $tag => {Authorization => "Bearer $imgur_access_token"})->result; } untie %secret; - if ($r->{success}) { - my $searchResult = eval { decode_json ($r->{content}) }; + if ($r->is_success) { + my $searchResult = eval { return $r->json; }; my @urls; if (defined $searchResult) { @@ -148,7 +132,7 @@ sub imgur { return undef; } } else { - cluck "Unable to get results from imgur api: $r->{content}"; + cluck "Unable to get results from imgur api: $r->message"; return undef; } } else { @@ -156,7 +140,7 @@ sub imgur { return undef; } } else { - cluck "Unable to get results from imgur api: $r->{status}, $r->{content}"; + cluck "Unable to get results from imgur api: $r->code, $r->message"; return undef; } } diff --git a/lib/monkeyuser.pm b/lib/monkeyuser.pm index 56fafdf..5688aac 100644 --- a/lib/monkeyuser.pm +++ b/lib/monkeyuser.pm @@ -7,9 +7,9 @@ use utf8; use open qw (:std :utf8); use English qw ( -no_match_vars ); use Carp qw (cluck); -use HTTP::Tiny; use HTML::TokeParser; use Math::Random::Secure qw (irand); +use Mojo::UserAgent; use version; our $VERSION = qw (1.0); use Exporter qw (import); @@ -21,18 +21,18 @@ sub monkeyuser { my @link; for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get ('https://www.monkeyuser.com/toc/'); + my $ua = Mojo::UserAgent->new->connect_timeout (3); + $r = $ua->get ('https://www.monkeyuser.com/toc/')->result; - if ($r->{success}) { + if ($r->is_success) { last; } sleep 2; } - if ($r->{success}) { - my $p = HTML::TokeParser->new(\$r->{content}); + if ($r->is_success) { + my $p = HTML::TokeParser->new(\$r->body); my @a; do { diff --git a/lib/weather.pm b/lib/weather.pm index 72f28ed..397dc65 100644 --- a/lib/weather.pm +++ b/lib/weather.pm @@ -7,11 +7,13 @@ use utf8; use open qw (:std :utf8); use English qw ( -no_match_vars ); use Carp qw (carp cluck); +use CHI; +use CHI::Driver::BerkeleyDB; use DB_File; use Digest::MD5 qw (md5_base64); use File::Path qw (make_path); -use HTTP::Tiny; -use JSON::XS; +use Mojo::Log; +use Mojo::UserAgent::Cached; use conf qw (loadConf); use util qw (trim urlencode); @@ -71,77 +73,53 @@ sub weather { sub __weather { my $city = shift; $city = urlencode $city; - my $id = md5_base64 $city; my $appid = $c->{openweathermap}->{appid}; my $cachedir = $c->{openweathermap}->{cachedir}; - my $cachetimefile = $cachedir . '/openweathermap.Id-Timestamp.db'; - my $cachedatafile = $cachedir . '/openweathermap.Id-Data.db'; my $now = time (); my $fc; my $w; - unless (-d $cachedir) { - make_path ($cachedir) || do { - cluck "[ERROR] Unable to create $cachedir: $OS_ERROR"; - return; + my $r; + + # try 3 times and giveup + for (1..3) { + my $ua = Mojo::UserAgent::Cached->new; + $ua->local_dir ($cachedir); + $ua->cache_agent( + CHI->new ( + driver => 'BerkeleyDB', + root_dir => $cachedir, + namespace => __PACKAGE__, + expires_in => '3 hours', + expires_on_backend => 1, + ) + ); + # just to make Mojo::UserAgent::Cached happy + $ua->logger (Mojo::Log->new (path => '/dev/null', level => 'error')); + $r = $ua->get (sprintf ('http://api.openweathermap.org/data/2.5/weather?q=%s&lang=ru&APPID=%s', $city, $appid))->result; + + if ($r->is_success) { + last; + } + + sleep 2; + } + + # all 3 times can give error, so check it here + if ($r->is_success) { + $fc = eval { + return $r->json; }; - } - # attach to cache data - tie my %cachetime, 'DB_File', $cachetimefile or do { - carp "[ERROR] Something nasty happen when cachetime ties to its data: $OS_ERROR"; - return undef; - }; - - tie my %cachedata, 'DB_File', $cachedatafile or do { - carp "[ERROR] Something nasty happen when cachedata ties to its data: $OS_ERROR"; - return undef; - }; - - # lookup cache - if (defined ($cachetime{$id}) && ($now - $cachetime{$id}) < 10800) { - $fc = decode_json $cachedata{$id}; - } else { - my $r; - - # try 3 times and giveup - for (1..3) { - my $http = HTTP::Tiny->new (timeout => 3); - $r = $http->get (sprintf ('http://api.openweathermap.org/data/2.5/weather?q=%s&lang=ru&APPID=%s', $city, $appid)); - - if ($r->{success}) { - last; - } - - sleep 2; - } - - # all 3 times can give error, so check it here - if ($r->{success}) { - $fc = eval { - decode_json $r->{content}; - }; - - if ($EVAL_ERROR) { - cluck "[WARN] openweathermap returns corrupted json: $EVAL_ERROR"; - untie %cachetime; - untie %cachedata; - return undef; - }; - - $cachetime{$id} = $now; - $cachedata{$id} = encode_json $fc; - } else { - cluck sprintf 'Server return status %s with message: %s', $r->{status}, $r->{reason}; - untie %cachetime; - untie %cachedata; + unless ($fc) { + cluck "[WARN] openweathermap returns corrupted json: $EVAL_ERROR"; return undef; - } + }; + } else { + cluck sprintf 'Server return status %s with message: %s', $r->code, $r->message; + return undef; } - untie %cachetime; - untie %cachedata; - # TODO: check all of this for existence $w->{'name'} = $fc->{name}; $w->{'state'} = $fc->{state}; diff --git a/lib/xkcd.pm b/lib/xkcd.pm index 7408900..e128a8d 100644 --- a/lib/xkcd.pm +++ b/lib/xkcd.pm @@ -5,18 +5,23 @@ use strict; use warnings; use utf8; use open qw (:std :utf8); -use HTTP::Tiny; +use Mojo::UserAgent; use version; our $VERSION = qw (1.0); use Exporter qw (import); our @EXPORT_OK = qw (xkcd); sub xkcd { - my $http = HTTP::Tiny->new (timeout => 5, max_redirect => 0); - my $r = $http->get ('https://xkcd.ru/random/'); + my $ua = Mojo::UserAgent->new->connect_timeout (5)->max_redirects (0); + my $r = $ua->get ('https://xkcd.ru/random/')->result; - if (defined $r->{headers} && defined $r->{headers}->{location} && $r->{headers}->{location} ne '') { - return sprintf '[xkcd.ru](https://xkcd.ru/i/%s_v1.png)', substr ($r->{headers}->{location}, 1, -1); + if ( + defined $r->content && + defined $r->content->headers && + defined $r->content->headers->location && + $r->content->headers->location ne '' + ) { + return sprintf '[xkcd.ru](https://xkcd.ru/i/%s_v1.png)', substr ($r->content->headers->location, 1, -1); } return 'Комикс-стрип нарисовать не так-то просто :(';