1
0
Fork 0
mirror of https://github.com/Kozea/Radicale.git synced 2025-08-10 18:40:53 +00:00

recurring events brought to rfc4791

This commit is contained in:
Georgiy 2023-03-30 23:13:00 +03:00
parent a07813ecc9
commit 72103c30c2

View file

@ -23,6 +23,7 @@ import posixpath
import socket import socket
import copy import copy
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from vobject.base import ContentLine
from http import client from http import client
from typing import ( from typing import (
Callable, Iterable, Iterator, Callable, Iterable, Iterator,
@ -197,28 +198,74 @@ def _expand(
) -> List[ET.Element]: ) -> List[ET.Element]:
expanded = [element] expanded = [element]
for component in item.vobject_item.components(): if hasattr(item.vobject_item.vevent, "rrule"):
if component.name != 'VEVENT': rulleset = item.vobject_item.vevent.getrruleset()
continue recurrences = rulleset.between(start, end)
recurring_item = _make_vobject_recurring_item(item)
if hasattr(component, "rrule"): expanded = []
rulleset = component.getrruleset() for recurrence_dt in recurrences:
recurrences = rulleset.between(start, end) try:
delattr(recurring_item.vobject_item.vevent, 'recurrence-id')
except AttributeError:
pass
expanded = [] recurrence_utc = recurrence_dt.astimezone(datetime.timezone.utc)
for recurrence_dt in recurrences:
try:
delattr(item.vobject_item.vevent, 'recurrence-id')
except AttributeError:
pass
item.vobject_item.vevent.add('RECURRENCE-ID').value = recurrence_dt recurring_item.vobject_item.vevent.recurrence_id = ContentLine(
element.text = item.vobject_item.serialize() name='RECURRENCE-ID',
expanded.append(element) value=recurrence_utc.strftime('%Y%m%dT%H%M%SZ'), params={}
)
element = copy.copy(element)
element.text = recurring_item.vobject_item.serialize()
expanded.append(element)
return expanded return expanded
def _make_vobject_recurring_item(
item: radicale_item.Item
) -> radicale_item.Item:
# https://www.rfc-editor.org/rfc/rfc4791#section-9.6.5
# The returned calendar components MUST NOT use recurrence
# properties (i.e., EXDATE, EXRULE, RDATE, and RRULE) and MUST NOT
# have reference to or include VTIMEZONE components. Date and local
# time with reference to time zone information MUST be converted
# into date with UTC time.
item = copy.copy(item)
vevent = item.vobject_item.vevent
start_utc = vevent.dtstart.value.astimezone(datetime.timezone.utc)
end_utc = vevent.dtend.value.astimezone(datetime.timezone.utc)
vevent.dtstart = ContentLine(
name='DTSTART',
value=start_utc.strftime('%Y%m%dT%H%M%SZ'), params={})
vevent.dtend = ContentLine(
name='DTEND',
value=end_utc.strftime('%Y%m%dT%H%M%SZ'), params={})
timezones_to_remove = []
for component in item.vobject_item.components():
if component.name == 'VTIMEZONE':
timezones_to_remove.append(component)
for timezone in timezones_to_remove:
item.vobject_item.remove(timezone)
try:
delattr(item.vobject_item.vevent, 'rrule')
delattr(item.vobject_item.vevent, 'exdate')
delattr(item.vobject_item.vevent, 'exrule')
delattr(item.vobject_item.vevent, 'rdate')
except AttributeError:
pass
return item
def xml_item_response(base_prefix: str, href: str, def xml_item_response(base_prefix: str, href: str,
found_props: Sequence[ET.Element] = (), found_props: Sequence[ET.Element] = (),
not_found_props: Sequence[ET.Element] = (), not_found_props: Sequence[ET.Element] = (),