o
    ՂFeA                     @   s*  d Z ddlZddlmZ ddlmZ ddlmZ ddlZddlZddlm	Z	 ddl
mZmZ ddlmZmZ ejr>eZeZneZeZG d	d
 d
eZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deeZG dd deZ G dd deZ!G dd deZ"dS )ap  
This module simplifies the process of obtaining an authenticated session for steam websites.
After authentication is completed, a :class:`requests.Session` is created containing the auth cookies.
The session can be used to access ``steamcommunity.com``, ``store.steampowered.com``, and ``help.steampowered.com``.

.. warning::
    A web session may expire randomly, or when you login from different IP address.
    Some pages will return status code `401` when that happens.
    Keep in mind if you are trying to write robust code.

.. note::
    If you are using :class:`.SteamClient` take a look at :meth:`.SteamClient.get_web_session()`

.. note::
    If you need to authenticate as a mobile device for things like trading confirmations
    use :class:`MobileWebAuth` instead. The login process is identical, and in addition
    you will get :attr:`.oauth_token`.


Example usage:

.. code:: python

    import steam.webauth as wa

    user = wa.WebAuth('username')

    # At a console, cli_login can be used to easily perform all login steps
    session = user.cli_login('password')
    session.get('https://store.steampowered.com/account/history')

    # Or the login steps be implemented for other situation like so
    try:
        user.login('password')
    except (wa.CaptchaRequired, wa.LoginIncorrect) as exp:
        if isinstance(exp, LoginIncorrect):
            # ask for new password
        else:
            password = self.password

        if isinstance(exp, wa.CaptchaRequired):
            print user.captcha_url
            # ask a human to solve captcha
        else:
            captcha = None

        user.login(password=password, captcha=captcha)
    except wa.EmailCodeRequired:
        user.login(email_code='ZXC123')
    except wa.TwoFactorCodeRequired:
        user.login(twofactor_code='ZXC123')

    user.session.get('https://store.steampowered.com/account/history/')

    N)time)	b64encode)getpass)SteamID)make_requests_sessiongenerate_session_id)rsa_publickeypkcs1v15_encryptc                   @   s|   e Zd ZdZdZdZdZdZdZdZ	dddZ
dd Zed	d
 Zdd Zdd ZdddZdd ZdddZdddZdS )WebAuthNF c                 C   s"   | j t  t | _|   d S N)__dict__updatelocalsr   session_session_setup)selfusernamepassword r   8/usr/local/lib/python3.10/dist-packages/steam/webauth.py__init__U   s   zWebAuth.__init__c                 C   s   d S r   r   r   r   r   r   r   Z   s   zWebAuth._session_setupc                 C   s   | j dkrdS d| j  S )zOIf a captch is required this property will return url to the image, or ``None``r   Nz6https://steamcommunity.com/login/rendercaptcha/?gid=%s)captcha_gidr   r   r   r   captcha_url]   s   

zWebAuth.captcha_urlc              
   C   sV   z| j jdd|tt d dd }W |S  tjjy* } ztt	|d}~ww )a   Get rsa key for a given username

        :param username: username
        :type  username: :class:`str`
        :return: json response
        :rtype: :class:`dict`
        :raises HTTPError: any problem with http request, timeouts, 5xx, 4xx etc
        z+https://steamcommunity.com/login/getrsakey/   i  )r   
donotcache)timeoutdataN)
r   postintr   jsonrequests
exceptionsRequestException	HTTPErrorstr)r   r   resper   r   r   get_rsa_keye   s   	
zWebAuth.get_rsa_keyc                 C   sD   | j s | | j}tt|d dt|d d| _ |d | _d S d S )Npublickey_mod   publickey_exp	timestamp)keyr*   r   r   intBaser.   )r   r(   r   r   r   	_load_key{   s   zWebAuth._load_keyc                 C   s   | j tt| j|d||rt| jnd|| j|d| jdt	t
 d d}z| jjd|dd	 W S  tjjyF } ztt|d }~ww )
Nasciir   python-steam webauthtrue順 )r   r   	emailauthemailsteamidtwofactorcode
captchagidcaptcha_textloginfriendlynamersatimestampremember_loginr   )https://steamcommunity.com/login/dologin/r   r   r   )r   r   r	   r/   encoder'   steam_idr   r.   r!   r   r   r    r"   r#   r$   r%   r&   r   r   captcha
email_codetwofactor_coder   r)   r   r   r   _send_login   s$   zWebAuth._send_loginc                 C   s
   d| _ d S )NzSTEAM_0:0:57296955)rA   )r   login_responser   r   r   _finalize_login   s   
