Recently I started playing around within Google's Calendar API in order to make a personal app for myself that would randomly create daily highlights and then make events out of them before passing it to my google calendar. I have very little experience with this sort of thing, almost none, but google's Quickstart guide got me set up in a decent place. I pretty much just took the Quickstart python code that they provided, added some of my own functions for making and deleting the events and adjusted the scope to include the permissions for creating and deleting said events. The code that I used:
from __future__ import print_function
import datetime
from hashlib import new
import os.path
from re import S
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from highlightsGenerator import *
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly',
'https://www.googleapis.com/auth/calendar.events',
'https://www.googleapis.com/auth/calendar']
templateEvent = {
'summary': 'Daily Highlight',
'description': '',
'start': {
'dateTime': '',
},
'end': {
'dateTime': '',
},
'reminders': {
'useDefault': True,
},
}
def createHighlightEvents(service):
workingDate = datetime.date.today()
workingDate += datetime.timedelta(days=1)
highlightSchedule = scheduleGenerator()
print(highlightSchedule)
for k in highlightSchedule:
newEvent = templateEvent
newEvent['description'] = k
newEvent['start']['dateTime'] = str(workingDate) + 'T13:00:00+3:00'
newEvent['end']['dateTime'] = str(workingDate) + 'T17:00:00+03:00'
service.events().insert(calendarId='primary', body=newEvent).execute()
workingDate += datetime.timedelta(days=1)
def deleteHighlightEvents(service):
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
events_result = service.events().list(calendarId='primary', q='Daily Highlight',timeMin=now,
maxResults=20, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
# if not events:
# print('No upcoming events found.')
# return
for event in events:
eID = event['id']
service.events().delete(calendarId='primary', eventId=eID).execute()
def reRollHighlightEvents(service):
deleteHighlightEvents(service)
createHighlightEvents(service)
def getDate(dateTime):
dateStr = dateTime[:len(dateTime) - 6]
date = datetime.datetime.strptime(dateStr, '%Y-%m-%dT%H:%M:%S')
return date
def shiftHighlights(service, numDays):
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
events_result = service.events().list(calendarId='primary', q='Daily Highlight',timeMin=now,
maxResults=20, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
print('No upcoming events found.')
return
for event in events:
newStartDate = getDate(event['start']['dateTime']) + datetime.timedelta(days=numDays)
newEndDate = getDate(event['end']['dateTime']) + datetime.timedelta(days=numDays)
newStartDateStr = 'T'.join([str(newStartDate.date()), str(newStartDate.time())])
newEndDateStr = 'T'.join([str(newEndDate.date()), str(newEndDate.time())])
newEvent = event
newEvent['start']['dateTime'] = newStartDateStr + '+03:00'
newEvent['end']['dateTime'] = newEndDateStr + '+03:00'
service.events().update(calendarId='primary', eventId=event['id'], body=newEvent).execute()
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.json 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.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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(
'client_secret_158794507060-ucqbqgapmlf7lmvre6knjc5nehd00ms0.apps.googleusercontent.com.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
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.')
return
# Prints the start and name of the next 10 events
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
print(start, event['summary'])
userInput = input('Create (c), Delete (d), Re-Roll (r), Shift (s) highlights?\n')
if userInput == 'c':
createHighlightEvents(service)
elif userInput == 'd':
deleteHighlightEvents(service)
elif userInput == 'r':
reRollHighlightEvents(service)
elif userInput == 's':
numDays = input('How many days would you like to shift by? (x) to cancel\n')
if numDays != 'x' and numDays.isnumeric:
shiftHighlights(service, int(numDays))
elif numDays != 'x':
print('Please input a number or (x) to cancel')
else:
print('That is not one of the options')
except HttpError as error:
print('An error occurred: %s' % error)
if __name__ == '__main__':
main()
I managed to get it to do what I wanted and for a bit that was basically it, but then when I tried running it yesterday it gave a http 400 error for a bad request. Clicking the link it provided gave me this:
{
"error": {
"code": 403,
"message": "The request is missing a valid API key.",
"errors": [
{
"message": "The request is missing a valid API key.",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}
Now as you may have seen I left in the code for retrieving and displaying the first 10 upcoming events. It is still able to run that just fine, but If attempt to create an event or delete an event then this error message shows up. I am quite confused by this message as I have done all the authorisation that I believed I needed to. My client secret has not changed, but even then I re-downloaded it to see if that would do anything, but it did not. I deleted the token and had it run the authorisation again and again I gave permission. This also proved fruitless and as far as I'm aware my scopes are fine.
There were a couple questions on here with similar errors, but they seemed to be getting it for different reasons than me (from what I could tell) or because they were missing an authorisation that I believe I already have.
Again, I have almost no experience with this sort of thing, so there may be something incredibly obvious that I am not doing, but I'm afraid I don't really know what that may be.
Any assistance you can provide would be much appreciated