Modifying a private calender with Python backend using google functions - python-3.x

so I have the following problem:
I want to manipulate a calendar(my private google calendar) using GoogleFunctions with python backend.I have now followed an code example (which inserts an event) and in the google console it is also shown that a call has taken place. Now I'm just wondering which calendar I'm modifying?
The problem for me is, as soon as I enter the calendarId of my private calendar, the function runs on an error. But actually the service user has all permissions. If I understand it correctly, then I can manipulate all calendars within the organization with the Service user?
So that's my code. It works so far. Now I only ask myself, can I see the calendar I am modifying somewhere?
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2 import service_account
SUBJECT = 's.........415.iam.gserviceaccount.com'
def main():
# create credntials
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject(SUBJECT)
service = build('calendar', 'v3', credentials=delegated_credentials)
d = datetime.utcnow().date()
tomorrow = datetime(d.year, d.month, d.day, 10)
start = tomorrow.isoformat()
end = (tomorrow).isoformat()
body={"summary": 'Hello there, Automating calendar',
"description": 'Google calendar with python',
"start": {"dateTime": start, "timeZone": 'Asia/Karachi'},
"end": {"dateTime": end, "timeZone": 'Asia/Karachi'},
}
event = service.events().insert(calendarId=SUBJECT,body=body).execute()
if __name__ == "__main__":
main()

Related

Service Error 500 coming when testing google calendar api in Django Framework

I am trying to develop a to do notes app in django framework. And I want to integrate Google Calendar Api with this project to sync tasks with google calendar. I followed the steps from this website: https://blog.benhammond.tech/connecting-google-cal-api-and-django#comments-list
But when I try to test the demo page of website, it shows Service Error 503. Please let me kindly know how to fix the problem! I only know some basics of django.
Here's my calendar API Code-
from decouple import config
from google.oauth2 import service_account
import googleapiclient.discovery
import datetime
import json
CAL_ID = "104a92a3cd198c2062645e570737318d05c2dfb2f1361e64b743a4b0e223de66#group.calendar.google.com"
SCOPES = ['https://www.googleapis.com/auth/calendar']
SERVICE_ACCOUNT_FILE = json.load(open('google-credentials.json'))
def test_calendar():
print("RUNNING TEST_CALENDAR()")
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = googleapiclient.discovery.build(
'calendar', 'v3', credentials=credentials)
print(service)
# CREATE A NEW EVENT
new_event = {
'summary': "New Task 1",
'location': 'Kolkata, WB',
'description': 'Description of Task 1',
'start': {
'date': f"{datetime.date.today()}",
'timeZone': 'America/New_York',
},
'end': {
'date': f"{datetime.date.today() + datetime.timedelta(days=3)}",
'timeZone': 'America/New_York',
},
}
service.events().insert(calendarId=CAL_ID, body=new_event).execute()
print('Event created')
# GET ALL EXISTING EVENTS
events_result = service.events().list(
calendarId=CAL_ID, maxResults=2500).execute()
events = events_result.get('items', [])
# LOG THEM ALL OUT IN DEV TOOLS CONSOLE
for e in events:
print(e)
# uncomment the following lines to delete each existing item in the calendar
#event_id = e['id']
# service.events().delete(calendarId=CAL_ID, eventId=event_id).execute()
return events
The interpreter when it runs the test_calendar() function , it doesn't prints the services.
This should let me see the demo page of django where list task are shown taken from the google calender.

Create an event with conference using python and Google Calendar API creates the event but not the conference

