Replace HTTP::Tiny with Mojo::UserAgent and Mojo::UserAgent::Cached

This commit is contained in:
eleksir
2021-04-05 00:56:27 +03:00
parent b8fb89358e
commit 57dee8b168
9 changed files with 205 additions and 199 deletions

View File

@@ -1,5 +1,8 @@
requires 'Carp'; requires 'Carp';
requires 'CHI';
requires 'CHI::Driver::BerkeleyDB';
requires 'Cwd::utf8'; requires 'Cwd::utf8';
requires 'DateTime';
requires 'DB_File'; requires 'DB_File';
requires 'SQLite_File'; requires 'SQLite_File';
requires 'Digest::HMAC_SHA1'; requires 'Digest::HMAC_SHA1';
@@ -10,7 +13,6 @@ requires 'File::Basename';
requires 'File::Path'; requires 'File::Path';
requires 'Hailo'; requires 'Hailo';
requires 'HTML::TokeParser'; requires 'HTML::TokeParser';
requires 'HTTP::Tiny';
requires 'IO::Socket::SSL'; requires 'IO::Socket::SSL';
requires 'JSON'; requires 'JSON';
requires 'JSON::XS'; requires 'JSON::XS';
@@ -23,6 +25,7 @@ requires 'Math::Random::Secure';
requires 'Mojo::Base'; requires 'Mojo::Base';
requires 'Mojo::IOLoop'; requires 'Mojo::IOLoop';
requires 'Mojo::UserAgent'; requires 'Mojo::UserAgent';
requires 'Mojo::UserAgent::Cached';
requires 'Text::Fuzzy'; requires 'Text::Fuzzy';
requires 'URI::Encode::XS'; requires 'URI::Encode::XS';
requires 'URI::URL'; requires 'URI::URL';

View File

