Moxad Enterprises Inc. ...blog

back to Moxad Enterprises

Google Calendar API v3 perl access

November 24th, 2014

The problem

Recently I was asked if I could answer why an on-line booking system using Google Calendar no longer worked. It turns out that the API it was using was shutdown on Nov 17, 2014. According to Google Developer (a Google web-page no longer available): "This API is subject to the Deprecation Policy and will be shutdown on November 17, 2014. Please use APIv3 instead."

It also turns out that as of v3, the API requires the OAuth2 authentication scheme to be used.
According to Google authentication Your application must use OAuth 2.0 to authorize requests. No other authorization protocols are supported.

There are two ways to gain access to Google Calendar with the v3 API. According to the Google access methods there is either the client libraries, or by Sending HTTP requests and parsing the responses. (ie: REST).

The application I was asked to look at was written in PHP. So first I started to look at the PHP client libraries. What I saw for PHP libraries ,did not give me a warm fuzzy feeling:
"This client library is in beta. We will make an effort to support the library and maintain backwards compatibility in the future, but we reserve the right to make incompatible changes when necessary."

Not only that, but I found the lack of documentation and code samples for the Google Calendar API to be frustrating. So it was with many other people as well. In fact, there is a article at Techcrunch saying that a survey of 100 developers found that Google came in 2nd place for having the worse APIs (They were beat by Facebook for having the worst).

Eureka

Just when I was ready to give up (I didn’t really need to do this), I found a comment to an article at arstechnica by scHarvey who eventually:
"said fuck it killed the PHP API and just went with the REST API and JSON data. Took me three hours to do what Id been struggling with for a week."
scHarvey also referred to an article that had everything (s)he needed to do what was wanted.

So, I looked up that article, and scHarvey was right. It was a 3-part article where part1 explained how to set up a Google Calendar, part2 was how to set up the OAuth2 authentication and get a refresh access token, and part3 was the actual PHP code to use the API.

I won't repeat here what has already been explained in those articles and suggest you use those. What this posting is about though is that I wanted to access Google Calendar via the command-line, and I didn't want to use PHP to do that. BTW, if you did want PHP command-line access, I ended up having to install the packages php5, libapache2-mod-php5, php5-cli, and php5-curl on my Linux Mint system to get a full PHP install, including command-line and curl functionality, if you wanted to go that route.

The code

So, I wrote a Perl library of functions so I could write command-line Perl programs. And I wrote several sample programs to call these functions. I also wrote a Bourne shell version of the oauth2.php program (from part2 of the above articles) to get a refresh token. The Bourne shell program requires that curl is installed. I'm not going to cover the Bourne shell program here, but if you use it, just read the comments at the top. It only requires modification once, as opposed to twice like the PHP version oauth2.php.
All of this stuff is here on Github.

I'll walk through a sample program to create a new Calendar entry using my library. Note that this is just a simple library file, not a module. If you really wanted to see what is happening under the covers (as I did), I suggest just grab the library calendar_functions.pl off of github. I believe it is fairly straight-forward if you wanted to use this to come up with different language versions.

The Perl requirements are the JSON and LWP packages from CPAN , and the Bourne shell requirements for creating the 'refresh' token is the curl command.

If you followed part1 and part2 of the article I referred to above, then you now have a calendar created, and you have OAuth2 authentication information. For this example, lets assume you don't know the calendar-ID (which you could get by just logging into your Google account and checking the Settings for your calendars).

We pull in the library:

      require "calendar_functions.pl" ;
      

First, you need to set up your authentication information:

      my %myauth = (
          'client_secret' => '123456789012345678901234',
          'refresh_token' => '123456789012345678901234567890',
          'client_id'     => '123456789.apps.googleusercontent.com',
          'grant_type'    => 'refresh_token',
      ) ;
      

and lets set an descriptive Agent and our timezone while we are at it:

      my $agent    = "MyApp/0.1" ;
      my $timezone = "-05:00" ;
      

I wrote the functions so that they always return a string. If successful, it is either a JSON string of the info we want, or a status, but if there is a error, then it is prepended with ‘Error:’.

So first we get a token:

      # get a token
      
      my $token = access_token( \%myauth, $agent ) ;
      if ( $token =~ /^Error/ ) {
          print "$token\n" ;
          exit(1) ;
      }
      

Now lets get our calendar list.
Remember, we're pretending we don't know the calendar-ID, so grab a list of all our calendars:

      # get our calendar list data
      
      my $cal_data = get_calendar_list_data( $token, $agent ) ;
      if ( $cal_data =~ /^Error/ ) {
          print "$cal_data\n" ;
          exit(1) ;
      }
      

Now lets say the calendar we want is called "Appointments". So lets look up the calendar ID of "Appointments" using the calendar list data we just got.

      # get calendar ID for Appointments calendar
      
      my $name = "Appointments" ;
      my $id   = get_calendar_id( $cal_data, $name ) ;
      if ( $id =~ /^Error/ ) {
          print "$id\n" ;
          exit(1) ;
      }
      

Now lets create a JSON structure of date/time/etc of the entry we want to post:

      # create our JSON event structure
    
      my $date        = "2014-11-27" ;
      my $starttime   = "18:00" ;
      my $endtime     = "19:30" ;
      my $title       = "Pick up Sally" ;
      my $description = "dont forget the ice-cream" ;
    
      my $json_dates  = create_JSON_dates(
          $date, $starttime, $endtime,
          $timezone, $title, $description ) ;
      

Lets see if that time-slot is available for booking.
First we need to get the bookings in that time slot:

      # get our current bookings for that date/time
      
      my $bookings = get_bookings(
          $date, $starttime, $endtime,
          $timezone, $id, \%myauth, $agent ) ;
      if ( $bookings =~ /^Error/ ) {
          print "$bookings\n" ;
          exit(1) ;
      }
      

Now get a count of the number of entries in the time we want.
So we want to bail if the number is greater than zero:

      # see if time-slot already taken
      
      my $count = is_booked( $bookings ) ;
      if ( $count ) {
          print "Sorry - that time is already booked\n" ;
          exit 0 ;
      }
      

Ok, we made it this far, now book the appointment:

      # now book the appointment
      
      my $post = create_cal_entry( $json_dates, $token, $id ) ;
      if ( $post =~ /^Error/ ) {
          print "$post\n" ;
          exit(1) ;
      }
      
      print "Booked appt. status from create_cal_entry() is $post\n" ;
      

And that's it.
This code is not in use and has not been torture tested. I wrote it as a programming exercise to make sure I really understood what was going on. The entire program, as well as several small example programs, the library and the 'refresh' token script can be downloaded here from Github

You can contact RJ by e-mail at rj@moxad.com