all repos — mycal @ 10527ff359e804c9706b0c16f6176ad1f1a9e858

private calendar anonymiser

output only one event when two have matching times

Alan Pearce
commit

10527ff359e804c9706b0c16f6176ad1f1a9e858

parent

f44aed1f50ff642c18b8737c1b0617ba2be0a255

1 file changed, 36 insertions(+), 21 deletions(-)

changed files
M mycal.pymycal.py
@@ -67,31 +67,26 @@ def looks_tentative(component):
summary = str(component.get('summary', '')) return component.get('status') == 'TENTATIVE' or 'TBD' in summary or summary.endswith("?") -def custom_tentative_detector(component): - """ - A custom function to determine if an event is tentative. - This can be passed to process_calendar_events to override the default logic. +def process_calendar_events(calendar, start_date, end_date, is_tentative_fn=looks_tentative): """ - summary = str(component.get('summary', '')) - # Add your custom logic here - return (component.get('status') == 'TENTATIVE' or - 'TBD' in summary or - summary.endswith("?")) + Process events from a calendar and return a list of event periods. -def process_calendar_events(calendar, busy, start_date, end_date, is_tentative_fn=None): - """ - Process events from a calendar and add them to the FreeBusy component. + This function examines calendar components, filters them by date range, + determines if they are tentative based on the provided function, + and returns them as a list of vPeriod objects with FBTYPE property set. Args: - calendar: The input calendar to process - busy: The FreeBusy component to add events to + calendar: The input calendar object to process start_date: Start date for filtering events end_date: End date for filtering events - is_tentative_fn: Optional function to determine if an event is tentative + is_tentative_fn: Optional function to determine if an event is tentative, + should accept a calendar component and return a boolean + + Returns: + List of vPeriod objects with FBTYPE set to either + BUSY_TENTATIVE or BUSY_UNAVAILABLE """ - if is_tentative_fn is None: - is_tentative_fn = looks_tentative - + events = [] for component in calendar.walk(): if component.name == "VEVENT": dtstart = fixup_date(component.get('dtstart').dt)
@@ -105,7 +100,9 @@ vp.FBTYPE = icalendar.enums.FBTYPE.BUSY_TENTATIVE
else: vp.FBTYPE = icalendar.enums.FBTYPE.BUSY_UNAVAILABLE - busy.add('freebusy', vp) + events.append(vp) + + return events @app.route(f'/{str.lower(config.name)}.ics') def index():
@@ -128,8 +125,8 @@ busy.add('dtstart', start_date.astimezone(tz=utc))
busy.add('dtend', end_date.astimezone(tz=utc)) try: - # Process calendars from the config calendars_to_process = [] + busy_periods = {} # For backward compatibility if config.calendar is not None and (config.calendar['file'] != "" or config.calendar['url'] != ""):
@@ -148,7 +145,25 @@ tentative_fn = lambda component: True
else: tentative_fn = looks_tentative - process_calendar_events(input_calendar, busy, start_date, end_date, is_tentative_fn=tentative_fn) + events = process_calendar_events(input_calendar, start_date, end_date, is_tentative_fn=tentative_fn) + + # Process events considering tentative status + for event in events: + period_key = (event.dt[0], event.dt[1]) + + if period_key in busy_periods: + existing_event = busy_periods[period_key] + + # If the existing event is tentative and the new one is not, + # replace the existing event with the non-tentative one + if (existing_event.FBTYPE == icalendar.enums.FBTYPE.BUSY_TENTATIVE and + event.FBTYPE == icalendar.enums.FBTYPE.BUSY_UNAVAILABLE): + busy_periods[period_key] = event + else: + busy_periods[period_key] = event + + for event in busy_periods.values(): + busy.add('freebusy', event) output.add_component(busy) return output.to_ical(), {"Content-Type": "text/calendar"}