
    `gj3-                    @   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ZddlZ	ddl
mZ ddlmZ ddlZdZdZdZd	Zd
ZdZdZ ej,                  d      Z ed       G d d             Z ed       G d d             Zd&d'dZd(dZd)dZd*dZddd+dZd,d-dZd&d.dZ eddf	 	 	 	 	 	 	 d/dZ!d0dZ"dedf	 	 	 	 	 	 	 d1dZ#	 d2	 	 	 	 	 	 	 d3d Z$	 d2	 	 	 	 	 	 	 d4d!Z%eef	 	 	 	 	 	 	 	 	 d5d"Z&eef	 	 	 	 	 	 	 	 	 d6d#Z'dedef	 	 	 	 	 	 	 	 	 d7d$Z(dedef	 	 	 	 	 	 	 	 	 d8d%Z)y)9a  Telegram Managed Bot onboarding client.

Uses Telegram's Managed Bots feature to create a user-owned child bot without
manual BotFather token copy-paste. Hermes talks only to the Nous onboarding
service; the raw Telegram token is saved locally after one-time retrieval.
    )annotationsN)	dataclass)Optionalz+https://setup.hermes-agent.nousresearch.comTELEGRAM_ONBOARDING_URLHermesSetupBotzHermes Agent       abcdefghijklmnopqrstuvwxyz234567z^\d+:[A-Za-z0-9_-]{30,}$T)frozenc                  R    e Zd ZU dZded<   ded<   ded<   ded<   ded<   dZd	ed
<   y)TelegramPairingz;Pairing record returned by the Telegram onboarding service.str
pairing_id
poll_tokensuggested_username	deep_link
qr_payloadN
str | None
expires_at)__name__
__module____qualname____doc____annotations__r        R/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/telegram_managed_bot.pyr   r   &   s)    EOONO!J
!r   r   c                  8    e Zd ZU dZded<   dZded<   dZded<   y)	TelegramBotSetupResultzDSuccessful Telegram onboarding result returned by the setup service.r   tokenNr   bot_username
int | Noneowner_user_id)r   r   r   r   r   r!   r#   r   r   r   r   r   2   s    NJ#L*# $M:$r   r   c                ~    | xs+ t         j                  j                  t              xs t        j                  d      S )z>Resolve the onboarding API URL, honoring the PoC env override./)osenvirongetTELEGRAM_ONBOARDING_URL_ENVDEFAULT_API_URLrstrip)api_urls    r   _api_urlr-   ;   s-     	Q2::>>"=>Q/fSkr   c                b    t        | t              xr t        t        j	                  |             S )z8Return True when *token* has Telegram's bot-token shape.)
isinstancer   bool_TELEGRAM_BOT_TOKEN_REmatch)r    s    r   is_valid_telegram_bot_tokenr3   B   s%    eS!Od+A+G+G+N&OOr   c                    t        | t              ry t        | t              r	| dkD  r| S d S t        | t              r$| j	                         rt        |       }|dkD  r|S d S y )Nr   )r/   r0   intr   	isdecimal)valueparseds     r   _parse_owner_user_idr9   G   sZ    %%	u+t+%%//"3U!v--r   c                0   	 ddl }ddl}|j                  d|j                  j                  dd      }|j                  |        |j                  d       |j                         }|j                  |d       |j                         S # t        $ r Y yw xY w)	z>Render a URL as a QR code string suitable for terminal output.r   N   )versionerror_correctionbox_sizeborderT)fit)outinvert )ioqrcodeQRCode	constantsERROR_CORRECT_Ladd_datamakeStringIOprint_asciigetvalueImportError)urlrD   rE   qrbufs        r   render_qr_terminalrR   R   s    ]]#--==	  
 	C
Dkkm
3t,||~ s   BB	 		BBinclude_linkc               n    t        |       }|rt        |       nt        d       |rt        d|         yy)zBPrint a QR code to stdout, with URL fallback if qrcode is missing.z@  (Install 'qrcode' for a scannable QR code: pip install qrcode)  Link: N)rR   print)rO   rT   qr_texts      r   print_qr_coderY   i   s6     %GgPQ r   c                D    dj                  d t        |       D              S )zGenerate a base32-ish slug for Telegram username correlation.

    Sixteen characters from a 32-symbol alphabet gives 80 bits of entropy while
    keeping ``hermes_<slug>_bot`` under Telegram's 32-character username limit.
    rC   c              3  N   K   | ]  }t        j                  t                y wN)secretschoice_USERNAME_SLUG_ALPHABET).0_s     r   	<genexpr>z)generate_username_slug.<locals>.<genexpr>z   s     Rq7>>"9:Rs   #%)joinrange)lengths    r   generate_username_slugrf   t   s     77RE&MRRRr   c                "    | }dt                dS )a  Generate a secure suggested bot username like ``hermes_<slug>_bot``.

    ``profile_name`` is accepted for backward compatibility with the original
    PoC, but is intentionally not embedded in the username. The username has to
    carry enough entropy for backend correlation.
    hermes__bot)rf   )profile_namera   s     r   generate_bot_usernamerk   }   s     	A+-.d33r   c                   | j                  d      }|xs
 t               }dt        j                  j	                  |       dt        j                  j	                  |       }|r(t        j                  j                  d|i      }| d| S |S )z;Build a ``t.me/newbot`` deep link for managed bot creation.@zhttps://t.me/newbot/r%   name?)lstriprk   urllibparsequote	urlencode)manager_botr   suggested_namemanagerusernamebase_urlparamss          r   generate_deep_linkr{      s       %G!<%:%<H<<g&
'q<<h'
(	*  ''(@A1VH%%Or   c                 ,    t        j                  d      S )a  Generate a legacy-compatible random nonce string.

    The new protocol uses service-created ``pairing_id`` + bearer
    ``poll_token`` instead of a path nonce, but this helper is harmless and
    still useful for callers/tests that need a generic random id.
       )r]   	token_hexr   r   r   generate_pairing_noncer      s     R  r         $@c                   	 t        j                  t        |        dd|i|      }|j                  dvry|j	                         d}t        fd|D              syj                  d      xs d	   }t        |t              syj                  d
      }t        d   d   d   d	   |t        |t              r|      S d      S # t         j
                  t        f$ r Y yw xY w)zCreate a Telegram onboarding pairing.

    ``POST /v1/telegram/pairings`` returns the deep link, QR payload, public
    pairing id, and secret poll token. The token is only used as a bearer
    credential while polling.
    z/v1/telegram/pairingsbot_name)jsontimeout)      N)r   r   r   r   c              3     K   | ]6  }t        j                  |      t              xr j                  |       8 y wr\   )r/   r(   r   )r`   keydatas     r   rb   z!create_pairing.<locals>.<genexpr>   s0     TCz$((3--?$((3-?Ts   <?r   r   r   r   r   r   )r   r   r   r   r   r   )httpxpostr-   status_coder   	HTTPError
ValueErrorallr(   r/   r   r   )r,   r   r   resprequiredr   r   r   s          @r   create_pairingr      s   
zz !!67h'

 :-yy{ OHT8TT,'<4+<Jj#&,'J%% 45{#!+J!<:  CG  OOZ( s   4C C C)(C)c           	        t        j                  t        |        d|j                   dd|j                   i|      }|j
                  dk7  ry|j                         }|j                  d      dk7  ry|j                  d	      }t        |      sy|j                  d
      }t        |t        |t              r|r|ndt        |j                  d                  S )zDPoll the onboarding service once. Returns setup metadata when ready.z/v1/telegram/pairings/AuthorizationzBearer )headersr   r   Nstatusreadyr    r!   r#   )r    r!   r#   )r   r(   r-   r   r   r   r   r3   r   r/   r   r9   )r,   pairingr   r   r   r    r!   s          r   poll_pairing_result_oncer      s     99G
