
    i5                        d Z ddlmZ ddlmZmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZmZmZmZ ddlmZ dd	lmZmZmZ erdd
lmZ ddlmZ ddlmZ e
ez  Z G d d          Z G d d          Zg dZdS )aQ  Compute the times and states of alarms.

This takes different calendar software into account and the RFC 9074 (Alarm Extension).

- RFC 9074 defines an ACKNOWLEDGED property in the VALARM.
- Outlook does not export VALARM information.
- Google Calendar uses the DTSTAMP to acknowledge the alarms.
- Thunderbird snoozes the alarms with a X-MOZ-SNOOZE-TIME attribute in the event.
- Thunderbird acknowledges the alarms with a X-MOZ-LASTACK attribute in the event.
- Etar deletes alarms that are acknowledged.
- Nextcloud's Webinterface does not do anything with the alarms when the time passes.
    )annotations)date	timedeltatzinfo)TYPE_CHECKING)Event)Todo)ComponentEndMissingComponentStartMissingIncompleteAlarmInformationLocalTimezoneMissing)tzp)is_datenormalize_pytzto_datetime)	Generator)datetime)Alarmc                      e Zd ZdZ	 	 	 dddZedd            Zedd            Zedd            ZddZ	edd            Z
dS )	AlarmTimezRepresents a computed alarm occurrence with its timing and state.

    An AlarmTime instance combines an alarm component with its resolved
    trigger time and additional state information, such as acknowledgment
    and snoozing.
    Nalarmr   triggerr   acknowledged_untildatetime | Nonesnoozed_untilparentParent | Nonec                L    || _         || _        || _        || _        || _        dS )a  Create an instance of ``AlarmTime`` with any of its parameters.

        Parameters:
            alarm: The underlying alarm component.
            trigger: A date or datetime at which to trigger the alarm.
            acknowledged_until: Optional datetime in UTC until which
                the alarm has been acknowledged.
            snoozed_until: Optional datetime in UTC until which
                the alarm has been snoozed.
            parent: Optional parent component to which the alarm refers.
        N)_alarm_parent_trigger	_last_ack_snooze_until)selfr   r   r   r   r   s         K/root/projects/butler/venv/lib/python3.11/site-packages/icalendar/alarms.py__init__zAlarmTime.__init__/   s.    & +*    returnc                h    | j         j        }|| j        S | j        |S t          || j                  S )zThe time in UTC at which this alarm was last acknowledged.

        If the alarm was not acknowledged (dismissed), then this is None.
        )r   ACKNOWLEDGEDr"   max)r$   acks     r%   acknowledgedzAlarmTime.acknowledgedH   s:     j%;>!>!J3'''r'   c                    | j         S )zThe alarm component.)r   r$   s    r%   r   zAlarmTime.alarmU   s     {r'   c                    | j         S )zThe component that contains the alarm.

        This is ``None`` if you didn't use :meth:`Alarms.add_component()
        <icalendar.alarms.Alarms.add_component>`.
        )r    r/   s    r%   r   zAlarmTime.parentZ   s     |r'   boolc                    | j         }|sdS | j        | j        |k    rdS | j        }|j        t	          d          ||k    S )a  Whether this alarm is active (``True``) or acknowledged (``False``).

        For example, in some calendar software, this is ``True`` until the user
        views the alarm message and dismisses it.

        Alarms can be in local time without a timezone. To calculate whether
        the alarm has occurred, the time must include timezone information.

        Raises:
            LocalTimezoneMissing: If a timezone is required but not given.
        TNzdA local timezone is required to check if the alarm is still active. Use Alarms.set_local_timezone().)r-   r#   r   r   r   )r$   r-   r   s      r%   	is_activezAlarmTime.is_activec   sg     ( 	4)d.@<.O.O4,>!&3   %%r'   r   c                L    | j         | j         | j        k    r| j         S | j        S )zThe time at which the alarm triggers.

        If the alarm has been snoozed, this may differ from the TRIGGER property.
        )r#   r!   r/   s    r%   r   zAlarmTime.trigger|   s-     )d.@4=.P.P%%}r'   )NNN)
r   r   r   r   r   r   r   r   r   r   )r(   r   )r(   r   )r(   r   )r(   r1   )r(   r   )__name__
__module____qualname____doc__r&   propertyr-   r   r   r3   r    r'   r%   r   r   '   s          /3)- $+ + + + +2 
( 
( 
( X
(    X    X& & & &2    X  r'   r   c                      e Zd ZdZd)d*dZd+dZd,d
Zd-dZd.dZd.dZ	d/dZ
d0dZd0dZd1dZed2d            Zd3d"Zd4d$Zd2d%Zd2d&Zd2d'Zed2d(            ZdS )5Alarmsa  Compute the times and states of alarms.

    This is an example using RFC 9074.
    One alarm is 30 minutes before the event and acknowledged.
    Another alarm is 15 minutes before the event and still active.

    >>> from icalendar import Event, Alarms
    >>> event = Event.from_ical(
    ... '''BEGIN:VEVENT
    ... CREATED:20210301T151004Z
    ... UID:AC67C078-CED3-4BF5-9726-832C3749F627
    ... DTSTAMP:20210301T151004Z
    ... DTSTART;TZID=America/New_York:20210302T103000
    ... DTEND;TZID=America/New_York:20210302T113000
    ... SUMMARY:Meeting
    ... BEGIN:VALARM
    ... UID:8297C37D-BA2D-4476-91AE-C1EAA364F8E1
    ... TRIGGER:-PT30M
    ... ACKNOWLEDGED:20210302T150004Z
    ... DESCRIPTION:Event reminder
    ... ACTION:DISPLAY
    ... END:VALARM
    ... BEGIN:VALARM
    ... UID:8297C37D-BA2D-4476-91AE-C1EAA364F8E1
    ... TRIGGER:-PT15M
    ... DESCRIPTION:Event reminder
    ... ACTION:DISPLAY
    ... END:VALARM
    ... END:VEVENT
    ... ''')
    >>> alarms = Alarms(event)
    >>> len(alarms.times)   # all alarms including those acknowledged
    2
    >>> len(alarms.active)  # the alarms that are not acknowledged, yet
    1
    >>> alarms.active[0].trigger  # this alarm triggers 15 minutes before 10:30
    datetime.datetime(2021, 3, 2, 10, 15, tzinfo=ZoneInfo(key='America/New_York'))

    RFC 9074 specifies that alarms can also be triggered by proximity.
    This is not implemented yet.
    N	componentAlarm | Event | Todo | Nonec                    g | _         g | _        g | _        d| _        d| _        d| _        d| _        d| _        d| _        || 	                    |           dS dS )zStart computing alarm times.N)
_absolute_alarms_start_alarms_end_alarms_start_endr    r"   r#   _local_tzinfoadd_component)r$   r=   s     r%   r&   zAlarms.__init__   sn    -/*,(*#'!%	&**..2,0 y))))) ! r'   Alarm | Parentc                   t          |t          t          f          r|                     |           |                     |j                   |                     |j                   |                                r5| 	                    |j
                   |                     |j                   n| 	                    |j                   |                    d          D ]}|                     |           dS )zAdd a component.

        If this is an alarm, it is added.
        Events and Todos are added as a parent and all
        their alarms are added, too.
        VALARMN)
isinstancer   r	   
set_parent	set_startstartset_endendis_thunderbirdacknowledge_untilX_MOZ_LASTACKsnooze_untilX_MOZ_SNOOZE_TIMEDTSTAMPwalk	add_alarm)r$   r=   r   s      r%   rF   zAlarms.add_component   s     i%// 	:OOI&&&NN9?+++LL''''')) :&&y'>???!!)"=>>>>&&y'8999^^H-- 	" 	"ENN5!!!!	" 	"r'   r   Parentc                R    | j         | j         |urt          d          || _         dS )z{Set the parent of all the alarms.

        If you would like to collect alarms from a component, use add_component
        Nz7You can only set one parent for this alarm calculation.)r    
ValueError)r$   r   s     r%   rK   zAlarms.set_parent   s2    
 <#F(B(BVWWWr'   r   r   r(   Nonec                    |j         }|dS t          |t                    r| j                            |           dS |j        dk    r| j                            |           dS | j                            |           dS )z!Optional: Add an alarm component.NSTART)TRIGGERrJ   r   r@   appendTRIGGER_RELATEDrA   rB   r$   r   r   s      r%   rW   zAlarms.add_alarm   s    -?Fgt$$ 	+!((/////"g--%%e,,,,,##E*****r'   dtdate | Nonec                    || _         dS )zSet the start of the component.

        If you have only absolute alarms, this is not required.
        If you have alarms relative to the start of a compoment, set the start here.
        N)rC   r$   rb   s     r%   rL   zAlarms.set_start   s     r'   c                    || _         dS )zSet the end of the component.

        If you have only absolute alarms, this is not required.
        If you have alarms relative to the end of a compoment, set the end here.
        N)rD   re   s     r%   rN   zAlarms.set_end   s     			r'   r   tdr   c                    t          |          r|j        dk    r||z   S t          |          }t          ||z             S )zAdd a timedelta to a datetime.r   )r   secondsr   r   )r$   rb   rg   s      r%   _addzAlarms._add   sA    2;; 	!zQBwRBb2g&&&r'   c                @    |t          j        |          nd| _        dS )a  The time in UTC when all the alarms of this component were acknowledged.

        Only the last call counts.

        Since RFC 9074 (Alarm Extension) was created later,
        calendar implementations differ in how they acknowledge alarms.
        For example, Thunderbird and Google Calendar store the last time
        an event has been acknowledged because of an alarm.
        All alarms that happen before this time count as acknowledged.
        N)r   localize_utcr"   re   s     r%   rQ   zAlarms.acknowledge_until  s#     24)"---Tr'   c                @    |t          j        |          nd| _        dS )zThis is the time in UTC when all the alarms of this component were snoozed.

        Only the last call counts.

        The alarms are supposed to turn up again at dt when they are not acknowledged
        but snoozed.
        N)r   rl   r#   re   s     r%   rS   zAlarms.snooze_until  s&     68^S-b111r'   r   tzinfo | str | Nonec                f    t          |t                    rt          j        |          n|| _        dS )au  Set the local timezone.

        Events are sometimes in local time.
        In order to compute the exact time of the alarm, some
        alarms without timezone are considered local.

        Some computations work without setting this, others don't.
        If they need this information, expect a LocalTimezoneMissing exception
        somewhere down the line.
        N)rJ   strr   timezonerE   )r$   r   s     r%   set_local_timezonezAlarms.set_local_timezone  s2     6@5L5LXS\&111RXr'   list[AlarmTime]c                ~    |                                  |                                 z   |                                 z   S )aP  Compute and return the times of the alarms given.

        If the information for calculation is incomplete, this will raise a
        IncompleteAlarmInformation exception.

        Please make sure to set all the required parameters before calculating.
        If you forget to set the acknowledged times, that is not problem.
        )_get_end_alarm_times_get_start_alarm_times_get_absolute_alarm_timesr/   s    r%   timeszAlarms.times&  s@     %%''))++,,,../	
r'   firstr   Generator[datetime]c              #     K   |V  |j         }|j        }|r3|r3t          d|dz             D ]!}|                     |||z            V  dS dS dS )z8The times when the alarm is triggered relative to start.   N)REPEATDURATIONrangerj   )r$   ry   r   repeatdurationis         r%   _repeatzAlarms._repeat6  s      > 	5h 	51fqj)) 5 5iix!|444444	5 	5 	5 	55 5r'   r   c                    t          |dd          /| j        (t          |                    | j                            }t	          ||| j        | j        | j                  S )z4Create an alarm time with the additional attributes.r   N)r   )getattrrE   r   replacer   r"   r#   r    ra   s      r%   _alarm_timezAlarms._alarm_time?  s^    7Hd++38J8V$W__D<N_%O%OPPG7DND,>
 
 	
r'   c                *      fd j         D             S )z&Return a list of absolute alarm times.c                x    g | ]6}                     |j        |          D ]}                    ||          7S r:   )r   r^   r   .0r   r   r$   s      r%   
<listcomp>z4Alarms._get_absolute_alarm_times.<locals>.<listcomp>I  s`     
 
 
<<u==
 
  UG,,
 
 
 
