o
    @MÆhêT  ã                   @   sÐ  d dl Z d dlZd dlZd dlmZmZmZmZmZm	Z	 d dl
Z
d dlmZ d dlmZ d dl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 zd dlZW n ey_   d dlZY nw dZe  d¡Z!e "¡ Z#g d	¢Z$g d
¢Z%g d¢Z&G dd„ dej'ƒZ(G dd„ dƒZ)G dd„ dƒZ*G dd„ dƒZ+dd„ Z,de-de.fdd„Z/de-de	e-df fdd„Z0de-de	e-df fdd„Z1de-dej2de-fdd „Z3de-d!e4dee- fd"d#„Z5efde-d!e4dee- fd$d%„Z6de-dee- fd&d'„Z7dSd)ej8d*e.de-fd+d,„Z9dTd.ee-ee-ef f d/e4dej:fd0d1„Z;d2d3„ Z<d4d5„ Z=d6d7„ Z>d8d9„ Z?dSd:d;„Z@dUd=e.d>ee fd?d@„ZAdAdB„ ZBdCdDœdEefdFdG„ZCdHe-dIe-fdJdK„ZDdHe-dIe-fdLdM„ZEde.fdNdO„ZFde	e4df fdPdQ„ZGdRZHdS )Vé    N)ÚAnyÚCallableÚListÚDictÚOptionalÚUnion)Úsha256)Ú	parse_qsl)Útypes)Úis_pil_imageÚis_dictÚ	is_stringÚis_bytesÚchunksÚgenerate_random_tokenÚpil_image_to_filei   ÚTeleBot)ÚtextÚaudioÚdocumentÚ	animationÚgameÚphotoÚstickerÚvideoÚ
video_noteÚvoiceÚcontactÚlocationÚvenueÚdiceÚinvoiceÚsuccessful_paymentÚconnected_websiteÚpollÚpassport_dataÚweb_app_dataÚstoryÚgiveawayÚgiftÚunique_gift))Únew_chat_membersÚleft_chat_memberÚnew_chat_titleÚnew_chat_photoÚdelete_chat_photoÚgroup_chat_createdÚsupergroup_chat_createdÚchannel_chat_createdÚmigrate_to_chat_idÚmigrate_from_chat_idÚpinned_messageÚproximity_alert_triggeredÚvideo_chat_scheduledÚvideo_chat_startedÚvideo_chat_endedÚvideo_chat_participants_invitedÚ!message_auto_delete_timer_changedÚchat_background_setÚforum_topic_createdÚforum_topic_closedÚforum_topic_reopenedÚforum_topic_editedÚgeneral_forum_topic_hiddenÚgeneral_forum_topic_unhiddenÚwrite_access_allowedÚusers_sharedÚchat_sharedÚgiveaway_createdÚgiveaway_winnersÚgiveaway_completedÚboost_addedÚpaid_message_price_changedÚchecklist_tasks_doneÚchecklist_tasks_addedÚdirect_message_price_changedÚsuggested_post_refundedÚsuggested_post_infoÚsuggested_post_approvedÚsuggested_post_approval_failedÚsuggested_post_declinedÚsuggested_post_paid)ÚmessageÚedited_messageÚchannel_postÚedited_channel_postÚinline_queryÚchosen_inline_resultÚcallback_queryÚshipping_queryÚpre_checkout_queryr$   Úpoll_answerÚmy_chat_memberÚchat_memberÚchat_join_requestÚmessage_reactionÚmessage_reaction_countÚremoved_chat_boostÚ
chat_boostÚbusiness_connectionÚbusiness_messageÚedited_business_messageÚdeleted_business_messagesÚpurchased_paid_mediac                   @   sF   e Zd 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S )ÚWorkerThreadú
    :meta private:
    r   Nc                 C   s”   |sd  | jjd ¡}| j jd7  _|st ¡ }tjj| |d || _d| _t 	¡ | _
t 	¡ | _t 	¡ | _t 	¡ | _|| _d | _d| _|  ¡  d S )NzWorkerThread{0}é   )ÚnameT)ÚformatÚ	__class__ÚcountÚQueueÚ	threadingÚThreadÚ__init__ÚqueueÚdaemonÚEventÚreceived_task_eventÚ
done_eventÚexception_eventÚcontinue_eventÚexception_callbackÚexception_infoÚ_runningÚstart)Úselfr|   ru   rm   © r   ú?/var/www/html/venv/lib/python3.10/site-packages/telebot/util.pyrt   A   s    



zWorkerThread.__init__c              
   C   s  | j rŒz<| jjddd\}}}| j ¡  | j ¡  | j ¡  | j ¡  t 	d¡ | j 
¡  ||i |¤Ž t 	d¡ | j 
¡  W nG tjyI   Y n> ty† } z2t 	t|ƒjd t|jƒ d t ¡  ¡ || _| j 
¡  | jrw|  | | j¡ | j ¡  W Y d }~nd }~ww | j sd S d S )NTg      à?)ÚblockÚtimeoutzReceived taskzTask completez occurred, args=Ú
)r~   ru   Úgetr{   Úclearrx   ry   rz   ÚloggerÚdebugÚsetrq   ÚEmptyÚ	ExceptionÚtypeÚ__name__ÚstrÚargsÚ	tracebackÚ
format_excr}   r|   Úwait)r€   Útaskr   ÚkwargsÚer   r   r‚   ÚrunV   s0   






*
€úñzWorkerThread.runc                 O   ó   | j  |||f¡ d S ©N)ru   Úput)r€   r”   r   r•   r   r   r‚   rš   n   ó   zWorkerThread.putc                 C   ó   | j  ¡ r| j‚d S r™   ©rz   Úis_setr}   ©r€   r   r   r‚   Úraise_exceptionsq   ó   
ÿzWorkerThread.raise_exceptionsc                 C   s   | j  ¡  | j ¡  d S r™   )rz   r‡   r{   rŠ   rŸ   r   r   r‚   Úclear_exceptionsu   s   
zWorkerThread.clear_exceptionsc                 C   s
   d| _ d S ©NF)r~   rŸ   r   r   r‚   Ústopy   s   
zWorkerThread.stop)NNN)rŽ   Ú
__module__Ú__qualname__Ú__doc__rp   rt   r—   rš   r    r¢   r¤   r   r   r   r‚   rj   ;   s    
rj   c                   @   sB   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S )Ú
ThreadPoolrk   é   c                    sB   |ˆ _ t ¡ ˆ _‡ fdd„t|ƒD ƒˆ _|ˆ _t ¡ ˆ _d ˆ _	d S )Nc                    s   g | ]	}t ˆ jˆ jƒ‘qS r   )rj   Úon_exceptionÚtasks)Ú.0Ú_rŸ   r   r‚   Ú
<listcomp>…   s    z'ThreadPool.__init__.<locals>.<listcomp>)
Útelebotrq   r«   ÚrangeÚworkersÚnum_threadsrr   rw   rz   r}   )r€   r¯   r²   r   rŸ   r‚   rt   ‚   s   


zThreadPool.__init__c                 O   r˜   r™   )r«   rš   )r€   Úfuncr   r•   r   r   r‚   rš   ‹   r›   zThreadPool.putc                 C   sB   | j jd ur| j j |¡}nd}|s|| _| j ¡  |j ¡  d S r£   )r¯   Úexception_handlerÚhandler}   rz   rŠ   r{   )r€   Úworker_threadÚexc_infoÚhandledr   r   r‚   rª   Ž   s   
zThreadPool.on_exceptionc                 C   rœ   r™   r   rŸ   r   r   r‚   r    ˜   r¡   zThreadPool.raise_exceptionsc                 C   s   | j  ¡  d S r™   )rz   r‡   rŸ   r   r   r‚   r¢   œ   s   zThreadPool.clear_exceptionsc                 C   s8   | j D ]}| ¡  q| j D ]}|t ¡ kr| ¡  qd S r™   )r±   r¤   rr   Úcurrent_threadÚjoin)r€   Úworkerr   r   r‚   ÚcloseŸ   s   


