Friday, October 3, 2014

Introduction to the Google Calendar API (HOWTO)




I have used Google Calendars to schedule and control a number of projects (eg. sprinkler system, alarm clock, etc) .  The following How To will get you started.  You will of course need a google account.


Create Project


1) Start by visiting the Google Developers Console

and create a new project.


2) Select the project and navigate on the left menu to APIs & auth then APIs and enable Calendar API for this project.  You can disabled all other APIs if you only need Calendar access.


3) Next, select the Consent screen menu option from the APIs & auth menu.  Enter a Product Name and select an Email Address.  If you do not do this step, you will get a Error: invalid_client error later on.


4) Next, select the Credentials menu option from the APIs & auth menu.  Under OAuth select Create new Client ID.


5) For the Create Client ID select Installed application for Application Type and select Other for Installed Application Type and finally click the Create Client ID button.


6) After the ID has finished being created, click the Download JSON button.  Save and rename the file as something simple like client_secret.json.

This json file contains your API credentials needed to access the Google Calendar APIs.


Install Google API Libraries


1) Install the Google API Libraries using Python's PIP installer:
$ sudo pip install --upgrade google-api-python-client

gflags may or may not be needed, depending on what code you use: (may be optional)
$ sudo pip install --upgrade python-gflags

If you would prefer alternatives, view the Google APIs Client Library for Python page.

Authorize Application


Next we will need to run our application and authorize it against the desired account.

1) Clone my sample code:
# git clone https://github.com/oeey/gcalendar.git

The sample code is just a slight modification from the Getting Started Sample Code.  The Google sample code has some outdated code that will throw some obsoleted warnings.

2) The application has not been authorized to an account yet.  Run the application once and you will be asked to paste a validation URL into your browser.  Login to your desired target account (with the calendars you want to access) and then paste the validation URL into your browser.

For convenience I have a first_auth.py script that is the same script as the gcalendar.py script, but terminates after authorization.  You can run any of the scripts to complete this authorization step.

The first_auth.py is pretty simple:
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow
from oauth2client.client import flow_from_clientsecrets

def main():
    scope = 'https://www.googleapis.com/auth/calendar'
    flow = flow_from_clientsecrets('client_secret.json', scope=scope)

    storage = Storage('credentials.dat')
    credentials = storage.get()

    class fakeargparse(object):  # fake argparse.Namespace
        noauth_local_webserver = True
        logging_level = "ERROR"
    flags = fakeargparse()

    if credentials is None or credentials.invalid:
        credentials = run_flow(flow, storage, flags)

if __name__ == '__main__':
    main()

You may notice the "fakeargparse" code. The run_flow() call wants the flags to be set from the parameters pulled from argparse. I think that is overkill for what I needed, so I just created a fake container so run_flow() wouldn't complain.

Run the first_auth.py script to collect the application authorization.
$ python first_auth.py
Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&client_id=1039XXXXXXXXXXXXXXXXXXXXXXXXXXcs46gdj2.apps.googleusercontent.com&access_type=offline

Enter verification code:

3) Copy the URL into the browser and accept the permissions.


4) You will be presented with a code, to which you will then enter back into the prompt of the first_auth.py application.  The authorization will be stored in the credentials.dat file for future requests.
$ python first_auth.py
Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&client_id=46XXXXXXXXXX2-bXXXXXXXXXXXXXusvh6.apps.googleusercontent.com&access_type=offline

Enter verification code: 4/WzAQfXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2vw2M2Pl7OykQI
Authentication successful.

Now that we have our API credentials and are authorized to access an account, we can begin to play with the Google Calendars.


View Upcoming Events


The upcoming.py script builds off of the first_auth.py script, cycles through the next few upcoming calendar events and displays the event titles.
...
    if credentials is None or credentials.invalid:
        credentials = run_flow(flow, storage, flags)

    http = httplib2.Http()
    http = credentials.authorize(http)
    service = build('calendar', 'v3', http=http)

    print "Upcoming Events:"
    request = service.events().list(calendarId='primary')
    while request != None:
        response = request.execute()
        for event in response.get('items', []):
            print event.get('summary', 'NO SUMMARY')
        request = service.events().list_next(request, response)

This script defaults to the primary calendar associated with the account.


Calendar ID


The previous script defaults to the primary calendar associated with the account.  If you wish to specify an alternate calendar, you will need the Calendar ID.  A calendar's ID can be found on the Calendar Details setting page (same page you can change a calendar's name on).  Look for the Calendar Address line, and the Calendar ID will be in the parenthesis.  It will look something like "a3sd5221ap2qe5ksbev3ip4@group.calendar.google.com".


Next 12 Hours of Events


