From 3bc9c7c5547d6a0d12edb46ce8f39b729b78ea6c Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Fri, 17 Jun 2016 07:47:41 +0100 Subject: [PATCH 1/5] docs: clean up some internal refs in SteamClient --- steam/client/__init__.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/steam/client/__init__.py b/steam/client/__init__.py index 50bfe6f..d9609b2 100644 --- a/steam/client/__init__.py +++ b/steam/client/__init__.py @@ -12,17 +12,17 @@ Events | ``auth_code_required`` - either email code or 2FA code is needed for login | ``logged_on`` - after successful login, client can send messages | ``new_login_key`` - after new login key has been received and acknowledged - | :class:`EMsg ` - all messages are emitted with their ``EMsg`` + | :class:`.EMsg` - all messages are emitted with their :class:`.EMsg` number .. note:: Mixins can emitter additional events. See their docs pages for details. .. note:: - Additional features are located in separate submodules. All functionality from ``bultins`` is inherited by default. + Additional features are located in separate submodules. All functionality from :mod:`.builtins` is inherited by default. .. note:: - Optional features are available as ``mixins``. This allows the client to remain light yet flexible. + Optional features are available as :mod:`.mixins`. This allows the client to remain light yet flexible. """ import os @@ -85,12 +85,12 @@ class SteamClient(CMClient, BuiltinBase): self.credential_location = path def connect(self, *args, **kwargs): - """Attempt to establish connection, see :method:`.CMClient.connect`""" + """Attempt to establish connection, see :meth:`.CMClient.connect`""" self._bootstrap_cm_list_from_file() CMClient.connect(self, *args, **kwargs) def disconnect(self, *args, **kwargs): - """Close connection, see :method:`.CMClient.disconnect`""" + """Close connection, see :meth:`.CMClient.disconnect`""" self.logged_on = False CMClient.disconnect(self, *args, **kwargs) @@ -211,12 +211,12 @@ class SteamClient(CMClient, BuiltinBase): def reconnect(self, maxdelay=30, retry=0): """Implements explonential backoff delay before attempting to connect. - It is otherwise identical to calling :meth:`steam.core.cm.CMClient.connect`. + It is otherwise identical to calling :meth:`.CMClient.connect`. The delay is reset upon a successful login. :param maxdelay: maximum delay in seconds before connect (0-120s) :type maxdelay: :class:`int` - :param retry: see :meth:`steam.core.cm.CMClient.connect` + :param retry: see :meth:`.CMClient.connect` :type retry: :class:`int` :return: successful connection :rtype: :class:`bool` @@ -233,7 +233,7 @@ class SteamClient(CMClient, BuiltinBase): Send a message to CM :param message: a message instance - :type message: :class:`steam.core.msg.Msg`, :class:`steam.core.msg.MsgProto` + :type message: :class:`.Msg`, :class:`.MsgProto` """ if not self.connected: raise RuntimeError("Cannot send message while not connected") @@ -247,7 +247,7 @@ class SteamClient(CMClient, BuiltinBase): Not all messages are jobs, you'll have to find out which are which :param message: a message instance - :type message: :class:`steam.core.msg.Msg`, :class:`steam.core.msg.MsgProto` + :type message: :class:`.Msg`, :class:`.MsgProto` :return: ``jobid`` event identifier :rtype: :class:`str` @@ -285,13 +285,13 @@ class SteamClient(CMClient, BuiltinBase): Not all messages are jobs, you'll have to find out which are which :param message: a message instance - :type message: :class:`steam.core.msg.Msg`, :class:`steam.core.msg.MsgProto` + :type message: :class:`.Msg`, :class:`.MsgProto` :param timeout: (optional) seconds to wait :type timeout: :class:`int` :param raises: (optional) On timeout if ``False`` return ``None``, else raise ``gevent.Timeout`` :type raises: :class:`bool` :return: response proto message - :rtype: :class:`steam.core.msg.Msg`, :class:`steam.core.msg.MsgProto` + :rtype: :class:`.Msg`, :class:`.MsgProto` :raises: ``gevent.Timeout`` """ job_id = self.send_job(message) @@ -305,15 +305,15 @@ class SteamClient(CMClient, BuiltinBase): Send a message to CM and wait for a defined answer. :param message: a message instance - :type message: :class:`steam.core.msg.Msg`, :class:`steam.core.msg.MsgProto` + :type message: :class:`.Msg`, :class:`.MsgProto` :param response_emsg: emsg to wait for - :type response_emsg: :class:`steam.enums.emsg.EMsg`,:class:`int` + :type response_emsg: :class:`.EMsg`,:class:`int` :param timeout: (optional) seconds to wait :type timeout: :class:`int` :param raises: (optional) On timeout if ``False`` return ``None``, else raise ``gevent.Timeout`` :type raises: :class:`bool` :return: response proto message - :rtype: :class:`steam.core.msg.Msg`, :class:`steam.core.msg.MsgProto` + :rtype: :class:`.Msg`, :class:`.MsgProto` :raises: ``gevent.Timeout`` """ self.send(message) From 7c59f6917a153ff1305f48ac47354ec3ee085bd9 Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Sat, 18 Jun 2016 10:04:30 +0100 Subject: [PATCH 2/5] fix #38: genenerate_twofactor_code parameter order --- steam/guard.py | 6 +++--- tests/test_guard.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/steam/guard.py b/steam/guard.py index 7668719..2076386 100644 --- a/steam/guard.py +++ b/steam/guard.py @@ -290,15 +290,15 @@ def generate_twofactor_code_for_time(shared_secret, timestamp): return code -def generate_confirmation_key(identity_secret, timestamp, tag=''): +def generate_confirmation_key(identity_secret, tag, timestamp): """Generate confirmation key for trades. Can only be used once. :param identity_secret: authenticator identity secret :type identity_secret: bytes - :param timestamp: timestamp to use for generating key - :type timestamp: int :param tag: tag identifies what the request, see list below :type tag: str + :param timestamp: timestamp to use for generating key + :type timestamp: int :return: confirmation key :rtype: bytes diff --git a/tests/test_guard.py b/tests/test_guard.py index a219259..0e8ec57 100644 --- a/tests/test_guard.py +++ b/tests/test_guard.py @@ -12,8 +12,8 @@ class TCguard(unittest.TestCase): self.assertEqual(code, '94R9D') def test_generate_confirmation_key(self): - key = g.generate_confirmation_key(b'itsmemario', 100000) + key = g.generate_confirmation_key(b'itsmemario', '', 100000) self.assertEqual(key, b'\xed\xb5\xe5\xad\x8f\xf1\x99\x01\xc8-w\xd6\xb5 p\xccz\xd7\xd1\x05') - key = g.generate_confirmation_key(b'itsmemario', 100000, 'allow') + key = g.generate_confirmation_key(b'itsmemario', 'allow', 100000) self.assertEqual(key, b"Q'\x06\x80\xe1g\xa8m$\xb2hV\xe6g\x8b'\x8f\xf1L\xb0") From 4b2bc7f9f08c8b1d47a298ba6b94bd324dc48ab3 Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Sat, 18 Jun 2016 10:07:28 +0100 Subject: [PATCH 3/5] SteamAuthenticator: remove unnecessary action map --- steam/guard.py | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/steam/guard.py b/steam/guard.py index 2076386..a4a3bbf 100644 --- a/steam/guard.py +++ b/steam/guard.py @@ -105,14 +105,6 @@ class SteamAuthenticator(object): self.get_time() if timestamp is None else timestamp) def _send_request(self, action, params): - action_map = { - 'add': 'AddAuthenticator', - 'finalize': 'FinalizeAddAuthenticator', - 'remove': 'RemoveAuthenticator', - 'status': 'QueryStatus', - 'createcodes': 'CreateEmergencyCodes', - 'destroycodes': 'DestroyEmergencyCodes', - } medium = self.medium if isinstance(medium, MobileWebAuth): @@ -123,7 +115,7 @@ class SteamAuthenticator(object): params['http_timeout'] = 10 try: - resp = webapi.post('ITwoFactorService', action_map[action], 1, params=params) + resp = webapi.post('ITwoFactorService', action, 1, params=params) except requests.exceptions.RequestException as exp: raise SteamAuthenticatorError("Error adding via WebAPI: %s" % str(exp)) @@ -132,14 +124,14 @@ class SteamAuthenticator(object): if not medium.logged_on: raise SteamAuthenticatorError("SteamClient instance not logged in") - resp = medium.unified_messages.send_and_wait("TwoFactor.%s#1" % action_map[action], + resp = medium.unified_messages.send_and_wait("TwoFactor.%s#1" % action, params, timeout=10) if resp is None: raise SteamAuthenticatorError("Failed to add authenticator. Request timeout") resp = proto_to_dict(resp) - if action == 'add': + if action == 'AddAuthenticator': for key in ['shared_secret', 'identity_secret', 'secret_1']: resp[key] = b64encode(resp[key]) @@ -151,15 +143,13 @@ class SteamAuthenticator(object): :raises: :class:`SteamAuthenticatorError` """ - params = { + resp = self._send_request('AddAuthenticator', { 'steamid': self.medium.steam_id, 'authenticator_time': int(time()), 'authenticator_type': int(ETwoFactorTokenType.ValveMobileApp), 'device_identifier': generate_device_id(self.medium.steam_id), 'sms_phone_id': '1', - } - - resp = self._send_request('add', params) + }) if resp['status'] != EResult.OK: raise SteamAuthenticatorError("Failed to add authenticator. Error: %s" % repr(EResult(resp['status']))) @@ -177,14 +167,12 @@ class SteamAuthenticator(object): :type activation_code: str :raises: :class:`SteamAuthenticatorError` """ - params = { + resp = self._send_request('FinalizeAddAuthenticator', { 'steamid': self.medium.steam_id, 'authenticator_time': int(time()), 'authenticator_code': self.get_code(), 'activation_code': activation_code, - } - - resp = self._send_request('finalize', params) + }) if resp['status'] != EResult.TwoFactorActivationCodeMismatch and resp.get('want_more', False) and self._finalize_attempts: self.steam_time_offset += 30 @@ -208,13 +196,11 @@ class SteamAuthenticator(object): if not self.secrets: raise SteamAuthenticatorError("No authenticator secrets available?") - params = { + resp = self._send_request('RemoveAuthenticator', { 'steamid': self.medium.steam_id, 'revocation_code': self.revocation_code, 'steamguard_scheme': 1, - } - - resp = self._send_request('remove', params) + }) if not resp['success']: raise SteamAuthenticatorError("Failed to remove authenticator. (attempts remaining: %s)" % ( @@ -230,8 +216,7 @@ class SteamAuthenticator(object): :return: dict with status parameters :rtype: dict """ - params = {'steamid': self.medium.steam_id} - return self._send_request('status', params) + return self._send_request('QueryStatus', {'steamid': self.medium.steam_id}) def create_emergency_codes(self): """Generate emergency codes @@ -240,15 +225,14 @@ class SteamAuthenticator(object): :return: list of codes :rtype: list """ - return self._send_request('createcodes', {}).get('code', []) + return self._send_request('CreateEmergencyCodes', {}).get('code', []) def destroy_emergency_codes(self): """Destroy all emergency codes :raises: :class:`SteamAuthenticatorError` """ - params = {'steamid': self.medium.steam_id} - self._send_request('destroycodes', params) + self._send_request('DestroyEmergencyCodes', {'steamid': self.medium.steam_id}) class SteamAuthenticatorError(Exception): From ea3d5c5ac094787413558675b72515d4216fed5c Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Sat, 18 Jun 2016 10:21:44 +0100 Subject: [PATCH 4/5] SA: used entire AddAuthenticator response --- steam/guard.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/steam/guard.py b/steam/guard.py index a4a3bbf..6a78c6f 100644 --- a/steam/guard.py +++ b/steam/guard.py @@ -154,10 +154,7 @@ class SteamAuthenticator(object): if resp['status'] != EResult.OK: raise SteamAuthenticatorError("Failed to add authenticator. Error: %s" % repr(EResult(resp['status']))) - for key in ['shared_secret', 'identity_secret', 'serial_number', 'secret_1', 'revocation_code', 'token_gid']: - if key in resp: - self.secrets[key] = resp[key] - + self.secrets = resp self.steam_time_offset = int(resp['server_time']) - time() def finalize(self, activation_code): From c7448aac4611ec033c8f8d93ca2b44a4a7ad2b2a Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Sat, 18 Jun 2016 10:34:41 +0100 Subject: [PATCH 5/5] fix docs links in README [ci skip] --- README.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index 4dd8663..bdfc99e 100644 --- a/README.rst +++ b/README.rst @@ -9,14 +9,14 @@ Documentation: http://steam.readthedocs.io/en/latest/ Key features ------------ -* `SteamAuthenticator `_ - enable/disable/manage 2FA on account and generate codes -* `SteamClient `_ - communication with the steam network based on ``gevent``. -* `SteamID `_ - convert between the various ID representations with ease -* `WebAPI `_ - simple API for Steam's Web API with automatic population of interfaces -* `WebAuth `_ - authentication for access to ``store.steampowered.com`` and ``steamcommunity.com`` - -Checkout the `User guide `_ for examples, -or the `API Reference `_ for details. +* `SteamAuthenticator `_ - enable/disable/manage 2FA on account and generate codes +* `SteamClient `_ - communication with the steam network based on ``gevent``. +* `SteamID `_ - convert between the various ID representations with ease +* `WebAPI `_ - simple API for Steam's Web API with automatic population of interfaces +* `WebAuth `_ - authentication for access to ``store.steampowered.com`` and ``steamcommunity.com`` + +Checkout the `User guide `_ for examples, +or the `API Reference `_ for details. For questions, issues or general curiosity visit the repo at `https://github.com/ValvePython/steam `_.