I am trying to create an event using Google Calendar API in Python 3. I also want to generate a Google Meet conference link for the event. I am using the documentations provided here:
https://developers.google.com/calendar/quickstart/python
https://developers.google.com/calendar/v3/reference/events#conferenceData
https://developers.google.com/calendar/create-events
The event is created without a problem. However, it is missing the conference link. My code so far is as follows:
from pathlib import Path
from pickle import load
from pickle import dump
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from uuid import uuid4
from typing import Dict, List
from oauth2client import file, client, tools
class EventPlanner:
def __init__(self, guests: Dict[str, str], schedule: Dict[str, str]):
guests = [{"email": email} for email in guests.values()]
service = self._authorize()
self.event_states = self._plan_event(guests, schedule, service)
#staticmethod
def _authorize():
scopes = ["https://www.googleapis.com/auth/calendar"]
credentials = None
token_file = Path("./calendar_creds/token.pickle")
if token_file.exists():
with open(token_file, "rb") as token:
credentials = load(token)
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
credentials.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('calendar_creds/credentials.json', scopes)
credentials = flow.run_local_server(port=0)
with open(token_file, "wb") as token:
dump(credentials, token)
calendar_service = build("calendar", "v3", credentials=credentials)
return calendar_service
#staticmethod
def _plan_event(attendees: List[Dict[str, str]], event_time, service: build):
event = {"summary": "test meeting",
"start": {"dateTime": event_time["start"]},
"end": {"dateTime": event_time["end"]},
"attendees": attendees,
"conferenceData": {"createRequest": {"requestId": f"{uuid4().hex}",
"conferenceSolutionKey": {"type": "hangoutsMeet"}}},
"reminders": {"useDefault": True}
}
event = service.events().insert(calendarId="primary", sendNotifications=True, body=event, conferenceDataVersion=1).execute()
return event
if __name__ == "__main__":
plan = EventPlanner({"test_guest": "test.guest#gmail.com"}, {"start": "2020-07-31T16:00:00",
"end": "2020-07-31T16:30:00"})
print(plan.event_states)
I suspect that the problem is with where I have passed conferenceDataVersion but the docs are not exactly clear about where it has to be passed other than that it must be passed. I also tried putting it in the body of the event or in createRequest. It always creates the event but not the conference. Unfortunately, I could not find anything about this online anywhere. Maybe I'm actually that bad at searching, but I have been testing different things and searching for a solution for several days! If anyone knows what I am missing, I will truly appreciate their assistance.
Thanks to #Tanaike, I found what was the problem. The token which is generated the first time the API is authenticated is very specific. The problem I was having turned out to be just with that. As soon as I removed the token and had it get generated again, the problem was solved. That being said, I have no idea why the problem appeared in the first place. I will update the response if I find the reason behind it. But for now, if you are having the same problem, just remove the token and regenerate it.
With this code we can create the conference (Google meet link) for me it works
"conferenceData": {
"createRequest": {
"requestId": "SecureRandom.uuid"
}
}

Google calendar API 400 error when creating event

I am trying to create an event using Google Calendar API in Python 3 using the documentations provided here:
https://developers.google.com/calendar/quickstart/python
https://developers.google.com/calendar/v3/reference/events#conferenceData
https://developers.google.com/calendar/create-events
However, I keep getting error 400 bad request and I have no idea why. My code is as follows:
from pathlib import Path
from pickle import load
from pickle import dump
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from uuid import uuid4
from typing import Dict, List
from oauth2client import file, client, tools
class EventPlanner:
"""
pass
"""
def __init__(self, guests: Dict[str, str], schedule: Dict[str, str]):
guests = [{"email": email} for email in guests.values()]
service = self._authorize()
self.event_states = self._plan_event(guests, schedule, service)
#staticmethod
def _authorize():
scopes = ["https://www.googleapis.com/auth/calendar"]
credentials = None
token_file = Path("./calendar_creds/token.pickle")
if token_file.exists():
with open(token_file, "rb") as token:
credentials = load(token)
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
credentials.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('calendar_creds/credentials.json', scopes)
credentials = flow.run_local_server(port=0)
with open(token_file, "wb") as token:
dump(credentials, token)
calendar_service = build("calendar", "v3", credentials=credentials)
return calendar_service
#staticmethod
def _plan_event(attendees: List[Dict[str, str]], event_time, service: build):
event = {"summary": "test meeting",
"start": {"dateTime": event_time["start"]},
"end": {"dateTime": event_time["end"]},
"attendees": attendees,
"conferenceData": {"createRequest": {"requestId": f"{uuid4().hex}",
"conferenceSolutionKey": {"type": "hangoutsMeet"}}},
"reminders": {"useDefault": True}
}
event = service.events().insert(calendarId="primary", sendNotifications=True, body=event).execute()
return event
if __name__ == "__main__":
plan = EventPlanner({"test_guest": "test.guest#gmail.com"}, {"start": "2020-07-29T20:00:00-4:00",
"end": "2020-07-29T20:30:00-4:00"})
print(plan.event_states)
The first time authentication was done successfully. I also tried the different ways mentioned in the docs but non work. Does anyone know what I am doing wrong? Thanks.
I think that the reason of your issue is as follows.
Modification points:
At RFC3339, for dateTime of start, please modify 2020-07-29T20:00:00-4:00 to 2020-07-29T20:00:00-04:00. Also please modify this for dateTime of end.
Please add the time zone.
Modified script:
plan = EventPlanner({"test_guest": "test.guest#gmail.com"}, {"start": "2020-07-29T20:00:00-04:00", "end": "2020-07-29T20:30:00-04:00"})
And
time_zone = str(get_localzone())
event = {"summary": "test meeting",
"start": {"dateTime": event_time["start"], "timeZone": time_zone},
"end": {"dateTime": event_time["end"], "timeZone": time_zone},
"attendees": attendees,
"conferenceData": {"createRequest": {"requestId": f"{uuid4().hex}",
"conferenceSolutionKey": {"type": "hangoutsMeet"}}},
"reminders": {"useDefault": True}
}
Note:
I'm not sure about your time zone. So I used get_localzone() for the modified script. In this case, please also use from tzlocal import get_localzone. If you want to change the time zone, please modify above script.
This modified script supposes that you have already been able to create new event to the Google Calendar using Calendar API. Please be careful this.
References:
Events: insert
RFC3339
For me what worked was to copy the URI that is in the redirect_uri_mismatch window and past it in the redirect URI in the credentials of my project in the google console.

