§
    ‰eîi]$  ã                  ó"  — U d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	 ddl
Z
 ej        e¦  «        ZdZdZdedd	œi d
œdedd	œddid
œgZded<   dgZded<   d.d/d„Z G d„ de
j        ¦  «        Zd0d„Zd1d„Zd2d„Zd3d#„Zd4d$„Zd5d)„Zd6d-„ZdS )7aY  Telegram-specific network helpers.

Provides a hostname-preserving fallback transport for networks where
api.telegram.org resolves to an endpoint that is unreachable from the current
host. The transport keeps the logical request host and TLS SNI as
api.telegram.org while retrying the TCP connection against one or more fallback
IPv4 addresses.
é    )ÚannotationsN)ÚIterableÚOptionalzapi.telegram.orgg      @zhttps://dns.google/resolveÚA)ÚnameÚtype)ÚurlÚparamsÚheadersz$https://cloudflare-dns.com/dns-queryÚAcceptzapplication/dns-jsonz
list[dict]Ú_DOH_PROVIDERSz149.154.167.220ú	list[str]Ú_SEED_FALLBACK_IPSÚreturnú
str | Nonec                ó(   — ddl m}  |d| ¬¦  «        S )Nr   )Úresolve_proxy_urlÚTELEGRAM_PROXY©Útarget_hosts)Úgateway.platforms.baser   )r   r   s     úD/home/div/.hermes/hermes-agent/gateway/platforms/telegram_network.pyÚ_resolve_proxy_urlr   .   s+   € à8Ð8Ð8Ð8Ð8Ð8ØÐÐ-¸LÐIÑIÔIÐIó    c                  ó*   — e Zd ZdZdd„Zdd	„Zdd„ZdS )ÚTelegramFallbackTransportad  Retry Telegram Bot API requests via fallback IPs while preserving TLS/SNI.

    Requests continue to target https://api.telegram.org/... logically, but on
    connect failures the underlying TCP connection is retried against a known
    reachable IP. This is effectively the programmatic equivalent of
    ``curl --resolve api.telegram.org:443:<ip>``.
    Úfallback_ipsúIterable[str]c                ó^  ‡— d„ t                                t          |¦  «        ¦  «        D ¦   «         | _        t	          t
          g| j        ¢¬¦  «        }|r	d‰vr|‰d<   t          j        di ‰¤Ž| _        ˆfd„| j        D ¦   «         | _	        d | _
        t          j        ¦   «         | _        d S )Nc                ó   — g | ]}|‘ŒS © r!   )Ú.0Úips     r   ú
