
    soj              J          d dl Z d dlZd dl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mZmZmZmZmZ d dlmZmZmZmZ d dlmZ d dlm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' d d	l(m)Z) d d
l*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:m;Z; d dl<m=Z= d dl>m?Z?m@Z@ dde=dejA        fdZBdeCdeCfdZDdeCdeCfdZE	 ddedeFdeGdeFfd ZH	 	 	 	 	 	 	 	 	 	 dd"eIeIe=                  dejA        ded#eGd$eIe+         d%e=d&eGd'eIeC         d(eFd)eCd*e+d+eGde
dz  fd,ZJ	 	 	 	 dded-eGd.eFd/eGdeFdz  f
d0ZKddddddd!dejL        dd!dd!d!ddddd!dddd ddddddd!d!ddf!dejA        deCdedeFeCz  d"eIeIe=                  d1eGd2eGd3eGd4eGd.eFd5eCd-eGd/eGd6eGd7eGd8eGd#eGd$eIe+         d%e=deGd&eGd9eFd:eIe9         d'eIeC         d(eFd;eMd<eGd=e'd>eGd*e+d?eGd+eGd@eGdAeGdBeGdeeGz  fHdCZNdejL        fdDe3dEeCd5eCdefdFZOddddddddd!ddejL        dd!d!ddddddd!dddddddd!dfdejA        dDe3dedeFeCz  dEeCd"eIeIe=                  d1eGd2eGd3eGd4eGd.eFd6eGd5eCd-eGd/eGd8eGdGeGdHeGd#eGd$eIe+         d%e=deGd&eGdIe5d=e'dJeIeP         dKeGd9eFdAeGdLeGd@eGdeeGz  f@dMZQdddejL        dd!dd!ddddddddd!dfdejA        deCdedeFeCz  d"eIeIe=                  d5eCd6eGd7eGdGeGdHeGd#eGd$eIe+         d1eGd2eGd%e=d:eIe9         d?eGd;eMd@eGdAeGdef*dNZRdejA        dedOeIe;         deGfdPZSdeCdeGfdQZTdReFeCz  dSeCdeCfdTZUd*e+deCfdUZVdVeCdeCfdWZWdd$eIe+         dXeCde=fdYZXdde#jY        e#jZ        dddddde1j[        ddddddddddddddfd*e+dZe9d[eCd\eCd]eFd^eMd_e9d`e9daeMdbeMdceCd%e=ddeGdeeGdfeGdgeGdheGdieIeC         djeGdkeGd$eIe+         dleIeC         dmeIeC         dneCdoeCdeIe=         f4dpZ\dd e#j]        ddfd%e=dqeIeC         d(eFdreCd*e+dseMde=fdtZ^	 	 	 	 	 	 ddedejA        deFeCz  dueFd=e'dveGfdwZ_dede/fdxZ`dyeCdeCfdzZa	 ddseMeCz  dZe9d:eIe9         deCfd{Zbd*e+d%e=deceGeGeGf         fd|ZdddejA        deCdefd}ZededeGfd~Zf	 	 	 ddueFd=e'deCdeCdeCf
dZgdede'dz  fdZh	 dded=e'de'dz  fdZid=e'defdZjdS )    N)uuid4)UpdateInlineKeyboardButtonInlineKeyboardMarkupMessage
InputMediaInputMediaPhotoInputMediaVideoInputMediaAnimationChatInlineQueryResultInlineQueryResultArticleInputTextMessageContent)
BadRequestTelegramError	ForbiddenTimedOut)ContextTypesmention_markdown)Group)	GroupChat)GroupChatAutoDelete)User)ContextDataKey)MessageSource)ReservedKeyboardKeys)
SavedMedia)SavedMediaName)SavedMediaTypeScreen)ContextDataValue)Keyboard)set_bot_context_dataget_bot_context_databuttoncontextc                     i }| j         | j         |d<   n*| j        | j        |d<   n|                     |          |d<   t          | dd          dt	          | j                  i|d<   t          | j        fi |S )zZ
    Create an InlineKeyboardButton, preserving project-specific styles when present.
    Nurlswitch_inline_querycallback_datastyle
api_kwargs)r*   r+   $set_and_get_callback_data_in_contextgetattrstrr-   r   text)r'   r(   inline_kwargss      #/app/src/service/message_service.pybuild_inline_keyboard_buttonr5   -   s    
 Mz%ze		#	//5/I+,,)/)T)TU\)])]o&vw%%1'.FL0A0A&Bl#==}===    r2   returnc                     d}t          j        dt          j        |           dd|           } |                     dd          } | S )zW
    Escape invalid markdown chars
    :param text: Text
    :return: Escaped text
    z#+-={}.!([])\\\1z\\\)resubescapereplacer2   escape_charss     r4   escape_invalid_markdown_charsrC   @   sL     L62ry..222GTBBD <<%%DKr6   c                 ^    d}t          j        dt          j        |           dd|           S )zU
    Escape valid markdown chars
    :param text: Text
    :return: Escaped text
    z_*[]()>|r9   r:   r;   )r=   r>   r?   rA   s     r4   escape_valid_markdown_charsrE   Q   s3     L62ry..222GTBBBr6   Fupdatechat_idsend_in_private_chatc                     ||S | | j         | j         j        t          t          j                  |r| j        j        S | j         j        S )z
    Get chat id
    :param update: Update object. Required if chat_id is None
    :param chat_id: Chat id. Required if update is None
    :param send_in_private_chat: Send in private chat. Default: False
    :return: Chat id
    )effective_chatid	ExceptionphrasesEXCEPTION_CHAT_ID_NOT_PROVIDEDeffective_userrF   rG   rH   s      r4   get_chat_idrQ   ]   sX     ~.6&:O:R:Z>??? ($'' ##r6   Tkeyboardadd_delete_buttonauthorized_usersinbound_keyboard"only_authorized_users_can_interactexcluded_keys_from_back_buttonback_screen_indexdelete_button_textuseradd_back_buttonc                   K   ddl m} t                    }|t          j        u rd}|g }d |D             }	 t          fd|D                       sQt          j        t          j         |j	        j
                   d{V k              }|                    |           n# t          $ r Y nw xY wd}| |du s|'g }| i| D ]e}g }|D ]G}|j        #|                    t          |                     -|j        #|                    t          |                     Wt!          j        |j                  rt'          |j                  dk    r||j        z|j                                        |_        t'          |j                  dk    rD|j        d         |j        cxk    r|j        k    r"n n|j                            |j                   |j        r|rB|j        r;8j        j        t6          j        k    rd	 |D             |j        t<          j        <   nB|j        s;t'          |j                   dk    r#d
 |j         D             |j        t<          j        <   t<          j        |j        v r:t'          |j        t<          j                           dk    r|j        t<          j        = |!                                 	 |                    t          ||                      # tD          $ r tG          j$        d| d           Y Ew xY w|                    |           g|du rWt'          |          dk    st          d          tK          ||	          }|                    t          ||          g           |M|rKtM          ||||
          }|!                                 |                    t          ||          g           tO          |          }|S )a  
    Get keyboard markup

    :param keyboard: Keyboard object
    :param context: The context
    :param update: Update object
    :param add_delete_button: True if the delete button should be added
    :param authorized_users: List of user ids that are allowed to delete the message
    :param inbound_keyboard: Inbound Keyboard object
    :param only_authorized_users_can_interact: True if only authorized users can interact with the
    keyboard
    :param excluded_keys_from_back_button: List of keys that should not be added to the back button
    info
    :param back_screen_index: Index of the screen to go back to from previous_screens. Default: 0
    :param delete_button_text: Text to be used for the delete button
    authorized users list
    :param user: User object
    :param add_back_button: True if the back button should be added to the keyboard if possible
    :return: Keyboard markup
    r   )get_effective_tg_user_idNFc                     g | ]}||S N .0us     r4   
