
    sojL                        U d Z 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mZ ddlmZ ddlmZ  ej        e          Zi Zeeef         ed<   d5d
ZdefdZded	dfdZd Z G d d          Zd6deded	efdZ d	e!fdZ"ded	efdZ# G d d          Z$ G d d          Z% G d d          Z& G d d          Z' G d d           Z( G d! d"          Z) G d# d$e)          Z*d	e)fd%Z+d& Z, G d' d(          Z G d) d*          Z- G d+ d,          Z. G d- d.          Z/ G d/ d0          Z0 G d1 d2          Z1 G d3 d4          Z2dS )7a  
Drop-in replacements for the ``telegram`` types used across the codebase
(``Update``, ``Message``, ``Chat``, ``User``, keyboard classes, media types,
etc). Every one of these is a plain Python object - no Telethon network calls
happen in ``__init__``; async operations (leaving a chat, checking admin
status, downloading a profile photo...) are implemented as async methods that
use the Telethon client stashed on the object at construction time.

This module is intentionally *not* a complete reimplementation of PTB's
``telegram`` package - it implements exactly the surface area exercised by
this codebase (see MIGRATION_NOTES.md for how that surface was audited).
    N)ChannelChatUserChatParticipantCreatorChatParticipantAdminChannelParticipantsAdmins)GetFullChatRequest   )
BadRequest)ChatMemberStatus_access_hash_cachereturnc                 n    t          | dd          }t          | dd          }|||t          |<   dS dS dS )a  
    Record a user's access_hash, if the given raw Telethon entity carries one
    (real ``User`` objects do; bare ``PeerUser`` stubs don't). Called from
    every place in this compat layer that observes a user entity (incoming
    messages, callback queries, chat member lookups, ...), so that by the
    time we need to @mention someone, we have the best possible chance of
    already knowing their access_hash - constructing a mention requires it,
    and Telegram only hands it to a bot the first time that bot "encounters"
    the user (a message, a shared chat, ...); this cache is what makes that
    encounter durable across the whole bot rather than scoped to wherever it
    happened to occur.
    idNaccess_hash)getattrr   )entityuser_idr   s      /app/src/tg_compat/_types.pyremember_access_hashr   +   sP     fdD))G&-66K{6&17### 66    r   c                 6    t                               |           S N)r   get)r   s    r   get_cached_access_hashr   >   s    !!'***r   c                    K   t          |          dS 	 |                     |           d{V }t          |           dS # t          $ r Y dS w xY w)a  
    Best-effort warm-up before sending a brand-new message directly to a
    user by ID - e.g. notification_service.py's proactive notifications,
    which aren't a reply to anything the user just did. Mirrors
    _mentions.py's resolve_mentions (cache check, then a live get_entity()
    fallback that also populates the cache for next time), just for "send
    to this user" instead of "reference this user inside message text".

    Deliberately swallows every exception here: this is purely a
    best-effort attempt to warm the cache before the real send, not a
    resolvability gate. A mention can gracefully degrade to plain bold
    text when a user turns out to be unresolvable; a message send can't -
    there's nothing to degrade *to*. So if this lookup fails, it's left to
    the send call right after it to raise its own, already-correctly-typed
    error (translate_errors turns Telethon's PeerIdInvalidError into this
    codebase's own BadRequest, which callers already know how to handle -
    see notification_service.py's send_notification_execute) rather than
    this raising a *different*, un-typed exception (e.g. a bare ValueError
    from get_entity() finding nothing locally) that those existing
    handlers wouldn't recognize.
    N)r   
get_entityr   	Exception)clientr   r   s      r   ensure_resolvable_peerr    B   s{      , g&&2((11111111V$$$$$   s   *A 
AAc                     t          | t                    rJ|                                 }|                    d                                          rt          |          S | S )a	  
    Business logic throughout this codebase passes chat/user ids as *either*
    int or str pretty much interchangeably (e.g. `chat_id: int | str` is the
    documented signature of message_service.py's full_message_send, and
    `group.tg_group_id`/`user.tg_user_id` are stored as string columns and
    frequently passed straight through). Bot API's HTTP/JSON transport
    didn't care either way, but Telethon's entity resolution does: given a
    bare numeric *string* (as opposed to an int), it doesn't recognize it as
    "just an ID" - it tries to resolve it the way a user account would
    (username, phone number, etc.), and a bot account is forbidden from
    doing that kind of contact/phone lookup at all, so it fails with
    BotMethodInvalidError wrapped in a confusing ValueError.

    Coerce any string that's actually just a plain (optionally negative)
    integer into a real int; leave anything else (usernames, already-
    resolved entities, None) untouched - Telethon handles those correctly
    already.
    -)
