Add Google Calendar integration
- New src/shared/calendar.py: OAuth service builder, list_events, create_event, check_availability (reuses gmail-oauth secret) - 3 new tools: get_calendar_events, create_calendar_event, check_availability - Extended OAuth scopes to include calendar in gmail.py and token script - Updated system prompt with calendar capabilities Requires re-running scripts/get_gmail_token.py to grant the calendar scope and updating the exec-aide/gmail-oauth secret with the new refresh token. Closes #2
This commit is contained in:
parent
31e015877c
commit
833a4fdd52
3 changed files with 80 additions and 2 deletions
|
|
@ -13,7 +13,10 @@ import json
|
||||||
|
|
||||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||||
|
|
||||||
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
|
SCOPES = [
|
||||||
|
"https://www.googleapis.com/auth/gmail.readonly",
|
||||||
|
"https://www.googleapis.com/auth/calendar",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
||||||
72
src/shared/calendar.py
Normal file
72
src/shared/calendar.py
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import google.auth.transport.requests
|
||||||
|
from google.oauth2.credentials import Credentials
|
||||||
|
from googleapiclient.discovery import build
|
||||||
|
|
||||||
|
from shared.secrets import get_gmail_oauth, save_gmail_tokens
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_service = None
|
||||||
|
|
||||||
|
SCOPES = [
|
||||||
|
"https://www.googleapis.com/auth/gmail.readonly",
|
||||||
|
"https://www.googleapis.com/auth/calendar",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_calendar_service():
|
||||||
|
global _service
|
||||||
|
oauth = get_gmail_oauth()
|
||||||
|
creds = Credentials(
|
||||||
|
token=oauth.get("access_token"),
|
||||||
|
refresh_token=oauth["refresh_token"],
|
||||||
|
token_uri="https://oauth2.googleapis.com/token",
|
||||||
|
client_id=oauth["client_id"],
|
||||||
|
client_secret=oauth["client_secret"],
|
||||||
|
scopes=SCOPES,
|
||||||
|
)
|
||||||
|
if not creds.valid:
|
||||||
|
creds.refresh(google.auth.transport.requests.Request())
|
||||||
|
save_gmail_tokens(
|
||||||
|
creds.token,
|
||||||
|
creds.expiry.isoformat() if creds.expiry else "",
|
||||||
|
)
|
||||||
|
_service = build("calendar", "v3", credentials=creds, cache_discovery=False)
|
||||||
|
return _service
|
||||||
|
|
||||||
|
|
||||||
|
def list_events(service, time_min, time_max, max_results=10):
|
||||||
|
result = service.events().list(
|
||||||
|
calendarId="primary",
|
||||||
|
timeMin=time_min,
|
||||||
|
timeMax=time_max,
|
||||||
|
maxResults=max_results,
|
||||||
|
singleEvents=True,
|
||||||
|
orderBy="startTime",
|
||||||
|
).execute()
|
||||||
|
return result.get("items", [])
|
||||||
|
|
||||||
|
|
||||||
|
def create_event(service, summary, start, end, attendees=None, description=None):
|
||||||
|
body = {
|
||||||
|
"summary": summary,
|
||||||
|
"start": start,
|
||||||
|
"end": end,
|
||||||
|
}
|
||||||
|
if description:
|
||||||
|
body["description"] = description
|
||||||
|
if attendees:
|
||||||
|
body["attendees"] = [{"email": a} for a in attendees]
|
||||||
|
return service.events().insert(calendarId="primary", body=body).execute()
|
||||||
|
|
||||||
|
|
||||||
|
def check_availability(service, time_min, time_max):
|
||||||
|
body = {
|
||||||
|
"timeMin": time_min,
|
||||||
|
"timeMax": time_max,
|
||||||
|
"items": [{"id": "primary"}],
|
||||||
|
}
|
||||||
|
result = service.freebusy().query(body=body).execute()
|
||||||
|
return result["calendars"]["primary"]["busy"]
|
||||||
|
|
@ -13,7 +13,10 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_service = None
|
_service = None
|
||||||
|
|
||||||
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
|
SCOPES = [
|
||||||
|
"https://www.googleapis.com/auth/gmail.readonly",
|
||||||
|
"https://www.googleapis.com/auth/calendar",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_authenticated_service():
|
def get_authenticated_service():
|
||||||
|
|
|
||||||
Reference in a new issue