<listcomp>z get_keyboard.<locals>.<listcomp>   s    EEEaq}}}}r6   c              3   \   K   | ]&}t          |j                  j        j        k    V  'd S r_   )int
tg_user_idrO   rK   )rb   rc   rF   s     r4   	<genexpr>zget_keyboard.<locals>.<genexpr>   s8      [[Q3q|$$(=(@@[[[[[[r6   Tc                     g | ]	}|j         
S r`   rK   ra   s     r4   rd   z get_keyboard.<locals>.<listcomp>   s-     ^* ^* ^*56AD^* ^* ^*r6   c                     g | ]	}|j         
S r`   rk   ra   s     r4   rd   z get_keyboard.<locals>.<listcomp>   s-     Z& Z& Z&12Z& Z& Z&r6   zButton z does not have a callback_dataz.No authorized users provided for delete buttonbutton_text)excluded_keysrX   rZ   )(src.service.user_servicer]   get_message_sourcer   NDanyr   getrg   rO   effective_messageappendrL   r*   r5   r+   jsonloadsr,   lenprevious_screen_listscreencopyrV   inherit_authorized_usersrJ   typer   PRIVATEinfor   AUTHORIZED_USERSrT   refresh_callback_dataAttributeErrorloggingerrorget_delete_buttonget_back_buttonr   )rR   r(   rF   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r]   message_sourceuser_from_updatekeyboard_markupkeyboard_listrowkeyboard_rowr'   delete_buttonback_buttons     `                   r4   get_keyboardr   t   s     D BAAAAA +F33]---16.') FE#3EEE[[[[JZ[[[[[ 	6 &*X11&2GIabbbbbbbbc& & ##$4555    O0D88<L<X:< F3 F3;=! B! B!Fz-$++,H,P,PQQQQ3?$++,H,P,PQQQQ  :f&:;; /; !$F$? @ @A E E %5$@(8(?(K )9(M(R(R(T(T %+$? ),F,G(H(H1(L(L,2,G,K+;+B-9 -9 -9 -9+1=-9 -9 -9 -9 -9 )/(C(J(JK[Kb(c(c(c  &H &$F!&(.(G!&
 )/(:,2,A,F$,,V,V^* ^*:J^* ^* ^*4H4Y(Z )/(G!&(+F,C(D(Dq(H(HZ& Z&6<6MZ& Z& Z&FK0D0U$V
 !5 E T T$'4H4Y(Z$[$[_`$`$`$*K0D0U$V"88:::!(//0LVU\0]0]^^^^- ! ! !#M*ZF*Z*Z*Z[[[ D! $$\2222$$'((1,, PQQQ-.>L^___M  0HH   'O') <"3	  K --///  0gFF   /}==s$   A,B) )
B65B6#K22"LLquotereply_to_message_idquote_if_groupc                     ||S 	 |r@| j         j        t          j        k    s| j         j        t          j        k    r| j        j        S n# t          $ r Y nw xY w|sdS | j        t          d          | j        j        S )az  
    Get reply message id
    :param update: Update object. Required if reply_to_message_id is None
    :param quote: Quote message. Default: False
    :param reply_to_message_id: Reply message id. Default: None
    :param quote_if_group: If the message should be quoted if it is in a filter_by_groups and
    update is not None. Default: True
    :return: Reply message id
    NzNo message to quote)	rJ   r~   r   GROUP
SUPERGROUPru   
message_idr   rL   rF   r   r   r   s       r4   get_reply_to_message_idr     s      &"" 	;%*dj88(-@@/::     t'-...'22s   AA	 	
AAanswer_callback
show_alertnew_messagedisable_notification
parse_modeprotect_contentdisable_web_page_previewallow_sending_without_replyedit_message_idprevious_screens"previous_screen_list_keyboard_infouse_close_delete
group_chatignore_exceptionfrom_exceptionshould_auto_deleteignore_bad_request_exceptionforce_auto_deletec#                   K   t           j        }#||r|| rt          d          nt          |          }#|rd}|r	|j        d}|!|
t
          j        k    r|st          |          }|rd}d}$||j        }$|j	        }%|%j
        }n|#t           j        u rt          |          }| o|p|"o
|#|#j        u o|} |||rt          d||d         |          }n|||xj        |z  c_        t          |||          }t!          || ||||||||rt"          j        nd||	           d{V }&|s	||j        |t'          |||	|
          }		 | j                            |||&||
||	|||$
  
         d{V }'| r(| j                            t1          ||'                     |'S # t2          $ r&}(|rt5          j        d|(            Y d}(~(dS |(d}(~(ww xY w||j        |t9          t"          j                  |r	 | j                            |j        j        ||           d{V S # t@          $ rj}(dtC          |(          "                                v s#dtC          |(          "                                v rt5          j#        d|(            Y d}(~(dS |(d}(~(ww xY w||n|j        j$        j%        }	 | j        &                    |||&|
||           d{V }'| r(| j                            t1          ||'                     |'S # t@          $ r8}(|!r/tC          |(          "                                })d|)v sd|)v rY d}(~(dS |(d}(~(ww xY w)a<  
    Send a message

    :param context: ContextTypes.DEFAULT_TYPE object
    :param text: Text to send
    :param update: Update object. Required if chat_id is None
    :param chat_id: Chat id. Required if update is None
    :param keyboard: Keyboard object
    :param answer_callback: If it is an answer callback
    :param show_alert: If to show an alert in the callback answer
    :param new_message: True if the message is a new message
    :param disable_notification: True if a notification should not be sent
    :param reply_to_message_id: Message ID to reply to
    :param parse_mode: Parse mode
    :param quote: True if the message should be quoted
    :param quote_if_group: True if the message should be quoted if it is in a filter_by_groups and
    update is not None
    :param protect_content: True if the message should be protected from saving and forwarding
    :param disable_web_page_preview: True if the web page preview should be disabled
    :param allow_sending_without_reply: True if the message should be sent if message to be replied
    to is not found
    :param add_delete_button: True if the delete button should be added
    :param authorized_users: List of users that are allowed to delete the message
    :param inbound_keyboard: Inbound Keyboard object. If not None, a back button will be added to
    the keyboard
    :param send_in_private_chat: True if the message should be sent in private chat. Not necessary
    if update is not None
    :param only_authorized_users_can_interact: True if only authorized users can interact with the
    message keyboard
    :param edit_message_id: ID of the message to edit
    :param previous_screens: List of previous screens. Ignored if inbound_keyboard is not None
    :param excluded_keys_from_back_button: List of keys that should not be added to the back button
    info
    :param back_screen_index: Index of the screen to go back to from previous_screens. Default: 0
    :param previous_screen_list_keyboard_info: In case inbound keyboard is inferred from
    previous_screens, this is the keyboard info to add to the back button
    :param use_close_delete: True if the close button should be used instead of the delete button
    :param group_chat: The group chat, used to get the group chat id
    :param ignore_exception: True if the TelegramError should be ignored
    :param user: User object
    :param from_exception: True if the message is sent from an exception
    :param add_back_button: True if the back button should be added to the keyboard when possible
    :param should_auto_delete: True if the message should be auto deleted
    :param ignore_bad_request_exception: True to ignore specific bad request exceptions like "message is not modified"
    :param force_auto_delete: True if the message should be auto deleted even without a delete button
    :return: Message
    N^Cannot add delete button without an update object, needed to enqueue for auto message deletionTF ri   )rz   r{   r   rP   )
rF   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r   )
r2   rG   reply_markupr   r   r   r   r   r   message_thread_idError while sending message: r2   r   query is too oldquery id is invalid4Callback query expired before it could be answered: )r2   rG   r   r   r   r   zmessage is not modifiedzmessage to edit not found)'r   rr   
ValueErrorrq   callback_querycTG_PARSE_MODE_MARKDOWNrC   tg_topic_idgrouptg_group_idr   get_group_chat_for_auto_deleter$   r   rQ   r   rM   KEYBOARD_OPTION_CLOSEr   botsend_messageapplicationcreate_taskenqueue_message_auto_deleter   r   r   r   EXCEPTION_NO_EDIT_MESSAGEanswer_callback_queryrK   r   r1   lowerwarningmessager   edit_message_text)*r(   r2   rF   rG   rR   r   r   r   r   r   r   r   r   r   r   r   rS   rT   rU   rH   rV   r   r   rW   rX   r   r   r   r   rZ   r   r[   r   r   r   r   topic_idr   r   r   e	error_msgs*                                             r4   full_message_sendr   B  s#     j %2$4N~ 	!38J!3$  
 );6(B(B   &'/J!*BBB?B,T22 H)!'#	=.	.	.3F;;
 	 	3"3	n22	 	  #)9)A^)A#!1#B'3	
 
 
 
,	7<L<X!CCw=Q  G )+))+M'E+<LV788RV'        O" 	"~)>)F