r'   )r@   r/   s   `r%   rw   z Alarms._get_absolute_alarm_timesG  s1    
 
 
 
.
 
 
 	
r'   c                d      j          j        rt          d           fd j        D             S )DReturn a list of alarm times relative to the start of the component.NzXUse Alarms.set_start because at least one alarm is relative to the start of a component.c                    g | ]O}                                         j        |j                  |          D ]}                    ||          PS r:   )r   rj   rC   r^   r   r   s      r%   r   z1Alarms._get_start_alarm_times.<locals>.<listcomp>V  sp     
 
 
<<		$+u}(M(MuUU
 
  UG,,
 
 
 
r'   )rC   rA   r   r/   s   `r%   rv   zAlarms._get_start_alarm_timesO  sX    ;4#5'(  
 
 
 
+
 
 
 	
r'   c                d      j          j        rt          d           fd j        D             S )r   NzTUse Alarms.set_end because at least one alarm is relative to the end of a component.c                    g | ]O}                                         j        |j                  |          D ]}                    ||          PS r:   )r   rj   rD   r^   r   r   s      r%   r   z/Alarms._get_end_alarm_times.<locals>.<listcomp>c  sp     
 
 
<<		$)U](K(KUSS
 
  UG,,
 
 
 
r'   )rD   rB   r
   r/   s   `r%   ru   zAlarms._get_end_alarm_times\  sX    9!1%"  
 
 
 
)
 
 
 	
r'   c                $    d | j         D             S )aS  The alarm times that are still active and not acknowledged.

        This considers snoozed alarms.

        Alarms can be in local time (without a timezone).
        To calculate if the alarm really happened, we need it to be in a timezone.
        If a timezone is required but not given, we throw an IncompleteAlarmInformation.
        c                :    g | ]}|                                 |S r:   )r3   )r   
alarm_times     r%   r   z!Alarms.active.<locals>.<listcomp>s  s)    RRRz:;O;O;Q;QR
RRRr'   )rx   r/   s    r%   activezAlarms.activei  s     SRTZRRRRr'   )N)r=   r>   )r=   rG   )r   rX   )r   r   r(   r[   )rb   rc   )rb   r   rg   r   )rb   rc   r(   r[   )r   rn   )r(   rs   )ry   r   r   r   r(   rz   )r   r   r   r   )r5   r6   r7   r8   r&   rF   rK   rW   rL   rN   rj   rQ   rS   rr   r9   rx   r   r   rw   rv   ru   r   r:   r'   r%   r<   r<      s       ( (T* * * * *" " " "(   
+ 
+ 
+ 
+      ' ' ' 'J J J JN N N NY Y Y Y 
 
 
 X
5 5 5 5
 
 
 

 
 
 

 
 
 

 
 
 
 	S 	S 	S X	S 	S 	Sr'   r<   )r   r<   r
   r   r   N) r8   
__future__r   r   r   r   r   typingr   icalendar.cal.eventr   icalendar.cal.todor	   icalendar.errorr
   r   r   r   icalendar.timezoner   icalendar.toolsr   r   r   collections.abcr   icalendar.cal.alarmr   rX   r   r<   __all__r:   r'   r%   <module>r      s    # " " " " " , , , , , , , , , ,             % % % % % % # # # # # #            # " " " " " @ @ @ @ @ @ @ @ @ @ *))))))!!!!!!))))))	] ] ] ] ] ] ] ]@lS lS lS lS lS lS lS lS^  r'   