
    ՟fY                        d Z ddlZddlmZ ddlmZ ddlmZmZm	Z	m
Z
mZmZmZmZmZmZmZ ddlmZmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZm Z m!Z!m"Z"m#Z#m$Z$ dZ%dZ& ede      Z'dee'   deee'      fdZ(dee'   de)de'fdZ*de'deeeee'   e)f   f   fdZ+ G d dejX                        Z- G d dej\                        Z/ G d dee!e ef         Z0y)z1This module contains the PicklePersistence class.    N)deepcopy)Path)AnyCallableDictOptionalSetTupleTypeTypeVarUnioncastoverload)BotTelegramObject)FilePathInput)warn)BasePersistencePersistenceInput)ContextTypes)BDCDUDCDCDataConversationDictConversationKeyz/a known bot replaced by PTB's PicklePersistencez2an unknown bot replaced by PTB's PicklePersistenceTelegramObj)boundclsreturnc           	          | j                         }t        |      j                  |D cg c]  }t        |      D ]  }|  c}}      S c c}}w )zsGets all subclasses of the specified object, recursively. from
    https://stackoverflow.com/a/3862957/9706202
    )__subclasses__setunion_all_subclasses)r   
subclassescss       Z/var/www/cvtools/html/venv/lib/python3.12/site-packages/telegram/ext/_picklepersistence.pyr%   r%   &   sG     ##%Jz?  Z!TQRAS!TA!!T!!TUU!Ts   A
kwargsc                 J    | j                  |       }|j                  |       |S )a  
    This method is used for unpickling. The data, which is in the form a dictionary, is
    converted back into a class. Works mostly the same as :meth:`TelegramObject.__setstate__`.
    This function should be kept in place for backwards compatibility even if the pickling logic
    is changed, since `_custom_reduction` places references to this function into the pickled data.
    )__new____setstate__)r   r*   objs      r)   _reconstruct_tor/   .   s%     ++c
CVJ    c                 p    | j                  d      }t        |d         |d<   t        | j                  |ffS )z
    This method is used for pickling. The bot attribute is preserved so _BotPickler().persistent_id
    works as intended.
    T)include_private
api_kwargs)
_get_attrsdictr/   	__class__)r   datas     r)   _custom_reductionr8   :   s>    
 >>$>/D d<01DS]]D111r0   c                   p     e Zd ZdZdededef fdZdedee	ee
e   ef   f   fdZdedee   fd	Z xZS )
_BotPickler_botbotargsr*   c                 2    || _         t        |   |i | y Nr<   super__init__selfr=   r>   r*   r6   s       r)   rC   z_BotPickler.__init__I       	$)&)r0   r.   r    c                 D    t        |t              st        S t        |      S )z
        This method is used for pickling. The bot attribute is preserved so
        _BotPickler().persistent_id works as intended.
        )
isinstancer   NotImplementedr8   rE   r.   s     r)   reducer_overridez_BotPickler.reducer_overrideM   s     #~.!! %%r0   c                 r    || j                   u rt        S t        |t              rt	        dd       t
        S y)zUsed to 'mark' the Bot, so it can be replaced later. See
        https://docs.python.org/3/library/pickle.html#pickle.Pickler.persistent_id for more info
        zHUnknown bot instance found. Will be replaced by `None` during unpickling   )
stacklevelN)r<   _REPLACED_KNOWN_BOTrH   r   r   _REPLACED_UNKNOWN_BOTrJ   s     r)   persistent_idz_BotPickler.persistent_idY   s9     $))&&c3Z )(r0   )__name__
__module____qualname__	__slots__r   r   rC   r   r
   r   r   r5   rK   objectr   strrQ   __classcell__r6   s   @r)   r:   r:   F   sg    I*C * *s *