!5 3)	
 
 
	%,[%=%=,)A%%9$7,G /"* &> & &            G " b#//0KJX_0`0`aaaN 	 	 	 AaAABBBuuuuuG		 	&/7_=TW>???  		 ::%(t
 ;           	 	 	!SVV\\^^337LPSTUPVPVP\P\P^P^7^7^ ZWX Z Z[[[uuuuuG		 & 	"*5 !(!>!>(!%=& "? "
 "
 
 
 
 
 
 
  	^++,G
T[,\,\]]]   ' 	AI(I559TXa9a9auuuuus]   
AF   
G*G	GG:,H' '
J1AJJJ4AL 
M+MMMsaved_mediacaptionc                 *   | j         xt          j        k    r t          | j        ||          S xt          j        k    r t          | j        ||          S t          j        k    rt          | j        ||          S 	 t          d| j                    )z
    Get InputMedia object from SavedMedia object
    :param saved_media: SavedMedia object
    :param caption: Caption
    :param parse_mode: Parse mode
    :return: InputMedia object
    )mediar   r   zInvalid media type: )
r~   r    PHOTOr	   media_idVIDEOr
   	ANIMATIONr   r   )r   r   r   s      r4    get_input_media_from_saved_mediar   *  s     
!^!!!!"!*G
    "^!!!!"!*G
    %%%&!*G
    FK4DFFGGGr6   edit_only_keyboardedit_only_caption_and_keyboardsaved_media_nameexceptions_to_ignoreignore_forbidden_exceptionshould_log_ignored_exceptionc                  ,  K   t           j        } ||r|t          d          nt          |          } |g }|r|                    t
                     |r4|                    t                     |                    t                     |!|t          j	        k    r|st          |          }||t          j        |          }d}!||j        t          |j        t                     s	 |j        (t%          | t&          j        |j        d          |_        nt*          n_# t*          $ rR t-          |j        d          5 }"|"                                |_        |j        du}!ddd           n# 1 swxY w Y   Y nw xY wd}#||j        }#|j        }$|$j        }n| t           j        u rt9          |          }|o|o
| | j        u o|}t;          |||          }t=          || ||||||           d{V }%|dup|p|}&|s|qt>          j         |j!        j"        t>          j#        |j!        j$        t>          j%        |j!        j&        i}'|'|j'                 tQ          |'|j'                           dk    rd	}	 |s
||j)        g|&sdtU          |||
|
          }
