Google Calendar Setup
Subscribe to Tech with Tim
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.
Step 2: Place the credentials.json file in your working directory (where your python file is).
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.