How to interact with the Gmail API - Delegate User - Python 3.7

I am trying to write a Python application which simply adds a user as a delegate to another users mailbox.
I am following the API # Google API Documentation - Users.settings.delegates: create
However, I am struggling to find how to the parameters of:
User - an account which is TOBE added to a delegate Mailbox
Mailbox - the account which has the Mailbox I wish the account to become a delegate of.
I have currently tried making an API which has the delegate user. However, it does not seem to be interacting how I would expect. I am hoping Google will create a responsive API for the browser to support this. However, I am struggling with the code:
from googleapiclient import discovery
from oauth2client.service_account import ServiceAccountCredentials
def main(user_to_be_added, delegated_mailbox):
service_account_credentials = ServiceAccountCredentials.from_json_keyfile_name('credentials/service_account.json')
service_account_credentials = service_account_credentials.create_scoped('https://mail.google.com/ https://www.googleapis.com/auth/gmail.insert https://www.googleapis.com/auth/gmail.modify')
service_account_credentials = service_account_credentials.create_delegated(user_to_be_added)
service = discovery.build('gmail', 'v1', credentials=service_account_credentials)
response = service.users().settings().delegates().create().execute(userId=delegated_mailbox)
if __name__ == '__main__':
main('some_account_to_be_added#gmail.com', 'delegated_mailbox#gmail.com')
Am I interacting with this API completely wrong? If so, how has anyone else achieved this?
Thank you for your time.
Jordan
Working Solution:
from googleapiclient import discovery
from google.oauth2 import service_account
def _create_client(subject):
credentials = service_account.Credentials
credentials = credentials.from_service_account_file('credentials/service_account.json',
scopes=['https://www.googleapis.com/auth/gmail.settings.sharing',
'https://www.googleapis.com/auth/gmail.settings.basic'],
subject=subject)
service = discovery.build('gmail', 'v1', credentials=credentials)
return service
def add_delegate_to_email(user_to_be_added, delegated_mailbox):
service = _create_client(user_to_be_added)
body = {
"delegateEmail": delegated_mailbox,
"verificationStatus": "accepted"
}
try:
response = service.users().settings().delegates().create(userId='me', body=body).execute()
print(response)
except Exception as e:
print('Exception: {}'.format(e))
Main problem: from oauth2client.service_account import ServiceAccountCredentials is deprecated as Google took ownership with google-auth.

Authorisation problems when using google service account. Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup

I am writing a python wrapper for fusion tables.
I decided to use google service account for accessing the service. My code is:
import httplib2
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
scopes = ['https://www.googleapis.com/auth/fusiontables']
credentials = ServiceAccountCredentials.from_json_keyfile_name('__Remak APIS-37c11e21531ad.json', scopes)
http = httplib2.Http()
if not credentials.access_token:
credentials.refresh(http)
service = build('fusiontables', 'v2', http=http)
def test():
table_id = '1esH-YayZegZH69VsiVBq0YK9hxgP-JWTCljRuQUZy'
print(service.query().sql(sql='SELECT * FROM {}'.format(table_id)).execute(http=http))
if __name__ == '__main__':
test()
the output is:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/fusiontables/v2/query?alt=json&sql=SELECT+%2A+FROM+1esH-YayrtegZH6VsiVBq0YK9hxgP-JWTCljRuQUZy returned "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.">
I just enabled this API that is why the daily limit is for sure hasn't reached. I also tried to find the answer in similar topics, but I wasn't succeeded.
Thank you in advance
Finally made it work:
there were one part missed:
credentials.authorize(http)
Now it seems OK
The code is:
import httplib2
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
scopes = ['https://www.googleapis.com/auth/fusiontables']
KEY = '__Remak APIS-a8cd56ca2b4e.json'
credentials = ServiceAccountCredentials.from_json_keyfile_name(KEY, scopes)
http = httplib2.Http()
credentials.authorize(http)
if not credentials.access_token:
credentials.refresh(http)
fusiontables = build('fusiontables', 'v2', http=http)
def test():
table_id = '1esH-YayZegZH97VsiVBq0YK9hxgP-JWTCljRuQUZy'
print(fusiontables.query().sql(sql='SELECT * FROM {}'.format(table_id)).execute())
if __name__ == '__main__':
test()

Resources