|j'        xt>          j         k    r3 | j+        ,                    ||j        ||%||	|
|||#dd           d{V }(nxt>          j#        k    r3 | j+        -                    ||j        ||%||	|
|||#dd           d{V }(nYt>          j%        k    r2| j+        .                    ||j        ||%||	|
|||#dd           d{V }(n	 t          d|j'                   |!r>|(j"        d         j/        |_        ta          | t&          j        |j        |j                   |r(| j1        2                    tg          ||(                     |(S ||j)        |ti          tj          j6                  |r	 | j+        7                    |j)        j8        ||           d{V S # t          $ rj})dt!          |)          9                                v s#dt!          |)          9                                v rtu          j;        d|)            Y d})~)dS |)d})~)ww xY w||n|j)        j<        j=        }|rO| j+        >                    |||%           d{V }(|r(| j1        2                    tg          ||(                     |(S |rP| j+        ?                    ||||%           d{V }(|r(| j1        2                    tg          ||(                     |(S t          ||          }*| j+        A                    |||*|%dd           d{V }(|r(| j1        2                    tg          ||(                     |(S # th          $ r<})|D ]2}+t          |)|+          r |rtu          jB        d|)             Y d})~)dS 3|)d})~)ww xY w)a-	  
    Send a media
    :param context: ContextTypes.DEFAULT_TYPE object
    :param saved_media: SavedMedia object
    :param update: Update object. Required if chat_id is None
    :param chat_id: Chat id. Required if update is None
    :param caption: Caption
    :param keyboard: Keyboard object
    :param answer_callback: If it is an answer callback
    :param show_alert: If to show an alert in the callback answer
    :param new_message: True if the message is a new message
    :param disable_notification: True if a notification should not be sent
    :param reply_to_message_id: Message ID to reply to
    :param protect_content: True if the message should be protected from saving and forwarding
    :param parse_mode: Parse mode
    :param quote: True if the message should be quoted
    :param quote_if_group: True if the message should be quoted if it is a group_chat message
    :param allow_sending_without_reply: True if the message should be sent if message to be replied
    to is not found
    :param edit_only_keyboard: If only the keyboard should be edited
    :param edit_only_caption_and_keyboard: If only the caption and keyboard should be edited. If
    keyboard is None, it will be removed
    :param add_delete_button: True if the delete button should be added
    :param authorized_users: List of users that are allowed to delete the message
    :param inbound_keyboard: Inbound Keyboard object. If not None, a back button will be added
    to the keyboard
    :param send_in_private_chat: True if the message should be sent in private chat
    :param only_authorized_users_can_interact: True if only authorized users can interact with the
    message keyboard
    :param saved_media_name: Saved media name
    :param group_chat: The group chat, used to get the group chat id
    :param exceptions_to_ignore: List of exceptions to ignore
    :param ignore_forbidden_exception: True if the forbidden exception should be ignored
    :param ignore_bad_request_exception: True if the bad request exception should be ignored
    :param should_log_ignored_exception: If to log the ignored exception error message
    :param edit_message_id: Message id to edit
    :param should_auto_delete: True if the message should be auto deleted
    :param delete_button_text: Text to be used for the delete button

    :return: Message
    Nr   F)	inner_keytolerate_key_exceptionrbrP   )rF   rS   rT   rU   rV   rY   r   Tr   <   )rG   photor   r   r   r   r   r   r   r   read_timeoutwrite_timeout)rG   videor   r   r   r   r   r   r   r   r   r   )rG   	animationr   r   r   r   r   r   r   r   r   r   zInvalid saved media type: ri   )r   r   r   r   r   )rG   r   r   )rG   r   r   r   )r   r   )rG   r   r   r   r   r   r   )Cr   rr   r   rq   rv   r   r   r   r   r   rC   r   get_by_name	file_name
isinstancer   r1   namer&   r   SAVED_MEDIAKeyErroropenreadr   r   r   r   r   rQ   r   r    r   ru   r   r   r   r   r   r~   ry   r   r   r   
send_photo
send_videosend_animationfile_idr%   r   r   r   rL   rM   r   r   rK   r   r   r   r   r   edit_message_reply_markupedit_message_captionr   edit_message_mediar   ),r(   r   rF   rG   r   rR   r   r   r   r   r   r   r   r   r   r   r   r   rS   rT   rU   rH   rV   r   r   r   r   r   r   r   r   rY   r   should_save_media_idmr   r   r   is_editmedia_type_mapr   r   input_mediae_to_ignores,                                               r4   full_media_sendr   F  s     X %2$4N~ 	!3$  
 );6(B(B#!! /##I...# .##J///##H---zQ-EEEoE/88/;","89I"J"J !!-;/55 .	D+';".).+0	( ( ($$  %  	D 	D 	Dk+T22 Da'(vvxx$'2'7t'C$D D D D D D D D D D D D D D D	D H)!'#	=.	.	.3F;;
 	 		n22	 	  w=Q  G )+))+M-	 	 	 	 	 	 	 	 	O T)a-?aCaG k5 &":"@ &":"@$f&>&H
 +*+3s>+JZ;[7\7\`a7a7aKU I	6>V-B-JT[-J"9$7-	# # # ")^))))-4[-C-C ')2 '%4#--A,?4O(7*2%'&( .D . . ( ( ( ( ( (GG *^))))-4[-C-C ')2 '%4#--A,?4O(7*2%'&( .D . . ( ( ( ( ( (GG $----4[-G-G '"-"6 '%4#--A,?4O(7*2%'&( .H . . ( ( ( ( ( (GG $%T+BR%T%TUUU# '.}R'8'@$$".().	    " b#//0KJX_0`0`aaaN Nf3;AXG=>>>  		$[>>),7z ?             %Q77;PTWXYTZTZT`T`TbTb;b;bO$^[\$^$^___ 55555	 * O&.9 	  	%,[%J%JO/ &K & &            G " b#//0KJX_0`0`aaaN * 	%,[%E%E*,	 &F & &            G " b#//0KJX_0`0`aaaN #C#W#
 #
 #
 ")!?!?&( "@ "
 "
 
 
 
 
 
 
  	^++,G
T[,\,\]]]   / 	 	K![)) / GM"E!"E"EFFFuuuuuu
 s   +6D" "E>#E0$E>0E4	4E>7E4	8E>=E>4E2W '&W ,P; ;
R/AR*"W (R**R//A(W AW *A"W 
X.XXXc                    K   	 t          | |fi d|d|d|d|d|d|d|d|d	|
d
|d|d|d|d|d|d| d{V S # t          $ r$ t          | f||||||
||	|||||||d d{V cY S w xY w)a  
    Edit a message or media, in case the type of message being edited is unknown
    :param context: ContextTypes.DEFAULT_TYPE object
    :param text: Text to send
    :param update: Update object. Required if chat_id is None
    :param chat_id: Chat id. Required if update is None
    :param keyboard: Keyboard object
    :param parse_mode: Parse mode
    :param protect_content: True if the message should be protected from saving and forwarding
    :param disable_web_page_preview: Only for text; True if the web page preview should be disabled
    :param edit_only_keyboard: Only for Media; if only the keyboard should be edited
    :param edit_only_caption_and_keyboard: Only for Media; If only the caption and keyboard should
    be edited.
    If keyboard is None, it will be removed
    :param add_delete_button: True if the delete button should be added
    :param authorized_users: List of user ids that are allowed to delete the message
    :param answer_callback: True if the callback should be answered
    :param show_alert: True if the callback should be answered with an alert
    :param inbound_keyboard: Inbound Keyboard object. If not None, a back button will be added to
    the keyboard
    :param previous_screens: List of previous screens. Ignored if inbound_keyboard is not None
    :param from_exception: True if the message is sent from an exception
    :param previous_screen_list_keyboard_info: In case inbound keyboard is inferred from
    previous_screens, this is the keyboard info to add to the back button
    :param should_auto_delete: True if the message should be auto deleted
    :param ignore_bad_request_exception: True if specific bad requests should be ignored

    :return: Message
    rF   rG   rR   r   r   r   r   r   rS   rT   rU   r   r   r   r   r   N)r   rF   rG   rR   r   rS   r   r   rT   r   r   r   rU   r   r   )r   r   r   )r(   r2   rF   rG   rR   r   r   r   r   r   rS   rT   r   r   rU   r   r   r   r   r   s                       r4   "full_message_or_media_send_or_editr     s     h'
&
 
 
 6
 G	

 X
 ,O
 "z
 "z
 ,O
 &>%=
 0/
 .-
 .-
 .-
 *>
  0R/Q!
"  21#
$ *F)E%
 
 
 
 
 
 
 	
(  
 
 
$
!/1+I-++!-1)E!
 
 
 
 
 
 
 
 
 	
 	
 	

s   AA +A43A4itemsc                   K   t          |          dk    rdS g }|D ]}t          |j                  r |j        |j         }n|j        }|j        t          |j        |            d{V nd}|                    t          t          t                                |j
        |j        t          t          |                    |                     |j                            |           d{V  dS )z
    Answer an inline query
    :param context: The context
    :param update: Update object
    :param items: List of items to display
    :return: True if the answer was sent
    r   FN)rK   titledescriptioninput_message_contentr   )ry   callabler2   argsrR   r   rv   r   r1   r   r  r  r   rC   inline_queryanswer)r(   rF   r   resultsitemr2   r   s          r4   full_inline_query_answerr
    s       5zzQu')G 
 
DI 	49di(DD9D ;?-:S,t}g666666666Y] 	 	$uww<<j ,&=>[\`>a>a&b&b,  	
 	
 	
 	
 

$
$W
-
----------r6   c                 N    	 | d         t           j        v S # t          $ r Y dS w xY w)z+
    Check if the message is a command
    r   F)r   COMMAND_PREFIX_ALIASES	TypeError)r2   s    r4   
is_commandr  	  s;    Aw!222   uus    
$$user_idr   c                 $    t          | |d          S )z&
    Create a mention markdown v2
       r   )r  r   s     r4   mention_markdown_v2r    s     GT1---r6   c                 6    t          | j        | j                  S )z0
    Create a mention markdown given a user
    )r  rg   tg_first_name)rZ   s    r4   mention_markdown_userr    s     t0BCCCr6   	image_urlc                     d|  dS )z!
    Create an image preview
    u   [​]()r`   )r  s    r4   get_image_previewr  !  s     !I    r6   rn   c                 Z    |t           j        }t          |t          j        di|           S )z
    Create a delete button
    :param authorized_users: List of users ids that can operate the delete button
    :param button_text: Text of the button. If not provided, the default Delete text is used
    NT)r   rT   )rM   KEYBOARD_OPTION_DELETEr$   r   DELETE)rT   rn   s     r4   r   r   (  s:     4")40)   r6   r{   yes_textno_textprimary_key
extra_keys
yes_screen	no_screenyes_extra_keysno_extra_keysconfirm_keyyes_is_back_buttonno_is_back_buttonyes_is_delete_buttonno_is_delete_buttonadd_inbound_key_infokeys_to_excludeexclude_yes_buttonexclude_no_buttonyes_keys_to_excludeno_keys_to_exclude	yes_styleno_stylec           
         |g }nd |D             }| |                     |            |||||j        }nt          d          ||ng }||ng }||ng }g }i }|||t          j        <   ||                                D ]