&
&	xtK0$677	8
& HSM r0   r:   c                   F     e Zd ZdZdededef fdZdedee   fdZ	 xZ
S )	_BotUnpicklerr;   r=   r>   r*   c                 2    || _         t        |   |i | y r@   rA   rD   s       r)   rC   z_BotUnpickler.__init__k   rF   r0   pidr    c                 j    |t         k(  r| j                  S |t        k(  ryt        j                  d      )zSReplaces the bot with the current bot if known, else it is replaced by :obj:`None`.Nz,Found unknown persistent id when unpickling!)rO   r<   rP   pickleUnpicklingError)rE   r]   s     r)   persistent_loadz_BotUnpickler.persistent_loado   s3    %%99''$$%STTr0   )rR   rS   rT   rU   r   r   rC   rW   r   ra   rX   rY   s   @r)   r[   r[   h   s<    I*C * *s *U3 U8C= Ur0   r[   c                   H    e Zd ZdZdZe	 	 	 	 d.dddedee   de	d	e	d
e
fd       Ze	 	 	 	 	 d/dddedee   de	d	e	d
e
deeeeeef      fd       Z	 	 	 	 	 d/dedee   de	d	e	d
e
deeeeeef      f fdZd0dZdedefdZd0dZdededdfdZdeeef   fdZdeeef   fdZdefdZdee   fdZdedefdZ dede!dee   ddfdZ"dededdfd Z#d!ededdfd"Z$deddfd#Z%deddfd$Z&d!eddfd%Z'deddfd&Z(ded'eddfd(Z)d!ed)eddfd*Z*d+eddfd,Z+d0d-Z, xZ-S )1PicklePersistenceaq  Using python's builtin :mod:`pickle` for making your bot persistent.

    Attention:
        The interface provided by this class is intended to be accessed exclusively by
        :class:`~telegram.ext.Application`. Calling any of the methods below manually might
        interfere with the integration of persistence into :class:`~telegram.ext.Application`.

    Note:
        This implementation of :class:`BasePersistence` uses the functionality of the pickle module
        to support serialization of bot instances. Specifically any reference to
        :attr:`~BasePersistence.bot` will be replaced by a placeholder before pickling and
        :attr:`~BasePersistence.bot` will be inserted back when loading the data.

    Examples:
        :any:`Persistent Conversation Bot <examples.persistentconversationbot>`

    .. seealso:: :wiki:`Making Your Bot Persistent <Making-your-bot-persistent>`

    .. versionchanged:: 20.0

        * The parameters and attributes ``store_*_data`` were replaced by :attr:`store_data`.
        * The parameter and attribute ``filename`` were replaced by :attr:`filepath`.
        * :attr:`filepath` now also accepts :obj:`pathlib.Path` as argument.

    Args:
        filepath (:obj:`str` | :obj:`pathlib.Path`): The filepath for storing the pickle files.
            When :attr:`single_file` is :obj:`False` this will be used as a prefix.
        store_data (:class:`~telegram.ext.PersistenceInput`, optional): Specifies which kinds of
            data will be saved by this persistence instance. By default, all available kinds of
            data will be saved.
        single_file (:obj:`bool`, optional): When :obj:`False` will store 5 separate files of
            `filename_user_data`, `filename_bot_data`, `filename_chat_data`,
            `filename_callback_data` and `filename_conversations`. Default is :obj:`True`.
        on_flush (:obj:`bool`, optional): When :obj:`True` will only save to file when
            :meth:`flush` is called and keep data in memory until that happens. When
            :obj:`False` will store data on any transaction *and* on call to :meth:`flush`.
            Default is :obj:`False`.
        context_types (:class:`telegram.ext.ContextTypes`, optional): Pass an instance
            of :class:`telegram.ext.ContextTypes` to customize the types used in the
            ``context`` interface. If not passed, the defaults documented in
            :class:`telegram.ext.ContextTypes` will be used.

            .. versionadded:: 13.6
        update_interval (:obj:`int` | :obj:`float`, optional): The
            :class:`~telegram.ext.Application` will update
            the persistence in regular intervals. This parameter specifies the time (in seconds) to
            wait between two consecutive runs of updating the persistence. Defaults to 60 seconds.

            .. versionadded:: 20.0
    Attributes:
        filepath (:obj:`str` | :obj:`pathlib.Path`): The filepath for storing the pickle files.
            When :attr:`single_file` is :obj:`False` this will be used as a prefix.
        store_data (:class:`~telegram.ext.PersistenceInput`): Specifies which kinds of data will
            be saved by this persistence instance.
        single_file (:obj:`bool`): Optional. When :obj:`False` will store 5 separate files of
            `filename_user_data`, `filename_bot_data`, `filename_chat_data`,
            `filename_callback_data` and `filename_conversations`. Default is :obj:`True`.
        on_flush (:obj:`bool`): Optional. When :obj:`True` will only save to file when
            :meth:`flush` is called and keep data in memory until that happens. When
            :obj:`False` will store data on any transaction *and* on call to :meth:`flush`.
            Default is :obj:`False`.
        context_types (:class:`telegram.ext.ContextTypes`): Container for the types used
            in the ``context`` interface.

            .. versionadded:: 13.6
    )	bot_datacallback_data	chat_datacontext_typesconversationsfilepathon_flushsingle_file	user_dataNrE   zAPicklePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any, Any]]ri   
