ovdashboard/api/ovdashboard_api/core/caldav.py

98 lines
2.6 KiB
Python
Raw Normal View History

import logging
from datetime import datetime, timedelta
from asyncify import asyncify
from cache import AsyncTTL
2023-10-26 16:50:04 +00:00
from caldav import Calendar, DAVClient, Event, Principal
from vobject.base import Component
from .calevent import CalEvent
from .config import Config
from .settings import SETTINGS
_logger = logging.getLogger(__name__)
class CalDAV:
_caldav_client = DAVClient(
url=SETTINGS.caldav.url,
username=SETTINGS.caldav.username,
password=SETTINGS.caldav.password,
)
@classmethod
2023-10-26 15:46:12 +00:00
@property
def principal(cls) -> Principal:
"""
Gets the `Principal` object of the main CalDAV client.
"""
return cls._caldav_client.principal()
2023-10-26 15:46:12 +00:00
@classmethod
@property
@AsyncTTL(
time_to_live=SETTINGS.caldav.cache_ttl,
maxsize=SETTINGS.caldav.cache_size,
skip_args=1,
)
@asyncify
def calendars(cls) -> list[str]:
"""
Asynchroneously lists all calendars using the main WebDAV client.
"""
_logger.debug("calendars")
return [str(cal.name) for cal in cls.principal.calendars()]
2023-10-26 16:04:03 +00:00
@classmethod
@AsyncTTL(
time_to_live=SETTINGS.caldav.cache_ttl,
maxsize=SETTINGS.caldav.cache_size,
skip_args=1,
)
@asyncify
def get_calendar(cls, calendar_name: str) -> Calendar:
"""
Get a calendar by name using the CalDAV principal object.
"""
return cls.principal.calendar(calendar_name)
@classmethod
2023-10-26 16:04:03 +00:00
@AsyncTTL(
time_to_live=SETTINGS.caldav.cache_ttl,
maxsize=SETTINGS.caldav.cache_size,
skip_args=1,
)
@asyncify
def get_events(cls, calendar_name: str, cfg: Config) -> list[CalEvent]:
"""
Get a sorted list of events by CalDAV calendar name.
"""
_logger.info(f"downloading {calendar_name!r} ...")
search_span = timedelta(days=cfg.calendar.future_days)
calendar = cls.principal.calendar(calendar_name)
date_start = datetime.utcnow().date()
time_min = datetime.min.time()
dt_start = datetime.combine(date_start, time_min)
dt_end = dt_start + search_span
2023-10-26 16:50:04 +00:00
search_result = calendar.search(
start=dt_start,
end=dt_end,
expand=True,
comp_class=Event,
split_expanded=False,
)
vevents = []
for event in search_result:
vobject: Component = event.vobject_instance # type: ignore
vevents.extend(vobject.vevent_list)
return sorted(CalEvent.from_vevent(vevent) for vevent in vevents)