From 5d14f0808492dab2013eeb2b6be43fffb013f219 Mon Sep 17 00:00:00 2001 From: eleksir Date: Mon, 1 Mar 2021 02:10:58 +0300 Subject: [PATCH] =?UTF-8?q?Implement=20(beta-quality)=20!rabbit,=20!bunny,?= =?UTF-8?q?=20!=D0=BA=D1=80=D0=BE=D0=BB=D0=B8=D0=BA=20commands=20and=20img?= =?UTF-8?q?ur=20api=20client=20for=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/sample_config.json | 9 +++ lib/botlib.pm | 6 ++ lib/image.pm | 166 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 180 insertions(+), 1 deletion(-) diff --git a/data/sample_config.json b/data/sample_config.json index 97972dc..110c364 100644 --- a/data/sample_config.json +++ b/data/sample_config.json @@ -4,6 +4,15 @@ "admin" : { "dir" : "data/admin" }, + "image": { + "dir" : "data/image", + "imgur" : { + "client-id" : "imgur api client id", + "secret" : "secret for client id", + "access_token" : "access token for querying imgur api", + "refresh_token" : "token for refreshing access token" + } + }, "friday" : { "dir" : "data/friday", "src" : "data/friday.txt" diff --git a/lib/botlib.pm b/lib/botlib.pm index 6dd4dfc..73a7a72 100644 --- a/lib/botlib.pm +++ b/lib/botlib.pm @@ -97,6 +97,11 @@ sub command { sleep (irand (2) + 1); $msg->replyMd ($reply); return; + } elsif (substr ($text, 1) eq 'rabbit' || substr ($text, 1) eq 'bunny' || substr ($text, 1) eq 'кролик') { + $msg->typing (); + $reply = rabbit (); + $msg->replyMd ($reply); + return; } elsif ( substr ($text, 1) eq 'tits' || substr ($text, 1) eq 'boobs' || @@ -150,6 +155,7 @@ sub command { $reply = << "MYHELP"; ``` ${csign}help | ${csign}помощь - список команд +${csign}bunny | ${csign}rabbit | ${csign}кролик - кролик (бета-версия) ${csign}cat | ${csign}кис - кошечка ${csign}dig | ${csign}копать - заняться археологией ${csign}fish | ${csign}рыба | ${csign}рыбка - порыбачить diff --git a/lib/image.pm b/lib/image.pm index f3bca09..65ee4ac 100644 --- a/lib/image.pm +++ b/lib/image.pm @@ -7,13 +7,23 @@ use utf8; 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 SQLite_File; +use conf qw (loadConf); use version; our $VERSION = qw (1.0); use Exporter qw (import); -our @EXPORT_OK = qw (kitty fox oboobs obutts); +our @EXPORT_OK = qw (kitty fox oboobs obutts rabbit); + +my $c = loadConf (); +my $dir = $c->{image}->{dir}; +my $imgur_client_id = $c->{image}->{imgur}->{client_id}; +my $imgur_client_secret = $c->{image}->{imgur}->{client_secret}; +my $imgur_access_token = $c->{image}->{imgur}->{access_token};; +my $imgur_refresh_token = $c->{image}->{imgur}->{refresh_token}; sub kitty { my $r; @@ -155,6 +165,160 @@ sub obutts { return $ret; } +sub imgur { + my $tag = shift; + + 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; + + unless (-d $dir) { + make_path ($dir) or do { + cluck "Unable to create $dir: $OS_ERROR"; + return undef; + }; + } + + tie my %secret, 'SQLite_File', $backingfile || do { + cluck "[ERROR] Unable to tie to $backingfile: $OS_ERROR"; + return undef; + }; + + # if there is no access_token in db - put there one from config + if (defined $secret{imgur_access_token}) { + $imgur_access_token = $secret{imgur_access_token}; + } else { + $secret{imgur_access_token} = $imgur_access_token; + } + + # if there is no refresh_token in db - put there one from config + if (defined $secret{imgur_refresh_token}) { + $imgur_refresh_token = $secret{imgur_refresh_token}; + } else { + $secret{imgur_refresh_token} = $imgur_refresh_token; + } + + # query api + my $r = $http->get ( + $search_url . $tag, + { + headers => { + Authorization => "Bearer $imgur_access_token" + } + } + ); + + # looks like we need to refresh token + if (($r->{status} == 401) || ($r->{status} == 403)) { + $r = $http->post_form ( + $refresh_url, + { + refresh_token => $imgur_refresh_token, + client_id => $imgur_client_id, + clinent_secret => $imgur_client_secret, + grant_type => 'refresh_token', + } + ); + + unless ($r->{success}) { + cluck "Unable to refresh imgur token, please re-authorise app! or imgur experiencing api outage: $r->{status} $r->{content}"; + untie %secret; + return undef; + } + + my $refresh = eval { decode_json $r->{content} }; + + if (defined $refresh) { + $imgur_refresh_token = $refresh->{refresh_token}; + $secret{imgur_refresh_token} = $refresh->{refresh_token}; + $imgur_access_token = $refresh->{access_token}; + $secret{imgur_access_token} = $refresh->{access_token}; + } else { + cluck "Unable to refresh imgur access_token, unable to decode json: $EVAL_ERROR"; + untie %secret; + return undef; + } + + # query api again + $r = $http->get ( + $search_url . $tag, + { + headers => { + Authorization => "Bearer $imgur_access_token" + } + } + ); + } + + untie %secret; + + if ($r->{success}) { + my $searchResult = eval { decode_json ($r->{content}) }; + my @urls; + + if (defined $searchResult) { + if ($searchResult->{success}) { + foreach my $item (@{$searchResult->{data}}) { + foreach my $image (@{$item->{images}}) { + if (defined ($image->{animated}) && (0 + $image->{animated}) != 0) { + next; + } + + if (($image->{type} eq 'image/jpeg') || ($image->{type} eq 'image/png')) { + if (defined ($image->{is_ad}) && (0 + $image->{is_ad}) !=0) { + next; + } + + if (defined ($image->{nsfw}) && (0 + $image->{nsfw}) != 0) { + next; + } + + push @urls, $image->{link}; + } + } + } + + if ($#urls > 0) { + return $urls[irand ($#urls + 1)]; + } else { + cluck 'Imgur api returned empty result.'; + return undef; + } + } else { + cluck "Unable to get results from imgur api: $r->{content}"; + return undef; + } + } else { + cluck "Unable to decode imgur api json: $EVAL_ERROR"; + return undef; + } + } else { + cluck "Unable to get results from imgur api: $r->{status}, $r->{content}"; + return undef; + } +} + +sub rabbit { + my @terms = ( + '?q=animals%20AND%20%28%20rabbits%20OR%20bunnies%20%29', + 'year?q=animals%20AND%20%28%20rabbits%20OR%20bunnies%20%29', + 'relevance?q=animals+AND+%28+rabbits+OR+bunnies+%29', + 'relevance/year?q=animals+AND+%28+rabbits+OR+bunnies+%29', + 'score?q_not=cat%20OR%20kitten%20OR%20kittens%20OR%20dog%20OR%20cats%20OR%20dogs%20OR%20puppy%20OR%20puppies&q_tags=bunnies%2Cbunny%2Crabbits%2Crabbit' + ); + + my $rabbit = imgur ($terms[irand ($#terms + 1)]); + + if (defined $rabbit) { + return sprintf '[(\_/)](%s)', $rabbit; + } else { + return 'Нету кроликов, все разбежались.' + } +} + 1; # vim: set ft=perl noet ai ts=4 sw=4 sts=4: