o
    .jZ3                     @  s   d Z ddlmZ ddlmZmZmZmZ ddlmZm	Z	 ddl
Z
ddl
mZmZ ddlmZ ddlmZ d	d
dZdddZddddddZdddddZd@d$d%ZdAd(d)ZdBd+d,ZdCd.d/ZdCd0d1ZdDd4d5ZdEd8d9ZdFd;d<ZdGd>d?ZdS )Hu   
JSCalendar → iCalendar conversion (RFC 8984 → RFC 5545).

Public API:
    jscal_to_ical(jscal: dict) -> str

Accepts a raw JSCalendar CalendarEvent dict (as returned by CalendarEvent/get
or produced by ical_to_jscal). Returns a VCALENDAR string.
    )annotations)datedatetime	timedeltatimezone)ZoneInfoZoneInfoNotFoundErrorN)vCalAddressvText)_duration_to_timedelta)vcalPRIVATECONFIDENTIAL)privatesecretTRANSPARENTOPAQUE)freebusyNEEDS-ACTIONACCEPTEDDECLINED	TENTATIVE	DELEGATED)zneeds-actionaccepteddeclined	tentative	delegated
INDIVIDUALGROUPRESOURCEROOM)
individualgroupresourceroom	componenticalendar.Event	start_strstr	time_zone
str | Noneshow_without_timeboolreturnNonec                 C  s   |rt |dd }| d| dS |dr+t|djtjd}| d| dS t|dd d}|rezt	|}|j|d}| d| W dS  t
yd   t|}||jd	< | d| Y dS w | d| dS )
a  Add a DTSTART property to component from JSCalendar start fields.

    Handles four cases:
    - All-day (showWithoutTime): VALUE=DATE
    - UTC (start ends with Z): UTC DATETIME
    - Timezone-aware: DATETIME;TZID=...
    - Floating (no timeZone, no Z): plain DATETIME
    N
   dtstartZ%Y-%m-%dT%H:%M:%SZtzinfo   %Y-%m-%dT%H:%M:%STZID)r   fromisoformataddendswithr   strptimereplacer   utcr   r   	icalendar	vDatetimeparams)r&   r(   r*   r,   dtdt_naivetzr1    rE   V/home/thesage/.local/lib/python3.10/site-packages/caldav/jmap/convert/jscal_to_ical.py_start_to_dtstart0   s(   


rG   ruledictc                 C  s  |  dd }|si S d|i}|  d}|r|dkr||d< |  d}|dur,||d	< |  d
}|rR|drFt|djtjd|d< nt|dd d|d< |  dg }|rg }|D ] }| dd }	| d}
|
ry||
 |	  q^||	 q^||d< |  dg }|rdd |D |d< |  dg }|r||d< |  dg }|r||d< |  dg }|r||d< |  dg }|r||d < |  d!g }|r||d"< |  d#g }|r||d$< |  d%g }|r||d&< |  d'}|r|d(kr| |d)< |S )*u   Convert a JSCalendar RecurrenceRule dict to an iCalendar vRecur-compatible dict.

    Strips @type and NDay @type fields — icalendar library rejects them.
    Returns a plain dict suitable for icalendar.vRecur.
    	frequency FREQinterval   INTERVALcountNCOUNTuntilr2   r3   r4   UNTILr6   r7   byDaydaynthOfPeriodBYDAYbyMonthc                 S  s,   g | ]}t |tr|ntt|d qS )L)
isinstanceintr)   rstrip).0mrE   rE   rF   
<listcomp>   s     z)_jscal_rrule_to_rrule.<locals>.<listcomp>BYMONTH
byMonthDay
BYMONTHDAY	byYearDay	BYYEARDAYbyWeekNoBYWEEKNObyHourBYHOURbyMinuteBYMINUTEbySecondBYSECONDbySetPositionBYSETPOSfirstDayOfWeekmoWKST)	getupperr;   r   r<   r=   r   r>   append)rH   freq	ical_rulerM   rP   rR   by_day
byday_strsndayrU   nthby_monthby_month_dayby_year_day
by_week_noby_hour	by_minute	by_second
by_set_pos	first_dayrE   rE   rF   _jscal_rrule_to_rruleY   sr   






r   pc                 C  sH   |  di }| dp| dp|  dd}|r"|ds"d| }|S )NsendToimipotheremailrK   zmailto:)rr   
startswith)r   send_tor   rE   rE   rF   _participant_imip   s
    
r   vCalAddress | Nonec                 C  sP   |  di }| ds| dsdS tt| }|  d}|r&t||jd< |S )zSBuild a vCalAddress for ORGANIZER, or None if this participant is not an organizer.rolesowner	organizerNnameCN)rr   r	   r   r
   rA   )r   r   addrr   rE   rE   rF   _participant_to_organizer   s   
r   c                   s  |  di  t fdddD }|s  ds  drdS tt| }|  d}|r3t||jd	< |  d
}|rFt || |jd< nd|jd< |  drUd|jd< |  d}|rgt || |jd<   drsd|jd< |S   dsz|rd|jd< |S )zPBuild a vCalAddress for ATTENDEE, or None if participant is purely an organizer.r   c                 3  s    | ]}  |V  qd S )N)rr   )r]   rr   rE   rF   	<genexpr>   s    