@@ -7,8 +7,8 @@ use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Carp qw (cluck); use Carp qw (cluck);
use HTTP::Tiny;
use HTML::TokeParser; use HTML::TokeParser;
use Mojo::UserAgent;
use version; our $VERSION = qw (1.0); use version; our $VERSION = qw (1.0);
use Exporter qw (import); use Exporter qw (import);
@@ -19,18 +19,18 @@ sub buni {
my $ret = 'Нету Buni'; my $ret = 'Нету Buni';
for (1..3) { for (1..3) {
my $http = HTTP::Tiny->new (timeout => 3); my $ua = Mojo::UserAgent->new->connect_timeout (3);
$r = $http->get ('http://www.bunicomic.com/?random&nocache=1'); $r = $ua->get ('http://www.bunicomic.com/?random&nocache=1')->result;
if ($r->{success}) { if ($r->is_success) {
last; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $p = HTML::TokeParser->new(\$r->{content}); my $p = HTML::TokeParser->new(\$r->body);
my @a; my @a;
# additional {} required in order "last" to work properly :) # additional {} required in order "last" to work properly :)
@@ -47,7 +47,7 @@ sub buni {
} while ($#{$a[0]} > 1); } while ($#{$a[0]} > 1);
} }
} else { } 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; return $ret;

View File

@@ -5,11 +5,16 @@ use strict;
use warnings; use warnings;
use utf8; use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use CHI;
use CHI::Driver::BerkeleyDB;
use DateTime;
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Encode; use Encode;
use Carp qw (cluck); use Carp qw (cluck);
use HTTP::Tiny;
use HTML::TokeParser; use HTML::TokeParser;
use Mojo::Log;
use Mojo::UserAgent::Cached;
use POSIX qw (strftime);
use version; our $VERSION = qw (1.0); use version; our $VERSION = qw (1.0);
use Exporter qw (import); use Exporter qw (import);
@@ -23,19 +28,56 @@ sub drink {
my ($dayNum, $monthNum) = (localtime ())[3, 4]; my ($dayNum, $monthNum) = (localtime ())[3, 4];
my $url = sprintf 'https://kakoysegodnyaprazdnik.ru/baza/%s/%s', $MONTH[$monthNum], $dayNum; my $url = sprintf 'https://kakoysegodnyaprazdnik.ru/baza/%s/%s', $MONTH[$monthNum], $dayNum;
for (1..3) { # Those POSIX assholes just forgot to add unix timestamps without TZ offset, so...
my $http = HTTP::Tiny->new (timeout => 3); my ($mday, $mon, $year) = (gmtime ())[3, 4, 5];
$r = $http->get ($url, {'Accept-Charset' => 'utf-8', 'Accept-Language' => 'ru-RU'}); 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; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $p = HTML::TokeParser->new(\$r->{content}); my $p = HTML::TokeParser->new(\$r->body);
my @a; my @a;
my @holyday; my @holyday;
@@ -58,7 +100,7 @@ sub drink {
$ret = join "\n", @holyday; $ret = join "\n", @holyday;
} }
} else { } 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; return $ret;

View File

@@ -9,10 +9,9 @@ use English qw ( -no_match_vars );
use Carp qw (cluck); use Carp qw (cluck);
use Digest::HMAC_SHA1 qw (hmac_sha1); use Digest::HMAC_SHA1 qw (hmac_sha1);
use File::Path qw (make_path); use File::Path qw (make_path);
use JSON::XS;
use HTTP::Tiny;
use Math::Random::Secure qw (irand); use Math::Random::Secure qw (irand);
use MIME::Base64; use MIME::Base64;
use Mojo::UserAgent;
use SQLite_File; use SQLite_File;
use URI::Encode::XS qw (uri_encode); use URI::Encode::XS qw (uri_encode);
@@ -120,15 +119,15 @@ sub flickrRequestToken {
uri_encode ($flickr_callback_url) uri_encode ($flickr_callback_url)
); );
my $http = HTTP::Tiny->new (timeout => 5); my $ua = Mojo::UserAgent->new->connect_timeout (5);
my $r = $http->get ($url); my $r = $ua->get ($url)->result;
my %params; my %params;
if ($r->{success}) { if ($r->is_success) {
# they ignore format=json, so... # they ignore format=json, so...
%params = map {split /=/} split /&/, $r->{content}; %params = map {split /=/} split /&/, $r->body;
} else { } 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; return %params;
@@ -161,15 +160,15 @@ sub flickrAccessToken {
uri_encode ($oauth_signature) uri_encode ($oauth_signature)
); );
my $http = HTTP::Tiny->new (timeout => 5); my $ua = Mojo::UserAgent->new->connect_timeout (5);
my $r = $http->get ($url); my $r = $ua->get ($url)->result;
my %params; my %params;
if ($r->{success}) { if ($r->is_success) {
# they ignore format=json # they ignore format=json
%params = map {split /=/} split /&/, $r->{content}; %params = map {split /=/} split /&/, $r->body;
} else { } 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; return %params;
@@ -183,13 +182,13 @@ sub flickrAuthorization {
$flickr_request_token, $flickr_request_token,
); );
my $http = HTTP::Tiny->new (timeout => 5); my $ua = Mojo::UserAgent->new->connect_timeout (5);
my $r = $http->get ($url); my $r = $ua->get ($url)->result;
if ($r->{success}) { if ($r->is_success) {
return $r->{url}; return $r->url;
} else { } 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; return;
} }
} }
@@ -224,24 +223,23 @@ sub flickrTestLogin {
uri_encode ($oauth_signature) uri_encode ($oauth_signature)
); );
my $http = HTTP::Tiny->new (timeout => 5); my $ua = Mojo::UserAgent->new->connect_timeout (5);
my $r = $http->get ($url); my $r = $ua->get ($url)->result;
if ($r->{success}) { if ($r->is_success) {
my $response = eval { my $response = eval {
my $j = JSON::XS->new->utf8->relaxed; return $r->json;
return $j->decode ($r->{content});
}; };
if (defined $response) { if (defined $response) {
say Dumper $response; ## no critic (InputOutput::RequireCheckedSyscalls) say Dumper $response; ## no critic (InputOutput::RequireCheckedSyscalls)
return 1; return 1;
} else { } 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; return 0;
} }
} else { } 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; return 0;
} }
} }
@@ -282,13 +280,12 @@ sub flickrSearchByText {
uri_encode ($text) uri_encode ($text)
); );
my $http = HTTP::Tiny->new (timeout => 5); my $ua = Mojo::UserAgent->new->connect_timeout (5);
my $r = $http->get ($url); my $r = $ua->get ($url)->result;
if ($r->{success}) { if ($r->is_success) {
my $response = eval { my $response = eval {
my $j = JSON::XS->new->utf8->relaxed; return $r->json;
return $j->decode ($r->{content});
}; };
if (defined $response) { if (defined $response) {
@@ -326,31 +323,31 @@ sub flickrSearchByText {
uri_encode ($text) uri_encode ($text)
); );
$http = HTTP::Tiny->new (timeout => 5); $ua = Mojo::UserAgent->new->connect_timeout (5);
$r = $http->get ($url); $r = $ua->get ($url)->result;
if ($r->{success}) {
if ($r->is_success) {
$response = eval { $response = eval {
my $j = JSON::XS->new->utf8->relaxed; return $r->json;
return $j->decode ($r->{content});
}; };
if (defined $response) { if (defined $response) {
return $response; return $response;
} else { } else {
cluck "Flickr api returns incorrect json: $r->{content}"; cluck "Flickr api returns incorrect json: $r->message";
return undef; return undef;
} }
} else { } else {
cluck "Flickr api returns incorrect json: $r->{content}"; cluck "Flickr api returns incorrect json: $r->message";
return undef; return undef;
} }
} else { } else {
cluck "Flickr api returns incorrect json: $r->{content}"; cluck "Flickr api returns incorrect json: $r->message";
return undef; return undef;
} }
} else { } else {
cluck "HTTP status code not 200: $r->{status}, $r->{content}"; cluck "HTTP status code not 200: $r->code, $r->message";
return undef; return undef;
} }
} }
@@ -391,13 +388,12 @@ sub flickrSearchByTags {
uri_encode ($tags) uri_encode ($tags)
); );
my $http = HTTP::Tiny->new (timeout => 5); my $ua = Mojo::UserAgent->new->connect_timeout (5);
my $r = $http->get ($url); my $r = $ua->get ($url)->result;
if ($r->{success}) { if ($r->is_success) {
my $response = eval { my $response = eval {
my $j = JSON::XS->new->utf8->relaxed; return $r->json;
return $j->decode ($r->{content});
}; };
if (defined $response) { if (defined $response) {
@@ -435,31 +431,30 @@ sub flickrSearchByTags {
uri_encode ($tags) uri_encode ($tags)
); );
$http = HTTP::Tiny->new (timeout => 5); $ua = Mojo::UserAgent->new->connect_timeout (5);
$r = $http->get ($url); $r = $ua->get ($url)->result;
if ($r->{success}) { if ($r->is_success) {
$response = eval { $response = eval {
my $j = JSON::XS->new->utf8->relaxed; return $r->json;
return $j->decode ($r->{content});
}; };
if (defined $response) { if (defined $response) {
return $response; return $response;
} else { } else {
cluck "Flickr api returns incorrect json: $r->{content}"; cluck "Flickr api returns incorrect json: $r->message";
return undef; return undef;
} }
} else { } else {
cluck "Flickr api returns incorrect json: $r->{content}"; cluck "Flickr api returns incorrect json: $r->message";
return undef; return undef;
} }
} else { } else {
cluck "Flickr api returns incorrect json: $r->{content}"; cluck "Flickr api returns incorrect json: $r->message";
return undef; return undef;
} }
} else { } else {
cluck "HTTP status code not 200: $r->{status}, $r>{contenr}"; cluck "HTTP status code not 200: $r->code, $r->message";
return undef; return undef;
} }
} }
@@ -484,8 +479,8 @@ sub flickr_init {
my $flickr_request_token_secret = $secret{flickr_request_token_secret}; my $flickr_request_token_secret = $secret{flickr_request_token_secret};
unless (defined $flickr_request_token || defined $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 "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"; say 'Please remove verifier settings from config.json and run this script again'; ## no critic (InputOutput::RequireCheckedSyscalls)
untie %secret; untie %secret;
return 0; return 0;
} }