€þzThreadPool.closeN©r©   )
rŽ   r¥   r¦   r§   rt   rš   rª   r    r¢   r¼   r   r   r   r‚   r¨   }   s    
	
r¨   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú	AsyncTaskrk   c                 O   s6   || _ || _|| _d| _tj| jd| _| j ¡  d S )NF)Útarget)	r¿   r   r•   Údonerr   rs   Ú_runÚthreadr   )r€   r¿   r   r•   r   r   r‚   rt   ¬   s   zAsyncTask.__init__c              
   C   sP   z| j | ji | j¤Ž| _W n ty" } z	|| _W Y d }~nd }~ww d| _d S )NT)r¿   r   r•   ÚresultrŒ   rÀ   )r€   r–   r   r   r‚   rÁ   µ   s   €ÿ
zAsyncTask._runc                 C   s(   | j s| j ¡  t| jtƒr| j‚| jS r™   )rÀ   rÂ   rº   Ú
isinstancerÃ   ÚBaseExceptionrŸ   r   r   r‚   r“   ¼   s
   
zAsyncTask.waitN)rŽ   r¥   r¦   r§   rt   rÁ   r“   r   r   r   r‚   r¾   §   s
    	r¾   c                   @   s"   e Zd ZdZd	dd„Zdd„ ZdS )
ÚCustomRequestResponserk   éÈ   Ú c                 C   s   || _ || _|| _d S r™   )Ústatus_coder   Úreason)r€   Ú	json_textrÉ   rÊ   r   r   r‚   rt   Ê   s   
zCustomRequestResponse.__init__c                 C   s   t  | j¡S r™   )ÚjsonÚloadsr   rŸ   r   r   r‚   rÌ   Ï   s   zCustomRequestResponse.jsonN)rÇ   rÈ   )rŽ   r¥   r¦   r§   rt   rÌ   r   r   r   r‚   rÆ   Å   s    
rÆ   c                  C   s   dd„ } | S )rk   c                    s   ‡ fdd„}|S )Nc                     s   t ˆ g| ¢R i |¤ŽS r™   )r¾   )r   r•   ©Úfnr   r‚   ÚwrapperÙ   r›   z-async_dec.<locals>.decorator.<locals>.wrapperr   )rÏ   rÐ   r   rÎ   r‚   Ú	decoratorØ   s   zasync_dec.<locals>.decoratorr   )rÑ   r   r   r‚   Ú	async_decÓ   s   rÒ   r   Úreturnc                 C   s   | du rdS |   d¡S )zì
    Checks if `text` is a command. Telegram chat commands start with the '/' character.
    
    :param text: Text to check.
    :type text: :obj:`str`

    :return: True if `text` is a command, else False.
    :rtype: :obj:`bool`
    NFú/)Ú
startswith©r   r   r   r‚   Ú
is_commandá   s   

r×   c                 C   s6   | du rdS t | ƒr|  ¡ d  d¡d dd… S dS )av  
    Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
    If `text` is not a command, this function returns None.

    .. code-block:: python3
        :caption: Examples:
        
        extract_command('/help'): 'help'
        extract_command('/help@BotName'): 'help'
        extract_command('/search black eyed peas'): 'search'
        extract_command('Good day to you'): None

    :param text: String to extract the command from
    :type text: :obj:`str`

    :return: the command if `text` is a command (according to is_command), else None.
    :rtype: :obj:`str` or :obj:`None`
    Nr   ú@rl   )r×   ÚsplitrÖ   r   r   r‚   Úextract_commandï   s   *rÚ   c                 C   s.   t  dt j¡}| | ¡}t| ƒr| d¡S dS )aÚ  
    Returns the argument after the command.
    
    .. code-block:: python3
        :caption: Examples:

        extract_arguments("/get name"): 'name'
        extract_arguments("/get"): ''
        extract_arguments("/get@botName name"): 'name'
    
    :param text: String to extract the arguments from a command
    :type text: :obj:`str`

    :return: the arguments if `text` is a command (according to is_command), else None.
    :rtype: :obj:`str` or :obj:`None`
    z/\w*(@\w*)*\s*([\s\S]*)r©   N)ÚreÚcompileÚ
