U
    hS5                     @   sd   d dl Z d dlZddlmZmZmZ ddlmZ ddlm	Z	m
Z
 ddlmZ eG dd	 d	eZdS )
    N   )EventBuilderEventCommonname_inner_event   )utils)types	functions)SenderGetterc                       sV   e Zd ZdZdddddd fddZedddZd	d
 ZG dd dee	Z
  ZS )CallbackQuerya  
    Occurs whenever you sign in as a bot and a user
    clicks one of the inline buttons on your messages.

    Note that the `chats` parameter will **not** work with normal
    IDs or peers if the clicked inline button comes from a "via bot"
    message. The `chats` parameter also supports checking against the
    `chat_instance` which should be used for inline callbacks.

    Args:
        data (`bytes`, `str`, `callable`, optional):
            If set, the inline button payload data must match this data.
            A UTF-8 string can also be given, a regex or a callable. For
            instance, to check against ``'data_1'`` and ``'data_2'`` you
            can use ``re.compile(b'data_')``.

        pattern (`bytes`, `str`, `callable`, `Pattern`, optional):
            If set, only buttons with payload matching this pattern will be handled.
            You can specify a regex-like string which will be matched
            against the payload data, a callable function that returns `True`
            if a the payload data is acceptable, or a compiled regex pattern.

    Example
        .. code-block:: python

            from telethon import events, Button

            # Handle all callback queries and check data inside the handler
            @client.on(events.CallbackQuery)
            async def handler(event):
                if event.data == b'yes':
                    await event.answer('Correct answer!')

            # Handle only callback queries with data being b'no'
            @client.on(events.CallbackQuery(data=b'no'))
            async def handler(event):
                # Pop-up message with alert
                await event.answer('Wrong answer!', alert=True)

            # Send a message with buttons users can click
            async def main():
                await client.send_message(user, 'Yes or no?', buttons=[
                    Button.inline('Yes!', b'yes'),
                    Button.inline('Nope', b'no')
                ])
    NF)blacklist_chatsfuncdatapatternc                   s  t  j|||d |r"|r"tdt|tr6|d}t|trJ|d}|rR|n|}t|trx|rh|n
t|j	| _	nj|rt
|r|| _	nVt|drt
|j	rtt|ddtst|jd|jtj @ }|j	| _	ntdtdd	 | j| j| j	fD | _d S )
N)r   r   z*Only pass either data or pattern not both.zutf-8matchr       z"Invalid data or pattern type givenc                 s   s   | ]}|d kV  qd S N ).0xr   r   A/tmp/pip-unpacked-wheel-c81u5j2r/telethon/events/callbackquery.py	<genexpr>U   s     z)CallbackQuery.__init__.<locals>.<genexpr>)super__init__
ValueError
isinstancestrencodebytesrecompiler   callablehasattrgetattrr   flagsUNICODE	TypeErrorallchatsr   	_no_check)selfr(   r   r   r   r   r   	__class__r   r   r   :   s0    





  zCallbackQuery.__init__c                 C   sv   t |tjr| ||j|jS t |tjrrtdt	d|jj
\}}|dk rZt| nt|}| |||S d S )Nz<iiz<qr   )r   r   ZUpdateBotCallbackQueryEventpeermsg_idUpdateInlineBotCallbackQuerystructunpackpackidZPeerChannelZPeerUser)clsupdateZothersself_idZmidpidr.   r   r   r   buildY   s    zCallbackQuery.buildc                 C   s   | j r
|S | jd k	rF|jj| jk}|jr8||j| jkO }|| jkrFd S | jrt| jrx| |jj |_	|_
|j	sd S n|jj| jkrd S | jr| |S dS )NT)r)   r(   querychat_instanceZchat_idr   r   r!   r   
data_matchpattern_matchr   )r*   eventZinsider   r   r   filterd   s$    



zCallbackQuery.filterc                       s   e Zd ZdZ fddZ fddZedd Zedd	 Zed
d Z	edd Z
dd Zdd Zd"dddddZedd Zdd Zdd Zdd Zd d! Z  ZS )#zCallbackQuery.Eventa  
        Represents the event of a new callback query.

        Members:
            query (:tl:`UpdateBotCallbackQuery`):
                The original :tl:`UpdateBotCallbackQuery`.

            data_match (`obj`, optional):
                The object returned by the ``data=`` parameter
                when creating the event builder, if any. Similar
                to ``pattern_match`` for the new message event.

            pattern_match (`obj`, optional):
                Alias for ``data_match``.
        c                    s@   t  j||d t| |j || _d | _d | _d | _d| _d S )N)r/   F)	r   r   r
   Zuser_idr:   r<   r=   _message	_answered)r*   r:   r.   r/   r+   r   r   r      s    zCallbackQuery.Event.__init__c                    s,   t  | t| j| j|j\| _| _d S r   )	r   _set_clientr   Z_get_entity_pair	sender_id	_entities_mb_entity_cache_sender_input_sender)r*   clientr+   r   r   rB      s      zCallbackQuery.Event._set_clientc                 C   s   | j jS )z
            Returns the query ID. The user clicking the inline
            button is the one who generated this random ID.
            )r:   query_idr*   r   r   r   r4      s    zCallbackQuery.Event.idc                 C   s   | j S )z\
            Returns the message ID to which the clicked inline button belongs.
            )_message_idrJ   r   r   r   
message_id   s    zCallbackQuery.Event.message_idc                 C   s   | j jS )zS
            Returns the data payload from the original inline button.
            )r:   r   rJ   r   r   r   r      s    zCallbackQuery.Event.datac                 C   s   | j jS )z
            Unique identifier for the chat where the callback occurred.
            Useful for high scores in games.
            )r:   r;   rJ   r   r   r   r;      s    z!CallbackQuery.Event.chat_instancec                    sd   | j dk	r| j S z6| jr&|  I dH nd}| jj|| jdI dH | _ W n tk