isinstancestrstriplstripisdigitint)valuestrippeds     r   coerce_peerr+   a   sT    & % !;;==??3'')) 	!x== Lr   c                       e Zd ZdZ	 	 	 	 	 	 ddedededed	ef
d
Zedefd            Z	e
ddd            ZddeddfdZd ZdS )TelegramUserz@Mirrors telegram.User (only the attributes this codebase reads).F Nr   is_bot
first_name	last_nameusernamec                 h    || _         || _        || _        || _        || _        || _        || _        d S r   r   r/   r0   r1   r2   _entity_client)selfr   r/   r0   r1   r2   r5   r6   s           r   __init__zTelegramUser.__init__   s9     $" r   r   c                 h    | j         r#| j         d| j                                          S | j        pdS )N r.   )r1   r0   r%   r7   s    r   	full_namezTelegramUser.full_name   s>    > 	Ao8888>>@@@$"$r   c                     |d S t          |            | |j        t          t          |dd                    t          |dd           pdt          |dd           t          |dd           ||          S )NbotFr0   r.   r1   r2   r4   )r   r   boolr   )clsr   r   s      r   from_entityzTelegramUser.from_entity   s    >4V$$$syu5566v|T::@bfk488VZ66
 
 
 	
r   d   limitUserProfilePhotosc                     K   ddl m}  | j                             j        p j        |                     d{V } j        p j         fd|D             }t          t          |          |          S )zGMirrors telegram.User.get_profile_photos / Bot.get_user_profile_photos.r
   translate_errors)rC   Nc                 @    g | ]}t          |j                   gS )owner_entity)	PhotoSizer6   ).0pownerr7   s     r   
<listcomp>z3TelegramUser.get_profile_photos.<locals>.<listcomp>   s-    SSSq9Q5AAABSSSr   total_countphotos)_errorsrG   r6   get_profile_photosr5   r   rD   len)r7   rC   rG   rR   groupsrN   s   `    @r   rT   zTelegramUser.get_profile_photos   s      ------''(G(GH_X\X_gl(G(m(mnnnnnnnn 'SSSSSFSSS S[[HHHHr   c                 (    d| j          d| j        dS )NzTelegramUser(id=z, username=))r   r2   r;   s    r   __repr__zTelegramUser.__repr__   s    H$'HHdmHHHHr   )Fr.   NNNNr   )r   r-   )rB   )__name__
__module____qualname____doc__r(   r?   r$   r8   propertyr<   classmethodrA   rT   rY    r   r   r-   r-      s       JJ
    	
     $ %3 % % % X%
 
 
 
 
 [
I Ic I<O I I I II I I I Ir   r-   kindfallback_pathc                 0   | |j         |j        t          j        |j                                      d          |j        d}|r||d<   dt          j        t          j        |          	                    d                                        d          z   S )a  
    Encode a Telethon Photo/Document object into an opaque string, mirroring
    the role of a Bot API file_id: a compact, reusable reference that lets us
    resend the same media later without re-uploading it.

    Unlike Bot API file_ids, MTProto file references expire after a while;
    the encoded fallback_path (if given) lets the sending code transparently
    fall back to a fresh upload if the cached reference has expired. See
    MIGRATION_NOTES.md ("Media re-use / file_id caching") for details.
    ascii)kr   ahfrdcfptgcref1:utf-8)
r   r   base64	b64encodefile_referencedecodedc_idjsondumpsencode)ra   tl_mediarb   payloads       r   _encode_media_refrv      s     k"x677>>wGGn G  &%(G)<)<)C)CG)L)LMMTTU\]]]]r   c                 V    t          | t                    o|                     d          S )Nrj   )r#   r$   
startswithr)   s    r   is_media_refrz      s%    eS!!Be&6&6z&B&BBr   r)   c                     t          j        t          j        | t	          d          d                                        d                    S )Nrj   rk   )rq   loadsrl   	b64decoderU   ro   ry   s    r   decode_media_refr~      s<    :f&uS__->->'?@@GGPPQQQr   c                   J    e Zd ZdZd
defdZedefd            ZddZd	 Z	dS )rK   z:Mirrors telegram.PhotoSize. Wraps a Telethon Photo object.Nrb   c                 j    || _         || _        || _        || _        t	          |dd           | _        d S Nsize)	_tl_photor6   _fallback_path_owner_entityr   	file_size)r7   tl_photor   rb   rJ   s        r   r8   zPhotoSize.__init__   s7    !+) 6488r   r   c                 8    t          d| j        | j                  S )Nphoto)rv   r   r   r;   s    r   file_idzPhotoSize.file_id   s     $.$:MNNNr   Filec                 H   K   t          | j        | j        | j                  S )NrI   )r   r   r6   r   r;   s    r   get_filezPhotoSize.get_file   s"      DNDLt?QRRRRr   c                     dS Nr
   r`   r;   s    r   __len__zPhotoSize.__len__   s	     qr   )NNNr   r   