IGNORECASEÚmatchr×   Úgroup)r   ÚregexprÃ   r   r   r‚   Úextract_arguments  s   
rá   r–   c                 C   sŒ   d}d}|   ¡ }t|ƒ}d}|D ]-}|d@ dkr9||jkr |}n||j |jkr,|} n|dkr5|d7 }n|d7 }|d7 }q|||…  ¡ S )a  
    Returns the content of the entity.
    
    :param text: The text of the message the entity belongs to
    :type text: :obj:`str`
    
    :param e: The entity to extract
    :type e: :obj:`MessageEntity`
    
    :return: The content of the entity
    :rtype: :obj:`str`
    r   éÀ   é€   éð   r©   rl   )ÚencodeÚlenÚoffsetÚlengthÚdecode)r   r–   rç   r   Úencoded_textÚendÚiÚbyter   r   r‚   Úextract_entity  s"   


rî   Úchars_per_stringc                    s    ‡ ‡fdd„t dtˆƒˆ ƒD ƒS )a×  
    Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
    This is very useful for splitting one giant message into multiples.

    :param text: The text to split
    :type text: :obj:`str`

    :param chars_per_string: The number of characters per line the text is split into.
    :type chars_per_string: :obj:`int`

    :return: The splitted text as a list of strings.
    :rtype: :obj:`list` of :obj:`str`
    c                    s   g | ]
}ˆ||ˆ  … ‘qS r   r   )r¬   rì   ©rï   r   r   r‚   r®   K  s    z split_string.<locals>.<listcomp>r   )r°   ræ   )r   rï   r   rð   r‚   Úsplit_string=  s    rñ   c                    sž   dt dt f‡ fdd„}|tkrt}g }	 t| ƒ|k r!| | ¡ |S | d|… ‰ dˆ v r0|dƒ‰ ndˆ v r9|dƒ‰ nd	ˆ v rA|d	ƒ‰ | ˆ ¡ | tˆ ƒd… } q)
aT  
    Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
    This is very useful for splitting one giant message into multiples.
    If `chars_per_string` > 4096: `chars_per_string` = 4096.
    Splits by '\n', '. ' or ' ' in exactly this priority.

    :param text: The text to split
    :type text: :obj:`str`

    :param chars_per_string: The number of maximum characters per part the text is split to.
    :type chars_per_string: :obj:`int`

    :return: The splitted text as a list of strings.
    :rtype: :obj:`list` of :obj:`str`
    ÚsubstrrÓ   c                    s   |   ˆ  | ¡d d… ¡|  S )Néÿÿÿÿ)rº   rÙ   )rò   ©Úpartr   r‚   Ú_text_before_last_  s   z&smart_split.<locals>._text_before_lastTNr…   z. ú )r   ÚMAX_MESSAGE_LENGTHræ   Úappend)r   rï   rö   Úpartsr   rô   r‚   Úsmart_splitN  s"   



ñrû   c                 C   s:   ddddœ}| du rdS |  ¡ D ]
\}}|  ||¡} q| S )z¬
    Replaces the following chars in `text` ('&' with '&amp;', '<' with '&lt;' and '>' with '&gt;').

    :param text: the text to escape
    :return: the escaped text
    z&amp;z&lt;z&gt;)ú&ú<ú>N)ÚitemsÚreplace)r   ÚcharsÚoldÚnewr   r   r‚   Úescapew  s   r  FÚuserÚ
