export free/busy components instead of events
1 file changed, 21 insertions(+), 4 deletions(-)
changed files
M mycal.py → mycal.py
@@ -1,12 +1,13 @@ from icalendar.cal import Calendar, FreeBusy +import icalendar + import requests from flask import Flask -from datetime import date, datetime, timedelta, time +from datetime import date, datetime, timedelta, time, timezone import zoneinfo from dataclasses import dataclass from danoan.toml_dataclass import TomlDataClassIO from os import environ -import calendar @dataclass class CalendarConfig(TomlDataClassIO):@@ -51,6 +52,13 @@ return dt.replace(tzinfo=tz) else: return dt.astimezone(tz) +def to_utc(dt): + return dt.astimezone(tz=timezone.utc) + +def looks_tentative(component): + summary = str(component.get('summary')) + return component.get('status') == 'TENTATIVE' or 'TBD' in summary or summary.endswith("?") + @app.route(f'/{str.lower(config.name)}.ics') def index(): today = date.today()@@ -69,12 +77,21 @@ for component in input.walk(): if component.name == "VEVENT": dtstart = fixup_date(component.get('dtstart').dt) dtend = fixup_date(component.get('dtend', component.get('dtstart')).dt) + dtstamp = fixup_date(component.get('dtstamp').dt) if dtstart >= start_date and dtend <= end_date: - busy = FreeBusy() + busy = FreeBusy(uid=component.get('uid')) + vp = icalendar.prop.vPeriod([ to_utc(d) for d in [dtstart, dtend] ]) + + if looks_tentative(component): + vp.FBTYPE = icalendar.enums.FBTYPE.BUSY_TENTATIVE + else: + vp.FBTYPE = icalendar.enums.FBTYPE.BUSY_UNAVAILABLE + + busy.add('freebusy', vp) busy.add('summary', f'{config.name} Busy') - busy.uid = component.get('uid') busy.add('dtstart', dtstart) busy.add('dtend', dtend) + busy.add('dtstamp', dtstamp) output.add_component(busy) return output.to_ical(), { "Content-Type": "text/plain" } except Exception as e: