o
    .j;                     @  s   d Z ddlmZ ddlZddlmZmZmZ ddlZddlm	Z	m
Z
 ddlmZ ddd	Zd
dddddZdddddZh dZd1ddZd2ddZd2ddZd3d d!Zd3d"d#Zd3d$d%Zd4d(d)Zd2d*d+Zd5d6d/d0ZdS )7u   
iCalendar → JSCalendar conversion (RFC 5545 → RFC 8984).

Public API:
    ical_to_jscal(ical_str, calendar_id=None) -> dict

The output dict is a raw JSCalendar CalendarEvent object suitable for passing
directly to CalendarEvent/set.
    )annotationsN)datedatetime	timedelta)_format_local_dt_timedelta_to_duration)vcalprivatesecret)PRIVATECONFIDENTIALzneeds-actionaccepteddeclined	tentative	delegated)zNEEDS-ACTIONACCEPTEDDECLINED	TENTATIVE	DELEGATED
individualgroupresourceroom)
INDIVIDUALGROUPRESOURCEROOM>   FRMOSASUTHTUWEreturntuple[str, str | None, bool]c                 C  s   | j }t|trt|ts|  dddfS |jdur,| tdkr,|dddfS |jdur?| j	
d}|d|dfS |dddfS )	zExtract JSCalendar start, timeZone, showWithoutTime from a DTSTART property.

    Returns:
        (start_str, time_zone, show_without_time)
    z	T00:00:00NTr   z%Y-%m-%dT%H:%M:%SzEtc/UTCFTZID)dt
isinstancer   r   	isoformattzinfo	utcoffsetr   strftimeparamsget)dtstart_propr'   tz_str r1   V/home/thesage/.local/lib/python3.10/site-packages/caldav/jmap/convert/ical_to_jscal.py_dtstart_to_jscal,   s   
r3   dictc                 C  sT  dddd}|  dg }|std| |d  |d< |  d	g }|r+t|d nd
|d< |  dg }|r=|d  nd|d< |  dg }|rQt|d |d< |  dg }|rat|d |d< |  dg }|rg }|D ]+}	t|	}
|
d}|
dt|
t|  }d| d}|rt||d< || qm||d< |  dg }|rdd |D |d< |  dg }|rdd |D |d < |  d!g }|rd"d |D |d#< |  d$g }|rd%d |D |d&< |  d'g }|rd(d |D |d)< |  d*g }|rd+d |D |d,< |  d-g }|rd.d |D |d/< |  d0g }|r(d1d |D |d2< |S )3u   Convert an iCalendar RRULE property to a JSCalendar RecurrenceRule dict.

    Always emits @type, interval, rscale, skip, firstDayOfWeek to match the
    fields Cyrus returns — makes round-trip comparison predictable.
    RecurrenceRule	gregorianomit)@typerscaleskipFREQz*RRULE is missing required FREQ component: r   	frequencyINTERVAL   intervalWKSTmofirstDayOfWeekCOUNTcountUNTILuntilBYDAYz+-0123456789NNDay)r8   daynthOfPeriodbyDayBYMONTHc                 S     g | ]}t |qS r1   str.0mr1   r1   r2   
<listcomp>u       z#_rrule_to_jscal.<locals>.<listcomp>byMonth
BYMONTHDAYc                 S  rM   r1   intrQ   dr1   r1   r2   rS   y   rT   
byMonthDay	BYYEARDAYc                 S  rM   r1   rW   rY   r1   r1   r2   rS   }   rT   	byYearDayBYWEEKNOc                 S  rM   r1   rW   )rQ   nr1   r1   r2   rS      rT   byWeekNoBYHOURc                 S  rM   r1   rW   )rQ   hr1   r1   r2   rS      rT   byHourBYMINUTEc                 S  rM   r1   rW   rP   r1   r1   r2   rS      rT   byMinuteBYSECONDc                 S  rM   r1   rW   )rQ   sr1   r1   r2   rS      rT   bySecondBYSETPOSc                 S  rM   r1   rW   )rQ   pr1   r1   r2   rS      rT   bySetPosition)	r.   
ValueErrorlowerrX   r   rO   lstriplenappend)
rrule_proprule	freq_listinterval_list	wkst_list
count_list
until_list
byday_listby_dayitemrg   day_abbrnth_strndaybymonth_list
bymonthday	byyeardaybyweeknobyhourbyminutebysecondbysetposr1   r1   r2   _rrule_to_jscalG   sn   
r   c                 C  sV   t | ts| g} i }| D ]}t|d|g}|D ]}t|d|}ddi|t|< qq|S )u   Convert an EXDATE property (single or list) to recurrenceOverrides entries.

    Returns:
        Dict mapping LocalDateTime/UTCDateTime string → {"excluded": True}
    dtsr'   excludedT)r(   listgetattrr   )exdate_prop	overridesexr   dt_propr'   r1   r1   r2   _exdate_to_overrides   s   