3G4F4F3GH GG,>,>+?"@AD
 399;DxxW$HHWE&u-88N+L!lC(\ "*488O+DE r   c                >    t        | ||      }|r|j                  S dS )z?Poll the onboarding service once. Returns the token when ready.)r   N)r   r    )r,   r   r   results       r   poll_pairing_oncer      s#     &gwHF!6<<+t+r   c                   t        j                         |z   }t        j                         |k  r?	 t        | |      }|r|S 	 t        j                  |       t        j                         |k  r?y# t        j                  t
        f$ r Y Iw xY w)zBPoll the pairing API until setup metadata is available or timeout.N)time	monotonicr   r   r   r   sleep)r,   r   r   intervaldeadliner   s         r   poll_for_setup_resultr      s     ~~')H
..
X
%	-gw?F  	

8 ..
X
%  , 		s   A/ /B
Bc                @    t        | |||      }|r|j                  S dS )zAPoll the pairing API until the bot token is available or timeout.)r   r   N)r   r    )r,   r   r   r   r   s        r   poll_for_tokenr     s%     #7GWxXF!6<<+t+r   c                   ||f}t        |       }t                t        d|        t        j                  j	                          t        |      }|st        d       t        d       yt        d       t        d       t        j                  j	                          t                t        d       t                t        |j                  d	       t                t        d
|j                          t                t        d       t        d       t                d}t        j                         }||z   }	d}
t        j                         |	k  r||
t        |      z     }t        t        j                         |z
        }t        dt        ||z
              }t        j                  j                  d| d| d       t        j                  j	                          |
