From 0cacd98f23287edb4aa2b8b0d6cfda185f2dde52 Mon Sep 17 00:00:00 2001 From: Kevin Alberts Date: Wed, 11 Nov 2020 21:20:45 +0100 Subject: [PATCH] Add padding to each event UID to avoid conflicts when adding same events/icalendars to caldav calendars. --- davinci/icalendar/ical_utils.py | 19 +++++++++++++++++++ davinci/icalendar/models.py | 6 +++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/davinci/icalendar/ical_utils.py b/davinci/icalendar/ical_utils.py index 25cc53c..39c0017 100644 --- a/davinci/icalendar/ical_utils.py +++ b/davinci/icalendar/ical_utils.py @@ -1,6 +1,11 @@ +from typing import List from urllib.request import urlopen import ics +from django.utils.text import slugify +from ics import Event + +from davinci.caldav.models import CalDAVCalendar def get_ical_from_url(ical_url): @@ -11,3 +16,17 @@ def get_ical_from_url(ical_url): def split_events(data): c = ics.Calendar(data.decode('utf-8')) return c.events + + +def fix_ical_uid(event: Event, padding: str): + e = event.clone() + e.uid = f"{event.uid}{padding}" + return e + + +def fix_ical_uids(events: List[Event], calendar: CalDAVCalendar): + # Pad the uids with some string related to the calendar + # So that if someone wants to sync the same .ics to two calendars, the UIDs are different. We will do this by + # appending the string "@slugified-server-name+slugified-username+slugified-calendar-name" to each uid. + padding = f"@{slugify(calendar.server.name)}+{slugify(calendar.server.username)}+{slugify(calendar.name)}" + return [fix_ical_uid(event, padding) for event in events] diff --git a/davinci/icalendar/models.py b/davinci/icalendar/models.py index 485b288..1e48a9a 100644 --- a/davinci/icalendar/models.py +++ b/davinci/icalendar/models.py @@ -30,4 +30,8 @@ class ICalSync(models.Model): def get_events(self): data = ical_utils.get_ical_from_url(self.ical_url) - return ical_utils.split_events(data) + events = ical_utils.split_events(data) + # We have to pad the uids with some string related to the target calendar, + # So that if someone wants to sync the same .ics to two calendars, the UIDs are different. + fixed_events = ical_utils.fix_ical_uids(events, self.target) + return fixed_events