
    i]Y                        d Z ddl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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j*                  Z+ G d dej,                  Z- G d deeeef                   Z.dS )z1This module contains the PicklePersistence class.    N)Callable)deepcopy)Path)AnyTypeVar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                     |                                  }t          |                              d |D                       S )zsGets all subclasses of the specified object, recursively. from
    https://stackoverflow.com/a/3862957/9706202
    c                 6    g | ]}t          |          D ]}|S  )_all_subclasses).0css      _/Users/shanyulin/my-agent/.venv/lib/python3.11/site-packages/telegram/ext/_picklepersistence.py
<listcomp>z#_all_subclasses.<locals>.<listcomp>-   s.    !T!T!TQRASAS!T!TA!!T!T!T!T    )__subclasses__setunion)r   
subclassess     r"   r   r   (   s>     ##%%Jz??  !T!TZ!T!T!TUUUr$   kwargsc                 Z    |                      |           }|                    |           |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.   0   s.     ++c

CVJr$   c                 ~    |                      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_reductionr6   <   sB    
 >>$>//D d<011DS]D111r$   c                        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d	z  fd
Z xZS )_BotPickler_botbotargsr)   c                 H    || _          t                      j        |i | d S Nr:   super__init__selfr;   r<   r)   r4   s       r"   rA   z_BotPickler.__init__K   ,    	$)&)))))r$   r-   r   c                 X    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   NotImplementedr6   rC   r-   s     r"   reducer_overridez_BotPickler.reducer_overrideO   s*     #~.. 	"!! %%%r$   Nc                     || j         u rt          S t          |t                    rt	          dd           t
          S dS )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_BOTrF   r
   r   _REPLACED_UNKNOWN_BOTrH   s     r"   persistent_idz_BotPickler.persistent_id[   sS     $)&&c3 	)Z    )(tr$   )__name__
__module____qualname__	__slots__r
   r   rA   r   tupler   typer3   rI   objectstrrO   __classcell__r4   s   @r"   r8   r8   H   s        I*C * *s * * * * * *