rZ   r[   r\   r]   r$   r8   r^   r   r   r   r`   r   r   rK   rK      s        DD9 9S 9 9 9 9 O O O O XOS S S S    r   rK   c                   J    e Zd ZdZd
defdZedefd            ZddZd	 Z	dS )VideozAMirrors telegram.Video. Wraps a Telethon Document (video) object.Nrb   c                 \    || _         || _        || _        t          |dd           | _        d S r   _tl_documentr6   r   r   r   r7   tl_documentr   rb   s       r   r8   zVideo.__init__   0    '+ fd;;r   r   c                 8    t          d| j        | j                  S )Nvideorv   r   r   r;   s    r   r   zVideo.file_id  s     $*;T=PQQQr   r   c                 :   K   t          | j        | j                  S r   r   r   r6   r;   s    r   r   zVideo.get_file        D%t|444r   c                     dS r   r`   r;   s    r   r   zVideo.__len__      qr   NNr   r   r`   r   r   r   r      s        KK< < < < < < R R R R XR5 5 5 5    r   r   c                   J    e Zd ZdZd
defdZedefd            ZddZd	 Z	dS )	AnimationzCMirrors telegram.Animation. Wraps a Telethon Document (gif) object.Nrb   c                 \    || _         || _        || _        t          |dd           | _        d S r   r   r   s       r   r8   zAnimation.__init__  r   r   r   c                 8    t          d| j        | j                  S )N	animationr   r;   s    r   r   zAnimation.file_id  s     d.?ATUUUr   r   c                 :   K   t          | j        | j                  S r   r   r;   s    r   r   zAnimation.get_file  r   r   c                     dS r   r`   r;   s    r   r   zAnimation.__len__  r   r   r   r   r   r`   r   r   r   r     s        MM< < < < < < V V V V XV5 5 5 5    r   r   c                   "    e Zd ZdZddZddZdS )r   zMirrors telegram.File.Nc                 0    || _         || _        || _        d S r   )	_tl_mediar6   r   )r7   rt   r   rJ   s       r   r8   zFile.__init__#  s     ! *r   c                    K   ddl m} | j        1 || j                            | j        |d                     d {V S  || j                            | j        |                     d {V S )Nr
   rF   T)filedownload_big)r   )rS   rG   r   r6   download_profile_photodownload_mediar   )r7   custom_pathrG   s      r   download_to_drivezFile.download_to_drive*  s      ------) *)33&[t 4           &%dl&A&A$.Wb&A&c&cdddddddddr   r   r   )rZ   r[   r\   r]   r8   r   r`   r   r   r   r      sH          * * * *e e e e e er   r   c                       e Zd ZdZdefdZdS )rD   z#Mirrors telegram.UserProfilePhotos.rQ   c                 "    || _         || _        d S r   rP   )r7   rQ   rR   s      r   r8   zUserProfilePhotos.__init__B  s    &r   N)rZ   r[   r\   r]   r(   r8   r`   r   r   rD   rD   ?  s5        --C      r   rD   c                   (    e Zd ZdZddededefdZdS )
ChatMemberz#Mirrors telegram.ChatMember (base).Nuserstatuscustom_titlec                 0    || _         || _        || _        d S r   r   r   r   )r7   r   r   r   s       r   r8   zChatMember.__init__O  s    	(r   r   )rZ   r[   r\   r]   r-   r$   r8   r`   r   r   r   r   L  sH        --) )\ )3 )c ) ) ) ) ) )r   r   c                   .     e Zd ZdZddedef fdZ xZS )ChatMemberAdministratorz)Mirrors telegram.ChatMemberAdministrator.Nr   r   c                 d    t                                          |t          j        |           d S )Nr   )superr8   r   ADMINISTRATOR)r7   r   r   	__class__s      r   r8   z ChatMemberAdministrator.__init__X  s-    d+;+IXdeeeeer   r   )rZ   r[   r\   r]   r-   r$   r8   __classcell__)r   s   @r   r   r   U  sc        33f f\ f f f f f f f f f f fr   r   c                 "  K   ddl m} t          |          }t          |          } ||                     |                     d{V }t                              ||           }	  ||                     ||                     d{V }n+# t          $ r t          |t          j
                  cY S w xY wt          |dd          rt          j        }n*t          |dd          rt          j        }nt          j        }t          ||          S )zResolve a single chat member's status. Never raises for "not currently
    a member" - both LEFT and BANNED collapse to LEFT, matching how this
    codebase's user_is_chat_member() treats them identically anyway.r
   rF   N)r   r   
is_creatorFis_admin)rS   rG   r+   r   r-   rA   get_permissionsr   r   r   LEFTr   OWNERr   MEMBER)r   chat_entityr   rG   user_entityr   permsr   s           r   _get_chat_memberr   \  sH      *)))))k**K'""G(():):7)C)CDDDDDDDDK##K88DC&&v'='=k7'S'STTTTTTTT C C Ct,<,ABBBBBBC ulE** )!'	
E	*	* )!/!(4////s   '%B %B54B5c           	        K   ddl m} t          |          }t          |t          t
          t          f          s$ ||                     |                     d{V }g }t          |t                    r ||                     |t                                           d{V }|D ]e}t          |dd          }|t          |dd          nd}|                    t          t                              ||           |                     f|S  | | t          |j                                       d{V }	t#                      }
t          |	j        j        d	g           D ]8}t          |t(          t*          f          r|
                    |j                   9d
 |	j        D             }|
D ]U}|                    |          }|<|                    t          t                              ||                                V|S )zReturns a list of ChatMemberAdministrator for the given chat. For
    basic (non-super) groups, falls back to inspecting the full chat's
    participant list since ChannelParticipantsAdmins only applies to
    channels/supergroups.r
   rF   N)filterparticipantrank)r   r   )chat_idparticipantsc                     i | ]
}|j         |S r`   )r   )rL   us     r   
<dictcomp>z,_get_chat_administrators.<locals>.<dictcomp>  s    ///q14///r   )r   )rS   rG   r+   r#   r   TLChatTLUserr   get_participantsr   r   appendr   r-   rA   r	   r   set	full_chatr   r   r   addr   usersr   )r   r   rG   r   resultadminsr   rawr   full	admin_idsrM   users_by_iduids                 r   _get_chat_administratorsr   v  sY     
 *)))))%%Ffw788 C''(9(9&(A(ABBBBBBBBF&'"" 
''##F3L3N3N#OO
 
 
 
 
 
 
 
  	 	A!]D11C9<73555dLMM'\-E-Ea-P-P_klll     "!&&);FI)N)N)N"O"OPPPPPPPPDIT^0."EE % %a02FGHH 	%MM!)$$$//DJ///K ] ]OOC  =MM1|7O7OPQSY7Z7Z[[[\\\Mr   c                       e Zd ZdZdZdZdZdZ	 	 	 	 	 dded	e	d
e	de	de
f
dZeddedd fd            Zd ZdedefdZd Zd ZdS )r   zMirrors telegram.Chat.privategroup
supergroupchannelNFr   typetitler2   is_forumc                 h    || _         || _        || _        || _        || _        || _        || _        d S r   r   r   r   r2   r   r5   r6   )r7   r   r   r   r2   r   r5   r6   s           r   r8   zChat.__init__  s9     	
  r   r   r   c           
        K   t          |t                    r| j        }d }d}nt          |t                    r;|j        r| j        n| j        }|j        }t          t          |dd                    }n1t          |t                    r| j        }|j        }d}n| j        }d }d}ddlm} ||n|                    |          } | |||t          |dd           |||          S )NFforumr   )utilsr2   r   )r#   r   PRIVATEr   	megagroup
SUPERGROUPCHANNELr   r?   r   r   GROUPtelethonr   get_peer_id)	r@   r   r   r   	chat_typer   r   r   resolved_ids	            r   rA   zChat.from_entity  s     ff%% 	IEHH(( 	*0*:KILEGFGU;;<<HH'' 		ILEHHIEH""""""!(!4gg%:K:KF:S:SsVZ66
 
 
 	
r   c                    K   ddl m}  || j                            | j        p| j                             d {V  d S )Nr
   rF   )rS   rG   r6   delete_dialogr5   r   )r7   rG   s     r   leavez
Chat.leave  sZ      ------t|99$,:Q$'RRSSSSSSSSSSSr   r   c                 V   K   t          | j        | j        p| j        |           d {V S r   )r   r6   r5   r   )r7   r   s     r   
get_memberzChat.get_member  s5      %dlDL4KDGWUUUUUUUUUr   c                 T   K   t          | j        | j        p| j                   d {V S r   )r   r6   r5   r   r;   s    r   get_administratorszChat.get_administrators  s3      -dlDL<SDGTTTTTTTTTr   c                 (    d| j          d| j        dS )NzChat(id=z, type=rX   )r   r   r;   s    r   rY   zChat.__repr__  s    8$'88$)8888r   )NNFNNr   )rZ   r[   r\   r]   r   r   r   r   r(   r$   r?   r8   r_   rA   r  r   r  r  rY   r`   r   r   r   r     s         GEJG    	
     $ 
 
 