include_idc                 C   s6   t | jƒ}d| j› d|› d|rd| j› d S d S )aæ  
    Returns an HTML user link. This is useful for reports.
    Attention: Don't forget to set parse_mode to 'HTML'!


    .. code-block:: python3
        :caption: Example:

        bot.send_message(your_user_id, user_link(message.from_user) + ' started the bot!', parse_mode='HTML')

    .. note::
        You can use formatting.* for all other formatting options(bold, italic, links, and etc.)
        This method is kept for backward compatibility, and it is recommended to use formatting.* for
        more options.

    :param user: the user (not the user_id)
    :type user: :obj:`telebot.types.User`

    :param include_id: include the user_id
    :type include_id: :obj:`bool`

    :return: HTML user link
    :rtype: :obj:`str`
    z<a href='tg://user?id=z'>z</a>z (<pre>z</pre>)rÈ   )r  Ú
first_nameÚid)r  r  rm   r   r   r‚   Ú	user_link†  s   
ÿÿr	  r©   ÚvaluesÚ	row_widthc                 C   s,   t j|d}dd„ |  ¡ D ƒ}|j|Ž  |S )aK  
    Returns a reply markup from a dict in this format: {'text': kwargs}
    This is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2 = InlineKeyboardButton(...)' 
    
    Example:

    .. code-block:: python3
        :caption: Using quick_markup:

        from telebot.util import quick_markup

        markup = quick_markup({
            'Twitter': {'url': 'https://twitter.com'},
            'Facebook': {'url': 'https://facebook.com'},
            'Back': {'callback_data': 'whatever'}
        }, row_width=2)
        # returns an InlineKeyboardMarkup with two buttons in a row, one leading to Twitter, the other to facebook
        # and a back button below

        # kwargs can be: 
        {
            'url': None, 
            'callback_data': None, 
            'switch_inline_query': None,
            'switch_inline_query_current_chat': None,
            'callback_game': None,
            'pay': None,
            'login_url': None,
            'web_app': None
        }
    
    :param values: a dict containing all buttons to create in this format: {text: kwargs} {str:}
    :type values: :obj:`dict`

    :param row_width: number of :class:`telebot.types.InlineKeyboardButton` objects on each row
    :type row_width: :obj:`int`

    :return: InlineKeyboardMarkup
    :rtype: :obj:`types.InlineKeyboardMarkup`
    )r  c                 S   s$   g | ]\}}t jdd |i|¤Ž‘qS )r   r   )r
   ÚInlineKeyboardButton)r¬   r   r•   r   r   r‚   r®   Î  s    ÿÿz quick_markup.<locals>.<listcomp>)r
   ÚInlineKeyboardMarkuprÿ   Úadd)r
  r  ÚmarkupÚbuttonsr   r   r‚   Úquick_markup¤  s   )þ
r  c                 C   ó   |   ¡  |  ¡  dS ©rk   N)Ú_setÚchangedrŸ   r   r   r‚   Úor_set×  ó   r  c                 C   r  r  )Ú_clearr  rŸ   r   r   r‚   Úor_clearß  r  r  c                    sJ   t ˆ dƒs	ˆ jˆ _t ˆ dƒsˆ jˆ _|ˆ _‡ fdd„ˆ _‡ fdd„ˆ _dS )rk   r  r  c                      ó   t ˆ ƒS r™   )r  r   ©r–   r   r‚   Ú<lambda>ð  ó    zorify.<locals>.<lambda>c                      r  r™   )r  r   r  r   r‚   r  ñ  r  N)ÚhasattrrŠ   r  r‡   r  r  )r–   Úchanged_callbackr   r  r‚   Úorifyç  s   

