Reputation: 53
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
Upvotes: 3
Views: 3453
Reputation: 1
actually the same error come with my code and i changes the code of datetime then also give me same error what i can do to resolved the issue regrading this'' and this is my code--> def create_events(self): start_date = datetime.datetime(2023,1,5,18,30,0,0).isoformat()+'Z' end_date = datetime.datetime(2023,1,5,18,45,0,0).isoformat()+'Z'
calendar_Id = '[email protected]'
hours_adjustment = -8
events_request_body = {
'start':{
'dateTime':start_date,
'timeZone':'Asia/kolkata'
},
'end':{
'dateTime':end_date,
'timeZone': 'Asia/kolkata'
},
}
calendar = service.events().insert(calendarId=calendar_Id,
body=events_request_body,).execute()
return calendar
how i can resolved the error and phase the error with in 3 days ... and i am very ferstated
Upvotes: 0
Reputation: 348
This may not help anyone else, but it was the solution for me. It may be what @Oriol Castander was getting at. I kept getting 403 errors saying missing an API key. But that was, for me, a false error. The actual problem was the date I was using. in the events().list command. I was using an exact date (June 4, 2022) rather than now() and I needed to format it as follows:
date=datetime.datetime(2022, 6, 4,0,0,0,0).isoformat() + 'Z'
Once I had the date correctly formatted the call ran without error.
Upvotes: 2
Reputation: 648
I have recreated and run your code and I could not bump into the 403
. The code looks fine and it should work, especially since you can retrieve the data with a list command. This is not a definitive answer, but to get it to work you could try:
'https://www.googleapis.com/auth/calendar'
scope, since is the least restrictive one and the one needed to create an event.Nevertheless, I did manage to find an error that will cause your code to fail when you get it up and running. The 'start'
and 'end'
properties need both a 'dateTime'
and a 'timeZone'
property as it is done in this example. Therefore this code will fail:
newEvent['start']['dateTime'] = str(workingDate) + 'T13:00:00+3:00'
newEvent['end']['dateTime'] = str(workingDate) + 'T17:00:00+03:00'
and should be replace with this one:
newEvent['start']['dateTime'] = str(workingDate) + 'T13:00:00'
newEvent['start']['timeZone'] = 'Your timeZone'
newEvent['end']['dateTime'] = str(workingDate) + 'T17:00:00'#Having the +3:00 will fail
newEvent['end']['timeZone'] = 'Your timeZone'
And you can find your timeZone in, of course, Wikipedia: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Upvotes: 2