o
    ưi8                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZmZ d dlZd dl	m
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 dZdZd	Zd
ZG dd dZdS )    N)AnyDictOptional)verbose_logger)_get_httpx_client   )
CHATGPT_API_BASECHATGPT_AUTH_BASECHATGPT_CLIENT_IDCHATGPT_DEVICE_CODE_URLCHATGPT_DEVICE_TOKEN_URLCHATGPT_DEVICE_VERIFY_URLCHATGPT_OAUTH_TOKEN_URLGetAccessTokenErrorGetDeviceCodeErrorRefreshAccessTokenError<   i  i,     c                   @   s  e Zd Zd4ddZdefddZdefddZdee fd	d
Zd4ddZ	dee
eef  fddZde
eef ddfddZde
eef dedefddZdedee fddZdede
eef fddZdee dee fddZde
eef fddZde
eef fdd Zd!e
eef de
eef fd"d#Zd$e
eef de
eef fd%d&Zd'ede
eef fd(d)Zd*e
eef de
eef fd+d,Zdee
eef  defd-d.Zd4d/d0Zd1edee fd2d3ZdS )5AuthenticatorreturnNc                 C   s<   t dt jd| _t j| jt dd| _|   d S )NZCHATGPT_TOKEN_DIRz~/.config/litellm/chatgptZCHATGPT_AUTH_FILEz	auth.json)osgetenvpath
expanduser	token_dirjoin	auth_file_ensure_token_dirself r    Y/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/chatgpt/authenticator.py__init__    s   
zAuthenticator.__init__c                 C   s   t dpt dptS )Nr   ZOPENAI_CHATGPT_API_BASE)r   r   r   r   r    r    r!   get_api_base*   s
   
zAuthenticator.get_api_basec           	   
   C   s   |   }|r?|d}|r| ||s|S |d}|r?z
| |}|d W S  ty> } ztd| W Y d }~nd }~ww | |}|dkrQ| |}|rQ|S | 	 }|d S )Naccess_tokenrefresh_tokenz3ChatGPT refresh token failed, re-login required: %sr   )
_read_auth_fileget_is_token_expired_refresh_tokensr   r   warning#_get_device_code_cooldown_remaining_wait_for_access_token_login_device_code)	r   	auth_datar$   r%   	refreshedexccooldown_remainingtokentokensr    r    r!   get_access_token1   s.   





zAuthenticator.get_access_tokenc                 C   s^   |   }|sd S |d}|r|S |d}|d}| |p |}|r-||d< | | |S )N
account_idid_tokenr$   )r&   r'   _extract_account_id_write_auth_file)r   r.   r5   r6   r$   Zderivedr    r    r!   get_account_idJ   s   



zAuthenticator.get_account_idc                 C   s&   t j| jst j| jdd d S d S )NT)exist_ok)r   r   existsr   makedirsr   r    r    r!   r   Y   s   zAuthenticator._ensure_token_dirc              
   C   s   zt | jd}t|W  d    W S 1 sw   Y  W d S  ty)   Y d S  tjyB } ztd| W Y d }~d S d }~ww )NrzInvalid ChatGPT auth file: %s)openr   jsonloadIOErrorJSONDecodeErrorr   r*   )r   fr0   r    r    r!   r&   ]   s   (zAuthenticator._read_auth_filedatac              
   C   sv   z!t | jd}t|| W d    W d S 1 sw   Y  W d S  ty: } ztd| W Y d }~d S d }~ww )Nwz%Failed to write ChatGPT auth file: %s)r>   r   r?   dumprA   r   error)r   rD   rC   r0   r    r    r!   r8   g   s   &zAuthenticator._write_auth_filer.   r$   c                 C   sR   | d}|d u r| |}|r||d< | | |d u rdS t t|t kS )N
expires_atT)r'   _get_expires_atr8   timefloatTOKEN_EXPIRY_SKEW_SECONDS)r   r.   r$   rH   r    r    r!   r(   n   s   


zAuthenticator._is_token_expiredr2   c                 C   s.   |  |}|d}t|ttfrt|S d S )Nexp)_decode_jwt_claimsr'   
isinstanceintrK   )r   r2   claimsrM   r    r    r!   rI   y   s
   

zAuthenticator._get_expires_atc                 C   sn   z+| d}t|dk ri W S |d }|dt| d  7 }t|}t|dW S  ty6   i  Y S w )N.   r   =   zutf-8)splitlenbase64urlsafe_b64decoder?   loadsdecode	Exception)r   r2   partsZpayload_b64Zpayload_bytesr    r    r!   rN      s   

z Authenticator._decode_jwt_claimsc                 C   sF   |sd S |  |}|d}t|tr!|d}t|tr!|r!|S d S )Nzhttps://api.openai.com/authZchatgpt_account_id)rN   r'   rO   dictstr)r   r2   rQ   Zauth_claimsr5   r    r    r!   r7      s   



z!Authenticator._extract_account_idc                 C   s   |  |  }|dkr| |}|rd|iS |  }|   tdt d|d  ddd | |}| |}| 	|}| 
| |S )	Nr   r$   z1Sign in with ChatGPT using device code:
1) Visit z
2) Enter code: 	user_codezB
Device codes are a common phishing target. Never share this code.T)flush)r+   r&   r,   _request_device_code_record_device_code_requestprintr   _poll_for_authorization_code_exchange_code_for_tokens_build_auth_recordr8   )r   r1   r2   device_codeZ	auth_coder3   r.   r    r    r!   r-      s,   