r   tuple[str, dict]c                 C  sv   t | d}t t }ddddt | drt | nd| id}| jd}|r3t ||d< ||d< ||fS )	zLConvert an ORGANIZER property to a (participant_id, Participant dict) tuple.mailto:T)owner	organizerimip)rolessendToCNnameemail)rO   removeprefixuuiduuid4
startswithr-   r.   )r   r   pidrj   cnr1   r1   r2   _organizer_to_participant   s    r   c           
      C  s  t | }|d}t t }ddid|dr|nd| i|d}| jd}|r1t ||d< | jd}|rEt| |	 |d	< | jd
d}t | dkrXd|d< | jd}|rlt
| |	 |d< | jd}	|	r|	 dkrd|d d< ||fS )zKConvert an ATTENDEE property to a (participant_id, Participant dict) tuple.r   attendeeTr   )r   r   r   r   r   PARTSTATparticipationStatusRSVP TRUEexpectReplyCUTYPEkindROLECHAIRr   chair)rO   r   r   r   r   r-   r.   _PARTSTAT_MAPupperrm   _CUTYPE_MAP)
r   addrr   r   rj   r   partstatrsvpcutyperoler1   r1   r2   _attendee_to_participant   s.   
r   c                 C  s   t t }t | dd }d|i}| d}|durI|j}t|tr=t||d< t |j	dd
 d	kr<d
|d< nt|trI|d|d< | d}|rVt ||d< ||fS )u   Convert a VALARM component to a (alert_id, Alert dict) tuple.

    Trigger is emitted as a plain SignedDuration string (e.g. "-PT15M") or
    UTCDateTime string per the JSCalendar Alert spec (RFC 8984 §4.5.2).
    ACTIONdisplayactionTRIGGERNtriggerRELATEDSTARTENDend
relativeToz%Y-%m-%dT%H:%M:%SZDESCRIPTIONdescription)rO   r   r   r.   rm   r'   r(   r   r   r-   r   r   r,   )alarmalert_idr   alerttrigger_proptrigger_valr   r1   r1   r2   _valarm_to_alert   s"   



r   location_strrO   c                 C  s   t t d| iiS )z|Convert a LOCATION string to a JSCalendar locations map entry.

    Returns:
        {"<uuid>": {"name": location_str}}
    r   )rO   r   r   )r   r1   r1   r2   _location_str_to_jscal   s   r   c                 C  s   t | drdd | jD }n3t| tr3g }| D ]}t |dr*|dd |jD  q|t| qnt| }dd |dD }dd	 |D S )
am  Convert a CATEGORIES property to a JSCalendar keywords map.

    icalendar returns one of three types depending on how CATEGORIES appears:
    - vCategory (single CATEGORIES line, possibly multi-value): access .cats
    - list of vCategory (multiple CATEGORIES lines): flatten .cats from each
    - vText (rare, single bare string value): str() and comma-split
    catsc                 S  rM   r1   rN   rQ   cr1   r1   r2   rS     rT   z+_categories_to_keywords.<locals>.<listcomp>c                 s  s    | ]}t |V  qd S NrN   r   r1   r1   r2   	<genexpr>  s    z*_categories_to_keywords.<locals>.<genexpr>c                 S  s   g | ]
}|  r|  qS r1   )striprQ   vr1   r1   r2   rS     s    ,c                 S  s   i | ]}|d qS )Tr1   r   r1   r1   r2   
<dictcomp>  s    z+_categories_to_keywords.<locals>.<dictcomp>)hasattrr   r(   r   extendrp   rO   split)categories_propvaluesrz   rawr1   r1   r2   _categories_to_keywords   s   