r   c                     sN   t  ¡ ‰‡ ‡fdd„}‡fdd„}ˆ D ]}t||ƒ qˆjˆ_|ˆ_|ƒ  ˆS )rk   c                     s.   dd„ ˆ D ƒ} t | ƒrˆ ¡  d S ˆ ¡  d S )Nc                 S   s   g | ]}|  ¡ ‘qS r   )rž   )r¬   Úevr   r   r‚   r®   û  s    z,OrEvent.<locals>.changed.<locals>.<listcomp>)ÚanyrŠ   r‡   )Úbools©ÚeventsÚor_eventr   r‚   r  ú  s   zOrEvent.<locals>.changedc                      s"   ˆ   ¡ sˆ  d¡ ˆ   ¡ rd S d S )Né   )rž   Ú_waitr   )r&  r   r‚   Ú	busy_wait  s   
þzOrEvent.<locals>.busy_wait)rr   rw   r   r“   r(  )r%  r  r)  r–   r   r$  r‚   ÚOrEventô  s   r*  c                 C   s*   |st t| ƒs|ƒ }tt| |ƒ tt| ƒS )rk   )r  Úthread_localÚsetattrÚgetattr)ÚkeyÚconstruct_valueÚresetÚvaluer   r   r‚   Ú
per_thread  s   
r2  TÚwarnÚalternativec                    s   ‡ ‡‡fdd„}|S )aß  
    Use this decorator to mark functions as deprecated.
    When the function is used, an info (or warning if `warn` is True) is logged.

    :meta private:
    
    :param warn: If True a warning is logged else an info
    :type warn: :obj:`bool`

    :param alternative: The new function to use instead
    :type alternative: :obj:`Callable`

    :param deprecation_text: Custom deprecation text
    :type deprecation_text: :obj:`str`

    :return: The decorated function
    c                    s   ‡‡‡ ‡fdd„}|S )Nc                     s\   dˆj › d}ˆ r|dˆ j › d7 }ˆr|dˆ 7 }ˆs"t |¡ nt |¡ ˆ| i |¤ŽS )Nú`z` is deprecated.z Use `z	` insteadr÷   )rŽ   rˆ   ÚinfoÚwarning)r   r•   r6  )r4  Údeprecation_textÚfunctionr3  r   r‚   rÐ   -  s   
z.deprecated.<locals>.decorator.<locals>.wrapperr   )r9  rÐ   ©r4  r8  r3  )r9  r‚   rÑ   ,  s   zdeprecated.<locals>.decoratorr   )r3  r4  r8  rÑ   r   r:  r‚   Ú
deprecated  s   r;  c              
   C   s`   |j r.z| ¡ }tj |¡}|  |g¡ W dS  ty- } zt|ƒ W Y d}~dS d}~ww dS )a(  
    A webhook endpoint for Google Cloud Functions FaaS.
    
    :param bot: The bot instance
    :type bot: :obj:`telebot.TeleBot` or :obj:`telebot.async_telebot.AsyncTeleBot`

    :param request: The request object
    :type request: :obj:`flask.Request`

    :return: The response object
    rÈ   N)zBot FAILi  zBot ON)Úis_jsonÚget_jsonr
   ÚUpdateÚde_jsonÚprocess_new_updatesrŒ   Úprint)ÚbotÚrequestÚrequest_jsonÚupdater–   r   r   r‚   Úwebhook_google_functions?  s   €þrF  é   )Únumber_retriesr9  c                O   s   ddl m} ddlm} t|d ƒD ].}z
| |i |¤ŽW   S  |y@ } z|jdkr5||jd d ƒ n‚ W Y d}~qd}~ww | |i |¤ŽS )	a‡  
    Use this function inside loops in order to avoid getting TooManyRequests error.
    Example:
    
    .. code-block:: python3
    
        from telebot.util import antiflood
        for chat_id in chat_id_list:
        msg = antiflood(bot.send_message, chat_id, text)
        
    :param function: The function to call
    :type function: :obj:`Callable`

    :param number_retries: Number of retries to send
    :type function: :obj:int

    :param args: The arguments to pass to the function
    :type args: :obj:`tuple`

    :param kwargs: The keyword arguments to pass to the function
    :type kwargs: :obj:`dict`

    :return: None
    r   )ÚApiTelegramException)Úsleeprl   i­  Ú
parametersÚretry_afterN)Útelebot.apihelperrI  ÚtimerJ  r°   Ú
error_codeÚresult_json)r9  rH  r   r•   rI  rJ  r­   Úexr   r   r‚   Ú	antifloodX  s   
þ€þrR  ÚtokenÚraw_init_datac              	   C   s`   t | |ƒ}|s	dS i }t|ƒD ]\}}zt |¡}W n tjy(   |||< Y qw |||< q|S )zÏ
    Parses web app data.

    :param token: The bot token
    :type token: :obj:`str`

    :param raw_init_data: The raw init data
    :type raw_init_data: :obj:`str`

    :return: The parsed init data
    F)Úvalidate_web_app_datar	   rÌ   rÍ   ÚJSONDecodeError)rS  rT  Úis_validrÃ   r.  r1  r   r   r‚   Úparse_web_app_data€  s   
