o
    "h(2                     @   s   d Z ddlZddlZddlZddlmZmZ ddlmZm	Z	m
Z
mZ z
ddlmZ dZW n ey7   dZY nw ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ejdkr_ejZnejded fddZeeddZG dd dee  Z!dS )zeThis module contains an implementation of the BaseRateLimiter class based on the aiolimiter
library.
    N)AsyncIterator	Coroutine)AnyCallableOptionalUnion)AsyncLimiterTF)	constants)
get_logger)JSONDict)
RetryAfter)BaseRateLimiter)   
   returnc                   C  s   d V  d S N r   r   r   O/var/www/html/venv/lib/python3.10/site-packages/telegram/ext/_aioratelimiter.pynull_context0   s   
r   AIORateLimiter)
class_namec                   @   sH  e Zd ZdZdZejjdejjddfde	de	de	d	e	d
e
ddfddZd%ddZd%ddZdeee
ef ddfddZdedeee
ef dededeeeeeeee f f f dedeeef deeeee f fddZdedeeeeeeee f f f dedeeef d ed!eeef d"ee
 deeeee f fd#d$ZdS )&r   ak  
    Implementation of :class:`~telegram.ext.BaseRateLimiter` using the library
    `aiolimiter <https://aiolimiter.readthedocs.io/en/stable>`_.

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

        .. code-block:: bash

           pip install "python-telegram-bot[rate-limiter]"

    The rate limiting is applied by combining two levels of throttling and :meth:`process_request`
    roughly boils down to::

        async with group_limiter(group_id):
            async with overall_limiter:
                await callback(*args, **kwargs)

    Here, ``group_id`` is determined by checking if there is a ``chat_id`` parameter in the
    :paramref:`~telegram.ext.BaseRateLimiter.process_request.data`.
    The ``overall_limiter`` is applied only if a ``chat_id`` argument is present at all.

    Attention:
        * Some bot methods accept a ``chat_id`` parameter in form of a ``@username`` for
          supergroups and channels. As we can't know which ``@username`` corresponds to which
          integer ``chat_id``, these will be treated as different groups, which may lead to
          exceeding the rate limit.
        * As channels can't be differentiated from supergroups by the ``@username`` or integer
          ``chat_id``, this also applies the group related rate limits to channels.
        * A :exc:`~telegram.error.RetryAfter` exception will halt *all* requests for
          :attr:`~telegram.error.RetryAfter.retry_after` + 0.1 seconds. This may be stricter than
          necessary in some cases, e.g. the bot may hit a rate limit in one group but might still
          be allowed to send messages in another group or with
          :paramref:`~telegram.Bot.send_message.allow_paid_broadcast` set to :obj:`True`.

    Tip:
        With `Bot API 7.1 <https://core.telegram.org/bots/api-changelog#october-31-2024>`_
        (PTB v27.1), Telegram introduced the parameter
        :paramref:`~telegram.Bot.send_message.allow_paid_broadcast`.
        This allows bots to send up to
        :tg-const:`telegram.constants.FloodLimit.PAID_MESSAGES_PER_SECOND` messages per second by
        paying a fee in Telegram Stars.

        .. versionchanged:: 21.11
            This class automatically takes the
            :paramref:`~telegram.Bot.send_message.allow_paid_broadcast` parameter into account and
            throttles the requests accordingly.

    Note:
        This class is to be understood as minimal effort reference implementation.
        If you would like to handle rate limiting in a more sophisticated, fine-tuned way, we
        welcome you to implement your own subclass of :class:`~telegram.ext.BaseRateLimiter`.
        Feel free to check out the source code of this class for inspiration.

    .. seealso:: :wiki:`Avoiding Flood Limits <Avoiding-flood-limits>`

    .. versionadded:: 20.0

    Args:
        overall_max_rate (:obj:`float`): The maximum number of requests allowed for the entire bot
            per :paramref:`overall_time_period`. When set to 0, no rate limiting will be applied.
            Defaults to :tg-const:`telegram.constants.FloodLimit.MESSAGES_PER_SECOND`.
        overall_time_period (:obj:`float`): The time period (in seconds) during which the
            :paramref:`overall_max_rate` is enforced.  When set to 0, no rate limiting will be
            applied. Defaults to ``1``.
        group_max_rate (:obj:`float`): The maximum number of requests allowed for requests related
            to groups and channels per :paramref:`group_time_period`.  When set to 0, no rate
            limiting will be applied. Defaults to
            :tg-const:`telegram.constants.FloodLimit.MESSAGES_PER_MINUTE_PER_GROUP`.
        group_time_period (:obj:`float`): The time period (in seconds) during which the
            :paramref:`group_max_rate` is enforced.  When set to 0, no rate limiting will be
            applied. Defaults to ``60``.
        max_retries (:obj:`int`): The maximum number of retries to be made in case of a
            :exc:`~telegram.error.RetryAfter` exception.
            If set to 0, no retries will be made. Defaults to ``0``.

    )_apb_limiter_base_limiter_group_limiters_group_max_rate_group_time_period_max_retries_retry_after_event   <   r   overall_max_rateoverall_time_periodgroup_max_rategroup_time_periodmax_retriesr   Nc                 C   s   t std|r|rt||d| _nd | _|r |r || _|| _nd| _d| _i | _ttjj	dd| _