r\   Y dS X | j S )zY
            Returns the message to which the clicked inline button belongs.
            N)ids)r@   Z
is_channelget_input_chat_clientZget_messagesrK   r   )r*   Zchatr   r   r   get_message   s    
 zCallbackQuery.Event.get_messagec                    s   | j | j| _| jsd S t| j| _t| jddsz$| j	j
t| jd  | _W n6 tk
r   |  I d H }|r|j| _|j| _Y nX d S )NZaccess_hashTr   )rD   getrC   rF   r   Zget_input_peerZ_chatrG   r#   rO   rE   Z
resolve_idZ
_sender_idZ_as_input_peerAttributeErrorrP   )r*   mr   r   r   _refetch_sender   s    z#CallbackQuery.Event._refetch_senderNr   F)urlalertc             	      s6   | j r
dS d| _ | tjj| jj||||dI dH S )aE  
            Answers the callback query (and stops the loading circle).

            Args:
                message (`str`, optional):
                    The toast message to show feedback to the user.

                cache_time (`int`, optional):
                    For how long this result should be cached on
                    the user's client. Defaults to 0 for no cache.

                url (`str`, optional):
                    The URL to be opened in the user's client. Note that
                    the only valid URLs are those of games your bot has,
                    or alternatively a 't.me/your_bot?start=xyz' parameter.

                alert (`bool`, optional):
                    Whether an alert (a pop-up dialog) should be used
                    instead of showing a toast. Defaults to `False`.
            NT)rI   
cache_timerV   messagerU   )rA   rO   r	   messagesZSetBotCallbackAnswerRequestr:   rI   )r*   rX   rW   rU   rV   r   r   r   answer   s    zCallbackQuery.Event.answerc                 C   s   t | jtjS )a3  
            Whether this callback was generated from an inline button sent
            via an inline query or not. If the bot sent the message itself
            with buttons, and one of those is clicked, this will be `False`.
            If a user sent the message coming from an inline query to the
            bot, and one of those is clicked, this will be `True`.

            If it's `True`, it's likely that the bot is **not** in the
            chat, so methods like `respond` or `delete` won't work (but
            `edit` will always work).
            )r   r:   r   r0   rJ   r   r   r   
via_inline   s    zCallbackQuery.Event.via_inlinec                    s6   | j j|   | j j|  I dH f||I dH S )aI  
            Responds to the message (not as a reply). Shorthand for
            `telethon.client.messages.MessageMethods.send_message` with
            ``entity`` already set.

            This method also creates a task to `answer` the callback.

            This method will likely fail if `via_inline` is `True`.
            N)rO   loopcreate_taskrZ   send_messagerN   r*   argskwargsr   r   r   respond  s    
zCallbackQuery.Event.respondc                    sB   | j j|   | jj|d< | j j|  I dH f||I dH S )aZ  
            Replies to the message (as a reply). Shorthand for
            `telethon.client.messages.MessageMethods.send_message` with
            both ``entity`` and ``reply_to`` already set.

            This method also creates a task to `answer` the callback.

            This method will likely fail if `via_inline` is `True`.
            Zreply_toN)rO   r\   r]   rZ   r:   r/   r^   rN   r_   r   r   r   reply  s    
zCallbackQuery.Event.replyc                    st   | j j|   t| jjtjtj	frF| j j
| jjf||I dH S | j j
|  I dH | jjf||I dH S dS )a[  
            Edits the message. Shorthand for
            `telethon.client.messages.MessageMethods.edit_message` with
            the ``entity`` set to the correct :tl:`InputBotInlineMessageID` or :tl:`InputBotInlineMessageID64`.

            Returns `True` if the edit was successful.

            This method also creates a task to `answer` the callback.

            .. note::

                This method won't respect the previous message unlike
                `Message.edit <telethon.tl.custom.message.Message.edit>`,
                since the message object is normally not present.
            N)rO   r\   r]   rZ   r   r:   r/   r   InputBotInlineMessageIDInputBotInlineMessageID64Zedit_messagerN   r_   r   r   r   edit+  s"    
 zCallbackQuery.Event.editc                    s\   | j j|   t| jjtjtj	fr0t
d| j j|  I dH | jjgf||I dH S )a  
            Deletes the message. Shorthand for
            `telethon.client.messages.MessageMethods.delete_messages` with
            ``entity`` and ``message_ids`` already set.

            If you need to delete more than one message at once, don't use
            this `delete` method. Use a
            `telethon.client.telegramclient.TelegramClient` instance directly.

            This method also creates a task to `answer` the callback.

            This method will likely fail if `via_inline` is `True`.
            zOInline messages cannot be deleted as there is no API request available to do soN)rO   r\   r]   rZ   r   r:   r/   r   rd   re   r&   Zdelete_messagesrN   r_   r   r   r   deleteF  s     zCallbackQuery.Event.delete)Nr   )__name__
__module____qualname____doc__r   rB   propertyr4   rL   r   r;   rP   rT   rZ   r[   rb   rc   rf   rg   __classcell__r   r   r+   r   r-   ~   s2   	



    $
r-   )N)NN)rh   ri   rj   rk   r   classmethodr9   r?   r   r
   r-   rm   r   r   r+   r   r   
   s   /    
r   )r   r1   commonr   r   r    r   tlr   r	   Ztl.custom.sendergetterr
   r   r   r   r   r   <module>   s   