o
    ߿.g/                     @   sR   d 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ZdZG dd dZ	dS )z}
This file contains a class to manage tokens
Coded by Tyler Bowers
Github: https://github.com/tylerebowers/Schwab-API-Python
    Nz/var/www/html/flask_project/c                   @   sx   e Zd Zed dfddZdedefddZd	ed
edefddZ	dd Z
dddZdd Zdd Zdd Zdd ZdS )Tokensztokens.jsonTc           
   
      s  |du rt d|du rt d|du rt d|du r t dt|dks,t|dkr0t d|d	d
 dkr<t d|d dkrFt d|d dkrPt d| _| _| _| _d _d _d _t	j	j
jt	jjd _t	j	j
jt	jjd _d _d _| _d  vr|r    jjr jt	j	t	jj j   }td|d	k rdnd tt|d ddtt|d d ddtt|d dd  jt	j	t	jj j   }td|d	k rdnd tt|d ddtt|d d ddtt|d dd n jjr tdt| d |r'   |r; fd d!}	tj|	d"d#  dS  jjrFtd$ dS dS )%a  
        Initialize a tokens manager
        :param client: client object (only used for .verbose setting)
        :type client: Client
        :param app_key: app key credentials
        :type app_key: str
        :param app_secret: app secret credentials
        :type app_secret: str
        :param callback_url: url for callback
        :type callback_url: str
        :param tokens_file: path to tokens file
        :type tokens_file: str
        Nz#[Schwabdev] app_key cannot be None.z&[Schwabdev] app_secret cannot be None.z([Schwabdev] callback_url cannot be None.z'[Schwabdev] tokens_file cannot be None.       z1[Schwabdev] App key or app secret invalid length.r      httpsz'[Schwabdev] callback_url must be https./z8[Schwabdev] callback_url cannot be path (ends with "/").z'[Schwabdev] Tokens file cannot be path.)tzinfoi  i:	 z$[Schwabdev] Access token expires in -   02H:<   M:Sz%[Schwabdev] Refresh token expires in zG[Schwabdev] Token file does not exist or invalid formatting, creating ""c                      s   	     td q)NT   )update_tokenstimesleep selfr   4/var/www/html/vps_streaming_csV2/schwabdev/tokens.pycheckerR   s   
z Tokens.__init__.<locals>.checkerT)targetdaemonz>[Schwabdev] Warning: Tokens will not be updated automatically.) 	Exceptionlen_client_app_key_app_secret_callback_urlaccess_tokenrefresh_tokenid_tokendatetimeminreplacetimezoneutc_access_token_issued_refresh_token_issued_access_token_timeout_refresh_token_timeout_tokens_file_read_tokensr   verbosenowtotal_secondsprintintabsstrupdate_refresh_token	threadingThreadstart)
r   clientapp_key
app_secretcallback_urltokens_fileupdate_tokens_autoat_deltart_deltar   r   r   r   __init__   s^   
 Z Z

zTokens.__init__
grant_typecodec                 C   st   dt t| j d| j dd dd}|dkr$d|| jd}n|dkr.d|d	}ntd
tj	d||dS )a  
        Makes API calls for auth code and refresh tokens
        :param grant_type: 'authorization_code' or 'refresh_token'
        :type grant_type: str
        :param code: authorization code
        :type code: str
        :return: response
        :rtype: requests.Response
        zBasic :zutf-8z!application/x-www-form-urlencoded)AuthorizationzContent-Typeauthorization_code)rF   rG   redirect_urir%   )rF   r%   zGInvalid grant type; options are 'authorization_code' or 'refresh_token'z(https://api.schwabapi.com/v1/oauth/token)headersdata)
base64	b64encodebytesr!   r"   decoder#   r   requestspost)r   rF   rG   rL   rM   r   r   r   _post_oauth_token[   s   (zTokens._post_oauth_token	at_issued	rt_issuedtoken_dictionaryc              
   C   s   | d| _| d| _| d| _|| _|| _z.t| jd}| | |d}t	j
