ovdashboard/api/ovdashboard_api/core/dav/caldav.py

91 lines
2.5 KiB
Python
Raw Permalink Normal View History

import logging
from datetime import UTC, datetime, timedelta
2023-10-26 17:04:26 +00:00
from typing import cast
from asyncify import asyncify
2023-11-09 11:16:25 +00:00
from cachetools import cachedmethod
2023-10-26 16:50:04 +00:00
from caldav import Calendar, DAVClient, Event, Principal
2023-10-26 17:04:26 +00:00
from vobject.base import Component, toVName
2023-11-09 11:13:48 +00:00
from ..calevent import CalEvent
from ..config import Config
from ..settings import SETTINGS
2023-11-09 11:16:25 +00:00
from .helpers import REDIS, RedisCache, davkey
_logger = logging.getLogger(__name__)
class CalDAV:
_caldav_client = DAVClient(
url=SETTINGS.caldav.url,
username=SETTINGS.caldav.username,
password=SETTINGS.caldav.password,
)
2023-11-09 11:16:25 +00:00
_cache = RedisCache(
cache=REDIS,
2023-10-26 20:42:26 +00:00
ttl=SETTINGS.caldav.cache_ttl,
)
@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
@asyncify
2023-11-09 11:16:25 +00:00
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("calendars"))
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
@asyncify
2023-11-09 11:16:25 +00:00
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("get_calendar"))
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
@asyncify
2023-11-09 11:16:25 +00:00
@cachedmethod(cache=lambda cls: cls._cache, key=davkey("get_events", slice(1, 2)))
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} ...")
2023-10-26 17:04:26 +00:00
dt_start = datetime.combine(
datetime.now(UTC).date(),
2023-10-26 17:04:26 +00:00
datetime.min.time(),
)
dt_end = dt_start + timedelta(days=cfg.calendar.future_days)
2023-10-26 17:04:26 +00:00
search_result = cls.principal.calendar(calendar_name).search(
2023-10-26 16:50:04 +00:00
start=dt_start,
end=dt_end,
expand=True,
comp_class=Event,
split_expanded=False,
)
vevents = []
for event in search_result:
2023-10-26 17:04:26 +00:00
vobject = cast(Component, event.vobject_instance)
vevents.extend(vobject.contents[toVName("vevent")])
return sorted(CalEvent.from_vevent(vevent) for vevent in vevents)