Finally, to specify a time range for events, I use the following code in my gcalendar.py script.  This code will collect the next 12 hours worth of events.
  ...

    service = build('calendar', 'v3', http=http)

    # get the next 12 hours of events
    epoch_time = time.time()
    start_time = epoch_time - 3600  # 1 hour ago
    end_time = epoch_time + 12 * 3600  # 12 hours in the future
    tz_offset = - time.altzone / 3600
    if tz_offset < 0:
        tz_offset_str = "-%02d00" % abs(tz_offset)
    else:
        tz_offset_str = "+%02d00" % abs(tz_offset)
    start_time = datetime.datetime.fromtimestamp(start_time).strftime("%Y-%m-%dT%H:%M:%S") + tz_offset_str
    end_time = datetime.datetime.fromtimestamp(end_time).strftime("%Y-%m-%dT%H:%M:%S") + tz_offset_str

    print "Getting calendar events between: " + start_time + " and " + end_time

    events = service.events().list(calendarId='primary', timeMin=start_time, timeMax=end_time, singleEvents=True).execute()singleEvents=True).execute()
    #pprint.pprint(events)
    for event in events['items']:
        print event["summary]


And this is the basis for the code I use to schedule my sprinkler system with.





23 comments:

Paul said...

Kenneth,

You're a star for posting this! I cannot tell you how many hours I've spent trying to get my Python calendar connection reestablished since Google (whose motto is "don't be evil") shut off the v1 and v2 APIs of which I never received notice.

These are exactly the instructions I needed. Everything else I found is a bit outdated or vague on certain mission-critical details.

Many thanks for taking the time to put this together and publish it.

Sneak Meeples said...

Paul, I am glad you found it useful. :-)

LaurieAndChris said...

Very, very helpful in getting through Oauth for the first time!

J said...

Wish Google had something as step-by-step as this, rather than documenting with more general syntax suggestions! THANKS!!!

J said...

Sidenote: I got the error

ImportError: cannot import name run_flow

But the project I'm working on isn't that important, so if I am the only one having this issue, then don't worry about it!

Using google-api-python-client version 1.1 if that matters.

Unknown said...

Very good

I can now update my script from API V2 to API V3
But, how can I know start time and end time for each event?

Unknown said...

Even more articles on the thematic of how to improve your skills, you can explore right at this blog

Cassidy said...

Your blog is great

vex 3 said...

wow, that's cool, i'm looking for what you post. thank you

Rajesh said...

Our Female Escorts in Aerocity have smooth bodies that can prepare you for a night of sexual loving. You don’t want to feel self-conscious as you’re safe here at our Call Girls agency. Our Services are all-time service that is accessible for you 24*7 hours. Our Escorts Girls are always prepared to make you fill you’ll have a fantastic alluring night with our lovely girls and you only need for believing simultaneously. Check our other Services also...
Female Escorts in Aerocity
Escorts Service in Aerocity
Call Girls in Mahipalpur
Escorts Service in Mahipalpur
Escorts Service in Mahipalpur

jackman10 said...

I am usually to blogging and i genuinely appreciate your content regularly. This content has truly peaks my interest. I will bookmark your web site and maintain checking achievable details. 마사지

jackman10 said...

Hi, i think that i noticed you visited my web site thus i came to °ßgo back the favor°®.I am attempting to to find things to improve my site!I suppose its adequate to use a few of your ideas!! 스웨디시

jackman10 said...

good post. Ne’er knew this, thankyou for letting me know. 셔츠룸

jackman10 said...

An impressive share, I simply with all this onto a colleague who was simply performing a small analysis on this. And then he the truth is bought me breakfast because I ran across it for him.. smile. So allow me to reword that: Thnx for that treat! But yeah Thnkx for spending plenty of time to discuss this, I believe strongly about it and enjoy reading much more about this topic. If possible, as you grow expertise, would you mind updating your website with an increase of details? It is extremely ideal for me. Huge thumb up in this writing! 강남가라오케

jackman10 said...

there are portable wine coolers which also fit in a small office space. i use them in my home office** แทงบอลออนไลน์

jackman10 said...

of course like your website but you have to take a look at the spelling on several of your posts. A number of them are rife with spelling issues and I in finding it very bothersome to tell the truth on the other hand I?ll definitely come back again. 사설토토

bunny jack said...

I’d constantly want to be update on new content on this website, bookmarked! best UnitedFinances bad credit personal loans guaranteed approval direct lenders

seomaster said...

Your texts on this subject are correct, see how I wrote this site is really very good. play sbobet online

seomaster said...

I might suggest solely beneficial in addition to trusted facts, and so find it: mother's day gift ideas

seomaster said...

I would recommend my profile is important to me, I invite you to discuss this topic. Michigan Microsoft 365 consultant

seomaster said...

members regarded as The most popular online gambling website,  UFABET,  the best direct website based on reviews on various social media. and a small number of members Choose to use online gambling services with football betting websites.  and of course the number of members of This แทงบอลออนไลน์อันดับ1

sabra said...

I am always searching online for storys that can accommodate me. There is obviously a multiple to understand about this. I feel you made few salubrious points in Attributes moreover. Detain busy, awesome career! piston upper assembly

Evan Kristine said...

At Acustom Boxes, we go beyond just providing boxes. We offer various packaging options and services to meet your diverse needs.


A Custom Boxes