<listcomp>z6TelegramFallbackTransport.__init__.<locals>.<listcomp>>   s   € Ð`Ð`Ð` R˜bÐ`Ð`Ð`r   r   Úproxyc                ó4   •— i | ]}|t          j        d i ‰¤Ž“ŒS )r!   )ÚhttpxÚAsyncHTTPTransport)r"   r#   Útransport_kwargss     €r   ú
<dictcomp>z6TelegramFallbackTransport.__init__.<locals>.<dictcomp>C   s:   ø€ ð 
ð 
ð 
ØACˆB•Ô(Ð<Ð<Ð+;Ð<Ð<ð
ð 
ð 
r   r!   )ÚdictÚfromkeysÚ_normalize_fallback_ipsÚ_fallback_ipsr   Ú_TELEGRAM_API_HOSTr'   r(   Ú_primaryÚ
_fallbacksÚ
_sticky_ipÚasyncioÚLockÚ_sticky_lock)Úselfr   r)   Ú	proxy_urls     ` r   Ú__init__z"TelegramFallbackTransport.__init__=   sÌ   ø€ Ø`Ð`­4¯=ª=Õ9PÐQ]Ñ9^Ô9^Ñ+_Ô+_Ð`Ñ`Ô`ˆÔÝ&Õ5GÐ4]È$ÔJ\Ð4]Ð^Ñ^Ô^ˆ	Øð 	2˜Ð(8Ð8Ð8Ø(1Ð˜WÑ%ÝÔ0ÐDÐDÐ3CÐDÐDˆŒð
ð 
ð 
ð 
ØGKÔGYð
ñ 
ô 
ˆŒð *.ˆŒÝ#œL™NœNˆÔÐÐr   Úrequestúhttpx.Requestr   úhttpx.Responsec           	   ƒ  óˆ  K  — |j         j        t          k    s| j        s | j                             |¦  «        ƒ d {V —†S | j        }|r|gnd g}| j        D ]}||k    r|                     |¦  «         Œd }|D �]8}|€|nt          ||¦  «        }|€| j        n| j	        |         }	 |                     |¦  «        ƒ d {V —†}|�i| j        |k    r^| j
        4 ƒd {V —† | j        |k    r"|| _        t                               d|¦  «         d d d ¦  «        ƒd {V —† n# 1 ƒd {V —†swxY w Y   |c S # t          $ ru}	|	}t          |	¦  «        s‚ |€:t                               d|	d                     | j        ¦  «        ¦  «         Y d }	~	�Œt                               d||	¦  «         Y d }	~	�Œ2d }	~	ww xY w|€t!          d¦  «        ‚|‚)NzQ[Telegram] Primary api.telegram.org path unreachable; using sticky fallback IP %szR[Telegram] Primary api.telegram.org connection failed (%s); trying fallback IPs %sú, z$[Telegram] Fallback IP %s failed: %sz=All Telegram fallback IPs exhausted but no error was recorded)r	   Úhostr/   r.   r0   Úhandle_async_requestr2   ÚappendÚ_rewrite_request_for_ipr1   r5   ÚloggerÚwarningÚ	ExceptionÚ_is_retryable_connect_errorÚjoinÚRuntimeError)
r6   r9   Ú	sticky_ipÚattempt_orderr#   Ú
last_errorÚ	candidateÚ	transportÚresponseÚexcs
             r   r?   z.TelegramFallbackTransport.handle_async_requestI   s·  è è € ØŒ;ÔÕ1Ò1Ð1¸Ô9KÐ1Øœ×;Ò;¸GÑDÔDÐDÐDÐDÐDÐDÐDÐDà”Oˆ	Ø<EÐ-Q¨i¨[¨[ÈDÈ6ˆØÔ$ð 	)ð 	)ˆBØ�YŠˆØ×$Ò$ RÑ(Ô(Ð(øà'+ˆ
Øð 	ñ 	ˆBØ#% :˜˜Õ3JÈ7ÐTVÑ3WÔ3WˆIØ)+¨˜œ˜¸¼ÈÔ9LˆIðØ!*×!?Ò!?À	Ñ!JÔ!JÐJÐJÐJÐJÐJÐJ�Ø�> d¤o¸Ò&;Ð&;Ø#Ô0ð ð ð ð ð ð ð ð Øœ?¨bÒ0Ð0Ø.0˜DœOÝ"ŸNšNØ sØ "ñô ð ðð ð ñ ô ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð øøøð ð ð ð ð  ���øÝð ð ð Ø �
Ý2°3Ñ7Ô7ð ØØ�:Ý—N’NØlØØŸ	š	 $Ô"4Ñ5Ô5ñô ð ð
 �H�H�H‘HÝ—’ÐEÀrÈ3ÑOÔOÐOØ���‘øøøøðøøøð ÐÝÐ^Ñ_Ô_Ð_ØÐsC   Â%5D/Ã.DÄD/Ä
D$	Ä$D/Ä'D$	Ä(D/Ä/
F.Ä9AF)ÆF)Æ)F.ÚNonec              ƒ  ó´   K  — | j                              ¦   «         ƒ d {V —† | j                             ¦   «         D ]}|                     ¦   «         ƒ d {V —† Œd S ©N)r0   Úacloser1   Úvalues)r6   rL   s     r   rR   z TelegramFallbackTransport.acloset   sz   è è € ØŒm×"Ò"Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$Øœ×/Ò/Ñ1Ô1ð 	%ð 	%ˆIØ×"Ò"Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$Ð$ð	%ð 	%r   N)r   r   )r9   r:   r   r;   )r   rO   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r8   r?   rR   r!   r   r   r   r   4   s[   € € € € € ðð ð
+ð 
+ð 
+ð 
+ð)ð )ð )ð )ðV%ð %ð %ð %ð %ð %r   r   rS   r   c                óà  — g }| D ]è}t          |¦  «                             ¦   «         }|sŒ&	 t          j        |¦  «        }n+# t          $ r t
                               d|¦  «         Y Œcw xY w|j        dk    rt
                               d|¦  «         ŒŽ|j        s|j	        s|j
        s|j        rt
                               d|¦  «         ŒÆ|                     t          |¦  «        ¦  «         Œé|S )Nz)Ignoring invalid Telegram fallback IP: %ré   z*Ignoring non-IPv4 Telegram fallback IP: %sz2Ignoring private/internal Telegram fallback IP: %s)ÚstrÚstripÚ	ipaddressÚ