View File

@@ -8,9 +8,8 @@ use open qw (:std :utf8);
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Carp qw (cluck); use Carp qw (cluck);
use File::Path qw (make_path); use File::Path qw (make_path);
use JSON::XS;
use HTTP::Tiny;
use Math::Random::Secure qw (irand); use Math::Random::Secure qw (irand);
use Mojo::UserAgent;
use SQLite_File; use SQLite_File;
use conf qw (loadConf); use conf qw (loadConf);
use flickr qw (flickr_by_tags); use flickr qw (flickr_by_tags);
@@ -29,19 +28,19 @@ sub kitty {
my $ret = 'Нету кошечек, все разбежались.'; my $ret = 'Нету кошечек, все разбежались.';
for (1..3) { for (1..3) {
my $http = HTTP::Tiny->new (timeout => 3); my $ua = Mojo::UserAgent->new->connect_timeout (3);
$r = $http->get ('https://api.thecatapi.com/v1/images/search'); $r = $ua->get ('https://api.thecatapi.com/v1/images/search')->result;
if ($r->{success}) { if ($r->is_success) {
last; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $jcat = eval { my $jcat = eval {
decode_json ($r->{content}) return $r->json;
}; };
unless (defined $jcat) { unless (defined $jcat) {
@@ -53,7 +52,7 @@ sub kitty {
} }
} }
} else { } 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; return $ret;
@@ -64,19 +63,19 @@ sub fox {
my $ret = 'Нету лисичек, все разбежались.'; my $ret = 'Нету лисичек, все разбежались.';
for (1..3) { for (1..3) {
my $http = HTTP::Tiny->new (timeout => 3); my $ua = Mojo::UserAgent->new->connect_timeout (3);
$r = $http->get ('https://randomfox.ca/floof/'); $r = $ua->get ('https://randomfox.ca/floof/')->result;
if ($r->{success}) { if ($r->is_success) {
last; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $jfox = eval { my $jfox = eval {
decode_json ($r->{content}) return $r->json;
}; };
unless (defined $jfox) { unless (defined $jfox) {
@@ -88,7 +87,7 @@ sub fox {
} }
} }
} else { } 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; return $ret;
@@ -99,19 +98,19 @@ sub oboobs {
my $ret = 'Нету cисичек, все разбежались.'; my $ret = 'Нету cисичек, все разбежались.';
for (1..3) { for (1..3) {
my $http = HTTP::Tiny->new (timeout => 3); my $ua = Mojo::UserAgent->new->connect_timeout (3);
$r = $http->get ('http://api.oboobs.ru/boobs/0/1/random'); $r = $ua->get ('http://api.oboobs.ru/boobs/0/1/random')->result;
if ($r->{success}) { if ($r->is_success) {
last; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $joboobs = eval { my $joboobs = eval {
decode_json ($r->{content}) return $r->json;
}; };
unless (defined $joboobs) { unless (defined $joboobs) {
@@ -123,7 +122,7 @@ sub oboobs {
} }
} }
} else { } 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; return $ret;
@@ -134,19 +133,19 @@ sub obutts {
my $ret = 'Нету попок, все разбежались.'; my $ret = 'Нету попок, все разбежались.';
for (1..3) { for (1..3) {
my $http = HTTP::Tiny->new (timeout => 3); my $ua = Mojo::UserAgent->new->connect_timeout (3);
$r = $http->get ('http://api.obutts.ru/butts/0/1/random'); $r = $ua->get ('http://api.obutts.ru/butts/0/1/random')->result;
if ($r->{success}) { if ($r->is_success) {
last; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $jobutts = eval { my $jobutts = eval {
decode_json ($r->{content}) return $r->json;
}; };
unless (defined $jobutts) { unless (defined $jobutts) {
@@ -158,7 +157,7 @@ sub obutts {
} }
} }
} else { } 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; return $ret;

View File

@@ -8,9 +8,8 @@ use open qw (:std :utf8);
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Carp qw (cluck); use Carp qw (cluck);
use File::Path qw (make_path); use File::Path qw (make_path);
use JSON::XS;
use HTTP::Tiny;
use Math::Random::Secure qw (irand); use Math::Random::Secure qw (irand);
use Mojo::UserAgent;
use SQLite_File; use SQLite_File;
use conf qw (loadConf); use conf qw (loadConf);
@@ -30,7 +29,6 @@ sub imgur {
my $refresh_url = 'https://api.imgur.com/oauth2/token'; my $refresh_url = 'https://api.imgur.com/oauth2/token';
my $search_url = 'https://api.imgur.com/3/gallery/search/'; my $search_url = 'https://api.imgur.com/3/gallery/search/';
my $http = HTTP::Tiny->new (timeout => 5);
# load all tokens from api secrets db # load all tokens from api secrets db
my $backingfile = sprintf '%s/secrets.sqlite', $dir; my $backingfile = sprintf '%s/secrets.sqlite', $dir;
@@ -62,20 +60,13 @@ sub imgur {
} }
# query api # query api
my $r = $http->get ( my $ua = Mojo::UserAgent->new->connect_timeout (3);
$search_url . $tag, my $r = $ua->get ($search_url . $tag => {Authorization => "Bearer $imgur_access_token"})->result;
{
headers => {
Authorization => "Bearer $imgur_access_token"
}
}
);
# looks like we need to refresh token # looks like we need to refresh token
if (($r->{status} == 401) || ($r->{status} == 403)) { if (($r->code == 401) || ($r->code == 403)) {
$r = $http->post_form ( $ua->post (
$refresh_url, $refresh_url => form {
{
refresh_token => $imgur_refresh_token, refresh_token => $imgur_refresh_token,
client_id => $imgur_client_id, client_id => $imgur_client_id,
clinent_secret => $imgur_client_secret, clinent_secret => $imgur_client_secret,
@@ -83,13 +74,13 @@ sub imgur {
} }
); );
unless ($r->{success}) { unless ($r->is_success) {
cluck "Unable to refresh imgur token, please re-authorise app! or imgur experiencing api outage: $r->{status} $r->{content}"; cluck "Unable to refresh imgur token, please re-authorise app! or imgur experiencing api outage: $r->code $r->message";
untie %secret; untie %secret;
return undef; return undef;
} }
my $refresh = eval { decode_json $r->{content} }; my $refresh = eval { return $r->json; };
if (defined $refresh) { if (defined $refresh) {
$imgur_refresh_token = $refresh->{refresh_token}; $imgur_refresh_token = $refresh->{refresh_token};
@@ -103,20 +94,13 @@ sub imgur {
} }
# query api again # query api again
$r = $http->get ( $r = $ua->get ($search_url . $tag => {Authorization => "Bearer $imgur_access_token"})->result;
$search_url . $tag,
{
headers => {
Authorization => "Bearer $imgur_access_token"
}
}
);
} }
untie %secret; untie %secret;
if ($r->{success}) { if ($r->is_success) {
my $searchResult = eval { decode_json ($r->{content}) }; my $searchResult = eval { return $r->json; };
my @urls; my @urls;
if (defined $searchResult) { if (defined $searchResult) {
@@ -148,7 +132,7 @@ sub imgur {
return undef; return undef;
} }
} else { } else {
cluck "Unable to get results from imgur api: $r->{content}"; cluck "Unable to get results from imgur api: $r->message";
return undef; return undef;
} }
} else { } else {
@@ -156,7 +140,7 @@ sub imgur {
return undef; return undef;
} }
} else { } 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; return undef;
} }
} }

View File

@@ -7,9 +7,9 @@ use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Carp qw (cluck); use Carp qw (cluck);
use HTTP::Tiny;
use HTML::TokeParser; use HTML::TokeParser;
use Math::Random::Secure qw (irand); use Math::Random::Secure qw (irand);
use Mojo::UserAgent;
use version; our $VERSION = qw (1.0); use version; our $VERSION = qw (1.0);
use Exporter qw (import); use Exporter qw (import);
@@ -21,18 +21,18 @@ sub monkeyuser {
my @link; my @link;
for (1..3) { for (1..3) {
my $http = HTTP::Tiny->new (timeout => 3); my $ua = Mojo::UserAgent->new->connect_timeout (3);
$r = $http->get ('https://www.monkeyuser.com/toc/'); $r = $ua->get ('https://www.monkeyuser.com/toc/')->result;
if ($r->{success}) { if ($r->is_success) {
last; last;
} }
sleep 2; sleep 2;
} }
if ($r->{success}) { if ($r->is_success) {
my $p = HTML::TokeParser->new(\$r->{content}); my $p = HTML::TokeParser->new(\$r->body);
my @a; my @a;
do { do {

View File

@@ -7,11 +7,13 @@ use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Carp qw (carp cluck); use Carp qw (carp cluck);
use CHI;
use CHI::Driver::BerkeleyDB;
use DB_File; use DB_File;
use Digest::MD5 qw (md5_base64); use Digest::MD5 qw (md5_base64);
use File::Path qw (make_path); use File::Path qw (make_path);
use HTTP::Tiny; use Mojo::Log;
use JSON::XS; use Mojo::UserAgent::Cached;
use conf qw (loadConf); use conf qw (loadConf);
use util qw (trim urlencode); use util qw (trim urlencode);
@@ -71,77 +73,53 @@ sub weather {
sub __weather { sub __weather {
my $city = shift; my $city = shift;
$city = urlencode $city; $city = urlencode $city;
my $id = md5_base64 $city;
my $appid = $c->{openweathermap}->{appid}; my $appid = $c->{openweathermap}->{appid};
my $cachedir = $c->{openweathermap}->{cachedir}; my $cachedir = $c->{openweathermap}->{cachedir};
my $cachetimefile = $cachedir . '/openweathermap.Id-Timestamp.db';
my $cachedatafile = $cachedir . '/openweathermap.Id-Data.db';
my $now = time (); my $now = time ();
my $fc; my $fc;
my $w; my $w;
unless (-d $cachedir) { my $r;
make_path ($cachedir) || do {
cluck "[ERROR] Unable to create $cachedir: $OS_ERROR"; # try 3 times and giveup
return; 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 unless ($fc) {
tie my %cachetime, 'DB_File', $cachetimefile or do { cluck "[WARN] openweathermap returns corrupted json: $EVAL_ERROR";
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;
return undef; 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 # TODO: check all of this for existence
$w->{'name'} = $fc->{name}; $w->{'name'} = $fc->{name};
$w->{'state'} = $fc->{state}; $w->{'state'} = $fc->{state};

View File

@@ -5,18 +5,23 @@ use strict;
use warnings; use warnings;
use utf8; use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use HTTP::Tiny; use Mojo::UserAgent;
use version; our $VERSION = qw (1.0); use version; our $VERSION = qw (1.0);
use Exporter qw (import); use Exporter qw (import);
our @EXPORT_OK = qw (xkcd); our @EXPORT_OK = qw (xkcd);
sub xkcd { sub xkcd {
my $http = HTTP::Tiny->new (timeout => 5, max_redirect => 0); my $ua = Mojo::UserAgent->new->connect_timeout (5)->max_redirects (0);
my $r = $http->get ('https://xkcd.ru/random/'); my $r = $ua->get ('https://xkcd.ru/random/')->result;
if (defined $r->{headers} && defined $r->{headers}->{location} && $r->{headers}->{location} ne '') { if (
return sprintf '[xkcd.ru](https://xkcd.ru/i/%s_v1.png)', substr ($r->{headers}->{location}, 1, -1); 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 'Комикс-стрип нарисовать не так-то просто :('; return 'Комикс-стрип нарисовать не так-то просто :(';