dz  }
	 t        ||      }|r?t        j                  j                  d       t        j                  j	                          |S 	 t        j&                  t(               t        j                         |	k  rt        j                  j                  d       t        j                  j	                          t        d       t        d       y# t         j"                  t$        f$ r Y w xY w)z2Run the full automatic Telegram bot creation flow.z1  Contacting Hermes Telegram onboarding service: u=     ✗ Could not reach the Hermes Telegram onboarding service.z8    Try the manual setup instead, or check your network.Nu     ✓ Pairing createdz  Rendering QR code...z<  Scan this QR code with your phone, or open the link below:FrS   rV   z3  When Telegram opens, tap 'Create Bot' to confirm.z7  (You can edit the bot display name before confirming)u   ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏r   z  z Waiting for bot creation... (zs remaining) r;   u?     ✓ Bot created successfully!                              
u?     ✗ Timed out waiting for bot creation.                    
u4       The bot may still be created — check Telegram.z<    You can paste the token manually below, or re-run setup.)r-   rW   sysstdoutflushr   rY   r   r   r   r   lenr5   maxwriter   r   r   r   r   POLL_INTERVAL)r,   ru   rj   poll_timeoutra   resolved_api_urlr   spinner_charsstartr   idxcharelapsed	remainingr   s                  r   auto_setup_telegram_bot_resultr     sJ    	\!A(	G	=>N=O
PQJJ-.GMNHI	
!"	
"#JJ	G	
HI	G'$$59	G	HW&&'
()	G	
?@	
CD	G4MNNE|#H
C
..
X
%S3}#556dnn&./3|g567	

4&6ykO	
 	

q		-.>HF

  W 

  "  	

=!) ..
X
%, JJXYJJ	
@A	
HI , 		s   (AJ< <KKc                @    t        | |||      }|r|j                  S dS )zBRun automatic Telegram bot creation and return only the bot token.)r,   ru   rj   r   N)r   r    )r,   ru   rj   r   r   s        r   auto_setup_telegram_botr   Y  s-     ,!!	F "6<<+t+r   r\   )r,   r   returnr   )r    objectr   r0   )r7   r   r   r"   )rO   r   r   r   )rO   r   rT   r0   r   None)r}   )re   r5   r   r   )rj   Optional[str]r   r   )ru   r   r   r   rv   r   r   r   )r   r   )r,   r   r   r   r   floatr   zTelegramPairing | None)r   )r,   r   r   r   r   r   r   zTelegramBotSetupResult | None)r,   r   r   r   r   r   r   r   )
r,   r   r   r   r   r   r   r   r    Optional[TelegramBotSetupResult])
r,   r   r   r   r   r   r   r   r   r   )
r,   r   ru   r   rj   r   r   r   r   r   )
r,   r   ru   r   rj   r   r   r   r   r   )*r   
__future__r   r&   rer]   r   r   urllib.parserq   dataclassesr   typingr   r   r*   r)   DEFAULT_MANAGER_BOTDEFAULT_BOT_NAMEDEFAULT_POLL_TIMEOUTr   r_   compiler1   r   r   r-   r3   r9   rR   rY   rf   rk   r{   r   r   r   r   r   r   r   r   r   r   r   <module>r      s   # 	 	  
   !   @7  ' !  < #$?@  $" " " $% % %P
. 59  S4 +(,$(% " 		(! $''' ' 	'Z   #	D ,,, , 	, *#	  	
 &, *#	,,, , 	,
 , *"&.	???  ? 	?
 &?F *"&.	,,,  , 	,
 ,r   