ÿ
rX  c                 C   sŠ   zt t|ƒƒ}W n
 ty   Y dS w d|vrdS | d¡}d dd„ t| ¡ ƒD ƒ¡}tjd|  	¡ t
d}t | ¡ | 	¡ t
¡ ¡ |kS )zÒ
    Validates web app data.

    :param token: The bot token
    :type token: :obj:`str`

    :param raw_init_data: The raw init data
    :type raw_init_data: :obj:`str`

    :return: The parsed init data
    FÚhashr…   c                 s   s"    | ]\}}|› d |› V  qdS )ú=Nr   )r¬   r.  r1  r   r   r‚   Ú	<genexpr>¯  s   €  z(validate_web_app_data.<locals>.<genexpr>s
   WebAppData)r.  ÚmsgÚ	digestmod)Údictr	   Ú
ValueErrorÚpoprº   Úsortedrÿ   Úhmacr  rå   r   ÚdigestÚ	hexdigest)rS  rT  Úparsed_dataÚinit_data_hashÚdata_check_stringÚ
secret_keyr   r   r‚   rU  ›  s   ÿ
rU  c                 C   sH   t dd„ | D ƒƒrtdƒ‚d| vrtdƒ‚t|  d¡ƒdkr"tdƒ‚dS )	Nc                 s   s    | ]}|  ¡ V  qd S r™   )Úisspace)r¬   Úcharr   r   r‚   r[  ¶  s   € z!validate_token.<locals>.<genexpr>zToken must not contain spacesú:zToken must contain a colonr©   z7Token must contain exactly 2 parts separated by a colonT)r"  r_  ræ   rÙ   ©rS  r   r   r‚   Úvalidate_tokenµ  s   rm  c                 C   s4   zt | ƒ W n
 ty   Y d S w t|  d¡d ƒS )Nrk  r   )rm  r_  ÚintrÙ   rl  r   r   r‚   Úextract_bot_idÁ  s   ÿro  )"Úcontent_type_mediaÚcontent_type_serviceÚupdate_typesrj   r¾   rÆ   rÒ   r;  r   r   r   r   r   r   r   r×   rÚ   rá   rñ   rû   r  r	  r  rR  rX  rU  r  r  r   r*  r2  rF  rm  ro  )Fr½   )TNN)IrÛ   rr   r‘   Útypingr   r   r   r   r   r   rb  Úhashlibr   Úurllib.parser	   ru   rq   Úloggingr¯   r
   Útelebot.service_utilsr   r   r   r   r   r   r   ÚujsonrÌ   ÚImportErrorrø   Ú	getLoggerrˆ   Úlocalr+  rp  rq  rr  rs   rj   r¨   r¾   rÆ   rÒ   r   Úboolr×   rÚ   rá   ÚMessageEntityrî   rn  rñ   rû   r  ÚUserr	  r  r  r  r  r   r*  r2  r;  rF  rR  rX  rU  rm  ro  Ú__all__r   r   r   r‚   Ú<module>   sb    $ÿ
	B*")*3
&(