ungana

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README

commit d73b0d2765ec641e5e3d232733d91de07c5fdf97
parent 9ef47194b8cf04fa013c4b497bb2675f77605626
Author: Carlosokumu <carlosokumu254@gmail.com>
Date:   Sat, 23 Aug 2025 16:03:02 +0300

extend  IcalManager:
-  update generate_uuid to generate a globally unique UID using UUID + domain format for new event entries.
- update load_ical_file  to return a calendar instance if the the provided ical_path does not exist.
-  add check_existing_event  to check if an event with same summary,start and end already exists.

Diffstat:
Mcalendarapp/ical/ical_manager.py | 62+++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/calendarapp/ical/ical_manager.py b/calendarapp/ical/ical_manager.py @@ -1,8 +1,11 @@ import os -from icalendar import Calendar, Event, vDuration +import uuid +from zoneinfo import ZoneInfo +from icalendar import Calendar, Event from datetime import datetime, timedelta, timezone from typing import Dict, Any + class ICalManager: """Handles parsing, representing, and writing iCalendar files""" @@ -39,7 +42,7 @@ class ICalManager: if 'uid' in event_data: event.add('uid', event_data['uid']) else: - event.add('uid', self._generate_uid(start_dt)) + event.add('uid', self._generate_uid()) return event @@ -103,14 +106,21 @@ class ICalManager: return timedelta(hours=hours, minutes=minutes) - def _generate_uid(self, dtstart: datetime) -> str: - """Generate a unique ID based on event start time.""" - return f"{dtstart.strftime('%Y%m%dT%H%M%S')}@calendarapp" + + def _generate_uid(self) -> str: + """Generate a globally unique UID using UUID + domain style.""" + domain = "calendarapp.org" # you can set this to your app's domain + return f"{uuid.uuid4()}@{domain}" + def load_ical_file(self, filename: str) -> Calendar: - """Load an iCalendar file from disk with error handling.""" + """Load an iCalendar file from disk, or return a new Calendar if missing.""" if not os.path.exists(filename): - raise FileNotFoundError(f"iCalendar file '{filename}' does not exist.") + ## return a new Calendar instance if the provided ical_path is missing + cal = Calendar() + cal.add('VERSION', '2.0') + cal.add('PRODID', '-//CalendarApp//mxm.dk//') + return cal try: with open(filename, 'rb') as f: @@ -139,6 +149,44 @@ class ICalManager: if component.name == "VEVENT": return component return None + + + def check_existing_event(self,cal: Calendar,event_data: Event) -> bool: + tzid = event_data.get("tzid") + + candidate_key = ( + self.normalize_ical_field(event_data.get("start"), tzid), + self.normalize_ical_field(event_data.get("end"), tzid), + self.normalize_ical_field(event_data.get("summary")), + ) + for component in cal.walk("VEVENT"): + existing_key = ( + self.normalize_ical_field(component.get("DTSTART"), tzid), + self.normalize_ical_field(component.get("DTEND"), tzid), + self.normalize_ical_field(component.get("SUMMARY")), + ) + if existing_key == candidate_key: + return True + return False + + + def normalize_ical_field(self, value, tzid: str | None = None): + if isinstance(value, list): + value = value[0] + if hasattr(value, "dt"): + value = value.dt + + if isinstance(value, datetime): + if value.tzinfo is None and tzid: + return value.replace(tzinfo=ZoneInfo(tzid)) + return value + + if hasattr(value, "to_ical"): + return value.to_ical().decode() + + return str(value) + + def save_ical_file(self, event: Event, filename: str) -> None: """Save calendar with event to .ics file."""