&
&	xtK0$677	8
& 
& 
& 
& C$J        r$   r8   c                   F     e Zd ZdZdededef fdZdededz  fd	Z xZ	S )
_BotUnpicklerr9   r;   r<   r)   c                 H    || _          t                      j        |i | d S r>   r?   rB   s       r"   rA   z_BotUnpickler.__init__m   rD   r$   pidr   Nc                 h    |t           k    r| j        S |t          k    rdS 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!)rM   r:   rN   pickleUnpicklingError)rC   r]   s     r"   persistent_loadz_BotUnpickler.persistent_loadq   s9    %%%9'''4$%STTTr$   )
rP   rQ   rR   rS   r
   r   rA   rW   ra   rX   rY   s   @r"   r[   r[   j   s        I*C * *s * * * * * *U3 U3: U U U U U U U Ur$   r[   c                   l    e Zd ZdZdZe	 	 	 	 d1ddd	ed
edz  dedede	fd            Z
e	 	 	 	 	 d2ddd	ed
edz  dedede	deeeeef         dz  fd            Z
	 	 	 	 	 d2d	ed
edz  dedede	deeeeef         dz  f fdZ
d3dZd	edefdZd3d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dz  fdZdedefdZdede d edz  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*d3d0Z+ xZ,S )4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_dataNTF<   rC   zAPicklePersistence[dict[Any, Any], dict[Any, Any], dict[Any, Any]]ri   
store_datark   rj   update_intervalc                     d S r>   r   )rC   ri   rn   rk   rj   ro   s         r"   rA   zPicklePersistence.__init__   s	     sr$   zPicklePersistence[UD, CD, BD]rg   c                     d S r>   r   )rC   ri   rn   rk   rj   ro   rg   s          r"   rA   zPicklePersistence.__init__   s	     sr$   c                    t                                          ||           t          |          | _        || _        || _        d | _        d | _        d | _        d | _	        d | _
        t          d|pt                                | _        d S )N)rn   ro   zContextTypes[Any, UD, CD, BD])r@   rA   r   ri   rk   rj   rl   rf   rd   re   rh   r   r   rg   )rC   ri   rn   rk   rj   ro   rg   r4   s          r"   rA   zPicklePersistence.__init__   s     	JPPP"8nn(3%-/3/3#'-1TX<@+]-Llnn=
 =
r$   r   c                    	 | j                             d          5 }t          | j        |                                          }d d d            n# 1 swxY w Y   |d         | _        |d         | _        |                    d| j        	                                          | _	        |                    di           | _
        |d         | _        d S # t          $ r> i | _        i | _        i | _        | j        	                                | _	        d | _
        Y d S 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)rC   filer5   excfilenames        r"   _load_singlefilez"PicklePersistence._load_singlefile   s   	^##D)) <T$TXt4499;;< < < < < < < < < < < < < < < "+.DN!+.DN HHZ1C1L1L1N1NOODM!%/2!>!>D!%o!6D 	& 	& 	&!#DDNDN .7799DM!%D% 	\ 	\ 	\})HQHQQQRRX[[ 	^ 	^ 	^St}?QSSTTZ]]	^sN   C (AC AC AA7C AE5E5& EE5E00E5c                 r   	 |                     d          5 }t          | j        |                                          cd d d            S # 1 swxY w Y   d S # t          $ r Y d S 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~   )rC   ri   r   r   s       r"   
_load_filezPicklePersistence._load_file  s+   		Yt$$ <$TXt4499;;< < < < < < < < < < < < < < < < < <  	 	 	44% 	a 	a 	aVHMVVVWW]`` 	Y 	Y 	YNx}NNOOUXX	YsK   A 'AA AA AA 
B6%B63BB6B11B6c                    | j         | j        | j        | j        | j        d}| j                            d          5 }t          | j        |t          j
                                      |           d d d            d S # 1 swxY w Y   d S )N)rh   rl   rf   rd   re   wbprotocol)rh   rl   rf   rd   re   ri   rx   r8   r;   r_   HIGHEST_PROTOCOLdump)rC   r5   r   s      r"   _dump_singlefilez"PicklePersistence._dump_singlefile  s    !/!/
 
 ]%% 	U$1HIIINNtTTT	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	Us   5A>>BBr5   c                     |                     d          5 }t          | j        |t          j                                      |           d d d            d S # 1 swxY w Y   d S )Nr   r   )rx   r8   r;   r_   r   r   )rC   ri   r5   r   s       r"   
_dump_filezPicklePersistence._dump_file#  s    ]]4   	UD$1HIIINNtTTT	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	U 	Us   5AAAc                    K   | j         rnQ| j        s6|                     t          | j         d                    }|si }|| _         n|                                  t          | j                   S )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   rC   r5   s     r"   get_user_datazPicklePersistence.get_user_data'  |       > 	$! 	$??44=(D(D(D#E#EFFD !DNN!!###'''r$   c                    K   | j         rnQ| j        s6|                     t          | j         d                    }|si }|| _         n|                                  t          | j                   S )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_data8  r   r$   c                   K   | j         rnh| j        sM|                     t          | j         d                    }|s| j                                         }|| _         n|                                  t          | j                   S )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_dataI  s       = 	$! 	$??44=(C(C(C#D#DEED 5)2244 DMM!!###&&&r$   c                    K   | j         rnQ| j        s6|                     t          | j         d                    }|sd}|| _         n|                                  | j         dS t          | j                   S )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_data[  s        	$! 	$??44=(H(H(H#I#IJJD !%D!!###%4*+++r$   r|   c                   K   | j         rnS| j        s8|                     t          | j         d                    }|s|i i}|| _         n|                                  | j                             |i                                           S )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)rC   r|   r5   s      r"   get_conversationsz#PicklePersistence.get_conversationsr  s        	$! 	$??44=(H(H(H#I#IJJD "bz!%D!!###!%%dB//44666r$   key	new_statec                 Z  K   | j         si | _         | j                             |i                               |          |k    rdS || j         |         |<   | j        sO| j        s2|                     t          | j         d          | j                    dS |                                  dS dS )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   )rC   r|   r   r   s       r"   update_conversationz%PicklePersistence.update_conversation  s       ! 	$!#D((r2266s;;yHHF(14 %} 	(# (%E%E%E F FHZ[[[[[%%'''''		( 	(r$   user_idc                 &  K   | j         i | _         | j                             |          |k    rdS || j         |<   | j        sO| j        s2|                     t          | j         d          | j                    dS |                                  dS dS )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   )rC   r   r5   s      r"   update_user_dataz"PicklePersistence.update_user_data         >!DN>g&&$..F"&w} 	(# (%A%A%A B BDNSSSSS%%'''''		( 	(r$   chat_idc                 &  K   | j         i | _         | j                             |          |k    rdS || j         |<   | j        sO| j        s2|                     t          | j         d          | j                    dS |                                  dS dS )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   )rC   r   r5   s      r"   update_chat_dataz"PicklePersistence.update_chat_data  r   r$   c                    K   | j         |k    rdS || _         | j        sO| j        s2|                     t	          | j         d          | j                    dS |                                  dS dS )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  s       =D  F} 	(# (%@%@%@ A A4=QQQQQ%%'''''		( 	(r$   c                    K   | j         |k    rdS || _         | j        sO| j        s2|                     t	          | j         d          | j                    dS |                                  dS dS )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  s       %%F!} 	(# (%E%E%E F FHZ[[[[[%%'''''		( 	(r$   c                    K   | j         dS | j                             |d           | j        sO| j        s2|                     t          | j         d          | j                    dS |                                  dS dS )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   )rC   r   s     r"   drop_chat_dataz PicklePersistence.drop_chat_data         >!F7D)))} 	(# (%A%A%A B BDNSSSSS%%'''''		( 	(r$   c                    K   | j         dS | j                             |d           | j        sO| j        s2|                     t          | j         d          | j                    dS |                                  dS dS )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   )rC   r   s     r"   drop_user_dataz PicklePersistence.drop_user_data  r   r$   rl   c                 
   K   dS )zDoes nothing.

        .. versionadded:: 13.6
        .. seealso:: :meth:`telegram.ext.BasePersistence.refresh_user_data`
        Nr   )rC   r   rl   s      r"   refresh_user_dataz#PicklePersistence.refresh_user_data
  
        r$   rf   c                 
   K   dS )zDoes nothing.

        .. versionadded:: 13.6
        .. seealso:: :meth:`telegram.ext.BasePersistence.refresh_chat_data`
        Nr   )rC   r   rf   s      r"   refresh_chat_dataz#PicklePersistence.refresh_chat_data  r   r$   rd   c                 
   K   dS )zDoes nothing.

        .. versionadded:: 13.6
        .. seealso:: :meth:`telegram.ext.BasePersistence.refresh_bot_data`
        Nr   )rC   rd   s     r"   refresh_bot_dataz"PicklePersistence.refresh_bot_data  r   r$   c                   K   | j         r;| j        s| j        s| j        s| j        s| j        r|                                  dS dS | j        r0|                     t          | j	         d          | j                   | j        r0|                     t          | j	         d          | j                   | j        r0|                     t          | j	         d          | j                   | j        r0|                     t          | j	         d          | j                   | j        r2|                     t          | j	         d          | j                   dS dS )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   )rC   s    r"   flushzPicklePersistence.flush  s      	\(>( =( %	(
 %( %%'''''( ( ~ T%A%A%A B BDNSSS~ T%A%A%A B BDNSSS} R%@%@%@ A A4=QQQ! \%E%E%E F FHZ[[[! \%E%E%E F FHZ[[[[[\ \r$   )NTFrm   )NTFrm   N)r   N)-rP   rQ   rR   __doc__rS   r	   r   r   boolfloatrA   r   r   r   r   r   r   r   r   r   rV   r   r3   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   z   s       A AF
I  /3 !# Q %t+ 	
     X  /3 !#>B - %t+ 	
   $CRO4t;   X /3 !#>B
 

 %t+
 	

 
 
 $CRO4t;
 
 
 
 
 
,^ ^ ^ ^.
Y4 
YC 
Y 
Y 
Y 
Y	U 	U 	U 	UU4 Uv U$ U U U U(T#r'] ( ( ( ("(T#r'] ( ( ( ("'B ' ' ' '$,4 , , , ,.7C 74D 7 7 7 7(((-(:@4-(	( ( ( (,(c ( ( ( ( ( ($(c ( ( ( ( ( ($(" ( ( ( ( ( (w (4 ( ( ( (((C (D ( ( ( (&(C (D ( ( ( (&s r d    s r d    r d    \ \ \ \ \ \ \ \r$   rc   )/r   r_   collections.abcr   r   r   pathlibr   typingr   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   rM   rN   r   rU   r&   r   r3   r.   rT   r6   Picklerr8   	Unpicklerr[   rc   r   r$   r"   <module>r      s|  & 8 7  $ $ $ $ $ $             / / / / / / / / / / / / ( ( ( ( ( ( ( ( / / / / / / ) ) ) ) ) ) : : : : : : : : 3 3 3 3 3 3 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \G L gm>:::Vk* Vs43D/E V V V V	k* 	D 	[ 	 	 	 		2; 	255kARTXAX;Y1Y+Z 	2 	2 	2 	2    &.   DU U U U UF$ U U U z\ z\ z\ z\ z\B
3 z\ z\ z\ z\ z\r$   