|| _t | _| j  d S )NzeTo use `AIORateLimiter`, PTB must be installed via `pip install "python-telegram-bot[rate-limiter]"`.max_ratetime_periodr   r   )AIO_LIMITER_AVAILABLERuntimeErrorr   r   r   r   r   r	   
FloodLimitPAID_MESSAGES_PER_SECONDr   r   asyncioEventr   set)selfr    r!   r"   r#   r$   r   r   r   __init__   s*   

zAIORateLimiter.__init__c                       dS zDoes nothing.Nr   r/   r   r   r   
initialize       zAIORateLimiter.initializec                    r1   r2   r   r3   r   r   r   shutdown   r5   zAIORateLimiter.shutdowngroup_idr   c                 C   sn   t | jdkr"| j  D ]\}}||krq||jr!| j|= q|| jvr2t| j| jd| j|< | j| S )Ni   r%   )	lenr   copyitemshas_capacityr&   r   r   r   )r/   r7   keylimiterr   r   r   _get_group_limiter   s   

z!AIORateLimiter._get_group_limiterchatgroupallow_paid_broadcastcallback.argskwargsc           
   
      s<  dt tttt f f fdd}|r;j4 I d H  | I d H W  d   I d H  S 1 I d H s4w   Y  d S |rCjrCjnt }|rPjrP|nt }	|	4 I d H 8 |4 I d H  | I d H W  d   I d H  W  d   I d H  S 1 I d H sw   Y  W d   I d H  d S 1 I d H sw   Y  d S )Nr   c                      s&   j  I d H   i I d H S r   )r   waitr   rC   rB   rD   r/   r   r   inner   s   z*AIORateLimiter._run_request.<locals>.inner)	r   boolr   listr   r   r   r   r>   )
r/   r?   r@   rA   rB   rC   rD   rG   base_contextgroup_contextr   rF   r   _run_request   s    &	
0
pzAIORateLimiter._run_requestendpointdatarate_limit_argsc                    s\  |p| j }d}d}	|d}
|dd}|
durd}	ttt t|
}
W d   n1 s0w   Y  t|
tr>|
dk sCt|
trE|
}t	|d D ]`}zXz| j
|	|||||dI dH W W | j    S  ty } z-||krztjd	||d
  |j d }td| | j  t|I dH  W Y d}~nd}~ww W | j  qK| j  w dS )a  
        Processes a request by applying rate limiting.

        See :meth:`telegram.ext.BaseRateLimiter.process_request` for detailed information on the
        arguments.

        Args:
            rate_limit_args (:obj:`None` | :obj:`int`): If set, specifies the maximum number of
                retries to be made in case of a :exc:`~telegram.error.RetryAfter` exception.
                Defaults to :paramref:`AIORateLimiter.max_retries`.
        Fchat_idrA   NTr   r   )r?   r@   rA   rB   rC   rD   z*Rate limit hit after maximum of %d retries)exc_infog?z)Rate limit hit. Retrying after %f seconds)r   get
contextlibsuppress
ValueError	TypeErrorint
isinstancestrrangerL   r   r.   r   _LOGGER	exception_retry_aftertotal_secondsinfoclearr,   sleep)r/   rB   rC   rD   rM   rN   rO   r$   r@   r?   rP   rA   iexcra   r   r   r   process_request   sN   



zAIORateLimiter.process_request)r   N)__name__
__module____qualname____doc__	__slots__r	   r*   MESSAGES_PER_SECONDMESSAGES_PER_MINUTE_PER_GROUPfloatrW   r0   r4   r6   r   rY   rH   r>   r   r   r   r   rI   dictrL   r   rd   r   r   r   r   r   8   sl    O

#
"

"

)"rh   r,   rS   syscollections.abcr   r   typingr   r   r   r   
aiolimiterr   r(   ImportErrortelegramr	   telegram._utils.loggingr
   telegram._utils.typesr   telegram.errorr   telegram.ext._baseratelimiterr   version_infonullcontextr   asynccontextmanagerre   r[   rW   r   r   r   r   r   <module>   s.   