zWebAuth._finalize_loginenglishc           	      C   s  | j r| jS |r|| _n| jr| j}ntd|s| jr| j}|   | j||||d}|d r|d rd| _ d | _| _d| _t| jj	D ]}dD ]}| jj	j
|j|j||jd	 qJqFt | _dD ]!}| jj	j
d
||d | jj	j
dd|d | jj	j
d| j|d qb| | | jS |ddr|d | _d| _|ddrd| _t|d t|d |ddrt|d | _t|d |ddrt|d d|ddv rt|d d| _t|d )a`  Attempts web login and returns on a session with cookies set

        :param password: password, if it wasn't provided on instance init
        :type  password: :class:`str`
        :param captcha: text reponse for captcha challenge
        :type  captcha: :class:`str`
        :param email_code: email code for steam guard
        :type  email_code: :class:`str`
        :param twofactor_code: 2FA code for steam guard
        :type  twofactor_code: :class:`str`
        :param language: select language for steam web pages (sets language cookie)
        :type  language: :class:`str`
        :return: a session on success and :class:`None` otherwise
        :rtype: :class:`requests.Session`, :class:`None`
        :raises HTTPError: any problem with http request, timeouts, 5xx, 4xx etc
        :raises LoginIncorrect: wrong username or password
        :raises CaptchaRequired: when captcha is needed
        :raises CaptchaRequiredLoginIncorrect: when captcha is needed and login is incorrect
        :raises EmailCodeRequired: when email is needed
        :raises TwoFactorCodeRequired: when 2FA is needed
        zpassword is not specified)r   rC   rD   rE   successlogin_completeTr   r   zstore.steampowered.comzhelp.steampowered.comzsteamcommunity.comdomainsecureSteam_LanguagerN   	birthtime-3333	sessionidcaptcha_neededFr   clear_password_fieldmessageemailauth_neededr7   requires_twofactorztoo many login failures)	logged_onr   r   LoginIncorrectcaptcha_coder1   rF   r   listcookiessetnamevaluerO   r   
session_idrH   getCaptchaRequiredLoginIncorrectCaptchaRequiredr   rA   EmailCodeRequiredTwoFactorCodeRequiredTooManyLoginFailures)	r   r   rC   rD   rE   languager(   cookierN   r   r   r   login   sT   


zWebAuth.loginc              
   C   s   	 z
|  |||||W S  ttfyH } z/d }}t|tr-|s"dnd}t|t| j }t|tr<d| j }t|}nd}W Y d}~n/d}~w t	y]   |sRdnd}t|d}}Y n t
yr   |sgd	nd
}dt|}}Y nw q)a  Generates CLI prompts to perform the entire login process

        :param password: password, if it wasn't provided on instance init
        :type  password: :class:`str`
        :param captcha: text reponse for captcha challenge
        :type  captcha: :class:`str`
        :param email_code: email code for steam guard
        :type  email_code: :class:`str`
        :param twofactor_code: 2FA code for steam guard
        :type  twofactor_code: :class:`str`
        :param language: select language for steam web pages (sets language cookie)
        :type  language: :class:`str`
        :return: a session on success and :class:`None` otherwise
        :rtype: :class:`requests.Session`, :class:`None`

        .. code:: python

            In [3]: user.cli_login()
            Enter password for 'steamuser':
            Solve CAPTCHA at https://steamcommunity.com/login/rendercaptcha/?gid=1111111111111111111
            CAPTCHA code: 123456
            Invalid password for 'steamuser'. Enter password:
            Solve CAPTCHA at https://steamcommunity.com/login/rendercaptcha/?gid=2222222222222222222
            CAPTCHA code: abcdef
            Enter 2FA code: AB123
            Out[3]: <requests.sessions.Session at 0x6fffe56bef0>

        Tr   zEnter password for %s: z)Invalid password for %s. Enter password: z"Solve CAPTCHA at %s
CAPTCHA code: NzEnter email code: z"Incorrect code. Enter email code: zEnter 2FA code: z Incorrect code. Enter 2FA code: )rk   r[   re   
isinstancer   reprr   r   
_cli_inputrf   rg   )r   r   rC   rD   rE   ri   exppromptr   r   r   	cli_login   s6   



zWebAuth.cli_login)r   r   r   r   r   )r   r   r   r   rI   )__name__
__module____qualname__r/   rZ   r   rb   r   r\   rA   r   r   propertyr   r*   r1   rF   rH   rk   rq   r   r   r   r   r
   L   s$    


	
Nr
   c                   @   s0   e Zd ZdZdZdddZdd Zdd	d
ZdS )MobileWebAuthzJIdentical to :class:`WebAuth`, except it authenticates as a mobile device.Nr   c                 C   s   | j tt| j|d||rt| jnd|| j|d| jdt	t
 d ddd}| jjd	d
 | jjdd z2z| jjd|dd W W | jjd	d  | jjdd  S  tjjyj } ztt|d }~ww | jjd	d  | jjdd  w )Nr2   r   r3   r4   r5   DE45CD61z3read_profile write_profile read_client write_client)r   r   r6   r7   r8   r9   r:   r;   r<   r=   r   oauth_client_idoauth_scopemobileClientVersion	0 (2.1.3)mobileClientandroidr>   r   r?   )r   r   r	   r/   r@   r'   rA   r   r.   r!   r   r   r^   r_   r    r"   popr#   r$   r%   r&   rB   r   r   r   rF   '  s4   zMobileWebAuth._send_loginc                 C   s*   t |d }t|d | _|d | _d S )Noauthsteamidoauth_token)r"   loadsr   rA   r   )r   rG   r   r   r   r   rH   C  s   zMobileWebAuth._finalize_loginrI   c           	   
   C   s  |r|| _ n| j r| j }ntd|rt|| _n| js td| jj}d|i}z
| jjd|d}W n tjj	yF } zt
t|d}~ww z| d }W n tjjyh } zd|jv rbtd	|d}~ww t | _d
D ]Z}| jjjdd|d | jjjd| j|d | jjjdd|d | jjjdd|d | jjjdt|d |d  |d | jjjdt|d |d  |dd | jjjd||d qod| _| jS )a.  Attempts a mobile authenticator login using an oauth token, which can be obtained from a previously logged-in
        `MobileWebAuth`

        :param oauth_token: oauth token string, if it wasn't provided on instance init
        :type  oauth_token: :class:`str`
        :param steam_id: `SteamID` of the account to log into, if it wasn't provided on instance init
        :type  steam_id: :class:`str` or :class:`SteamID`
        :param language: select language for steam web pages (sets language cookie)
        :type  language: :class:`str`
        :return: a session on success and :class:`None` otherwise
        :rtype: :class:`requests.Session`, :class:`None`
        :raises HTTPError: any problem with http request, timeouts, 5xx, 4xx etc
        :raises LoginIncorrect: Invalid token or SteamID
        ztoken is not specifiedzsteam_id is not specifiedaccess_tokenz@https://api.steampowered.com/IMobileAuthService/GetWGToken/v0001)r   Nresponsez-Please verify your <pre>key=</pre> parameter.zinvalid tokenrL   rR   rS   rQ   rT   r{   r|   r}   r~   
steamLoginz%7C%7CtokensteamLoginSecuretoken_secureTrM   rP   )r   r[   r   rA   as_64r   r    r#   r$   r%   r&   r'   r"   decoderJSONDecodeErrortextr   rb   r^   r_   rZ   )	r   r   rA   ri   r   r(   r)   	resp_datarN   r   r   r   oauth_loginH  sN   
$zMobileWebAuth.oauth_loginrr   )r   r   rI   )rs   rt   ru   __doc__r   rF   rH   r   r   r   r   r   rw   #  s    
rw   c                   @      e Zd ZdS )WebAuthExceptionNrs   rt   ru   r   r   r   r   r         r   c                   @   r   )r&   Nr   r   r   r   r   r&     r   r&   c                   @   r   )r[   Nr   r   r   r   r   r[     r   r[   c                   @   r   )re   Nr   r   r   r   r   re     r   re   c                   @   r   )rd   Nr   r   r   r   r   rd     r   rd   c                   @   r   )rf   Nr   r   r   r   r   rf     r   rf   c                   @   r   )rg   Nr   r   r   r   r   rg     r   rg   c                   @   r   )rh   Nr   r   r   r   r   rh     r   rh   )#r   r"   r   base64r   r   sixr#   steam.steamidr   steam.utils.webr   r   steam.core.cryptor   r	   PY2longr0   	raw_inputrn   r!   inputobjectr
   rw   	Exceptionr   r&   r[   re   rd   rf   rg   rh   r   r   r   r   <module>   s4   7 Xd