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:
parent
a07813ecc9
commit
72103c30c2
1 changed files with 62 additions and 15 deletions
|
@ -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] = (),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue