
    `gj-'                    f   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ej                  j                  dd      j!                  d      Zej                  j                  dd	      Z G d
 de      ZddZddZddZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZddZddZddZy)u  
DingTalk Device Flow authorization.

Implements the same 3-step registration flow as dingtalk-openclaw-connector:
  1. POST /app/registration/init   → get nonce
  2. POST /app/registration/begin  → get device_code + verification_uri_complete
  3. POST /app/registration/poll   → poll until SUCCESS → get client_id + client_secret

The verification_uri_complete is rendered as a QR code in the terminal so the
user can scan it with DingTalk to authorize, yielding AppKey + AppSecret
automatically.
    )annotationsN)OptionalTupleDINGTALK_REGISTRATION_BASE_URLzhttps://oapi.dingtalk.com/DINGTALK_REGISTRATION_SOURCEopenClawc                      e Zd ZdZy)RegistrationErrorz3Raised when a DingTalk registration API call fails.N)__name__
__module____qualname____doc__     K/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/dingtalk_auth.pyr   r   %   s    =r   r   c           	     b   t          |  }	 t        j                  ||d      }|j                          |j	                         }|j                  dd      }|dk7  r'|j                  d	d
      }t        d|  d| d| d      |S # t        j
                  $ r}t        d| d|       |d}~ww xY w)z=POST to the registration API and return the parsed JSON body.   )jsontimeoutzNetwork error calling z: Nerrcoder   errmsgzunknown errorzAPI error [z]: z
 (errcode=))REGISTRATION_BASE_URLrequestspostraise_for_statusr   RequestExceptionr   get)pathpayloadurlrespdataexcr   r   s           r   	_api_postr'   )   s    "#D6
*CP}}Sw;yy{ hhy"%G!|(O4+dV3vhj	QR STTK $$ P"8Ru EFCOPs   8B B.B))B.c                    t        ddt        i      } t        | j                  dd            j	                         }|st        d      t        dd|i      }t        |j                  dd            j	                         }t        |j                  dd            j	                         }|st        d	      |st        d
      ||t        |j                  dd            t        t        |j                  dd            d      dS )zStart a device-flow registration.

    Returns a dict with keys:
        device_code, verification_uri_complete, expires_in, interval
    z/app/registration/initsourcenonce zinit response missing noncez/app/registration/begindevice_codeverification_uri_completez"begin response missing device_codez0begin response missing verification_uri_complete
expires_in   interval      )r,   r-   r.   r0   )r'   REGISTRATION_SOURCEstrr    stripr   intmax)	init_datar*   
begin_datar,   r-   s        r   begin_registrationr:   <   s     2X?R4STI	gr*+113E =>> 4w6FGJjnn]B78>>@K #JNN3NPR$S T Z Z \ DEE$ RSS #%>*..t<=JNN:q9:A>	 r   c           	        t        dd| i      }t        |j                  dd            j                         j	                         }|dvrd}|t        |j                  dd            j                         xs dt        |j                  d	d            j                         xs dt        |j                  d
d            j                         xs ddS )zxPoll the registration status once.

    Returns a dict with keys:  status, client_id?, client_secret?, fail_reason?
    z/app/registration/pollr,   statusr+   >   FAILEXPIREDSUCCESSWAITINGUNKNOWN	client_idNclient_secretfail_reason)r<   rB   rC   rD   )r'   r4   r    r5   upper)r,   r%   
status_raws      r   poll_registrationrG   Y   s    
 -{/KLDTXXh+,224::<JBB
+r2399;CtTXXor:;AACKt488M267==?G4	 r   c                d   t        j                         |z   }d}d}t        j                         |k  rt        j                  |       	 t        |       }|d   }|dk(  rd}|r |        N|dk(  r|d   }	|d   }
|	r|
st	        d	      |	|
fS |dk(  rt        j                         }t        j                         |z
  |k  r|j                  d
      xs |}t	        d|       t	        d      # t        $ r8 |dk(  rt        j                         }t        j                         |z
  |k  rY  w xY w)zaBlock until the registration succeeds or times out.

    Returns (client_id, client_secret).
    x   g        r   r<   r@   r?   rB   rC   z3authorization succeeded but credentials are missingrD   zauthorization failed: z%authorization timed out, please retry)time	monotonicsleeprG   r   r    )r,   r0   r.   
on_waitingdeadlineretry_windowretry_startresultr<   cidcsecretreasons               r   wait_for_registration_successrU   j   s@    ~~*,HLK
..
X
%

8	&{3F !YKY%C_-Gg'(]^^<!..*K>>k)L8M*4f"8 ABB
C
DD7 ! 	a"nn.~~+-<	s   	C. .<D/-D/c                     	 ddl } y# t        $ r Y nw xY wddl}ddlm} 	  |ddgd      }|j
                  dk(  rddl } y	 y	# |j                  t        t        f$ r Y y	w xY w)
z=Try to import qrcode; if missing, auto-install it via pip/uv.r   NT)_pip_installz-qqrcoderI   )r   F)rX   ImportError
subprocesshermes_cli.tools_configrW   
returncodeSubprocessErrorOSError)rX   rZ   rW   rQ   s       r   _ensure_qrcode_installedr_      s      4tX.<! "
  &&W= s    	A A A c                   	 ddl }|j                  d|j                  j                  dd      }|j                  |        |j                  d       |j                         }t        |      }g }d}d	}d
}d}	t        d|d      D ]  }
g }t        t        ||
               D ]n  }||
   |   }|
dz   |k  r||
dz      |   nd}|r|r|j                  |       6|r|j                  |       J|r|j                  |       ^|j                  |	       p |j                  ddj                  |      z           t        dj                  |             y# t        $ r Y yw xY w)zRender *url* as a compact QR code in the terminal.

    Returns True if the QR code was printed, False if the library is missing.
    r   NF   )versionerror_correctionbox_sizeborderT)fitu   ▀u   ▄u   █ r2   z    r+   
)rX   rY   QRCode	constantsERROR_CORRECT_Ladd_datamake
get_matrixlenrangeappendjoinprint)r#   rX   qrmatrixrowslinesTOP_HALFBOTTOM_HALF
FULL_BLOCKEMPTYr
line_charsctopbottoms                  r   render_qr_to_terminalr      sp   
 
))99	 
 
B KKGGG ]]_Fv;DEHKJE1dA 3 "
s6!9~& 
	)A)A,C)*QVAE]1%5Fv!!*-!!(+!!+.!!%(
	) 	Vbggj1123 
$))E
M  s   E 	EEc                   
 ddl m} m}m}m} t                 | d        | d        | d       	 t               }|d   }t               s |d	       t                 | d
       t                t        |      s |d       t                 | d|        t                 | d       d

fd}	 t        |d   |d   |d   |      \  }}	t                 |d        |d|         |d|	dd  dt        |	      dz
  z          ||	fS # t        $ r} |d|        Y d}~yd}~ww xY w# t        $ r}t                 |d|        Y d}~yd}~ww xY w)zRun the interactive QR-code device-flow authorization.

    Returns (client_id, client_secret) on success, or None if the user
    cancelled or the flow failed.
    r   )
print_infoprint_successprint_warningprint_errorz/  Initializing DingTalk device authorization...u:     Note: the scan page is branded 'OpenClaw' — DingTalk'sz1        ecosystem onboarding bridge. Safe to use.z  Authorization init failed: Nr-   z5  qrcode library install failed, will show link only.z;  Please scan the QR code below with DingTalk to authorize:zA  QR code render failed, please open the link below to authorize:z  Or open this link manually: z9  Waiting for QR scan authorization... (timeout: 2 hours)c                      dz    dz  dk(  r>t         j                  j                  d       t         j                  j                          y y )Nra   
   r   .)sysstdoutwriteflush)	dot_counts   r   _on_waitingz%dingtalk_qr_auth.<locals>._on_waiting  s?    Q	r>QJJS!JJ r   r,   r0   r.   )r,   r0   r.   rM   z  Authorization failed: z#  QR scan authorization successful!z  Client ID:     z  Client Secret:    *)hermes_cli.setupr   r   r   r   rs   r:   r   r_   r   rU   ro   )r   r   r   r   regr&   r#   r   rB   rC   r   s             @r   dingtalk_qr_authr      s~    WV	G@AKLBC "
 )
*C $%MN	GLM	G %YZ	G/u56	GJKI
#@M*_<("	$
 	= 
G78%i[12%mBQ&7%8M@RUV@V9W8XYZm##a  3C59:L  .se45s/   
D 0D, 	D)D$$D),	E5EE)r!   r4   r"   dictreturnr   )r   r   )r,   r4   r   r   )r1   r/   N)
r,   r4   r0   r6   r.   r6   rM   zOptional[callable]r   zTuple[str, str])r   bool)r#   r4   r   r   )r   zOptional[Tuple[str, str]])r   
__future__r   osr   rJ   loggingtypingr   r   r   	getLoggerr   loggerenvironr    rstripr   r3   	Exceptionr   r'   r:   rG   rU   r_   r   r   r   r   r   <module>r      s    # 	 
   " 			8	$ 

$&A&+  jjnn%CZP 
>	 >&:& %)	-E-E-E -E #	-E
 -Ed,-d?$r   