Skip to content

Commit

Permalink
Merge pull request MLSysOps#149 from leeeizhang/feat/google_calender
Browse files Browse the repository at this point in the history
[MRG] add google calender integration
  • Loading branch information
huangyz0918 authored Aug 30, 2024
2 parents 348690a + b13e234 commit c30d4d4
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions mle/integration/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .github import GitHubIntegration
from .google_calendar import GoogleCalendarIntegration, google_calendar_login
118 changes: 118 additions & 0 deletions mle/integration/google_calendar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import os
import os.path
import datetime

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

# Path to the application's OAuth 2.0 credentials.
app_crediential = os.path.join(
os.path.expanduser("~"), ".local/google_oauth/credentials.json"
)


def google_calendar_login(app_crediential_path=app_crediential):
"""
Authenticate the user using Google OAuth 2.0 and return the credentials.
:param app_crediential_path: Path to the client secrets file.
:return: Google OAuth 2.0 credentials or None if authentication fails.
"""
try:
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]
flow = InstalledAppFlow.from_client_secrets_file(
app_crediential_path,
SCOPES,
)
creds = flow.run_local_server(host="127.0.0.1", port=0)
except Exception as e:
return None
return creds


class GoogleCalendarIntegration:
"""
Class to interface with Google Calendar API to fetch events.
:param token: Google OAuth 2.0 credentials.
"""

def __init__(self, token=None):
self.token = token

def get_events(self, start_date=None, end_date=None, limit=100):
"""
Fetch upcoming calendar events.
:param start_date: Start date for calender events (inclusive), in 'YYYY-MM-DD' format
:param end_date: End date for calender events (inclusive), in 'YYYY-MM-DD' format
:param limit: The maximum number of events to return.
:return: A list of events with details or None if an error occurs.
"""
try:
# Build the service object for interacting with the Google Calendar API
service = build("calendar", "v3", credentials=self.token)

if start_date is None:
start_date = (
datetime.datetime.utcnow().isoformat() + "Z"
) # 'Z' indicates UTC time
else:
start_date = f"{start_date}T00:00:00Z"

if end_date is not None:
end_date = f"{end_date}T00:00:00Z"

start_dt = datetime.strptime(start_date, "%Y-%m-%dT%H:%M:%S%z")
end_dt = datetime.strptime(end_date, "%Y-%m-%dT%H:%M:%S%z")
if start_dt >= end_dt:
raise ValueError("start_date must be less than end_date")

# Retrieve the events from the primary calendar
events_result = (
service.events()
.list(
calendarId="primary",
timeMin=start_date,
timeMax=end_date,
maxResults=limit,
singleEvents=True,
orderBy="startTime",
)
.execute()
)
events_result = events_result.get("items", [])

# Format the events into a specified structure
return [
{
"summary": event.get("summary"),
"kind": event.get("kind"),
"status": event.get("status"),
"description": event.get("description"),
"creator": event.get("creator"),
"organizer": event.get("organizer"),
"htmlLink": event.get("htmlLink"),
"start_time": datetime.datetime.fromisoformat(
event["start"].get("dateTime")
),
"end_time": datetime.datetime.fromisoformat(
event["end"].get("dateTime")
),
}
for event in events_result
]

except Exception as e:
return None


if __name__ == "__main__":
# Example usage of the GoogleCalendarIntegration class
# Noted: please follow the following docs to set up the credentials in `~/.local/google_oauth/credentials.json`
# refer to: https://developers.google.com/calendar/api/quickstart/python
token = google_calendar_login()
calendar = GoogleCalendarIntegration(token)
print(calendar.get_events())
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ instructor
setuptools
numexpr~=2.10.1
bottleneck~=1.4.0

google-api-python-client~=2.143.0
google-auth-httplib2~=0.2.0
google-auth-oauthlib~=1.2.1

0 comments on commit c30d4d4

Please sign in to comment.