Tech With Tim Logo
Go back

Google Calendar Setup

In this python voice assistant tutorial we will be setting up the google calendar API for python. In later videos we will use this API to remind us of upcoming events and to check if we are free at certain times.

Setup

The setup for this is pretty straightforward and can be followed directly from here.

Step 1: Enable the Google Calendar API from here. Then download the credentials.json file from the prompt. kuva_2023-05-01_184427470.png

Step 2: Place the credentials.json file in your working directory (where your python file is). kuva_2023-05-01_184444319.png

Step 3: Install modules with pip.

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

Step 4: Copy the following code into the mainline of your python file.

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

def main():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Getting the upcoming 10 events')
    events_result = service.events().list(calendarId='primary', timeMin=now,
                                        maxResults=10, singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        print(start, event['summary'])

if __name__ == '__main__':
    main()

Refactoring

Now that we've copied this mess of code we need to refactor it to work in our project.

We will split up the code into two main functions: authenticate_google, get_events. Then we will move the import statements and global variables to the top of our program. After these changes we get something that looks like this.

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import os
import time
import playsound
import speech_recognition as sr
from gtts import gTTS

SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

def speak(text):
    tts = gTTS(text=text, lang="en")
    filename = "voice.mp3"
    tts.save(filename)
    playsound.playsound(filename)


def get_audio():
    r = sr.Recognizer()
    with sr.Microphone() as source:
        audio = r.listen(source)
        said = ""

        try:
            said = r.recognize_google(audio)
            print(said)
        except Exception as e:
            print("Exception: " + str(e))

    return said


def authenticate_google():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)

    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)

        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    return service


def get_events(n, service):
    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print(f'Getting the upcoming {n} events')
    events_result = service.events().list(calendarId='primary', timeMin=now,
                                        maxResults=n, singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        print(start, event['summary'])


service = authenticate_google()
get_events(2, service)

The authenticate_google function will be responsible for performing the authentication at the beginning of our script. While the get_events function will get the n amount of events that appear next in our calendar.

Running the Program

For the first run of the program you will see that a web browser opens and asks you if you would like to proceed. You must click the advanced tab -> then select visit website anyways. Now you can sign into the google account that you would like to use with the bot.

The next times you run the program you will not need to perform this step. This is because the script we've copied saves our credential information in a .pickle file. You can see the file in your main script. If you want to change to a new google calendar account simply delete the .pickle file and run the program again.

In later tutorials we will add more functionality to this.

Design & Development by Ibezio Logo