84 lines
2.1 KiB
Python
84 lines
2.1 KiB
Python
|
"""
|
||
|
Definition of an asyncio compatible CalDAV calendar.
|
||
|
|
||
|
Caches events using `timed_alru_cache`.
|
||
|
"""
|
||
|
|
||
|
from datetime import datetime
|
||
|
from functools import total_ordering
|
||
|
from logging import getLogger
|
||
|
from typing import Annotated, Self
|
||
|
|
||
|
from pydantic import AfterValidator, BaseModel, ConfigDict
|
||
|
from vobject.base import Component
|
||
|
|
||
|
_logger = getLogger(__name__)
|
||
|
StrippedStr = Annotated[str, AfterValidator(lambda s: s.strip())]
|
||
|
|
||
|
|
||
|
@total_ordering
|
||
|
class CalEvent(BaseModel):
|
||
|
"""
|
||
|
A CalDAV calendar event.
|
||
|
|
||
|
Properties are to be named as in the EVENT component of
|
||
|
RFC5545 (iCalendar).
|
||
|
|
||
|
https://icalendar.org/iCalendar-RFC-5545/3-6-1-event-component.html
|
||
|
"""
|
||
|
|
||
|
model_config = ConfigDict(frozen=True)
|
||
|
|
||
|
summary: StrippedStr = ""
|
||
|
description: StrippedStr = ""
|
||
|
dtstart: datetime = datetime.utcnow()
|
||
|
dtend: datetime = datetime.utcnow()
|
||
|
|
||
|
def __lt__(self, other: Self) -> bool:
|
||
|
"""
|
||
|
Order Events by start time.
|
||
|
"""
|
||
|
|
||
|
return self.dtstart < other.dtstart
|
||
|
|
||
|
def __eq__(self, other: Self) -> bool:
|
||
|
"""
|
||
|
Compare all properties.
|
||
|
"""
|
||
|
|
||
|
return self.model_dump() == other.model_dump()
|
||
|
|
||
|
@classmethod
|
||
|
def from_vevent(cls, event: Component) -> Self:
|
||
|
"""
|
||
|
Create a CalEvent instance from a `VObject.VEvent` object.
|
||
|
"""
|
||
|
|
||
|
data = {}
|
||
|
keys = ("summary", "description", "dtstart", "dtend", "duration")
|
||
|
|
||
|
for key in keys:
|
||
|
try:
|
||
|
data[key] = event.contents[key][0].value # type: ignore
|
||
|
|
||
|
except KeyError:
|
||
|
pass
|
||
|
|
||
|
if "dtend" not in data:
|
||
|
data["dtend"] = data["dtstart"]
|
||
|
|
||
|
if "duration" in data:
|
||
|
try:
|
||
|
data["dtend"] += data["duration"]
|
||
|
|
||
|
except (ValueError, TypeError, AttributeError):
|
||
|
_logger.warn(
|
||
|
"Could not add duration %s to %s",
|
||
|
repr(data["duration"]),
|
||
|
repr(data["dtstart"]),
|
||
|
)
|
||
|
|
||
|
del data["duration"]
|
||
|
|
||
|
return cls.model_validate(data)
|