API-Google

 view release on metacpan or  search on metacpan

bin/goauth  view on Meta::CPAN

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.371 second using v1.01-cache-2.11-cpan-a5abf4f5562 )