||ddd W d	   W d	S 1 s?w   Y  W d	S  tya } zt| td
 W Y d	}~d	S d	}~ww )a6  
        Writes token file and sets variables
        :param at_issued: access token issued
        :type at_issued: datetime.pyi
        :param rt_issued: refresh token issued
        :type rt_issued: datetime.pyi
        :param token_dictionary: token dictionary
        :type token_dictionary: dict
        r$   r%   r&   w)access_token_issuedrefresh_token_issuedrW   F   )ensure_asciiindentNz'[Schwabdev] Could not write tokens file)getr$   r%   r&   r,   r-   openr0   	isoformatjsondumpr   r5   )r   rU   rV   rW   fto_writeer   r   r   _write_tokenss   s$   
&zTokens._write_tokensc              
   C   s   zQt | jd@}t|}|d}|d| _|d| _|d| _tj	|d| _
tj	|d| _| j
| j|fW  d   W S 1 sJw   Y  W dS  tyh } zt| W Y d}~d	S d}~ww )
z
        Reads token file and sets variables
        :return: access token issued, refresh token issued, token dictionary
        :rtype: datetime.pyi, datetime.pyi, dict
        rrW   r$   r%   r&   rY   rZ   N)NNN)r_   r0   ra   loadr^   r$   r%   r&   r'   fromisoformatr,   r-   r   r5   )r   rc   drW   re   r   r   r   r1      s    

(	zTokens._read_tokensFc              
   C   s   | j tjtjj| j   }|dk rAtd|dk rdnd tt	|d ddtt	|d d	 dd
tt	|d	 dd |dk sG|rQtd | 
  dS | jtjtjj| j   dk rq| jjrktd |   dS dS )z
        Checks if tokens need to be updated and updates if needed (only access token is automatically updated)
        :param force: force update of refresh token (also updates access token)
        :type force: bool
        i  z1[Schwabdev] The refresh token will expire soon! (r   r
   r   r   r   r   r   r   zS remaining)z*[Schwabdev] The refresh token has expired!=   zA[Schwabdev] The access token has expired, updating automatically.N)r/   r'   r3   r*   r+   r-   r4   r5   r6   r7   r9   r.   r,   r    r2   update_access_token)r   forcerD   r   r   r   r      s    Z$zTokens.update_tokensc                 C   sn   |  d| j}|jr,tjtjj}| || j|	  | j
jr*td| j  dS dS t|j td dS )zD
        "refresh" the access token using the refresh token
        r%   z"[Schwabdev] Access token updated: zS[Schwabdev] Could not get new access token, refresh_token probably expired randomlyN)rT   r%   okr'   r3   r*   r+   rf   r-   ra   r    r2   r5   r,   text)r   responserU   r   r   r   rl      s   
zTokens.update_access_tokenc                 C   s   d| j  d| j S )z'
        Get authorization url
        z7https://api.schwabapi.com/v1/oauth/authorize?client_id=z&redirect_uri=)r!   r#   r   r   r   r   get_refresh_token_auth_url   s   z!Tokens.get_refresh_token_auth_urlc                 C   s   | dr||dd |d  d}n|}| d|}|jr?tjtjj}| |||	  | j
jr=td d	S d	S t|j td d	S )
z
        Get new access and refresh tokens using callback url or authorization code.
        :param url_or_code: callback url (full url) or authorization code (the code=... in url)
        :type url_or_code: str
        zhttps://zcode=r   z%40@rJ   z-[Schwabdev] Refresh and Access tokens updatedz[Schwabdev] Could not get new refresh and access tokens, check these:
1. App status is "Ready For Use".
2. App key and app secret are valid.
3. You pasted the whole url within 30 seconds. (it has a quick expiration)N)
startswithindexrT   rn   r'   r3   r*   r+   rf   ra   r    r2   r5   ro   )r   url_or_coderG   rp   r3   r   r   r   update_refresh_token_from_code   s   
$
z%Tokens.update_refresh_token_from_codec                 C   s6   |   }td|  t| td}| | dS )zM
        Get new access and refresh tokens using authorization code.
        z"[Schwabdev] Open to authenticate: z?[Schwabdev] After authorizing, paste the address bar url here: N)rq   r5   
webbrowserr_   inputrv   )r   auth_urlresponse_urlr   r   r   r9      s
   
zTokens.update_refresh_tokenN)F)__name__
__module____qualname__PATH_UBUNTUrE   r8   rT   r'   dictrf   r1   r   rl   rq   rv   r9   r   r   r   r   r      s    I
r   )
__doc__ra   r   rN   rR   r'   r:   rw   r~   r   r   r   r   r   <module>   s    