ip_addressÚ
ValueErrorrB   rC   ÚversionÚ
is_privateÚis_loopbackÚis_link_localÚis_unspecifiedr@   )rS   Ú
normalizedÚvalueÚrawÚaddrs        r   r-   r-   z   s  € Ø€JØð %ð %ˆÝ�%‰jŒj×ÒÑ Ô ˆØð 	Øð	ÝÔ'¨Ñ,Ô,ˆDˆDøÝð 	ð 	ð 	Ý�NŠNÐFÈÑLÔLÐLØˆHð	øøøð Œ<˜1ÒÐÝ�NŠNÐGÈÑMÔMÐMØØŒ?ð 	˜dÔ.ð 	°$Ô2Dð 	ÈÔH[ð 	Ý�NŠNÐOÐQTÑUÔUÐUØØ×Ò�#˜d™)œ)Ñ$Ô$Ð$Ð$ØÐs   ¬AÁ%A)Á(A)re   c                óf   — | sg S d„ |                       d¦  «        D ¦   «         }t          |¦  «        S )Nc                ó6   — g | ]}|                      ¦   «         ‘ŒS r!   )r[   )r"   Úparts     r   r$   z)parse_fallback_ip_env.<locals>.<listcomp>’   s    € Ð7Ð7Ð7˜dˆT�ZŠZ‰\Œ\Ð7Ð7Ð7r   Ú,)Úsplitr-   )re   Úpartss     r   Úparse_fallback_ip_envrn   �   s<   € Øð Øˆ	Ø7Ð7 e§k¢k°#Ñ&6Ô&6Ð7Ñ7Ô7€EÝ" 5Ñ)Ô)Ð)r   úset[str]c                 ó¢   — 	 t          j        t          dt           j        ¦  «        } d„ | D ¦   «         S # t          $ r t          ¦   «         cY S w xY w)zJReturn the IPv4 addresses that the OS resolver gives for api.telegram.org.i»  c                ó*   — h | ]}|d          d         ’ŒS )rY   r   r!   )r"   rg   s     r   ú	<setcomp>z&_resolve_system_dns.<locals>.<setcomp>š   s    € Ð/Ð/Ð/˜t��Q”˜”
Ð/Ð/Ð/r   )ÚsocketÚgetaddrinfor/   ÚAF_INETrD   Úset)Úresultss    r   Ú_resolve_system_dnsrx   –   sZ   € ðÝÔ$Õ%7¸½f¼nÑMÔMˆØ/Ð/ wÐ/Ñ/Ô/Ð/øÝð ð ð Ý‰uŒuˆˆˆðøøøs   ‚03 ³AÁAÚclientúhttpx.AsyncClientÚproviderr+   c              ƒ  ó`  K  — 	 |                       |d         |d         |d         ¬¦  «        ƒ d{V —†}|                     ¦   «          |                     ¦   «         }g }|                      dg ¦  «        D ]~}|                      d¦  «        dk    rŒ|                      d	d
¦  «                             ¦   «         }	 t	          j        |¦  «         |                     |¦  «         Œo# t          $ r Y Œ{w xY w|S # t          $ r.}t           
                    d|d         |¦  «         g cY d}~S d}~ww xY w)z/Query one DoH provider and return A-record IPs.r	   r
   r   )r
   r   NÚAnswerr   é   ÚdataÚ zDoH query to %s failed: %s)ÚgetÚraise_for_statusÚjsonr[   r\   r]   r@   r^   rD   rB   Údebug)ry   r{   Úrespr   ÚipsÚanswerrf   rN   s           r   Ú_query_doh_providerrˆ   Ÿ   sg  è è € ðØ—Z’ZØ�UŒO H¨XÔ$6ÀÈÔ@Sð  ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
ˆð 	×ÒÑÔÐØ�yŠy‰{Œ{ˆØˆØ—h’h˜x¨Ñ,Ô,ð 	ð 	ˆFØ�zŠz˜&Ñ!Ô! QÒ&Ð&ØØ—*’*˜V RÑ(Ô(×.Ò.Ñ0Ô0ˆCðÝÔ$ SÑ)Ô)Ð)Ø—
’
˜3‘”��øÝð ð ð Ø�ðøøøàˆ
øÝð ð ð Ý�ŠÐ1°8¸E´?ÀCÑHÔHÐHØˆ	ˆ	ˆ	ˆ	ˆ	ˆ	øøøøðøøøsB   „B4C5 Â9)C#Ã"C5 Ã#
C0Ã-C5 Ã/C0Ã0C5 Ã5
D-Ã?#D(Ä"D-Ä(D-c               ƒ  óà  ‡
K  — t          j        t          j        t          ¦  «        ¬¦  «        4 ƒd{V —†Š
ˆ
fd„t          D ¦   «         } t          j        t          ¦  «        }t          j        |g| ¢R ddiŽƒ d{V —†}ddd¦  «        ƒd{V —† n# 1 ƒd{V —†swxY w Y   t          |d         t          ¦  «        r|d         nt          ¦   «         }g }|dd…         D ],}t          |t          ¦  «        r|                     |¦  «         Œ-t          ¦   «         }g }|D ]4}||vr.||vr*|                     |¦  «         |                     |¦  «         Œ5t          |¦  «        }	|	r0t                                dd	                     |	¦  «        ¦  «         |	S t                                d
d	                     |¦  «        pdd	                     t(          ¦  «        ¦  «         t          t(          ¦  «        S )a<  Auto-discover Telegram API IPs via DNS-over-HTTPS.

    Resolves api.telegram.org through Google and Cloudflare DoH, collects all
    unique IPs, and excludes the system-DNS-resolved IP (which is presumably
    unreachable on this network).  Falls back to a hardcoded seed list when DoH
    is also unavailable.
    )ÚtimeoutNc                ó0   •— g | ]}t          ‰|¦  «        ‘ŒS r!   )rˆ   )r"   Úpry   s     €r   r$   z)discover_fallback_ips.<locals>.<listcomp>Â   s$   ø€ ÐLÐLÐL¸Õ(¨°Ñ3Ô3ÐLÐLÐLr   Úreturn_exceptionsTr   r~   z,Discovered Telegram fallback IPs via DoH: %sr=   zMDoH discovery yielded no new IPs (system DNS: %s); using seed fallback IPs %sÚunknown)r'   ÚAsyncClientÚTimeoutÚ_DOH_TIMEOUTr   r3   Ú	to_threadrx   ÚgatherÚ
isinstancerv   ÚlistÚextendÚaddr@   r-   rB   r„   rF   Úinfor   )Ú	doh_tasksÚsystem_dns_taskrw   Ú
system_ipsÚdoh_ipsÚrÚseenÚ
candidatesr#   Ú	validatedry   s             @r   Údiscover_fallback_ipsr¡   ¹   sš  øè è € õ Ô ­¬µ|Ñ)DÔ)DÐEÑEÔEð \ð \ð \ð \ð \ð \ð \ÈØLÐLÐLÐL½^ÐLÑLÔLˆ	Ý!Ô+Õ,?Ñ@Ô@ˆÝœ Ð[¸Ð[Ð[Ð[ÐVZÐ[Ð[Ð[Ð[Ð[Ð[Ð[Ð[ˆð\ð \ð \ñ \ô \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \ð \øøøð \ð \ð \ð \õ *4°G¸A´JÅÑ)DÔ)DÐO˜7 1œ:˜:Í#É%Ì%€Jà€GØ�Q�R�RŒ[ð ð ˆÝ�a�ÑÔð 	Ø�NŠN˜1ÑÔÐøõ ‘U”U€DØ€JØð "ð "ˆØ�Tˆ>ˆ>˜b¨
Ð2Ð2Ø�HŠH�R‰LŒLˆLØ×Ò˜bÑ!Ô!Ð!øõ (¨
Ñ3Ô3€Iàð Ý�ŠÐCÀTÇYÂYÈyÑEYÔEYÑZÔZÐZØÐå
‡K‚KØWØ�	Š	�*ÑÔÐ* Ø�	Š	Õ$Ñ%Ô%ñô ð õ
 Õ"Ñ#Ô#Ð#s   ¶ABÂ
BÂBr9   r:   r#   rZ   c                ó  — | j         j        pt          }| j                              |¬¦  «        }| j                             ¦   «         }||d<   t          | j        ¦  «        }||d<   t          j	        | j
        ||| j        |¬¦  «        S )N)r>   r>   Úsni_hostname)Úmethodr	   r   ÚstreamÚ
extensions)r	   r>   r/   Ú	copy_withr   Úcopyr+   r¦   r'   ÚRequestr¤   r¥   )r9   r#   Úoriginal_hostr	   r   r¦   s         r   rA   rA   å   sŒ   € Ø”KÔ$Ð:Õ(:€MØ
Œ+×
Ò
 RÐ
Ñ
(Ô
(€CØŒo×"Ò"Ñ$Ô$€GØ#€GˆF�OÝ�gÔ(Ñ)Ô)€JØ!.€Jˆ~ÑÝŒ=ØŒ~ØØØŒ~Øðñ ô ð r   rN   rD   Úboolc                óN   — t          | t          j        t          j        f¦  «        S rQ   )r”   r'   ÚConnectTimeoutÚConnectError)rN   s    r   rE   rE   õ   s   € Ý�c�EÔ0µ%Ô2DÐEÑFÔFÐFr   rQ   )r   r   )rS   r   r   r   )re   r   r   r   )r   ro   )ry   rz   r{   r+   r   r   )r   r   )r9   r:   r#   rZ   r   r:   )rN   rD   r   r«   )rW   Ú
__future__r   r3   r\   Úloggingrs   Útypingr   r   r'   Ú	getLoggerrT   rB   r/   r‘   r   Ú__annotations__r   r   ÚAsyncBaseTransportr   r-   rn   rx   rˆ   r¡   rA   rE   r!   r   r   ú<module>rµ      sò  ððð ð ð #Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ø €€€Ø €€€Ø %Ð %Ð %Ð %Ð %Ð %Ð %Ð %à €€€à	ˆÔ	˜8Ñ	$Ô	$€à'Ð ð €ð ,Ø-°sÐ;Ð;Øðð ð 6Ø-°sÐ;Ð;ØÐ4Ð5ðð ð€ð ð ð ñ ð "3Ð 3Ð Ð 3Ð 3Ð 3Ñ 3ðJð Jð Jð Jð JðC%ð C%ð C%ð C%ð C% Ô 8ñ C%ô C%ð C%ðLð ð ð ð**ð *ð *ð *ðð ð ð ðð ð ð ð4)$ð )$ð )$ð )$ðXð ð ð ð Gð Gð Gð Gð Gð Gr   