Merge pull request #565 from reinlemmens/fix/calendar-meeting-links
Display meeting links in calendar event output
This commit is contained in:
@@ -172,6 +172,21 @@ def _preserve_existing_fields(
|
|||||||
event_body[field_name] = new_value
|
event_body[field_name] = new_value
|
||||||
|
|
||||||
|
|
||||||
|
def _get_meeting_link(item: Dict[str, Any]) -> str:
|
||||||
|
"""Extract video meeting link from event conference data or hangoutLink."""
|
||||||
|
conference_data = item.get("conferenceData")
|
||||||
|
if conference_data and "entryPoints" in conference_data:
|
||||||
|
for entry_point in conference_data["entryPoints"]:
|
||||||
|
if entry_point.get("entryPointType") == "video":
|
||||||
|
uri = entry_point.get("uri", "")
|
||||||
|
if uri:
|
||||||
|
return uri
|
||||||
|
hangout_link = item.get("hangoutLink", "")
|
||||||
|
if hangout_link:
|
||||||
|
return hangout_link
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def _format_attendee_details(
|
def _format_attendee_details(
|
||||||
attendees: List[Dict[str, Any]], indent: str = " "
|
attendees: List[Dict[str, Any]], indent: str = " "
|
||||||
) -> str:
|
) -> str:
|
||||||
@@ -448,6 +463,8 @@ async def get_events(
|
|||||||
)
|
)
|
||||||
attendee_details_str = _format_attendee_details(attendees, indent=" ")
|
attendee_details_str = _format_attendee_details(attendees, indent=" ")
|
||||||
|
|
||||||
|
meeting_link = _get_meeting_link(item)
|
||||||
|
|
||||||
event_details = (
|
event_details = (
|
||||||
f"Event Details:\n"
|
f"Event Details:\n"
|
||||||
f"- Title: {summary}\n"
|
f"- Title: {summary}\n"
|
||||||
@@ -456,6 +473,10 @@ async def get_events(
|
|||||||
f"- Description: {description}\n"
|
f"- Description: {description}\n"
|
||||||
f"- Location: {location}\n"
|
f"- Location: {location}\n"
|
||||||
f"- Color ID: {color_id}\n"
|
f"- Color ID: {color_id}\n"
|
||||||
|
)
|
||||||
|
if meeting_link:
|
||||||
|
event_details += f"- Meeting Link: {meeting_link}\n"
|
||||||
|
event_details += (
|
||||||
f"- Attendees: {attendee_emails}\n"
|
f"- Attendees: {attendee_emails}\n"
|
||||||
f"- Attendee Details: {attendee_details_str}\n"
|
f"- Attendee Details: {attendee_details_str}\n"
|
||||||
)
|
)
|
||||||
@@ -494,10 +515,16 @@ async def get_events(
|
|||||||
)
|
)
|
||||||
attendee_details_str = _format_attendee_details(attendees, indent=" ")
|
attendee_details_str = _format_attendee_details(attendees, indent=" ")
|
||||||
|
|
||||||
|
meeting_link = _get_meeting_link(item)
|
||||||
|
|
||||||
event_detail_parts = (
|
event_detail_parts = (
|
||||||
f'- "{summary}" (Starts: {start_time}, Ends: {end_time})\n'
|
f'- "{summary}" (Starts: {start_time}, Ends: {end_time})\n'
|
||||||
f" Description: {description}\n"
|
f" Description: {description}\n"
|
||||||
f" Location: {location}\n"
|
f" Location: {location}\n"
|
||||||
|
)
|
||||||
|
if meeting_link:
|
||||||
|
event_detail_parts += f" Meeting Link: {meeting_link}\n"
|
||||||
|
event_detail_parts += (
|
||||||
f" Attendees: {attendee_emails}\n"
|
f" Attendees: {attendee_emails}\n"
|
||||||
f" Attendee Details: {attendee_details_str}\n"
|
f" Attendee Details: {attendee_details_str}\n"
|
||||||
)
|
)
|
||||||
@@ -513,9 +540,12 @@ async def get_events(
|
|||||||
event_details_list.append(event_detail_parts)
|
event_details_list.append(event_detail_parts)
|
||||||
else:
|
else:
|
||||||
# Basic output format
|
# Basic output format
|
||||||
event_details_list.append(
|
meeting_link = _get_meeting_link(item)
|
||||||
f'- "{summary}" (Starts: {start_time}, Ends: {end_time}) ID: {item_event_id} | Link: {link}'
|
basic_line = f'- "{summary}" (Starts: {start_time}, Ends: {end_time})'
|
||||||
)
|
if meeting_link:
|
||||||
|
basic_line += f" Meeting: {meeting_link}"
|
||||||
|
basic_line += f" ID: {item_event_id} | Link: {link}"
|
||||||
|
event_details_list.append(basic_line)
|
||||||
|
|
||||||
if event_id:
|
if event_id:
|
||||||
# Single event basic output
|
# Single event basic output
|
||||||
|
|||||||
@@ -1463,6 +1463,7 @@ async def update_paragraph_style(
|
|||||||
indent_end: float = None,
|
indent_end: float = None,
|
||||||
space_above: float = None,
|
space_above: float = None,
|
||||||
space_below: float = None,
|
space_below: float = None,
|
||||||
|
named_style_type: str = None,
|
||||||
list_type: str = None,
|
list_type: str = None,
|
||||||
list_nesting_level: int = None,
|
list_nesting_level: int = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
@@ -1488,6 +1489,8 @@ async def update_paragraph_style(
|
|||||||
indent_end: Right/end indent in points
|
indent_end: Right/end indent in points
|
||||||
space_above: Space above paragraph in points (e.g., 12 for one line)
|
space_above: Space above paragraph in points (e.g., 12 for one line)
|
||||||
space_below: Space below paragraph in points
|
space_below: Space below paragraph in points
|
||||||
|
named_style_type: Direct named style type - 'NORMAL_TEXT', 'TITLE', 'SUBTITLE',
|
||||||
|
'HEADING_1' through 'HEADING_6'. Mutually exclusive with heading_level.
|
||||||
list_type: Create a list from existing paragraphs ('UNORDERED' for bullets, 'ORDERED' for numbers)
|
list_type: Create a list from existing paragraphs ('UNORDERED' for bullets, 'ORDERED' for numbers)
|
||||||
list_nesting_level: Nesting level for lists (0-8, where 0 is top level, default is 0)
|
list_nesting_level: Nesting level for lists (0-8, where 0 is top level, default is 0)
|
||||||
Use higher levels for nested/indented list items
|
Use higher levels for nested/indented list items
|
||||||
@@ -1546,12 +1549,30 @@ async def update_paragraph_style(
|
|||||||
if list_nesting_level < 0 or list_nesting_level > 8:
|
if list_nesting_level < 0 or list_nesting_level > 8:
|
||||||
return "Error: list_nesting_level must be between 0 and 8"
|
return "Error: list_nesting_level must be between 0 and 8"
|
||||||
|
|
||||||
|
# Validate named_style_type
|
||||||
|
if named_style_type is not None and heading_level is not None:
|
||||||
|
return "Error: heading_level and named_style_type are mutually exclusive; provide only one"
|
||||||
|
|
||||||
|
if named_style_type is not None:
|
||||||
|
valid_styles = [
|
||||||
|
"NORMAL_TEXT", "TITLE", "SUBTITLE",
|
||||||
|
"HEADING_1", "HEADING_2", "HEADING_3",
|
||||||
|
"HEADING_4", "HEADING_5", "HEADING_6",
|
||||||
|
]
|
||||||
|
if named_style_type not in valid_styles:
|
||||||
|
return f"Error: Invalid named_style_type '{named_style_type}'. Must be one of: {', '.join(valid_styles)}"
|
||||||
|
|
||||||
# Build paragraph style object
|
# Build paragraph style object
|
||||||
paragraph_style = {}
|
paragraph_style = {}
|
||||||
fields = []
|
fields = []
|
||||||
|
|
||||||
|
# Handle named_style_type (direct named style)
|
||||||
|
if named_style_type is not None:
|
||||||
|
paragraph_style["namedStyleType"] = named_style_type
|
||||||
|
fields.append("namedStyleType")
|
||||||
|
|
||||||
# Handle heading level (named style)
|
# Handle heading level (named style)
|
||||||
if heading_level is not None:
|
elif heading_level is not None:
|
||||||
if heading_level < 0 or heading_level > 6:
|
if heading_level < 0 or heading_level > 6:
|
||||||
return "Error: heading_level must be between 0 (normal text) and 6"
|
return "Error: heading_level must be between 0 (normal text) and 6"
|
||||||
if heading_level == 0:
|
if heading_level == 0:
|
||||||
|
|||||||
@@ -475,6 +475,7 @@ class BatchOperationManager:
|
|||||||
"indent_end",
|
"indent_end",
|
||||||
"space_above",
|
"space_above",
|
||||||
"space_below",
|
"space_below",
|
||||||
|
"named_style_type",
|
||||||
],
|
],
|
||||||
"description": "Apply paragraph-level styling (headings, alignment, spacing, indentation)",
|
"description": "Apply paragraph-level styling (headings, alignment, spacing, indentation)",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -316,6 +316,12 @@ class ValidationManager:
|
|||||||
"At least one paragraph style parameter must be provided (heading_level, alignment, line_spacing, indent_first_line, indent_start, indent_end, space_above, space_below, or named_style_type)",
|
"At least one paragraph style parameter must be provided (heading_level, alignment, line_spacing, indent_first_line, indent_start, indent_end, space_above, space_below, or named_style_type)",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if heading_level is not None and named_style_type is not None:
|
||||||
|
return (
|
||||||
|
False,
|
||||||
|
"heading_level and named_style_type are mutually exclusive; provide only one",
|
||||||
|
)
|
||||||
|
|
||||||
if named_style_type is not None:
|
if named_style_type is not None:
|
||||||
valid_styles = [
|
valid_styles = [
|
||||||
"NORMAL_TEXT",
|
"NORMAL_TEXT",
|
||||||
|
|||||||
Reference in New Issue
Block a user