r   ical_strcalendar_id
str | Nonec           7      C  s  t | }tj|}d}i }|jD ]"}t|tjsq|ddur.t	|d j
}|||< q|du r4|}q|du r=tdt|d }|d}	|	rNt|	nd}
|d }t|\}}}|drht|d j
}n|d	rz|d	 j
|j
 }t|}nd
}d||
||d}|dur|di|d< |dur||d< |rd|d< |d}|rt||d< |d}|durt||d< |d}|durt|}|dkr||d< |d}|rtt| }|r||d< |d}|rt| dkrd|d< |d}|rt||d< |d }|durt|}|r||d!< |d"}|r)tt||d#< i }|d$}|dur?t|\}} | ||< |d%}!|!du rLg }"nt|!trU|!}"n|!g}"|"D ]}#t|#\}} | ||< qZ|ro||d&< |d'}$|$durt|$ts|$g}$d(d) |$D |d*< |d+}%|%durt|%ts|%g}%d,d) |%D |d-< i }&|d.}'|'dur|&t|' | D ]i\}(})i }*|)d}+|+rt|+|
krt|+|*d/< |)d},|,rt|,\}-}.}.|-|kr|-|*d0< |)d}/|/rt|/j
}0|0|kr|0|*d1< |)d}1|1rt|1|dkrt|1|*d< |*p#i |&|(< q|&r/|&|d2< d3d) |jD }2|2rPi }3|2D ]}4t|4\}5}6|6|3|5< q>|3|d4< |S )5u  Convert an iCalendar string to a JSCalendar CalendarEvent dict (RFC 8984).

    Processes the first VEVENT found in the string. Any sibling VEVENTs with a
    RECURRENCE-ID are folded into the ``recurrenceOverrides`` map of the master
    event. EXDATE entries are also added to ``recurrenceOverrides``.

    Args:
        ical_str: A VCALENDAR string (or bare VEVENT — vcal.fix normalises it).
        calendar_id: If provided, sets ``calendarIds: {calendar_id: true}``
            on the output. Required when the result will be used in
            ``CalendarEvent/set`` (the server needs to know which calendar).

    Returns:
        Raw JSCalendar dict suitable for passing directly to ``CalendarEvent/set``.

    Raises:
        ValueError: If no VEVENT component is found.
    NzRECURRENCE-IDz-No VEVENT component found in iCalendar stringUIDSUMMARYr   DTSTARTDURATIONDTENDP0DEvent)r8   uidtitlestartdurationTcalendarIdstimeZoneshowWithoutTimer   r   SEQUENCEsequencePRIORITYr   priorityCLASSprivacyTRANSPTRANSPARENTfreefreeBusyStatusCOLORcolor
CATEGORIESkeywordsLOCATION	locations	ORGANIZERATTENDEEparticipantsRRULEc                 S  rM   r1   r   rQ   rr1   r1   r2   rS     rT   z!ical_to_jscal.<locals>.<listcomp>recurrenceRulesEXRULEc                 S  rM   r1   r   r  r1   r1   r2   rS     rT   excludedRecurrenceRulesEXDATEr   r   r   recurrenceOverridesc                 S  s    g | ]}t |d ddkr|qS )r   NVALARM)r   r   r1   r1   r2   rS     s     alerts)r   fix	icalendarCalendar	from_icalsubcomponentsr(   r   r.   r   r'   rl   rO   r3   r   rX   
_CLASS_MAPr   r   r   r   r   r   updater   itemsr   )7r   r   fixedcalmasteroverrides_by_recurrence_id	componentridr   summaryr   r/   r   	time_zoneshow_without_timer   deltajscalr   r   r   p_intclsr   transpr   
categorieskwlocationr   r   r   rj   raw_attendees	attendeesr   rrulesexrulesrecurrence_overridesexdaterid_keychildpatchchild_summarychild_start_propchild_start_child_duration_prop	child_durchild_descriptionalarmsr	  r   r   r   r1   r1   r2   ical_to_jscal  s   
































r4  )r$   r%   )r$   r4   )r$   r   )r   rO   r$   r4   r   )r   rO   r   r   r$   r4   )__doc__
__future__r   r   r   r   r   r  caldav.jmap.convert._utilsr   r   
caldav.libr   r  r   r   _BYDAY_ABBRr3   r   r   r   r   r   r   r   r4  r1   r1   r1   r2   <module>   s>    
	


M


!

	