z+_participant_to_attendee.<locals>.<genexpr>)attendeechairinformationaloptionalr   r   Nr   r   participationStatusPARTSTATr   expectReplyTRUERSVPkindCUTYPEr   CHAIRROLEr   zREQ-PARTICIPANT)	rr   anyr	   r   r
   rA   _PARTSTAT_MAPrs   _KIND_TO_CUTYPE)r   has_attendee_roler   r   partstatr   rE   r   rF   _participant_to_attendee   s2   








r   alerticalendar.Alarmc                 C  s,  t  }| dd }|d| | dd}|rs|drDzt|djt	j
d}|d| W nH tyC   |dtd Y n8w zt|}t |}| d	d
krZd|jd< |d| W n tyr   |dtd Y n	w |dtd | d}|r|d| |S |dkr|dd |S )z@Convert a JSCalendar Alert dict to an icalendar.Alarm component.actiondisplaytriggerrK   r2   r3   r4   r   
relativeToendENDRELATEDdescriptionDISPLAYReminder)r?   Alarmrr   rs   r:   r;   r   r<   r=   r   r>   
ValueErrorr   r   	vDurationrA   )r   alarmr   trigger_strrB   tdr   r   rE   rE   rF   _alert_to_valarm   s>   



r   keywords	list[str]c                 C  s   dd |   D S )z@Convert JSCalendar keywords map to a list of CATEGORIES strings.c                 S  s   g | ]\}}|r|qS rE   rE   )r]   kvrE   rE   rF   r_   
  s    z+_keywords_to_categories.<locals>.<listcomp>)items)r   rE   rE   rF   _keywords_to_categories  s   r   	locationsc                 C  s,   |   D ]}|d}|rt|  S qdS )z@Extract the first location name from a JSCalendar locations map.r   N)valuesrr   r)   )r   locr   rE   rE   rF   _locations_to_location  s   
r   jscalc           ,      C  s  t  }|dd |dd t  }| dd}|r"|d| |dtjtjd | d	d
}|r;|d	| | dd}| d}| dd}|rUt	|||| | dd}|rk|dkrkt
|}	|d|	 | dd}
|
ry|d|
 | d}|r|d| | dd
}|r|d| | d}|rt|}|r|d| | dd}t|d}|dkr|d| | d}|r|d| | dpi }|rt|}|r|d| | dpi }|rt|}|r|d| | d pg D ]}t|}|r|d!| q| d"pg D ]}t|}|r#|d#| qg }g }| d$p0i  D ]\}}|d%rIt|d&jtjd'}n
t|d(d) d*}|d(u sdt|trk|d+rk|| q3t  }|d| |dtjtjd |d,| |d|}|d|}|d|} |rt	||||  |d|}!|!r|!dkr|dt
|! |d|
}"|"r|d|" |d|}#|#r|d|# || q3|r|D ]	}$|d-|$ qd}%| d.pi  D ]$}&t|&}'|'r|%s|d/|' d0}%t|&}(|(d(ur|d1|( q| d2p$i  D ]})t|)}*||* q'|| |D ]}|| q;| d3}+t|+S )4a  Convert a JSCalendar CalendarEvent dict to an iCalendar VCALENDAR string.

    Handles the full set of fields supported by ``ical_to_jscal`` for round-trip
    fidelity. ``recurrenceOverrides`` entries with ``excluded: true`` become
    EXDATE properties; patch dicts become child VEVENTs with RECURRENCE-ID.

    Args:
        jscal: A raw JSCalendar CalendarEvent dict as returned by ``CalendarEvent/get``.

    Returns:
        An iCalendar VCALENDAR string, normalised by ``vcal.fix()``.
    prodidz-//python-caldav//JMAP//ENversionz2.0uidrK   dtstamp)rD   sequencer   starttimeZoneshowWithoutTimeFdurationP0Dtitlesummaryr   priorityprivacyclassfreeBusyStatusr   r   transpcolorr   
categoriesr   locationrecurrenceRulesrruleexcludedRecurrenceRulesexrulerecurrenceOverridesr2   r3   r4   Nr6   r7   excludedzrecurrence-idexdateparticipantsr   Tr   alertszutf-8) r?   Calendarr:   Eventrr   r   nowr   r>   rG   r   _PRIVACY_TO_CLASS_FREE_BUSY_TO_TRANSPr   r   r   r   r;   r<   r=   rZ   rI   rt   r   r   r   r   add_componentto_icaldecoder   fix),r   caleventr   r   r(   r*   r,   duration_strr   r   r   r   r   cls	free_busyr   r   r   catsr   loc_namerH   rv   exdateschild_eventsoverride_keypatchrid_dtchildchild_startchild_tz	child_swt	child_durchild_title
child_desc	exdate_dtorganizer_addedr   orgattr   r   rawrE   rE   rF   jscal_to_ical  s   




"


r  )
r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   )rH   rI   r.   rI   )r   rI   r.   r)   )r   rI   r.   r   )r   rI   r.   r   )r   rI   r.   r   )r   rI   r.   r+   )r   rI   r.   r)   )__doc__
__future__r   r   r   r   r   zoneinfor   r   r?   r	   r
   caldav.jmap.convert._utilsr   
caldav.libr   r   r   r   r   rG   r   r   r   r   r   r   r   r  rE   rE   rE   rF   <module>   sD    
	

)
R


#
%
	