Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade SteamAuthenticatorError to have the eresult available where available. #361

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 54 additions & 18 deletions steam/guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
from time import time
from steam import webapi
from steam.enums import ETwoFactorTokenType
from steam.steamid import SteamID
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an unused import.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, unless documentation for the android generate_device_id method actually needs that...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best to leave unrelated changes out of this PR

from steam.exceptions import SteamError
from steam.core.crypto import hmac_sha1, sha1_hash
from steam.enums.common import EResult
from steam.webauth import MobileWebAuth
Expand Down Expand Up @@ -127,30 +127,43 @@ def _send_request(self, action, params):

if isinstance(backend, MobileWebAuth):
if not backend.logged_on:
raise SteamAuthenticatorError("MobileWebAuth instance not logged in")
raise SteamAuthenticatorError(
message="MobileWebAuth instance not logged in",
eresult=None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where eresult is not available, simply don't set it. Default is EResult.Fail.

)

params['access_token'] = backend.oauth_token
params['http_timeout'] = 10

try:
resp = webapi.post('ITwoFactorService', action, 1, params=params)
except requests.exceptions.RequestException as exp:
raise SteamAuthenticatorError("Error adding via WebAPI: %s" % str(exp))
raise SteamAuthenticatorError(
message="Error adding via WebAPI: %s" % str(exp),
eresult=None,
)

resp = resp['response']
else:
if not backend.logged_on:
raise SteamAuthenticatorError("SteamClient instance not logged in")
raise SteamAuthenticatorError(
message="SteamClient instance not logged in",
eresult=None,
)

resp = backend.send_um_and_wait("TwoFactor.%s#1" % action,
params, timeout=10)

if resp is None:
raise SteamAuthenticatorError("Failed. Request timeout")
raise SteamAuthenticatorError(
message="Failed. Request timeout",
eresult=None,
)
if resp.header.eresult != EResult.OK:
raise SteamAuthenticatorError("Failed: %s (%s)" % (resp.header.error_message,
repr(resp.header.eresult)))

raise SteamAuthenticatorError(
message="Failed: %s (%s)" % (resp.header.error_message, repr(resp.header.eresult)),
eresult=resp.header.eresult,
)
resp = proto_to_dict(resp.body)

if action == 'AddAuthenticator':
Expand All @@ -166,7 +179,10 @@ def add(self):
:raises: :class:`SteamAuthenticatorError`
"""
if not self.has_phone_number():
raise SteamAuthenticatorError("Account doesn't have a verified phone number")
raise SteamAuthenticatorError(
message="Account doesn't have a verified phone number",
eresult=None,
)

resp = self._send_request('AddAuthenticator', {
'steamid': self.backend.steam_id,
Expand All @@ -177,7 +193,10 @@ def add(self):
})

if resp['status'] != EResult.OK:
raise SteamAuthenticatorError("Failed to add authenticator. Error: %s" % repr(EResult(resp['status'])))
raise SteamAuthenticatorError(
message="Failed to add authenticator. Error: %s" % repr(EResult(resp['status'])),
eresult=resp['status'],
)

self.secrets = resp
self.steam_time_offset = int(resp['server_time']) - time()
Expand All @@ -203,7 +222,10 @@ def finalize(self, activation_code):
return
elif not resp['success']:
self._finalize_attempts = 5
raise SteamAuthenticatorError("Failed to finalize authenticator. Error: %s" % repr(EResult(resp['status'])))
raise SteamAuthenticatorError(
message="Failed to finalize authenticator. Error: %s" % repr(EResult(resp['status'])),
eresult=resp['status'],
)

self.steam_time_offset = int(resp['server_time']) - time()

Expand All @@ -222,9 +244,15 @@ def remove(self, revocation_code=None):
:raises: :class:`SteamAuthenticatorError`
"""
if not self.secrets:
raise SteamAuthenticatorError("No authenticator secrets available?")
raise SteamAuthenticatorError(
message="No authenticator secrets available?",
eresult=None,
)
if not isinstance(self.backend, MobileWebAuth):
raise SteamAuthenticatorError("Only available via MobileWebAuth")
raise SteamAuthenticatorError(
message="Only available via MobileWebAuth",
eresult=None,
)

resp = self._send_request('RemoveAuthenticator', {
'steamid': self.backend.steam_id,
Expand All @@ -233,9 +261,11 @@ def remove(self, revocation_code=None):
})

if not resp['success']:
raise SteamAuthenticatorError("Failed to remove authenticator. (attempts remaining: %s)" % (
resp['revocation_attempts_remaining'],
))
raise SteamAuthenticatorError(
message="Failed to remove authenticator. (attempts remaining: %s)" %
(resp['revocation_attempts_remaining'],),
eresult=None,
)

self.secrets.clear()

Expand Down Expand Up @@ -466,8 +496,14 @@ def validate_phone_number(self, phone_number):
return resp


class SteamAuthenticatorError(Exception):
pass
class SteamAuthenticatorError(SteamError):
def __init__(self, message, eresult=None):
Exception.__init__(self, message, eresult)
self.message = message
self.eresult = EResult(eresult) if eresult is not None else None #: :class:`.EResult`|:class:`None`
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have plenty cases where there's no EResult available.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these is not needed. Simply inherit from SteamError. Don't set eresult to None where there is not result. Just leave the default.


def __str__(self):
return "(%s) %s" % (self.eresult, self.message) if self.eresult is not None else self.message


def generate_twofactor_code(shared_secret):
Expand Down