store_datark   rj   update_intervalc                      y r@    )rE   ri   rm   rk   rj   rn   s         r)   rC   zPicklePersistence.__init__   s     r0   zPicklePersistence[UD, CD, BD]rg   c                      y r@   rp   )rE   ri   rm   rk   rj   rn   rg   s          r)   rC   zPicklePersistence.__init__   s     r0   c                    t         |   ||       t        |      | _        || _        || _        d | _        d | _        d | _        d | _	        d | _
        t        t        t        t        t        t         f   |xs
 t                     | _        y )N)rm   rn   )rB   rC   r   ri   rk   rj   rl   rf   rd   re   rh   r   r   r   r   r   r   rg   )rE   ri   rm   rk   rj   rn   rg   r6   s          r)   rC   zPicklePersistence.__init__   s|     	JP"8n+6(02626&*04]a<@b"b)=+JLN=
r0   r    c                    	 | j                   j                  d      5 }t        | j                  |      j	                         }d d d        d   | _        |d   | _        |j                  d| j                  j                               | _	        |j                  di       | _
        |d   | _        y # 1 sw Y   nxY w# t        $ r> i | _        i | _        i | _        | j                  j                         | _	        d | _
        Y y t        j                  $ r+}| j                   j                  }t!        d| d      |d }~wt"        $ r(}t!        d	| j                   j                         |d }~ww xY w)
Nrbrl   rf   rd   re   rh   File # does not contain valid pickle data Something went wrong unpickling )ri   openr[   r=   loadrl   rf   getrg   rd   re   rh   OSErrorr_   r`   name	TypeError	Exception)rE   filer7   excfilenames        r)   _load_singlefilez"PicklePersistence._load_singlefile   sL   	^##D) <T$TXXt499;< "+.DN!+.DN HHZ1C1C1L1L1NODM!%/2!>D!%o!6D< <  	&!#DDNDN ..779DM!%D%% 	\}}))HeH:-PQRX[[ 	^>t}}?Q?Q>RSTZ]]	^sB   B; %B/A,B; /B84B; ;AE-E-&D99E-#E((E-c                 b   	 |j                  d      5 }t        | j                  |      j                         cd d d        S # 1 sw Y   y xY w# t        $ r Y y t
        j                  $ r}t        d|j                   d      |d }~wt        $ r}t        d|j                         |d }~ww xY w)Nrt   ru   rv   rw   )