\  }}|||<   |r&|$|j                                        D ]
\  }}|||<   |D ]}||v r|                    |           |s|                                }|D ]}|                    |d           |r+|                     t          ||| |||z                        n}|r%|                     t          ||                     nV||
diz  }||                                D ]
\  }}|||<   ||n|}|                     t          ||||d|                     |s|                                }|D ]}|                    |d           |r+|                     t          ||| |||z                        n}|r%|                     t          ||                     nV||
diz  }|	|	                                D ]
\  }}|||<   ||n|}|                     t          ||||d|                     |S )	ah  
    Create a yes/no keyboard

    :param user: User that can operate the keyboard
    :param primary_key: Primary key
    :param yes_text: Text for the yes button
    :param no_text: Text for the no button
    :param screen: The default screen that will be called when the user clicks on the yes/no button
    :param extra_keys: Dict of extra keys to add to the keyboard
    :param yes_screen: Screen to call when the user clicks on the yes button. If None, the default
    screen will be called
    :param no_screen: Screen to call when the user clicks on the no button. If None, the default
    screen will be called
    :param yes_extra_keys: Dict of extra keys for the yes button, in a dict of key and value
    :param no_extra_keys: Dict of extra keys for the no button, in a dict of key and value
    :param confirm_key: Yes or no key. If None, default value will be used
    :param inbound_keyboard: The inbound keyboard
    :param yes_is_back_button: True if the yes button should be a back button
    :param no_is_back_button: True if the no button should be a back button
    :param yes_is_delete_button: True if the yes button should be a delete button
    :param no_is_delete_button: True if the no button should be a delete button
    :param add_inbound_key_info: True if the inbound key info should be added to the yes and no
    buttons
    :param keys_to_exclude: List of keys to exclude from the copy of info dict
    :param exclude_yes_button: True if the yes button should be excluded
    :param exclude_no_button: True if the no button should be excluded
    :param authorized_users: List of users that can operate the keyboard
    :param yes_keys_to_exclude: List of keys to exclude from the copy of info dict for the yes
    button
    :param no_keys_to_exclude: List of keys to exclude from the copy of info dict for the no button
    :return: The yes and no keyboard
    Nc                     g | ]}||S r_   r`   ra   s     r4   rd   z'get_yes_no_keyboard.<locals>.<listcomp>y  s    III!1=A===r6   z4screen or yes_screen and no_screen must be specified)key_textrZ   r   ro   rm   TF)r   r{   rT   r}   r-   )rv   r{   r   r   DEFAULT_PRIMARY_KEYr   r   popr|   r   r   r$   )rZ   r{   r  r  r  r   r!  r"  r#  r$  r%  rU   r&  r'  r(  r)  r*  r+  r,  r-  rT   r.  r/  r0  r1  keyboard_linedefault_keyboard_datakeyvaluekeyboard_data_yeskeyboard_data_nos                                  r4   get_yes_no_keyboardr=  9  s   x  JI'7III%%%~:-1B'%,FFSTTT)8)Doo"O1D1P--VX/A/M++SU$&M JU2FG $**,, 	/ 	/JC).!#&&  / 0 <*/5577 	/ 	/JC).!#&& + +'''!%%c***  $"7"<"<">"> ' 	- 	-C!!#t,,,, 	  $%*#25H#H      " 	  !23CQY!Z!Z!Z[[[[ +t!44)"0"6"6"8"8 3 3JC-2%c**#-#5:J  *%%5-2#  	 	 	  #!6!;!;!=!= & 	, 	,C  d++++ 	  $$)#25G#G      ! 	  !23CQX!Y!Y!YZZZZ e 44("/"5"5"7"7 2 2JC,1$S))"+"3I  )$%5-2"  	 	 	 r6   ro   r4  r   c                    ||                                 ni }||j        d|_        | | j                                         |z  }||D ]}|                    |d           |                    t
          j        d           |                    t
          j        d           | j        }n.d |j	        
                    t          j                  D             }| t          | j                  dk    rm| j        t          j        u rt#          |t$          j        |          S | j        t          j        u rt#          |t$          j        |          S t-          d          d}	| +t
          j        | j        v r| j        t
          j                 }	n	||j        }	|r|j        nd}
|A|j        r:|
s8d}|                                d         }|j        r|j        |t
          j        <   n|	>|	dk    r8|
s6|r4|j        -d}|d         }| | j        }||j        d	z
  |t
          j        <   nHd|z
  }||         }	 | | j        |u r||d	z
           }n## t:          t<          t>          t@          f$ r Y nw xY wt#          |||d|         |
          S )a  
    Create a back button

    :param inbound_keyboard: Keyboard object
    :param excluded_keys: List of keys to exclude from the copy of info dict
    :param back_screen_index: Index of the screen to go back to from previous_screens. Default: 0
    :param key_text: Text for the back button
    :param user: The user, used for previous screens if inbound_keyboard is None
    :param info: Info dict to add to the back button
    NTc                 ,    g | ]}t          |          S r`   r!   rb   ss     r4   rd   z#get_back_button.<locals>.<listcomp>  s+      
  
  
