
    ՟fH                        d Z ddl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 ddlmZ 	 ddlmZ dZddlZdd	lmZmZmZmZmZ dd
lmZ ddlmZ ddlmZ erddlm Z   G d de      Z! G d d      Z" G d d      Z#y# e$ r dZY Uw xY w)z1This module contains the CallbackDataCache class.    N)datetime)TYPE_CHECKINGAnyDictMutableMappingOptionalTupleUnioncast)uuid4)LRUCacheTF)CallbackQueryInlineKeyboardButtonInlineKeyboardMarkupMessageUser)to_float_timestamp)TelegramError)CDCData)ExtBotc                   Z     e Zd ZdZdZddee   ddf fdZdee	eee      f   fdZ
 xZS )	InvalidCallbackDataa2  
    Raised when the received callback data has been tampered with or deleted from cache.

    Examples:
        :any:`Arbitrary Callback Data Bot <examples.arbitrarycallbackdatabot>`

    .. seealso:: :wiki:`Arbitrary callback_data <Arbitrary-callback_data>`

    .. versionadded:: 13.6

    Args:
        callback_data (:obj:`int`, optional): The button data of which the callback data could not
            be found.

    Attributes:
        callback_data (:obj:`int`): Optional. The button data of which the callback data could not
            be found.
    callback_dataNr   returnc                 2    t         |   d       || _        y )Nz\The object belonging to this callback_data was deleted or the callback_data was manipulated.)super__init__r   )selfr   	__class__s     Z/var/www/cvtools/html/venv/lib/python3.12/site-packages/telegram/ext/_callbackdatacache.pyr   zInvalidCallbackData.__init__B   s    	
 -:    c                 4    | j                   | j                  ffS )zDefines how to serialize the exception for pickle. See
        :py:meth:`object.__reduce__` for more info.

        Returns:
            :obj:`tuple`
        )r    r   r   s    r!   
__reduce__zInvalidCallbackData.__reduce__I   s     ~~ 2 2444r"   N)__name__
__module____qualname____doc__	__slots__r   strr   r	   typer%   __classcell__)r    s   @r!   r   r   ,   sE    & #I:hsm :t :5E$hsm(<"<= 5r"   r   c            
       j    e Zd ZdZ	 	 d