z Authenticator._login_device_codec              
   C   s   zt  }|jtdtid}|  | }W n, tjy. } ztd| |j	j
dd }~w tyB } z	td| ddd }~ww |d}|dpQ|d}|d	}|r[|sdtd
| dd||t|pjddS )N	client_idr?   zFailed to request device code: messagestatus_code  device_auth_idr`   Zusercodeintervalz%Device code response missing fields: 5)ro   r`   rp   )r   postr   r
   raise_for_statusr?   httpxHTTPStatusErrorr   responserm   r\   r'   r_   )r   clientresprD   r0   ro   r`   rp   r    r    r!   rb      sB   


z"Authenticator._request_device_coderh   c              
      s^  t  }t|dd}t }t | tk rz:|jt|d |d dd}|jdkr=|  t	 fdd	d
D r= W S |jdv rLt
t|t W q|  W nG tjy } z&|jra|jjnd }|dv rut
t|t W Y d }~qtd| |jjdd }~w ty } z	td| ddd }~ww t
t|t t | tk stddd)Nrp   rq   ro   r`   )ro   r`   rj      c                 3       | ]}| v V  qd S Nr    .0keyrD   r    r!   	<genexpr>   s
    
z=Authenticator._poll_for_authorization_code.<locals>.<genexpr>)authorization_codeZcode_challengecode_verifier)i  i  zPolling failed: rk   rn   z*Timed out waiting for device authorizationi  )r   rP   r'   rJ   DEVICE_CODE_TIMEOUT_SECONDSrr   r   rm   r?   allsleepmaxDEVICE_CODE_POLL_SLEEP_SECONDSrs   rt   ru   rv   r   r\   )r   rh   rw   rp   
start_timerx   r0   rm   r    r   r!   re      sX   

(z*Authenticator._poll_for_authorization_code	code_datac              
      s   z.t  }t d}d|d  d| dt d|d  }|jtdd	i|d
}|  |  W n, tjyF } zt	d| |j
jdd }~w tyZ } z	t	d| ddd }~ww t fdddD sot	d  dd d  d  d dS )Nz/deviceauth/callbackz#grant_type=authorization_code&code=r   z&redirect_uri=z&client_id=z&code_verifier=r   zContent-Typez!application/x-www-form-urlencoded)headerscontentzToken exchange failed: rk   rn   c                 3   rz   r{   r    r|   r   r    r!   r     s    z:Authenticator._exchange_code_for_tokens.<locals>.<genexpr>r$   r%   r6   z(Token exchange response missing fields: r$   r%   r6   )r   r	   r
   rr   r   rs   r?   rt   ru   r   rv   rm   r\   r   )r   r   rw   Zredirect_uribodyrx   r0   r    r   r!   rf     sT   
z'Authenticator._exchange_code_for_tokensr%   c           
   
   C   s   zt  }|jttd|ddd}|  | }W n, tjy1 } ztd| |j	j
dd }~w tyE } z	td| ddd }~ww |d}|d	}|rT|s]td
| dd||d||d}| |}	| |	 |S )Nr%   zopenid profile email)ri   Z
grant_typer%   scoperj   zRefresh token failed: rk   rn   r$   r6   z!Refresh response missing fields: r   )r   rr   r   r
   rs   r?   rt   ru   r   rv   rm   r\   r'   rg   r8   )
r   r%   rw   rx   rD   r0   r$   r6   r/   r.   r    r    r!   r)   *  sN   	




zAuthenticator._refresh_tokensr3   c                 C   sJ   | d}| d}|r| |nd }| |p|}|| d|||dS )Nr$   r6   r%   )r$   r%   r6   rH   r5   )r'   rI   r7   )r   r3   r$   r6   rH   r5   r    r    r!   rg   T  s   

z Authenticator._build_auth_recordc              	   C   sj   |sdS | d}t|tttfsdS zt|}W n ttfy%   Y dS w t | }t| }t	d|S )N        device_code_requested_at)
r'   rO   rP   rK   r_   	TypeError
ValueErrorrJ   DEVICE_CODE_COOLDOWN_SECONDSr   )r   r.   Zrequested_atelapsed	remainingr    r    r!   r+   a  s   

z1Authenticator._get_device_code_cooldown_remainingc                 C   s&   |   pi }t |d< | | d S )Nr   )r&   rJ   r8   )r   r.   r    r    r!   rc   q  s   z)Authenticator._record_device_code_requesttimeout_secondsc                 C   s   t   | }t   |k r?|  }|r!|d}|r!| ||s!|S tttd|t    }|dkr4	 d S t | t   |k sd S )Nr$   r   r   )rJ   r&   r'   r(   minr   r   r   )r   r   deadliner.   r$   Z	sleep_forr    r    r!   r,   v  s    

z$Authenticator._wait_for_access_token)r   N)__name__
__module____qualname__r"   r_   r#   r4   r   r9   r   r   r   r&   r8   boolr(   rP   rI   rN   r7   r-   rb   re   rf   r)   rg   rK   r+   rc   r,   r    r    r    r!   r      s2    



"""1("*

r   )rX   r?   r   rJ   typingr   r   r   rt   Zlitellm._loggingr   Z&litellm.llms.custom_httpx.http_handlerr   Zcommon_utilsr   r	   r
   r   r   r   r   r   r   r   rL   r   r   r   r   r    r    r    r!   <module>   s    0