Skip to content

Commit 62d6e4a

Browse files
committed
Simplify, and add configs for date range
1 parent 5c4da38 commit 62d6e4a

2 files changed

Lines changed: 125 additions & 161 deletions

File tree

connectors/sources/google_calendar.py

Lines changed: 77 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -72,45 +72,31 @@ async def get_calendar(self, calendar_id):
7272
resource="calendars", method="get", calendarId=calendar_id
7373
)
7474

75-
async def list_events(self, calendar_id):
76-
"""Fetch all events from a specific calendar.
75+
async def list_events(self, calendar_id, time_min=None, time_max=None):
76+
"""Fetch all events from a specific calendar within the specified time range.
7777
7878
Args:
7979
calendar_id (str): The calendar ID.
80+
time_min (str): Start time in ISO format. Optional.
81+
time_max (str): End time in ISO format. Optional.
8082
8183
Yields:
8284
dict: Events page.
8385
"""
86+
params = {
87+
"calendarId": calendar_id,
88+
"maxResults": 100,
89+
}
90+
if time_min:
91+
params["timeMin"] = time_min
92+
if time_max:
93+
params["timeMax"] = time_max
94+
8495
async for page in self.api_call_paged(
85-
resource="events",
86-
method="list",
87-
calendarId=calendar_id,
88-
maxResults=100,
96+
resource="events", method="list", **params
8997
):
9098
yield page
9199

92-
async def get_free_busy(self, calendar_ids, time_min, time_max):
93-
"""Get free/busy information for a list of calendars.
94-
95-
Args:
96-
calendar_ids (list): List of calendar IDs.
97-
time_min (str): Start time in ISO format.
98-
time_max (str): End time in ISO format.
99-
100-
Returns:
101-
dict: Free/busy information.
102-
"""
103-
items = [{"id": calendar_id} for calendar_id in calendar_ids]
104-
request_body = {
105-
"timeMin": time_min,
106-
"timeMax": time_max,
107-
"items": items,
108-
}
109-
110-
return await self.api_call(
111-
resource="freebusy", method="query", body=request_body
112-
)
113-
114100

115101
class GoogleCalendarDataSource(BaseDataSource):
116102
"""Google Calendar connector for Elastic Enterprise Search.
@@ -119,7 +105,6 @@ class GoogleCalendarDataSource(BaseDataSource):
119105
- CalendarList entries (the user's list of calendars)
120106
- Each underlying Calendar resource
121107
- Events belonging to each Calendar
122-
- Free/Busy data for each Calendar
123108
124109
Reference:
125110
https://developers.google.com/calendar/api/v3/reference
@@ -136,7 +121,6 @@ def __init__(self, configuration):
136121
"""
137122
super().__init__(configuration=configuration)
138123
self._calendar_client = None
139-
self.include_freebusy = self.configuration.get("include_freebusy", False)
140124

141125
@classmethod
142126
def get_default_configuration(cls):
@@ -157,12 +141,19 @@ def get_default_configuration(cls):
157141
"required": True,
158142
"type": "str",
159143
},
160-
"include_freebusy": {
161-
"display": "toggle",
162-
"label": "Include Free/Busy Data",
144+
"days_back": {
145+
"display": "numeric",
146+
"label": "Days back to fetch events",
163147
"order": 3,
164-
"type": "bool",
165-
"value": False,
148+
"type": "int",
149+
"value": 30,
150+
},
151+
"days_forward": {
152+
"display": "numeric",
153+
"label": "Days forward to fetch events",
154+
"order": 4,
155+
"type": "int",
156+
"value": 30,
166157
},
167158
}
168159

@@ -244,15 +235,6 @@ async def get_docs(self, filtering=None):
244235
async for event_doc in self._generate_event_docs(client, cal_list_doc):
245236
yield event_doc, None
246237

247-
# 4) (Optionally) yield free/busy data for each calendar
248-
if self.include_freebusy:
249-
calendar_ids = [cal["calendar_id"] for cal in calendar_list_entries]
250-
if calendar_ids:
251-
async for freebusy_doc in self._generate_freebusy_docs(
252-
client, calendar_ids
253-
):
254-
yield freebusy_doc, None
255-
256238
async def _generate_calendar_list_docs(self, client):
257239
"""Yield documents for each calendar in the user's CalendarList.
258240
@@ -319,6 +301,14 @@ async def _generate_event_docs(self, client, cal_list_doc):
319301
"""
320302
calendar_id = cal_list_doc["calendar_id"]
321303

304+
# Calculate time range based on configuration
305+
now = datetime.utcnow()
306+
days_back = self.configuration.get("days_back", 30)
307+
days_forward = self.configuration.get("days_forward", 30)
308+
309+
time_min = (now - timedelta(days=days_back)).isoformat() + "Z"
310+
time_max = (now + timedelta(days=days_forward)).isoformat() + "Z"
311+
322312
# Create calendar reference for events
323313
calendar_ref = {
324314
"id": calendar_id,
@@ -329,7 +319,7 @@ async def _generate_event_docs(self, client, cal_list_doc):
329319
}
330320

331321
try:
332-
async for page in client.list_events(calendar_id):
322+
async for page in client.list_events(calendar_id, time_min, time_max):
333323
for event in page.get("items", []):
334324
event_id = event["id"]
335325
# Extract date/time fields
@@ -339,89 +329,69 @@ async def _generate_event_docs(self, client, cal_list_doc):
339329
start_date = start_info.get("date")
340330
end_datetime = end_info.get("dateTime")
341331
end_date = end_info.get("date")
342-
created_at_str = event.get("created")
343-
updated_at_str = event.get("updated")
344-
345-
# Convert created/updated to datetime if present
346-
created_at = (
347-
datetime.fromisoformat(created_at_str.replace("Z", "+00:00"))
348-
if created_at_str
349-
else None
350-
)
351-
updated_at = (
352-
datetime.fromisoformat(updated_at_str.replace("Z", "+00:00"))
353-
if updated_at_str
354-
else None
355-
)
332+
333+
# Extract attendee names and emails
334+
attendees_info = []
335+
if event.get("attendees"):
336+
for attendee in event.get("attendees", []):
337+
attendee_info = {}
338+
if attendee.get("displayName"):
339+
attendee_info["name"] = attendee.get("displayName")
340+
if attendee.get("email"):
341+
attendee_info["email"] = attendee.get("email")
342+
if attendee_info:
343+
attendees_info.append(attendee_info)
344+
345+
# Extract meeting/zoom links from conferenceData or location
346+
meeting_link = None
347+
if event.get("conferenceData"):
348+
entry_points = event.get("conferenceData", {}).get(
349+
"entryPoints", []
350+
)
351+
for entry_point in entry_points:
352+
if entry_point.get("uri"):
353+
meeting_link = entry_point.get("uri")
354+
break
355+
356+
# Extract attachments
357+
attachments_info = []
358+
if event.get("attachments"):
359+
for attachment in event.get("attachments", []):
360+
attachment_info = {}
361+
if attachment.get("title"):
362+
attachment_info["title"] = attachment.get("title")
363+
if attachment.get("fileUrl"):
364+
attachment_info["url"] = attachment.get("fileUrl")
365+
if attachment.get("mimeType"):
366+
attachment_info["mime_type"] = attachment.get(
367+
"mimeType"
368+
)
369+
if attachment_info:
370+
attachments_info.append(attachment_info)
356371

357372
doc = {
358373
"_id": event_id,
359374
"type": "event",
360375
"event_id": event_id,
361376
"calendar_id": calendar_id,
362377
"calendar": calendar_ref,
363-
"status": event.get("status"),
364-
"html_link": event.get("htmlLink"),
365-
"created_at": created_at.isoformat() if created_at else None,
366-
"updated_at": updated_at.isoformat() if updated_at else None,
367378
"summary": event.get("summary"),
368379
"description": event.get("description"),
369380
"location": event.get("location"),
370-
"color_id": event.get("colorId"),
381+
"meeting_link": meeting_link,
371382
"start_datetime": start_datetime,
372383
"start_date": start_date,
373384
"end_datetime": end_datetime,
374385
"end_date": end_date,
375-
"recurrence": event.get("recurrence"),
376-
"recurring_event_id": event.get("recurringEventId"),
377-
"organizer": event.get("organizer"),
378-
"creator": event.get("creator"),
379-
"attendees": event.get("attendees"),
380-
"transparency": event.get("transparency"),
381-
"visibility": event.get("visibility"),
382-
"conference_data": event.get("conferenceData"),
383-
"event_type": event.get("eventType"),
386+
"attendees": attendees_info,
387+
"attachments": attachments_info,
384388
}
385389
yield doc
386390
except Exception as e:
387391
self._logger.warning(
388392
f"Error fetching events for calendar {calendar_id}: {str(e)}"
389393
)
390394

391-
async def _generate_freebusy_docs(self, client, calendar_ids):
392-
"""Yield documents for free/busy data for the next 7 days for each calendar.
393-
394-
Args:
395-
client (GoogleCalendarClient): The Google Calendar client.
396-
calendar_ids (list): List of calendar IDs.
397-
398-
Yields:
399-
dict: Free/busy document.
400-
"""
401-
now = datetime.utcnow()
402-
in_7_days = now + timedelta(days=7)
403-
time_min = now.isoformat() + "Z"
404-
time_max = in_7_days.isoformat() + "Z"
405-
406-
try:
407-
data = await client.get_free_busy(calendar_ids, time_min, time_max)
408-
calendars = data.get("calendars", {})
409-
410-
for calendar_id, busy_info in calendars.items():
411-
busy_ranges = busy_info.get("busy", [])
412-
413-
doc = {
414-
"_id": f"{calendar_id}_freebusy",
415-
"type": "freebusy",
416-
"calendar_id": calendar_id,
417-
"busy": busy_ranges,
418-
"time_min": time_min,
419-
"time_max": time_max,
420-
}
421-
yield doc
422-
except Exception as e:
423-
self._logger.warning(f"Error fetching free/busy data: {str(e)}")
424-
425395
async def close(self):
426396
"""Close any resources."""
427397
pass

0 commit comments

Comments
 (0)