v 
 
 
 [
>T T T
V V
 V V V VU U U9 9 9 9 9r   r   c                       e Zd ZdefdZdS )MessageOriginUsersender_userc                     || _         d S r   )r	  )r7   r	  s     r   r8   zMessageOriginUser.__init__      &r   N)rZ   r[   r\   r-   r8   r`   r   r   r  r    s/        'L ' ' ' ' ' 'r   r  c                       e Zd ZdefdZdS )MessageOriginChatsender_chatc                     || _         d S r   )r  )r7   r  s     r   r8   zMessageOriginChat.__init__  r  r   N)rZ   r[   r\   r   r8   r`   r   r   r  r    s/        'D ' ' ' ' ' 'r   r  c                   $    e Zd ZddededefdZdS )MessageOriginChannelNchat
message_idauthor_signaturec                 0    || _         || _        || _        d S r   )r  r  r  )r7   r  r  r  s       r   r8   zMessageOriginChannel.__init__  s    	$ 0r   r   )rZ   r[   r\   r   r(   r$   r8   r`   r   r   r  r    sB        1 1T 1s 1S 1 1 1 1 1 1r   r  c                       e Zd ZddefdZdS )MessageOriginHiddenNsender_user_namec                     || _         d S r   )r  )r7   r  s     r   r8   zMessageOriginHidden.__init__  s     0r   r   )rZ   r[   r\   r$   r8   r`   r   r   r  r     s4        1 1 1 1 1 1 1 1r   r  c                        e Zd ZddedefdZdS )
PollOptionr   textvoter_countc                 "    || _         || _        d S r   )r  r  )r7   r  r  s      r   r8   zPollOption.__init__  s    	&r   N)r   )rZ   r[   r\   r$   r(   r8   r`   r   r   r  r  
  s;        ' 'S 's ' ' ' ' ' 'r   r  c                        e Zd ZddedefdZdS )PollFquestionallows_multiple_answersc                 0    || _         || _        || _        d S r   )r!  optionsr"  )r7   r!  r$  r"  s       r   r8   zPoll.__init__  s     '>$$$r   N)F)rZ   r[   r\   r$   r?   r8   r`   r   r   r   r     s;        ? ? ? ? ? ? ? ? ?r   r   )r   Nr   )3r]   rq   rl   loggingtelethon.tl.typesr   r   r   r   r   r   r   r   telethon.tl.functions.messagesr	   errorr   	constantsr   	getLoggerrZ   loggerr   dictr(   __annotations__r   r   r    r+   r-   r$   rv   r?   rz   r~   rK   r   r   r   rD   r   r   r   r   r  r  r  r  r  r   r`   r   r   <module>r.     su                       > = = = = =       ' ' ' ' ' '		8	$	$ &( DcN ' ' '2 2 2 2&+C + + + +# $    >  >:I :I :I :I :I :I :I :ID^ ^C ^# ^ ^ ^ ^ ^.C4 C C C CRC RD R R R R       .       (       (e e e e e e e e>       ) ) ) ) ) ) ) )f f f f fj f f f0J 0 0 0 04# # #VF9 F9 F9 F9 F9 F9 F9 F9\' ' ' ' ' ' ' '
' ' ' ' ' ' ' '
1 1 1 1 1 1 1 11 1 1 1 1 1 1 1' ' ' ' ' ' ' '? ? ? ? ? ? ? ? ? ?r   