rx   r[   r=   ry   r{   r_   r`   r}   r|   r~   )rE   ri   r   r   s       r)   
_load_filezPicklePersistence._load_file
  s    		Yt$ <$TXXt499;< < <  	%% 	aeHMM?2UVW]`` 	Y>x}}oNOUXX	YsE   A $A	A A
A 
A 	B.B.*BB.B))B.c                 B   | j                   | j                  | j                  | j                  | j                  d}| j
                  j                  d      5 }t        | j                  |t        j                        j                  |       d d d        y # 1 sw Y   y xY w)N)rh   rl   rf   rd   re   wbprotocol)rh   rl   rf   rd   re   ri   rx   r:   r=   r_   HIGHEST_PROTOCOLdump)rE   r7   r   s      r)   _dump_singlefilez"PicklePersistence._dump_singlefile  s    !//!//
 ]]% 	U$1H1HINNtT	U 	U 	Us   6BBr7   c                     |j                  d      5 }t        | j                  |t        j                        j                  |       d d d        y # 1 sw Y   y xY w)Nr   r   )rx   r:   r=   r_   r   r   )rE   ri   r7   r   s       r)   
_dump_filezPicklePersistence._dump_file!  sJ    ]]4  	UD$1H1HINNtT	U 	U 	Us   6AAc                    K   | j                   rnO| j                  s3| j                  t        | j                   d            }|si }|| _         n| j                          t        | j                         S w)zReturns the user_data from the pickle file if it exists or an empty :obj:`dict`.

        Returns:
            Dict[:obj:`int`, :obj:`dict`]: The restored user data.
        
_user_data)rl   rk   r   r   ri   r   r   rE   r7   s     r)   get_user_datazPicklePersistence.get_user_data%  c      >>!!??44==/(D#EFD!DN!!#''   A2A4c                    K   | j                   rnO| j                  s3| j                  t        | j                   d            }|si }|| _         n| j                          t        | j                         S w)zReturns the chat_data from the pickle file if it exists or an empty :obj:`dict`.

        Returns:
            Dict[:obj:`int`, :obj:`dict`]: The restored chat data.
        
_chat_data)rf   rk   r   r   ri   r   r   r   s     r)   get_chat_datazPicklePersistence.get_chat_data6  r   r   c                   K   | j                   rng| j                  sK| j                  t        | j                   d            }|s| j
                  j                         }|| _         n| j                          t        | j                         S w)a  Returns the bot_data from the pickle file if it exists or an empty object of type
        :obj:`dict` | :attr:`telegram.ext.ContextTypes.bot_data`.

        Returns:
            :obj:`dict` | :attr:`telegram.ext.ContextTypes.bot_data`: The restored bot data.
        	_bot_data)rd   rk   r   r   ri   rg   r   r   r   s     r)   get_bot_datazPicklePersistence.get_bot_dataG  sr      ==!!??44==/(C#DED))224 DM!!#&&s   B
Bc                   K   | j                   rnO| j                  s3| j                  t        | j                   d            }|sd}|| _         n| j                          | j                   yt        | j                         S w)ad  Returns the callback data from the pickle file if it exists or :obj:`None`.

        .. versionadded:: 13.6

        Returns:
            Tuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]],
            Dict[:obj:`str`, :obj:`str`]] | :obj:`None`: The restored metadata or :obj:`None`,
            if no data was stored.
        _callback_dataN)re   rk   r   r   ri   r   r   r   s     r)   get_callback_dataz#PicklePersistence.get_callback_dataY  sw      !!??44==/(H#IJD!%D!!#%**++s   A?Br|   c                   K   | j                   rnQ| j                  s5| j                  t        | j                   d            }|s|i i}|| _         n| j                          | j                   j                  |i       j                         S w)zReturns the conversations from the pickle file if it exists or an empty dict.

        Args:
            name (:obj:`str`): The handlers name.

        Returns:
            :obj:`dict`: The restored conversations for the handler.
        _conversations)rh   rk   r   r   ri   r   rz   copy)rE   r|   r7   s      r)   get_conversationsz#PicklePersistence.get_conversationsp  s}      !!??44==/(H#IJDbz!%D!!#!!%%dB/4466s   B	Bkey	new_statec                 l  K   | j                   si | _         | j                   j                  |i       j                  |      |k(  ry|| j                   |   |<   | j                  sP| j                  s3| j                  t        | j                   d      | j                          y| j                          yyw)aJ  Will update the conversations for the given handler and depending on :attr:`on_flush`
        save the pickle file.

        Args:
            name (:obj:`str`): The handler's name.
            key (:obj:`tuple`): The key the state is changed for.
            new_state (:class:`object`): The new state for the given key.
        Nr   )	rh   
setdefaultrz   rj   rk   r   r   ri   r   )rE   r|   r   r   s       r)   update_conversationz%PicklePersistence.update_conversation  s      !!!#D((r266s;yH(14 %}}##n%E FHZHZ[%%'	 s   B2B4user_idc                 F  K   | j                   i | _         | j                   j                  |      |k(  ry|| j                   |<   | j                  sP| j                  s3| j	                  t        | j                   d      | j                          y| j                          yyw)a  Will update the user_data and depending on :attr:`on_flush` save the pickle file.

        Args:
            user_id (:obj:`int`): The user the data might have been changed for.
            data (:obj:`dict`): The :attr:`telegram.ext.Application.user_data` ``[user_id]``.
        Nr   )rl   rz   rj   rk   r   r   ri   r   )rE   r   r7   s      r)   update_user_dataz"PicklePersistence.update_user_data        >>!DN>>g&$."&w}}##j%A BDNNS%%'	    BB!chat_idc                 F  K   | j                   i | _         | j                   j                  |      |k(  ry|| j                   |<   | j                  sP| j                  s3| j	                  t        | j                   d      | j                          y| j                          yyw)a  Will update the chat_data and depending on :attr:`on_flush` save the pickle file.

        Args:
            chat_id (:obj:`int`): The chat the data might have been changed for.
            data (:obj:`dict`): The :attr:`telegram.ext.Application.chat_data` ``[chat_id]``.
        Nr   )rf   rz   rj   rk   r   r   ri   r   )rE   r   r7   s      r)   update_chat_dataz"PicklePersistence.update_chat_data  r   r   c                    K   | j                   |k(  ry|| _         | j                  sP| j                  s3| j                  t	        | j
                   d      | j                          y| j                          yyw)zWill update the bot_data and depending on :attr:`on_flush` save the pickle file.

        Args:
            data (:obj:`dict` | :attr:`telegram.ext.ContextTypes.bot_data`): The
                :attr:`telegram.ext.Application.bot_data`.
        Nr   )rd   rj   rk   r   r   ri   r   r   s     r)   update_bot_dataz!PicklePersistence.update_bot_data  sa      ==D }}##i%@ A4==Q%%'	    A5A7c                    K   | j                   |k(  ry|| _         | j                  sP| j                  s3| j                  t	        | j
                   d      | j                          y| j                          yyw)a  Will update the callback_data (if changed) and depending on :attr:`on_flush` save the
        pickle file.

        .. versionadded:: 13.6

        Args:
            data (Tuple[List[Tuple[:obj:`str`, :obj:`float`,                 Dict[:obj:`str`, :class:`object`]]], Dict[:obj:`str`, :obj:`str`]]):
                The relevant data to restore :class:`telegram.ext.CallbackDataCache`.
        Nr   )re   rj   rk   r   r   ri   r   r   s     r)   update_callback_dataz&PicklePersistence.update_callback_data  sf      %!}}##n%E FHZHZ[%%'	 r   c                   K   | j                   y| j                   j                  |d       | j                  sP| j                  s3| j	                  t        | j                   d      | j                          y| j                          yyw)zWill delete the specified key from the ``chat_data`` and depending on
        :attr:`on_flush` save the pickle file.

        .. versionadded:: 20.0

        Args:
            chat_id (:obj:`int`): The chat id to delete from the persistence.
        Nr   )rf   poprj   rk   r   r   ri   r   )rE   r   s     r)   drop_chat_dataz PicklePersistence.drop_chat_data  l      >>!7D)}}##j%A BDNNS%%'	    BB	c                   K   | j                   y| j                   j                  |d       | j                  sP| j                  s3| j	                  t        | j                   d      | j                          y| j                          yyw)zWill delete the specified key from the ``user_data`` and depending on
        :attr:`on_flush` save the pickle file.

        .. versionadded:: 20.0

        Args:
            user_id (:obj:`int`): The user id to delete from the persistence.
        Nr   )rl   r   rj   rk   r   r   ri   r   )rE   r   s     r)   drop_user_dataz PicklePersistence.drop_user_data  r   r   rl   c                    K   yw)zDoes nothing.

        .. versionadded:: 13.6
        .. seealso:: :meth:`telegram.ext.BasePersistence.refresh_user_data`
        Nrp   )rE   r   rl   s      r)   refresh_user_dataz#PicklePersistence.refresh_user_data          rf   c                    K   yw)zDoes nothing.

        .. versionadded:: 13.6
        .. seealso:: :meth:`telegram.ext.BasePersistence.refresh_chat_data`
        Nrp   )rE   r   rf   s      r)   refresh_chat_dataz#PicklePersistence.refresh_chat_data  r   r   rd   c                    K   yw)zDoes nothing.

        .. versionadded:: 13.6
        .. seealso:: :meth:`telegram.ext.BasePersistence.refresh_bot_data`
        Nrp   )rE   rd   s     r)   refresh_bot_dataz"PicklePersistence.refresh_bot_data  r   r   c                 .  K   | j                   rN| j                  s0| j                  s$| j                  s| j                  s| j
                  r| j                          yy| j                  r2| j                  t        | j                   d      | j                         | j                  r2| j                  t        | j                   d      | j                         | j                  r2| j                  t        | j                   d      | j                         | j                  r2| j                  t        | j                   d      | j                         | j
                  r3| j                  t        | j                   d      | j
                         yyw)z/Will save all data in memory to pickle file(s).r   r   r   r   r   N)
rk   rl   rf   rd   re   rh   r   r   r   ri   )rE   s    r)   flushzPicklePersistence.flush  s#    >>==%%%%%%' & ~~j%A BDNNS~~j%A BDNNS}}i%@ A4==Q!!n%E FHZHZ[!!n%E FHZHZ[ "s   FF)NTF<   )NTFr   N)r    N).rR   rS   rT   __doc__rU   r   r   r   r   boolfloatrC   r   r   r   r   r   r   r   r   r   rV   r   r   intr   r   r   r   r   rW   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rX   rY   s   @r)   rc   rc   x   s   AF
I  26 !#Q -. 	
     26 !#AE- -. 	
    S"b"_ =>  26 !#AE

 -.
 	

 
 
  S"b"_ =>
,^.
Y4 
YC 
Y	UU4 Uv U$ U(T#r'] ("(T#r'] ("'B '$,'): ,.7C 74D 7(((-(:B6:J(	(,(c ( ( ($(c ( ( ($(" ( ( (w (4 (((C (D (&(C (D (&s r d s r d r d \r0   rc   )1r   r_   r   r   pathlibr   typingr   r   r   r   r	   r
   r   r   r   r   r   telegramr   r   telegram._utils.typesr   telegram._utils.warningsr   telegram.extr   r   telegram.ext._contexttypesr   telegram.ext._utils.typesr   r   r   r   r   r   rO   rP   r   r%   r5   r/   r8   Picklerr:   	Unpicklerr[   rc   rp   r0   r)   <module>r      s   & 8    b b b b ( / ) : 3 \ \G L m>:Vk* Vs43D/E V	k* 	D 	[ 		2; 	255kARTXAX;Y1Y+Z 	2&.. DUF$$ U z\B
3 z\r0   