API-Google
view release on metacpan or search on metacpan
if (-e $filename) {
say "File $filename exists";
input_if_not_exists(['gapi/client_id', 'gapi/client_secret']);
runserver();
} else {
say "JSON file $filename with API tokens not found. Creating new file...";
setup();
runserver();
}
sub setup {
my $oauth = {};
say "Obtain app client_id and client_secret from http://console.developers.google.com/";
print "client_id: ";
chomp ($oauth->{client_id} = <STDIN>);
print "client_secret: ";
chomp ($oauth->{client_secret} = <STDIN>);
my $tokensfile = Config::JSON->create($filename);
$tokensfile->set('gapi/client_id', $oauth->{client_id});
$tokensfile->set('gapi/client_secret', $oauth->{client_secret});
say 'OAuth details was updated!';
# Remove comment for Mojolicious::Plugin::JSONConfig compatibility
tie my @array, 'Tie::File', $filename or die $!;
shift @array;
untie @array;
};
sub input_if_not_exists {
my $fields = shift;
my $config = Config::JSON->new($filename);
for my $i (@$fields) {
if (!defined $config->get($i) ) {
print "$i: ";
chomp (my $val = <STDIN>);
$config->set($i, $val);
}
}
}
sub runserver {
my $port = empty_port(3000);
say "Starting web server. Before authorization don't forget to set redirect_uri to http://127.0.0.1:$port/";
$ENV{'GOAUTH_TOKENSFILE'} = $filename;
Mojolicious::Commands->start_app('API::Google::Server', 'daemon', '-l', 'http://*:'.$port);
}
__END__
=pod
lib/API/Google.pm view on Meta::CPAN
# ABSTRACT: Perl library for easy access to Google services via their API
use strict;
use warnings;
use Mojo::UserAgent;
use Config::JSON;
use Data::Dumper;
sub new {
my ($class, $params) = @_;
my $h = {};
if ($params->{tokensfile}) {
$h->{tokensfile} = Config::JSON->new($params->{tokensfile});
} else {
die 'no json file specified!';
}
$h->{ua} = Mojo::UserAgent->new();
$h->{debug} = $params->{debug};
$h->{max_refresh_attempts} = $params->{max_refresh_attempts} || 5;
return bless $h, $class;
}
sub refresh_access_token {
my ($self, $params) = @_;
warn "Attempt to refresh access_token with params: ".Dumper $params if $self->{debug};
$params->{grant_type} = 'refresh_token';
$self->{ua}->post('https://www.googleapis.com/oauth2/v4/token' => form => $params)->res->json; # tokens
};
sub client_id {
shift->{tokensfile}->get('gapi/client_id');
}
sub ua {
shift->{ua};
}
sub client_secret {
shift->{tokensfile}->get('gapi/client_secret');
}
sub refresh_access_token_silent {
my ($self, $user) = @_;
my $tokens = $self->refresh_access_token({
client_id => $self->client_id,
client_secret => $self->client_secret,
refresh_token => $self->get_refresh_token_from_storage($user)
});
warn "New tokens got" if $self->{debug};
my $res = {};
$res->{old} = $self->get_access_token_from_storage($user);
warn Dumper $tokens if $self->{debug};
if ($tokens->{access_token}) {
$self->set_access_token_to_storage($user, $tokens->{access_token});
}
$res->{new} = $self->get_access_token_from_storage($user);
return $res;
};
sub get_refresh_token_from_storage {
my ($self, $user) = @_;
warn "get_refresh_token_from_storage(".$user.")" if $self->{debug};
return $self->{tokensfile}->get('gapi/tokens/'.$user.'/refresh_token');
};
sub get_access_token_from_storage {
my ($self, $user) = @_;
$self->{tokensfile}->get('gapi/tokens/'.$user.'/access_token');
};
sub set_access_token_to_storage {
my ($self, $user, $token) = @_;
$self->{tokensfile}->set('gapi/tokens/'.$user.'/access_token', $token);
};
sub build_headers {
my ($self, $user) = @_;
my $t = $self->get_access_token_from_storage($user);
my $headers = {};
$headers->{'Authorization'} = 'Bearer '.$t;
return $headers;
}
sub build_http_transaction {
my ($self, $params) = @_;
warn "build_http_transaction() params : ".Dumper $params if $self->{debug};
my $headers = $self->build_headers($params->{user});
my $http_method = $params->{method};
my $tx;
if ($http_method eq 'get' || $http_method eq 'delete') {
$tx = $self->{ua}->build_tx(uc $http_method => $params->{route} => $headers);
lib/API/Google.pm view on Meta::CPAN
} else {
die 'wrong http_method on no payload if using POST';
}
return $tx;
}
sub api_query {
my ($self, $params, $payload) = @_;
warn "api_query() params : ".Dumper $params if $self->{debug};
$payload = { payload => $payload };
%$params = (%$params, %$payload);
my $tx = $self->build_http_transaction($params);
my $res = $self->{ua}->start($tx)->res->json;
lib/API/Google/GCal.pm view on Meta::CPAN
$API::Google::GCal::VERSION = '0.12';
use parent 'API::Google';
# use base 'API::Google';
# ABSTRACT: Google Calendar API client
sub new {
my ($class, $params) = @_;
my $self = API::Google->new($params);
$self->{api_base} = 'https://www.googleapis.com/calendar/v3';
bless $self, $class;
return $self; # just for clearance
}
sub get_calendars {
my ($self, $user, $fields) = @_;
my $res = $self->api_query({
method => 'get',
route => $self->{api_base}.'/users/me/calendarList',
user => $user
});
if ($fields) {
my @a;
for my $item (@{$res->{items}}) {
push @a, { map { $_ => $item->{$_} } grep { exists $item->{$_} } @$fields };
}
return \@a;
} else {
return $res;
}
}
sub get_calendar_id_by_name {
my ($self, $user, $name) = @_;
my $all = $self->get_calendars($user, ['id', 'summary']); # arr ref
my @n = grep { $_->{'summary'} eq $name } @$all;
my $full_id = $n[0]->{id};
return $full_id;
}
sub add_event {
my ($self, $user, $calendar_id, $event_data) = @_;
$self->api_query({
method => 'post',
route => $self->{api_base}.'/calendars/'.$calendar_id.'/events',
user => $user
}, $event_data);
}
sub busy_time_ranges {
my ($self, $params) = @_;
$self->api_query({
method => 'post',
route => $self->{api_base}.'/freeBusy',
user => $params->{user}
}, {
timeMin => $params->{dt_start},
timeMax => $params->{dt_end},
timeZone => $params->{timeZone},
items => [{ 'id' => $params->{calendarId} }]
});
};
sub events_list {
my ($self, $params) = @_;
if (!defined $params->{calendarId}) { die "No calendarId provided as parameter"}
if (!defined $params->{user}) { die "No user provided as parameter"}
my $res = $self->api_query({
method => 'get',
route => $self->{api_base}.'/calendars/'.$params->{calendarId}.'/events',
user => $params->{user}
});
lib/API/Google/Server.pm view on Meta::CPAN
use Data::Dumper;
use Config::JSON;
use Tie::File;
use Crypt::JWT qw(decode_jwt);
use feature 'say';
use Mojo::Util 'getopt';
use Mojolicious::Plugin::OAuth2;
# use Mojo::JWT;
# sub return_json_filename {
# use Cwd;
# my $cwd = getcwd;
# opendir my $dir, $cwd or die "Cannot open directory: $!";
# my @files = readdir $dir;
# my @j = grep { $_ =~ /\w+.json/ } @files;
# return $j[0];
# }
# my $f = return_json_filename();
lib/API/Google/Server.pm view on Meta::CPAN
google => {
key => $config->get('gapi/client_id'), # $config->{gapi}{client_id},
secret => $config->get('gapi/client_secret'), #$config->{gapi}{client_secret},
authorize_url => 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code',
token_url => 'https://www.googleapis.com/oauth2/v4/token'
}
};
helper get_new_tokens => sub {
my ($c,$auth_code) = @_;
my $hash = {};
$hash->{code} = $c->param('code');
$hash->{redirect_uri} = $c->url_for->to_abs->to_string;
$hash->{client_id} = $config->get('gapi/client_id');
$hash->{client_secret} = $config->get('gapi/client_secret');
$hash->{grant_type} = 'authorization_code';
my $tokens = $c->ua->post('https://www.googleapis.com/oauth2/v4/token' => form => $hash)->res->json;
return $tokens;
};
lib/API/Google/Server.pm view on Meta::CPAN
# =method get_all_google_jwk_keys
# Get all Google JWK keys for validation of JSON Web Token
# Check https://jwt.io/ and https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken for more details
# return arrayref
# =cut
# helper get_all_google_jwk_keys => sub {
# my $c = shift;
# my $certs = $c->ua->get('https://www.googleapis.com/oauth2/v3/certs')->res->json;
# # return $certs;
# my @keys = @{$certs->{keys}};
# return \@keys;
# # return $certs->{keys}[1];
# };
# =method get_google_jwk_key_by_kid
lib/API/Google/Server.pm view on Meta::CPAN
# $c->get_google_cert_by_kid($kid,$crts) # $kid - string, $crts - arrayref
# Example of usage:
# $c->get_google_cert_by_kid($header->{kid},$crts)
# =cut
# helper get_google_jwk_key_by_kid => sub {
# my ($c, $kid, $jwks_arrayref) = @_;
# if (!defined $jwks_arrayref) {
# warn 'get_google_cert_by_kid(): $ctrs is not defined, obtaining from Google...';
# $jwks_arrayref = $c->ua->get('https://www.googleapis.com/oauth2/v3/certs')->res->json->{keys};
# }
# # my @keys = @{$crts->{keys}};
# my @keys = @$jwks_arrayref;
# my $size = scalar @keys;
lib/API/Google/Server.pm view on Meta::CPAN
# }
# }
# warn 'JWK key with particular kid not found';
# return undef;
# };
helper get_email => sub {
my ($c, $access_token) = @_;
my %h = (
'Authorization' => 'Bearer '.$access_token
);
$c->ua->get('https://www.googleapis.com/auth/plus.profile.emails.read' => form => \%h)->res->json;
};
get "/" => sub {
my $c = shift;
app->log->info("Will store tokens at".$config->getFilename ($config->pathToFile));
if ($c->param('code')) {
app->log->info("Authorization code was retrieved: ".$c->param('code'));
my $tokens = $c->get_new_tokens($c->param('code'));
app->log->info("App got new tokens: ".Dumper $tokens);
if ($tokens) {
my $user_data;
( run in 0.302 second using v1.01-cache-2.11-cpan-4d50c553e7e )