F1II 
  
  
r6   r   )r{   inbound_infoz&Invalid message source for back buttonFri      )r{   rz   rB  )!r|   private_screen_stay_stepprivate_screen_stayr   r6  r   TOGGLECONFIRMrz   private_screen_listsplitr   STANDARD_SPLIT_CHARry   r   r   r   r$   r"   	PVT_STARTr   GRP_SETTINGSr   SCREEN_STEPprivate_screen_previous_stepprivate_screen_force_go_backget_private_screen_listprivate_screen_stepr{   r   r   r  
IndexError)rU   ro   rX   r4  rZ   r   	info_copyr9  rz   rQ  force_back_to_previous_screenprevious_screen_end_indexr{   s                r4   r   r     s   &  $/		RID9E#' #$)..009<	$$ ) )c4(((( 	*14888*2D999/D 
  
#7==a>STT 
  
  
 #,<,Q(R(RVW(W(W*m.CCCHV-=IVVVV,0CCCHV-@yYYYYABBB#(<(HL\La(a(a.34H4TU		"?IM$XD$E$ESX!D4=Z$(!5577;( 	X:>:WI*67'!##- $ $ $0 %)!-b1'%,F:>:RUV:VI*67 %'):$:!-.GH	+0@0G60Q0Q-.G!.KL)Z@ 	 	 	D	 12L3L2LM	   s   5I I,+I,r   is_auto_deletec           	        K   ||j         }|j        }| |||t          j        d           dS 	 | 9| j        j        }| j        j        }| j                                         d{V  dS |j	        
                    ||           d{V  dS # t          $ r0}|rY d}~dS t          j        d| d| d|            Y d}~dS d}~ww xY w)a#  
    Delete a message with the best effort method
    :param update: Update object
    :param context: Context object
    :param chat_id: Chat id
    :param message_id: Message id
    :param group_chat: The group chat
    :param is_auto_delete: True if the message is being auto deleted
    NzPupdate or context and chat_id and message_id must be specified to delete messagezFailed to delete message z	 in chat z: )r   r   r   r   ru   r   rJ   rK   deleter   delete_messager   )rF   r(   rG   r   r   rV  r   tes           r4   rY  rY  P  sA     $ !'#~7?goAS^	
 	
 	
 	X1<J+.G*1133333333333+,,WjAAAAAAAAAAA X X X 	FFFFFV*VVwVVRTVVWWWWWWWWW	Xs#   9B -!B 
C
C"CC
c                    	 | j         j        t          j        k    rt          j        S | j         j        t          j        t          j        fv rt          j        S t          j        	                                8| j         j
        t          j                                        k    rt          j        S n*# t          $ r | j        j        t          j        cY S Y nw xY wt          j        S )zc
    Get the message source
    :param update: Update object
    :return: MessageSource object
    )rJ   r~   r   r   r   r   r   EnvTG_REST_CHANNEL_IDrt   rK   get_intTG_RESTr   r  queryINLINE_QUERYrr   rF   s    r4   rq   rq   z  s    . %55 (( %$*do)FFF && "&&((4%(C,B,J,J,L,LLL (( . . .$0 ---- 10. s   %B/ /B/ AB/ /"CCcommandc                 J    dt           j                                         d|  S )zh
    Get the start with command url
    :param command: Command
    :return: Start with command url
    https://t.me/z?start=)r\  BOT_USERNAMErt   )rc  s    r4   get_start_with_command_urlrg    s*     D3+//11CC'CCCr6   c                 Z   | i } t          | t                    rJ||dd         | t          j        <   |d |D             | t          j        <   t          j        | d          } |                                 }t          j	        |          
                                }t          |          S )z
    Get the deeplink
    :param info: Info dict
    :param screen: Screen
    :param previous_screens: List of previous screens
    :return: Deeplink
    NrC  c                 "    g | ]}|d d         S )rC  Nr`   r@  s     r4   rd   z get_deeplink.<locals>.<listcomp>  s     9Z9Z9ZA!ABB%9Z9Z9Zr6   ),:)
separators)r   dictr   SCREENPREVIOUS_SCREENrw   dumpsencodebase64	b64encodedecoderg  )r   r{   r   encoded_bytesencoded_strings        r4   get_deeplinkrw    s     |$ 706qrr
D%,-'9Z9ZIY9Z9Z9ZD%56z$:666KKMMM%m44;;==N%n555r6   c                 X    d}d}d}|| j         
| j        d}n| j        d}|d}|||fS )z
    Get the item creation/edit status
    :param user: User object
    :param inbound_keyboard: Keyboard object
    :return: Tuple with should ignore input, should create item and should validate input
    TF)rQ  private_screen_in_edit_id)rZ   rU   should_create_itemshould_validate_inputshould_ignore_inputs        r4   get_create_or_edit_statusr}    sc       	 $,*2")5!&+(-% 24IIIr6   c                    K   d|                                  }t          j                                        }|t	          j        d|            dS t          | |||           d{V  dS )z
    Send an error to the error log chat
    :param context: Context object
    :param text: Text to send
    :param update: Update object
    zError: NzError log chat id is not set: )rF   rG   )upperr\  ERROR_LOG_CHAT_IDrt   r   r   r   )r(   r2   rF   error_log_chat_ids       r4   	log_errorr    s       T!!##D-1133 =t==>>>
GT&BS
T
T
TTTTTTTTTTr6   c                 h    	 | j         j        duo| j         j        j        du S # t          $ r Y dS w xY w)z
    Check if the message is a reply. Necessary because, due to a Telegram bug, the reply_to_message
    field is set
    for every message sent in not general topics
    :param update: Update object
    :return: True if the message is a reply
    NF)ru   reply_to_messageforum_topic_createdr   rb  s    r4   message_is_replyr    sV    $5TA V(9MQUU	
    uus    # 
11chat_usernamec                    |rd| d|  S ||t          d          |}||j        }t          |j                  }|                    dd          }d| d|  }|                                s|                    dd          }|S )	a  
    Gets the message url
    :param group_chat: The group chat
    :param message_id: The message id
    :param chat_id: The chat id
    :param chat_username: The chat's public username (without @), if set, takes priority over
    chat_id/group_chat and builds a public post link (e.g. https://t.me/username/123) instead of
    the private https://t.me/c/.../123 link, which only works for members who already joined
    :return: The message url
    re  /Nz'chat_id or group_chat must be specifiedz-100r   zhttps://t.me/c/z/c/)r   r   r1   r   r@   	isnumeric)r   r   rG   r  
tg_chat_idr   r*   s          r4   get_message_urlr    s    "  <;};;z;;;:-BCCCJ!'*++
##FB//J
5J
5
5
5
5C !! &kk%%%Jr6   c                    t          j        t           j        | j        j        k              }|dS d}| j        j        r| j        j        r| j        j        }t          j        t          j
        |k    t          j        |k    z            }|S )zg
    Gets the group chat from the update
    :param update: The update
    :return: The group chat
    N)r   get_or_noner   rJ   rK   is_forumru   is_topic_messager   r   r   r   )rF   r   r   r   s       r4   get_group_chat_from_updater     s     e/63H3KKLLE}K% A&*B*S A.@&	E	!i&;{&JK J r6   c                    ||S | ;t          j        d           t          j        t          j                               dS t	          |           t
          j        urdS t          |           }|t          d          |S )z
    Gets the group chat for auto delete
    :param update: The update
    :param group_chat: The group chat
    :return: The group chat
    Nz?Cannot add delete button without an update or group chat objectzGroup chat not found)	r   r   	tracebackformat_stackrq   r   r   r  r   )rF   r   s     r4   r   r   6  s     ~YZZZ	.00111f%%)<<<+F33J/000r6   r   c                    K   ddl m} | j        dS t                      }| |_        |j        |_         || j                  |_        |                                 dS )zq
    Enqueue a message for auto delete
    :param group_chat: The group chat
    :param message: The message
    r   )get_datetime_in_future_minutesN)src.service.date_servicer  auto_delete_durationr   r   r   delete_datesave)r   r   r  auto_deletes       r4   r   r   S  su       HGGGGG&.':'<'<K'K$/K<<Z=\]]Kr6   r_   )NNF)
