- Move most modules to subdirs - Rename functions according perlcritic guidelines - Fix and add some bugs
599 lines
19 KiB
Perl
599 lines
19 KiB
Perl
package BotLib::Image::Flickr;
|
|
|
|
use 5.018;
|
|
use strict;
|
|
use warnings;
|
|
use utf8;
|
|
use open qw (:std :utf8);
|
|
use English qw ( -no_match_vars );
|
|
use Carp qw (cluck);
|
|
use CHI;
|
|
use CHI::Driver::BerkeleyDB;
|
|
use Digest::HMAC_SHA1 qw (hmac_sha1);
|
|
use Math::Random::Secure qw (irand);
|
|
use MIME::Base64;
|
|
use Mojo::UserAgent;
|
|
use URI::Encode::XS qw (uri_encode);
|
|
|
|
use BotLib::Conf qw (LoadConf);
|
|
use BotLib::Util qw (urlencode);
|
|
|
|
use Data::Dumper;
|
|
|
|
use version; our $VERSION = qw (1.0);
|
|
use Exporter qw (import);
|
|
our @EXPORT_OK = qw (FlickrInit FlickrByTags FlickrByText FlickrTestLogin);
|
|
|
|
my $c = LoadConf ();
|
|
my $cachedir = $c->{cachedir};
|
|
|
|
my $flickr_consumer_key = $c->{image}->{flickr}->{consumer_key};
|
|
my $flickr_consumer_secret = $c->{image}->{flickr}->{consumer_secret};
|
|
my $flickr_verifier = $c->{image}->{flickr}->{verifier};
|
|
my $flickr_request_token_url = 'https://www.flickr.com/services/oauth/request_token';
|
|
my $flickr_authorization_url = 'https://www.flickr.com/services/oauth/authorize';
|
|
my $flickr_access_token_url = 'https://www.flickr.com/services/oauth/access_token';
|
|
my $flickr_callback_url = 'http://www.example.com';
|
|
my $flickr_api_url = 'https://www.flickr.com/services/rest/';
|
|
|
|
sub mknonce {
|
|
# make random number, 8 symbols in length
|
|
my $nonce = sprintf '%08d', irand (99999999);
|
|
return $nonce;
|
|
}
|
|
|
|
sub flickerSignReq {
|
|
my %p = @_;
|
|
my $string;
|
|
my $hmac;
|
|
|
|
if ($p{type} eq 'request_token') {
|
|
my @parameters;
|
|
delete $p{type};
|
|
push @parameters, 'oauth_signature_method=HMAC-SHA1';
|
|
push @parameters, 'oauth_version=1.0';
|
|
push @parameters, sprintf 'oauth_callback=%s', uri_encode ($flickr_callback_url);
|
|
push @parameters, sprintf 'oauth_consumer_key=%s', $flickr_consumer_key;
|
|
|
|
foreach my $param (keys %p) {
|
|
push @parameters, sprintf ('%s=%s', $param, $p{$param});
|
|
}
|
|
|
|
$string = sprintf 'GET&%s&', uri_encode ($flickr_request_token_url);
|
|
$string .= uri_encode (join '&', sort (@parameters));
|
|
# Thanks to twitter api dev portal, they explain this particular case: while we requesting this token
|
|
# we do not yet know access_token secret, so we just omit it in this signature
|
|
# https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature
|
|
$hmac = Digest::HMAC_SHA1->new (sprintf '%s&', uri_encode ($flickr_consumer_secret));
|
|
} elsif ($p{type} eq 'access_token') {
|
|
my @parameters;
|
|
my $flickr_request_token_secret = $p{oauth_token_secret};
|
|
delete $p{oauth_token_secret};
|
|
delete $p{type};
|
|
push @parameters, 'oauth_signature_method=HMAC-SHA1';
|
|
push @parameters, 'oauth_version=1.0';
|
|
push @parameters, sprintf 'oauth_consumer_key=%s', $flickr_consumer_key;
|
|
|
|
foreach my $param (keys %p) {
|
|
push @parameters, sprintf ('%s=%s', $param, $p{$param});
|
|
}
|
|
|
|
$string = sprintf 'GET&%s&', uri_encode ($flickr_access_token_url);
|
|
$string .= uri_encode (join '&', sort (@parameters));
|
|
$hmac = Digest::HMAC_SHA1->new (sprintf '%s&%s', uri_encode ($flickr_consumer_secret), uri_encode ($flickr_request_token_secret));
|
|
} elsif ($p{type} eq 'test_login' || $p{type} eq 'search_text' || $p{type} eq 'search_tags') {
|
|
my @parameters;
|
|
my $flickr_request_token_secret = $p{oauth_token_secret};
|
|
delete $p{oauth_token_secret};
|
|
delete $p{type};
|
|
|
|
foreach my $param (keys %p) {
|
|
push @parameters, sprintf ('%s=%s', $param, $p{$param});
|
|
}
|
|
|
|
$string = sprintf 'GET&%s&', uri_encode ($flickr_api_url);
|
|
$string .= uri_encode (join '&', sort (@parameters));
|
|
$hmac = Digest::HMAC_SHA1->new (sprintf '%s&%s', uri_encode ($flickr_consumer_secret), uri_encode ($flickr_request_token_secret));
|
|
}
|
|
|
|
$hmac->add ($string);
|
|
return encode_base64 ($hmac->digest, '');
|
|
}
|
|
|
|
sub flickrRequestToken {
|
|
my $oauth_timestamp = time ();
|
|
my $oauth_nonce = mknonce ();
|
|
|
|
my $oauth_signature = flickerSignReq (
|
|
type => 'request_token',
|
|
oauth_timestamp => $oauth_timestamp,
|
|
oauth_nonce => $oauth_nonce
|
|
);
|
|
|
|
my $url = $flickr_request_token_url . sprintf (
|
|
'?oauth_nonce=%s&oauth_timestamp=%s&oauth_consumer_key=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&&oauth_signature=%s&oauth_callback=%s',
|
|
$oauth_nonce,
|
|
$oauth_timestamp,
|
|
$flickr_consumer_key,
|
|
uri_encode ($oauth_signature),
|
|
uri_encode ($flickr_callback_url)
|
|
);
|
|
|
|
my $ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
my $r = $ua->get ($url)->result;
|
|
my %params;
|
|
|
|
if ($r->is_success) {
|
|
# they ignore format=json, so...
|
|
%params = map {split /=/} split /&/, $r->body;
|
|
} else {
|
|
say "Something bad returns from flickr api: $r->code $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
}
|
|
|
|
return %params;
|
|
}
|
|
|
|
sub flickrAccessToken {
|
|
my $flickr_request_token = shift;
|
|
my $flickr_request_token_secret = shift;
|
|
my $flickr_verifier = shift; ## no critic (Variables::ProhibitReusedNames)
|
|
|
|
my $oauth_timestamp = time ();
|
|
my $oauth_nonce = mknonce ();
|
|
|
|
my $oauth_signature = flickerSignReq (
|
|
type => 'access_token',
|
|
oauth_timestamp => $oauth_timestamp,
|
|
oauth_nonce => $oauth_nonce,
|
|
oauth_token => $flickr_request_token,
|
|
oauth_token_secret => $flickr_request_token_secret,
|
|
oauth_verifier => $flickr_verifier
|
|
);
|
|
|
|
my $url = $flickr_access_token_url . sprintf (
|
|
'?oauth_nonce=%s&oauth_timestamp=%s&oauth_verifier=%s&oauth_consumer_key=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=%s&oauth_signature=%s',
|
|
$oauth_nonce,
|
|
$oauth_timestamp,
|
|
$flickr_verifier,
|
|
$flickr_consumer_key,
|
|
$flickr_request_token,
|
|
uri_encode ($oauth_signature)
|
|
);
|
|
|
|
my $ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
my $r = $ua->get ($url)->result;
|
|
my %params;
|
|
|
|
if ($r->is_success) {
|
|
# they ignore format=json
|
|
%params = map {split /=/} split /&/, $r->body;
|
|
} else {
|
|
say "Something bad returns from flickr api: $r->code $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
}
|
|
|
|
return %params;
|
|
}
|
|
|
|
sub flickrAuthorization {
|
|
my $flickr_request_token = shift;
|
|
|
|
my $url = $flickr_authorization_url . sprintf (
|
|
'?oauth_token=%s&perms=read',
|
|
$flickr_request_token,
|
|
);
|
|
|
|
my $ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
my $r = $ua->get ($url)->result;
|
|
|
|
if ($r->is_success) {
|
|
return $r->url;
|
|
} else {
|
|
say "Something went wrong: $r->code $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
return;
|
|
}
|
|
}
|
|
|
|
sub flickrTestLogin {
|
|
my $flickr_access_token = shift;
|
|
my $flickr_access_token_secret = shift;
|
|
|
|
my $oauth_timestamp = time ();
|
|
my $oauth_nonce = mknonce ();
|
|
|
|
my $oauth_signature = flickerSignReq (
|
|
nojsoncallback => 1,
|
|
oauth_nonce => $oauth_nonce,
|
|
format => 'json',
|
|
oauth_consumer_key => $flickr_consumer_key,
|
|
oauth_timestamp => $oauth_timestamp,
|
|
type => 'test_login',
|
|
method => 'flickr.test.login',
|
|
oauth_token => $flickr_access_token,
|
|
oauth_token_secret => $flickr_access_token_secret,
|
|
oauth_signature_method => 'HMAC-SHA1',
|
|
oauth_version => '1.0'
|
|
);
|
|
|
|
my $url = $flickr_api_url . sprintf (
|
|
'?nojsoncallback=1&oauth_nonce=%s&format=json&oauth_consumer_key=%s&oauth_timestamp=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=%s&oauth_signature=%s&method=flickr.test.login',
|
|
$oauth_nonce,
|
|
$flickr_consumer_key,
|
|
$oauth_timestamp,
|
|
$flickr_access_token,
|
|
uri_encode ($oauth_signature)
|
|
);
|
|
|
|
my $ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
my $r = $ua->get ($url)->result;
|
|
|
|
if ($r->is_success) {
|
|
my $response = eval {
|
|
return $r->json;
|
|
};
|
|
|
|
if (defined $response) {
|
|
say Dumper $response; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
return 1;
|
|
} else {
|
|
say "Flickr api returns incorrect json: $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
return 0;
|
|
}
|
|
} else {
|
|
say "HTTP status code not 200: $r->code, $r->message"; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
sub flickrSearchByText {
|
|
my $flickr_access_token = shift;
|
|
my $flickr_access_token_secret = shift;
|
|
my $text = shift;
|
|
|
|
my $oauth_timestamp = time ();
|
|
my $oauth_nonce = mknonce ();
|
|
|
|
my $oauth_signature = flickerSignReq (
|
|
nojsoncallback => 1,
|
|
oauth_nonce => $oauth_nonce,
|
|
format => 'json',
|
|
oauth_consumer_key => $flickr_consumer_key,
|
|
oauth_timestamp => $oauth_timestamp,
|
|
type => 'search_text',
|
|
content_type => 1,
|
|
media => 'photos',
|
|
method => 'flickr.photos.search',
|
|
text => $text,
|
|
per_page => 1,
|
|
oauth_token => $flickr_access_token,
|
|
oauth_token_secret => $flickr_access_token_secret,
|
|
oauth_signature_method => 'HMAC-SHA1',
|
|
oauth_version => '1.0'
|
|
);
|
|
|
|
my $url = $flickr_api_url . sprintf (
|
|
'?nojsoncallback=1&oauth_nonce=%s&format=json&oauth_consumer_key=%s&oauth_timestamp=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=%s&oauth_signature=%s&method=flickr.photos.search&content_type=1&media=photos&per_page=1&text=%s',
|
|
$oauth_nonce,
|
|
$flickr_consumer_key,
|
|
$oauth_timestamp,
|
|
$flickr_access_token,
|
|
uri_encode ($oauth_signature),
|
|
uri_encode ($text)
|
|
);
|
|
|
|
my $ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
my $r = $ua->get ($url)->result;
|
|
|
|
if ($r->is_success) {
|
|
my $response = eval {
|
|
return $r->json;
|
|
};
|
|
|
|
if (defined $response) {
|
|
# lets make another query, this time with random picture
|
|
my $page = irand int ($response->{photos}->{total} / 500);
|
|
$oauth_timestamp = time ();
|
|
$oauth_nonce = mknonce ();
|
|
$oauth_signature = flickerSignReq (
|
|
nojsoncallback => 1,
|
|
oauth_nonce => $oauth_nonce,
|
|
format => 'json',
|
|
oauth_consumer_key => $flickr_consumer_key,
|
|
oauth_timestamp => $oauth_timestamp,
|
|
type => 'search_text',
|
|
content_type => 1,
|
|
media => 'photos',
|
|
method => 'flickr.photos.search',
|
|
text => $text,
|
|
page => $page,
|
|
per_page => 500,
|
|
oauth_token => $flickr_access_token,
|
|
oauth_token_secret => $flickr_access_token_secret,
|
|
oauth_signature_method => 'HMAC-SHA1',
|
|
oauth_version => '1.0'
|
|
);
|
|
|
|
$url = $flickr_api_url . sprintf (
|
|
'?nojsoncallback=1&oauth_nonce=%s&format=json&oauth_consumer_key=%s&oauth_timestamp=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=%s&oauth_signature=%s&method=flickr.photos.search&content_type=1&media=photos&per_page=500&page=%d&text=%s',
|
|
$oauth_nonce,
|
|
$flickr_consumer_key,
|
|
$oauth_timestamp,
|
|
$flickr_access_token,
|
|
uri_encode ($oauth_signature),
|
|
$page,
|
|
uri_encode ($text)
|
|
);
|
|
|
|
$ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
$r = $ua->get ($url)->result;
|
|
|
|
|
|
if ($r->is_success) {
|
|
$response = eval {
|
|
return $r->json;
|
|
};
|
|
|
|
if (defined $response) {
|
|
return $response;
|
|
} else {
|
|
cluck "Flickr api returns incorrect json: $r->message";
|
|
return undef;
|
|
}
|
|
} else {
|
|
cluck "Flickr api returns incorrect json: $r->message";
|
|
return undef;
|
|
}
|
|
} else {
|
|
cluck "Flickr api returns incorrect json: $r->message";
|
|
return undef;
|
|
}
|
|
} else {
|
|
cluck "HTTP status code not 200: $r->code, $r->message";
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
sub flickrSearchByTags {
|
|
my $flickr_access_token = shift;
|
|
my $flickr_access_token_secret = shift;
|
|
my $tags = shift;
|
|
|
|
my $oauth_timestamp = time ();
|
|
my $oauth_nonce = mknonce ();
|
|
|
|
my $oauth_signature = flickerSignReq (
|
|
nojsoncallback => 1,
|
|
oauth_nonce => $oauth_nonce,
|
|
format => 'json',
|
|
oauth_consumer_key => $flickr_consumer_key,
|
|
oauth_timestamp => $oauth_timestamp,
|
|
type => 'search_tags',
|
|
content_type => 1,
|
|
media => 'photos',
|
|
method => 'flickr.photos.search',
|
|
tags => $tags,
|
|
per_page => 1,
|
|
oauth_token => $flickr_access_token,
|
|
oauth_token_secret => $flickr_access_token_secret,
|
|
oauth_signature_method => 'HMAC-SHA1',
|
|
oauth_version => '1.0'
|
|
);
|
|
|
|
my $url = $flickr_api_url . sprintf (
|
|
'?nojsoncallback=1&oauth_nonce=%s&format=json&oauth_consumer_key=%s&oauth_timestamp=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=%s&oauth_signature=%s&method=flickr.photos.search&content_type=1&media=photos&per_page=1&tags=%s&tag_mode=all',
|
|
$oauth_nonce,
|
|
$flickr_consumer_key,
|
|
$oauth_timestamp,
|
|
$flickr_access_token,
|
|
uri_encode ($oauth_signature),
|
|
uri_encode ($tags)
|
|
);
|
|
|
|
my $ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
my $r = $ua->get ($url)->result;
|
|
|
|
if ($r->is_success) {
|
|
my $response = eval {
|
|
return $r->json;
|
|
};
|
|
|
|
if (defined $response) {
|
|
# lets make another query, this time with random picture
|
|
my $page = irand int ($response->{photos}->{total} / 500);
|
|
$oauth_timestamp = time ();
|
|
$oauth_nonce = mknonce ();
|
|
$oauth_signature = flickerSignReq (
|
|
nojsoncallback => 1,
|
|
oauth_nonce => $oauth_nonce,
|
|
format => 'json',
|
|
oauth_consumer_key => $flickr_consumer_key,
|
|
oauth_timestamp => $oauth_timestamp,
|
|
type => 'search_text',
|
|
content_type => 1,
|
|
media => 'photos',
|
|
method => 'flickr.photos.search',
|
|
tags => $tags,
|
|
page => $page,
|
|
per_page => 500,
|
|
oauth_token => $flickr_access_token,
|
|
oauth_token_secret => $flickr_access_token_secret,
|
|
oauth_signature_method => 'HMAC-SHA1',
|
|
oauth_version => '1.0'
|
|
);
|
|
|
|
$url = $flickr_api_url . sprintf (
|
|
'?nojsoncallback=1&oauth_nonce=%s&format=json&oauth_consumer_key=%s&oauth_timestamp=%s&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=%s&oauth_signature=%s&method=flickr.photos.search&content_type=1&media=photos&per_page=500&page=%d&tags=%s&tag_mode=all',
|
|
$oauth_nonce,
|
|
$flickr_consumer_key,
|
|
$oauth_timestamp,
|
|
$flickr_access_token,
|
|
uri_encode ($oauth_signature),
|
|
$page,
|
|
uri_encode ($tags)
|
|
);
|
|
|
|
$ua = Mojo::UserAgent->new->connect_timeout (5);
|
|
$r = $ua->get ($url)->result;
|
|
|
|
if ($r->is_success) {
|
|
$response = eval {
|
|
return $r->json;
|
|
};
|
|
|
|
if (defined $response) {
|
|
return $response;
|
|
} else {
|
|
cluck "Flickr api returns incorrect json: $r->message";
|
|
return undef;
|
|
}
|
|
} else {
|
|
cluck "Flickr api returns incorrect json: $r->message";
|
|
return undef;
|
|
}
|
|
} else {
|
|
cluck "Flickr api returns incorrect json: $r->message";
|
|
return undef;
|
|
}
|
|
} else {
|
|
cluck "HTTP status code not 200: $r->code, $r->message";
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
sub FlickrInit {
|
|
my $cache = CHI->new (
|
|
driver => 'BerkeleyDB',
|
|
root_dir => $cachedir,
|
|
namespace => __PACKAGE__
|
|
);
|
|
|
|
if (defined $flickr_verifier && $flickr_verifier) {
|
|
my $flickr_request_token = $cache->get ('flickr_request_token');
|
|
my $flickr_request_token_secret = $cache->get ('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 config db."; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
say 'Please remove verifier settings from config.json and run this script again.'; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
return 0;
|
|
}
|
|
|
|
my %accessToken = flickrAccessToken ($flickr_request_token, $flickr_request_token_secret, $flickr_verifier);
|
|
|
|
if (defined ($accessToken{oauth_token}) && defined ($accessToken{oauth_token_secret})) {
|
|
# TODO: check set
|
|
$cache->set ('flickr_access_token', $accessToken{oauth_token}, 'never');
|
|
$cache->set ('flickr_access_token_secret', $accessToken{oauth_token_secret}, 'never');
|
|
|
|
say sprintf ( ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
'Access token (%s) and access token secret (%s) are config db',
|
|
$accessToken{oauth_token},
|
|
$accessToken{oauth_token_secret},
|
|
);
|
|
|
|
return 1;
|
|
}
|
|
} else {
|
|
my %req = flickrRequestToken ();
|
|
if (defined ($req{oauth_token}) && defined ($req{oauth_token_secret}) && defined ($req{oauth_token})) {
|
|
# TODO: check set
|
|
$cache->set ('flickr_request_token', $req{oauth_token}, 'never');
|
|
$cache->set ('flickr_request_token_secret', $req{oauth_token_secret}, 'never');
|
|
my $confirm_url = flickrAuthorization ($req{oauth_token});
|
|
|
|
if (defined $confirm_url) {
|
|
say "Please open this url in your browser and grant access for this app:\n$confirm_url"; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
say 'Do not forget to put oauth_verifier to config.json file and re-run this script to get access token'; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
say 'Note that you should be logged off from flickr account.'; ## no critic (InputOutput::RequireCheckedSyscalls)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
sub FlickrTestLogin {
|
|
my $text = shift;
|
|
my $cache = CHI->new (
|
|
driver => 'BerkeleyDB',
|
|
root_dir => $cachedir,
|
|
namespace => __PACKAGE__
|
|
);
|
|
|
|
my $flickr_access_token = $cache->get ('flickr_access_token');
|
|
my $flickr_access_token_secret = $cache->get ('flickr_access_token_secret');
|
|
|
|
if (flickrTestLogin ($flickr_access_token, $flickr_access_token_secret)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
sub FlickrByTags {
|
|
my $text = shift;
|
|
|
|
my $cache = CHI->new (
|
|
driver => 'BerkeleyDB',
|
|
root_dir => $cachedir,
|
|
namespace => __PACKAGE__
|
|
);
|
|
|
|
my $flickr_access_token = $cache->get ('flickr_access_token');
|
|
my $flickr_access_token_secret = $cache->get ('flickr_access_token_secret');
|
|
|
|
# NB: I honestly query random page (among number of pages) of results from api, but always got first page,
|
|
# no matter what is shown in response' "page" parameter. Looks like bug in API. Try to little bit mitigate
|
|
# this bug via query 500 results per page, then we can select random result in this heap. But anyway, let's
|
|
# make this thing future proof and leave randomizer in page select.
|
|
my $result = flickrSearchByTags ($flickr_access_token, $flickr_access_token_secret, $text);
|
|
|
|
if ($result) {
|
|
if (defined ($result->{photos}) && defined ($result->{photos}->{photo})) {
|
|
my $item = irand int(@{$result->{photos}->{photo}});
|
|
$item = ${$result->{photos}->{photo}}[$item];
|
|
$item = sprintf 'https://live.staticflickr.com/%s/%s_%s_z.jpg', $item->{server}, $item->{id}, $item->{secret};
|
|
return $item;
|
|
} else {
|
|
cluck 'Flickr api returns empty search result list';
|
|
return;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
sub FlickrByText {
|
|
my $text = shift;
|
|
|
|
my $cache = CHI->new (
|
|
driver => 'BerkeleyDB',
|
|
root_dir => $cachedir,
|
|
namespace => __PACKAGE__
|
|
);
|
|
|
|
my $flickr_access_token = $cache->get ('flickr_access_token');
|
|
my $flickr_access_token_secret = $cache->get ('flickr_access_token_secret');
|
|
|
|
# NB: I honestly query random page (among number of pages) of results from api, but always got first page,
|
|
# no matter what is shown in response' "page" parameter. Looks like bug in API. Try to little bit mitigate
|
|
# this bug via query 500 results per page, then we can select random result in this heap. But anyway, let's
|
|
# make this thing future proof and leave randomizer in page select.
|
|
my $result = flickrSearchByText ($flickr_access_token, $flickr_access_token_secret, $text);
|
|
|
|
if ($result) {
|
|
if (defined ($result->{photos}) && defined ($result->{photos}->{photo})) {
|
|
my $item = irand int(@{$result->{photos}->{photo}});
|
|
$item = ${$result->{photos}->{photo}}[$item];
|
|
$item = sprintf 'https://live.staticflickr.com/%s/%s_%s_z.jpg', $item->{server}, $item->{id}, $item->{secret};
|
|
return $item;
|
|
} else {
|
|
cluck 'Flickr api returns empty search result list';
|
|
return;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
1;
|