dedee   deeeef      fdZ	ddZ
deeeeeef   f   fd	Zy)_KeyboardData)access_timebutton_datakeyboard_uuidNr3   r1   r2   c                 b    || _         |xs i | _        |xs t        j                         | _        y r&   )r3   r2   timer1   )r   r3   r1   r2   s       r!   r   z_KeyboardData.__init__V   s,     +&,"&5$))+r"   r   c                 6    t        j                          | _        y)z.Updates the access time with the current time.N)r5   r1   r$   s    r!   update_access_timez _KeyboardData.update_access_time`   s    99;r"   c                 H    | j                   | j                  | j                  fS )zsGives a tuple representation consisting of the keyboard uuid, the access time and the
        button data.
        r3   r1   r2   r$   s    r!   to_tuplez_KeyboardData.to_tupled   s#     !!4#3#3T5E5EEEr"   )NNr   N)r'   r(   r)   r+   r,   r   floatr   objectr   r7   r	   r:    r"   r!   r0   r0   S   sj    ?I
 (,37	66 e_6 d3;/0	6'F%UDf,= => Fr"   r0   c                      e Zd ZdZdZ	 	 d!dddedee   fdZded	dfd
Z	e
d	efd       Ze
d	efd       Zded	efdZededed	efd       Zded	eeeef   edef   f   fdZeded	eeef   fd       Zded	dfdZded	ee   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"deee e!f      d	dfdZ"d#dZ#	 d"de$deee e!f      d	dfd Z%y)$CallbackDataCachea  A custom cache for storing the callback data of a :class:`telegram.ext.ExtBot`. Internally,
    it keeps two mappings with fixed maximum size:

    * One for mapping the data received in callback queries to the cached objects
    * One for mapping the IDs of received callback queries to the cached objects

    The second mapping allows to manually drop data that has been cached for keyboards of messages
    sent via inline mode.
    If necessary, will drop the least recently used items.

    Important:
        If you want to use this class, you must install PTB with the optional requirement
        ``callback-data``, i.e.

        .. code-block:: bash

           pip install "python-telegram-bot[callback-data]"

    Examples:
        :any:`Arbitrary Callback Data Bot <examples.arbitrarycallbackdatabot>`

    .. seealso:: :wiki:`Architecture Overview <Architecture>`,
        :wiki:`Arbitrary callback_data <Arbitrary-callback_data>`

    .. versionadded:: 13.6

    .. versionchanged:: 20.0
        To use this class, PTB must be installed via
        ``pip install "python-telegram-bot[callback-data]"``.

    Args:
        bot (:class:`telegram.ext.ExtBot`): The bot this cache is for.
        maxsize (:obj:`int`, optional): Maximum number of items in each of the internal mappings.
            Defaults to ``1024``.

        persistent_data (Tuple[List[Tuple[:obj:`str`, :obj:`float`,         Dict[:obj:`str`, :class:`object`]]], Dict[:obj:`str`, :obj:`str`]], optional):         Data to initialize the cache with, as returned by         :meth:`telegram.ext.BasePersistence.get_callback_data`.

    Attributes:
        bot (:class:`telegram.ext.ExtBot`): The bot this cache is for.

    )_callback_queries_keyboard_data_maxsizebotNrD   zExtBot[Any]maxsizepersistent_datac                     t         st        d      || _        || _        t	        |      | _        t	        |      | _        |r| j                  |       y y )NziTo use `CallbackDataCache`, PTB must be installed via `pip install "python-telegram-bot[callback-data]"`.)rE   )CACHE_TOOLS_AVAILABLERuntimeErrorrD   rC   r   rB   rA   load_persistence_data)r   rD   rE   rF   s       r!   r   zCallbackDataCache.__init__   sZ     %9 
 !$$BJSZB[;CG;T&&7 r"   r   c                     |\  }}|j                         D ]  \  }}|| j                  |<    |D ]!  \  }}}t        |||      | j                  |<   # y)a  Loads data into the cache.

        Warning:
            This method is not intended to be called by users directly.

        .. versionadded:: 20.0

        Args:
            persistent_data (Tuple[List[Tuple[:obj:`str`, :obj:`float`,             Dict[:obj:`str`, :class:`object`]]], Dict[:obj:`str`, :obj:`str`]], optional):             Data to load, as returned by             :meth:`telegram.ext.BasePersistence.get_callback_data`.
        r9   N)itemsrA   r0   rB   )	r   rF   keyboard_datacallback_querieskeyvalueuuidr1   datas	            r!   rJ   z'CallbackDataCache.load_persistence_data   sm     +:''*002 	0JC*/D""3'	0'4 	#D+t(5")D%	r"   c                     | j                   S )z:obj:`int`: The maximum size of the cache.

        .. versionchanged:: 20.0
           This property is now read-only.
        )rC   r$   s    r!   rE   zCallbackDataCache.maxsize   s     }}r"   c                     | j                   j                         D cg c]  }|j                          c}t        | j                  j                               fS c c}w )zTuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]],
        Dict[:obj:`str`, :obj:`str`]]: The data that needs to be persisted to allow
        caching callback data across bot reboots.
        )rB   valuesr:   dictrA   rL   )r   rR   s     r!   persistence_dataz"CallbackDataCache.persistence_data   sN     -1,?,?,F,F,HIDI4""((*L
 
 	
Is   Areply_markupc                 r   t               j                  }t        |      }|j                  D cg c]O  }|D cg c]A  }|j                  r1t        |j                  | j                  |j                  |            n|C c}Q }}}|j                  s|S || j                  |<   t        |      S c c}w c c}}w )a  Registers the reply markup to the cache. If any of the buttons have
        :attr:`~telegram.InlineKeyboardButton.callback_data`, stores that data and builds a new
        keyboard with the correspondingly replaced buttons. Otherwise, does nothing and returns
        the original reply markup.

        Args:
            reply_markup (:class:`telegram.InlineKeyboardMarkup`): The keyboard.

        Returns:
            :class:`telegram.InlineKeyboardMarkup`: The keyboard to be passed to Telegram.

        r   )r   hexr0   inline_keyboardr   r   text_CallbackDataCache__put_buttonr2   rB   r   )r   rX   r3   rM   columnbtnbuttonss          r!   process_keyboardz"CallbackDataCache.process_keyboard   s     %m4" '66
  "  ((	 )&*&7&78I8I=&Y
 	
 
" ((-:M*#G,,+
s   	B3AB.>B3.B3r   rM   c                 h    t               j                  }| |j                  |<   |j                   | S )zStores the data for a single button in :attr:`keyboard_data`.
        Returns the string that should be passed instead of the callback_data, which is
        ``keyboard_uuid + button_uuids``.
        )r   rZ   r2   r3   )r   rM   rQ   s      r!   __put_buttonzCallbackDataCache.__put_button  s5     w{{*7!!$'--.tf55r"   c                     | j                  |      \  }}	 | j                  |   }|j                  |   }|j                          ||fS # t        $ r d t        |      fcY S w xY wr&   )extract_uuidsrB   r2   r7   KeyErrorr   )r   r   keyboardbuttonrM   r2   s         r!   #__get_keyboard_uuid_and_button_dataz5CallbackDataCache.__get_keyboard_uuid_and_button_data  s{      --m<&	< !//9M'33F;K,,. $$  	<,];;;	<s   .A A! A!c                     | dd | dd fS )aZ  Extracts the keyboard uuid and the button uuid from the given :paramref:`callback_data`.

        Args:
            callback_data (:obj:`str`): The
                :paramref:`~telegram.InlineKeyboardButton.callback_data` as present in the button.

        Returns:
            (:obj:`str`, :obj:`str`): Tuple of keyboard and button uuid

        N    r>   r   s    r!   re   zCallbackDataCache.extract_uuids  s     Sb!=#555r"   messagec                 &    | j                  |       y)aH  Replaces the data in the inline keyboard attached to the message with the cached
        objects, if necessary. If the data could not be found,
        :class:`telegram.ext.InvalidCallbackData` will be inserted.

        Note:
            Checks :attr:`telegram.Message.via_bot` and :attr:`telegram.Message.from_user` to check
            if the reply markup (if any) was actually sent by this cache's bot. If it was not, the
            message will be returned unchanged.

            Note that this will fail for channel posts, as :attr:`telegram.Message.from_user` is
            :obj:`None` for those! In the corresponding reply markups the callback data will be
            replaced by :class:`telegram.ext.InvalidCallbackData`.

        Warning:
            * Does *not* consider :attr:`telegram.Message.reply_to_message` and
              :attr:`telegram.Message.pinned_message`. Pass them to this method separately.
            * *In place*, i.e. the passed :class:`telegram.Message` will be changed!

        Args:
            message (:class:`telegram.Message`): The message.

        N)#_CallbackDataCache__process_message)r   rl   s     r!   process_messagez!CallbackDataCache.process_message,  s    . 	w'r"   c                    |j                   sy|j                  r|j                  }n|j                  r|j                  }nd}||| j                  j                  k7  ryd}|j                   j                  D ]k  }|D ]d  }|j
                  st        t        |j
                        }| j                  |      \  }}|j                  |       |rRt        |t              rc|}f m |S )zAs documented in process_message, but returns the uuid of the attached keyboard, if any,
        which is relevant for process_callback_query.

        **IN PLACE**
        N)rX   via_bot	from_userrD   r[   r   r   r,   5_CallbackDataCache__get_keyboard_uuid_and_button_dataupdate_callback_data
isinstancer   )	r   rl   senderr3   rowrh   r2   keyboard_idr   s	            r!   __process_messagez#CallbackDataCache.__process_messageE  s     ##??%,__F&&FF&DHHLL"8''77 	4C 4''"&sF,@,@"AK151Y1Y#2.K //> )MK^1_(34	4 r"   callback_queryc                 $   d}|j                   rm|j                   }| j                  |      \  }}|j                         5  ||_         ddd       |s+t        |t              s|| j
                  |j                  <   d}t        |j                  t              ro| j                  |j                         |j                  j                  |j                  j                  fD ]$  }t        |t              s| j                  |       & yy# 1 sw Y   xY w)aM  Replaces the data in the callback query and the attached messages keyboard with the
        cached objects, if necessary. If the data could not be found,
        :class:`telegram.ext.InvalidCallbackData` will be inserted.
        If :attr:`telegram.CallbackQuery.data` or :attr:`telegram.CallbackQuery.message` is
        present, this also saves the callback queries ID in order to be able to resolve it to the
        stored data.

        Note:
            Also considers inserts data into the buttons of
            :attr:`telegram.Message.reply_to_message` and :attr:`telegram.Message.pinned_message`
            if necessary.

        Warning:
            *In place*, i.e. the passed :class:`telegram.CallbackQuery` will be changed!

        Args:
            callback_query (:class:`telegram.CallbackQuery`): The callback query.

        FNT)rR   rs   	_unfrozenru   r   rA   idrl   r   rn   pinned_messagereply_to_message)r   rz   mappedrR   r3   r2   maybe_messages          r!   process_callback_queryz(CallbackDataCache.process_callback_queryk  s    ( !&&D *.)Q)QRV)W&M;))+ 2&1#2 *[:M"N<I&&~'8'89 n,,g6"">#9#9:&&55&&77" : mW5**=9: 72 2s   DDc                     	 | j                   j                  |j                        }| j                  |       y# t        $ r}t	        d      |d}~ww xY w)a  Deletes the data for the specified callback query.

        Note:
            Will *not* raise exceptions in case the callback data is not found in the cache.
            *Will* raise :exc:`KeyError` in case the callback query can not be found in the
            cache.

        Args:
            callback_query (:class:`telegram.CallbackQuery`): The callback query.

        Raises:
            KeyError: If the callback query can not be found in the cache
        z%CallbackQuery was not found in cache.N)rA   popr}   !_CallbackDataCache__drop_keyboardrf   )r   rz   r3   excs       r!   	drop_datazCallbackDataCache.drop_data  sR    	M 2266~7H7HIM  / 	MBCL	Ms   69 	AAAr3   c                     t        j                  t              5  | j                  j	                  |       d d d        y # 1 sw Y   y xY wr&   )
contextlibsuppressrf   rB   r   )r   r3   s     r!   __drop_keyboardz!CallbackDataCache.__drop_keyboard  s9      * 	3##M2	3 	3 	3s	   ?Atime_cutoffc                 >    | j                  | j                  |       y)a  Clears the stored callback data.

        Args:
            time_cutoff (:obj:`float` | :obj:`datetime.datetime`, optional): Pass a UNIX timestamp
                or a :obj:`datetime.datetime` to clear only entries which are older.
                For timezone naive :obj:`datetime.datetime` objects, the default timezone of the
                bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is
                used.

        )r   N)_CallbackDataCache__clearrB   )r   r   s     r!   clear_callback_dataz%CallbackDataCache.clear_callback_data  s     	T((kBr"   c                 :    | j                  | j                         y)z%Clears the stored callback query IDs.N)r   rA   r$   s    r!   clear_callback_queriesz(CallbackDataCache.clear_callback_queries  s    T++,r"   mappingc                 v   |s|j                          y t        |t              rDt        || j                  j
                  r | j                  j
                  j                  nd       }n|}|j                         D cg c]  \  }}|j                  |k  s| }}}|D ]  }|j                  |        y c c}}w )N)tzinfo)
clearru   r   r   rD   defaultsr   rL   r1   r   )r   r   r   effective_cutoffrO   rR   to_drops          r!   __clearzCallbackDataCache.__clear  s     MMOk8,1@Q@QDHH$5$5$<$<W[   + )0_934;K;KN^;^3__ 	CKK	 `s   =B5B5)i   Nr&   r;   )&r'   r(   r)   r*   r+   intr   r   r   rJ   propertyrE   rW   r   ra   staticmethodr=   r0   r,   r]   r
   r	   r   rs   re   r   ro   rn   r   r   r   r   r<   r   r   r   r   r   r>   r"   r!   r@   r@   k   s   +Z KI
 -1	88 8 "'*	8(W  ,    

' 

 

'--A '-FZ '-R 6F 6= 6S 6 6% %	uS&[!5/B)B#CC	D% 6S 6U38_ 6 6(w (4 (2$ $Xc] $L,:] ,:t ,:\M M$ M(3S 3T 3CxeXo8N/O C[_ C-
 X\%4<U5(?=S4T	r"   r@   )$r*   r5   r   typingr   r   r   r   r   r	   r
   r   rQ   r   
cachetoolsr   rH   ImportErrorr   telegramr   r   r   r   r   telegram._utils.datetimer   telegram.errorr   telegram.ext._utils.typesr   telegram.extr   r   r0   r@   r>   r"   r!   <module>r      s   & 8   Y Y Y "# 
  ] ] 7 ( -#$5- $5NF F0i i]  "!"s   A< <BB