CalEvent creation and validation

This commit is contained in:
Jörn-Michael Miehe 2022-09-04 21:41:40 +00:00
parent 9d1329d8da
commit 2deda42194

View file

@ -5,7 +5,8 @@ from functools import total_ordering
from typing import Iterator from typing import Iterator
from caldav import Calendar from caldav import Calendar
from pydantic import BaseModel from caldav.lib.error import ReportError
from pydantic import BaseModel, validator
from vobject.icalendar import VEvent from vobject.icalendar import VEvent
from . import caldav_principal, get_ttl_hash, run_in_executor, timed_alru_cache from . import caldav_principal, get_ttl_hash, run_in_executor, timed_alru_cache
@ -13,12 +14,19 @@ from . import caldav_principal, get_ttl_hash, run_in_executor, timed_alru_cache
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
def _string_strip(in_str: str) -> str:
return in_str.strip()
@total_ordering @total_ordering
class CalEvent(BaseModel): class CalEvent(BaseModel):
summary: str summary: str = ""
description: str description: str = ""
dtstart: datetime dtstart: datetime = datetime.utcnow()
dtend: datetime dtend: datetime = datetime.utcnow()
class Config:
frozen = True
def __lt__(self, other: "CalEvent") -> bool: def __lt__(self, other: "CalEvent") -> bool:
return self.dtstart < other.dtstart return self.dtstart < other.dtstart
@ -26,6 +34,29 @@ class CalEvent(BaseModel):
def __eq__(self, other: "CalEvent") -> bool: def __eq__(self, other: "CalEvent") -> bool:
return self.dict() == other.dict() return self.dict() == other.dict()
_validate_summary = validator(
"summary",
allow_reuse=True,
)(_string_strip)
_validate_description = validator(
"description",
allow_reuse=True,
)(_string_strip)
@classmethod
def from_vevent(cls, event: VEvent) -> "CalEvent":
data = {}
for key in cls().dict().keys():
try:
data[key] = event.contents[key][0].value
except KeyError:
pass
return cls.parse_obj(data)
@timed_alru_cache(maxsize=20) @timed_alru_cache(maxsize=20)
async def _get_calendar( async def _get_calendar(
@ -50,23 +81,37 @@ async def _get_calendar_events(
print(f"updating {calendar_name}") print(f"updating {calendar_name}")
calendar = caldav_principal().calendar(calendar_name) calendar = caldav_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 + timedelta(days=365)
try:
search_result = calendar.date_search(
start=dt_start,
end=dt_end,
expand=True,
verify_expand=True,
)
except ReportError:
_logger.warn("CalDAV server does not support expanded search")
search_result = calendar.date_search(
start=dt_start,
end=dt_end,
expand=False,
)
return ( return (
vevent vevent
for event in calendar.date_search( for event in search_result
start=datetime.now(),
end=datetime.now() + timedelta(days=365),
expand=True,
)
for vevent in event.vobject_instance.contents["vevent"] for vevent in event.vobject_instance.contents["vevent"]
) )
return sorted([ return sorted([
CalEvent( CalEvent.from_vevent(vevent)
summary=vevent.summary.value,
description=vevent.description.value,
dtstart=vevent.dtstart.value,
dtend=vevent.dtend.value,
)
for vevent in await _inner() for vevent in await _inner()
]) ])