a76760edba
Funciones reutilizables creadas esta sesion para el sistema self-hosted de contactos/calendario (Xandikos) y la app osint_web: - grupo dav (infra): split_vcards, split_vevents_to_vcalendars, extract_or_make_uid, carddav_put_vcard, caldav_put_event, dav_list_resources, dav_get_resource, dav_list_calendars - pipelines: import_vcf_to_carddav, import_ics_to_caldav - obsidian: build_obsidian_graph (grafo agregado del vault)
57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
"""Divide un .ics (un VCALENDAR con N VEVENT) en N VCALENDARs independientes.
|
|
|
|
Funcion pura: sin I/O, sin estado, determinista. Cada salida es un VCALENDAR
|
|
completo y autonomo con un unico VEVENT, listo para subir como recurso CalDAV
|
|
individual. Las VTIMEZONE del original se incluyen en cada salida (un VEVENT
|
|
puede referenciar un TZID definido en el VCALENDAR padre). Solo usa stdlib (re).
|
|
"""
|
|
|
|
import re
|
|
|
|
_VEVENT_RE = re.compile(r"BEGIN:VEVENT.*?END:VEVENT", re.DOTALL)
|
|
_VTIMEZONE_RE = re.compile(r"BEGIN:VTIMEZONE.*?END:VTIMEZONE", re.DOTALL)
|
|
|
|
_DEFAULT_PRODID = "-//xandikos-migracion//google-export//EN"
|
|
|
|
|
|
def _to_crlf(text: str) -> str:
|
|
"""Normaliza saltos de linea a CRLF (RFC 5545)."""
|
|
return text.strip().replace("\r\n", "\n").replace("\n", "\r\n")
|
|
|
|
|
|
def split_vevents_to_vcalendars(ics_text: str, prodid: str = _DEFAULT_PRODID) -> list:
|
|
"""Divide un VCALENDAR con N VEVENT en N VCALENDARs independientes.
|
|
|
|
Args:
|
|
ics_text: contenido completo del .ics (un VCALENDAR con uno o varios
|
|
VEVENT). Tolera LF o CRLF.
|
|
prodid: valor del campo PRODID a usar en el header de cada VCALENDAR de
|
|
salida. Default: identifica la migracion a Xandikos.
|
|
|
|
Returns:
|
|
Lista de strings. Cada elemento es un VCALENDAR completo y autonomo
|
|
('BEGIN:VCALENDAR'..'END:VCALENDAR' terminado en CRLF) con header
|
|
VERSION/PRODID/CALSCALE, las VTIMEZONE del original (si las habia) y un
|
|
unico VEVENT. Lista vacia si no hay ningun VEVENT.
|
|
"""
|
|
if not ics_text:
|
|
return []
|
|
events = _VEVENT_RE.findall(ics_text)
|
|
timezones = _VTIMEZONE_RE.findall(ics_text)
|
|
tz_block = ""
|
|
for tz in timezones:
|
|
tz_block += _to_crlf(tz) + "\r\n"
|
|
|
|
header = (
|
|
"BEGIN:VCALENDAR\r\n"
|
|
"VERSION:2.0\r\n"
|
|
"PRODID:%s\r\n"
|
|
"CALSCALE:GREGORIAN\r\n" % prodid
|
|
)
|
|
|
|
out = []
|
|
for ev in events:
|
|
body = header + tz_block + _to_crlf(ev) + "\r\nEND:VCALENDAR\r\n"
|
|
out.append(body)
|
|
return out
|