NFNNTNr   NNT)NFNT)NNNNNF)NNN)krr  rw   r   r=   r  uuidr   src.tg_compatr   r   r   r   r   r	   r
   r   r   r   r   r   src.tg_compat.errorr   r   r   r   src.tg_compat.extr   src.tg_compat.helpersr   	constantsr   resources.EnvironmentEnvironmentr\  resources.phrasesrM   src.model.Groupr   src.model.GroupChatr   src.model.GroupChatAutoDeleter   src.model.Userr   src.model.enums.ContextDataKeyr   src.model.enums.MessageSourcer   $src.model.enums.ReservedKeyboardKeysr   src.model.enums.SavedMediar   src.model.enums.SavedMediaNamer   src.model.enums.SavedMediaTyper    src.model.enums.Screenr"   src.model.pojo.ContextDataValuer#   src.model.pojo.Keyboardr$   src.utils.context_utilsr%   r&   DEFAULT_TYPEr5   r1   rC   rE   rf   boolrQ   listr   r   TG_DEFAULT_PARSE_MODErm  r   r   rL   r   r   r
  r  r  r  r  r   KEYBOARD_OPTION_YESKEYBOARD_OPTION_NOrG  r=  KEYBOARD_OPTION_BACKr   rY  rq   rg  rw  tupler}  r  r  r  r  r   r   r`   r6   r4   <module>r     s      				                                      O N N N N N N N N N N N * * * * * * 2 2 2 2 2 2     # # # # # # # # # # # # ! ! ! ! ! ! ) ) ) ) ) ) = = = = = =       9 9 9 9 9 9 7 7 7 7 7 7 E E E E E E 1 1 1 1 1 1 9 9 9 9 9 9 9 9 9 9 9 9 ) ) ) ) ) ) < < < < < < , , , , , , N N N N N N N N> > >L<U > > > >&     "	Cc 	Cc 	C 	C 	C 	C NS$ $$$'$FJ$$ $ $ $4 ##'!%/304" d d4>"d&d d 	d
 4jd d )-d %)Id d d d d D d d d dP #	$3 $3$3$3 $3 	$3
 	4Z$3 $3 $3 $3T %)!!%#-!%)(,##'!%!&/3%)04/3" "  #).#Ge e&e
e e 3Y	e
 4>"e e e e e e e e e e #e  "&!e" #e$ 4j%e& 'e( )e* )-+e, -e. 6l/e0 %)I1e2 3e4 )-5e6 7e8 9e: ;e< =e> ?e@ AeB CeD #'EeF GeH t^Ie e e eR -1AD[H HH&)H>AHH H H H< #%)!!%#!-(,$+0##'!%!&/3'+ ,0',).).#A} }&}} } 3Y	}
 } 4>"} } } } } } } } } }  "&!}" #}$ %)%}& '}( 4j)}* +}, -}. )-/}0 %1}2 3}4 y/5}6 !%7}8 9}: #';}< #'=}> ?}B t^C} } } }F
 %)-!%)$+/##'!!%%) /3#).)[
 [
&[

[
 [
 3Y	[

 4>"[
 [
 [
 #[
 [
 %)[
 [
 4j[
 [
 [
 [
  6l![
" #[
$ )-%[
& '[
( #')[
* +[
 [
 [
 [
|".&".06".?CDT?U".	". ". ". ".JS T    .s .# .# . . . .D D D D D D! ! ! ! ! ! T
  PX    $ /-+3!%$#!& %!&!%$##'%)$(3r r
rr r 	r
 r r r r r r r r r r r  !r" #r$ #Y%r& 'r( )r* 4j+r, c-r. S	/r0 1r2 3r4 
(^5r r r rn  $0_ __9_ _ 	_
 _ _ _ _ _ _F )-  'X 'X'X&'X 3Y'X 	'X
 'X 'X 'X 'X 'XTv -    4D D D D D D VZ6 6
*6%+6FJ6l66 6 6 6:JD JH JtUY[_O_I` J J J J6U U\6 Uc U6 U U U U"V     ( !	% %%% % 	%
 	% % % %Pv )d2B    . -1  )   :) g      r6   