예제 #1
0
    def get_product_info(self, appids=[], packageids=[]):
        try:
            resp = self.steam.send_job_and_wait(MsgProto(EMsg.ClientPICSProductInfoRequest),
                                                {
                'apps': map(lambda x: {'appid': x}, appids),
                'packages': map(lambda x: {'packageid': x}, packageids),
            },
                timeout=10
            )

            if not resp:
                return {}

            resp = proto_to_dict(resp)

            for app in resp.get('apps', []):
                app['appinfo'] = vdf.loads(
                    app.pop('buffer')[:-1].decode('utf-8', 'replace'))['appinfo']
                app['sha'] = hexlify(app['sha']).decode('utf-8')
            for pkg in resp.get('packages', []):
                pkg['appinfo'] = vdf.binary_loads(pkg.pop('buffer')[4:])[
                    str(pkg['packageid'])]
                pkg['sha'] = hexlify(pkg['sha']).decode('utf-8')

            return resp
        except Exception as e:
            print('get_product_info() exception: ' + str(e))
            return {}
예제 #2
0
    def query(self, filter_text, max_servers=10, timeout=30, **kw):
        r"""
        Query game servers

        https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol

        .. note::
            When specifying ``filter_text`` use *raw strings* otherwise python won't treat backslashes
            as literal characters (e.g. ``query(r'\appid\730\white\1')``)

        :param filter_text: filter for servers
        :type  filter_text: str
        :param max_servers: (optional) number of servers to return
        :type  max_servers: int
        :param timeout: (optional) timeout for request in seconds
        :type  timeout: int
        :param app_id: (optional) app id
        :type  app_id: int
        :param geo_location_ip: (optional) ip (e.g. '1.2.3.4')
        :type  geo_location_ip: str
        :returns: list of servers, see below. (``None`` is returned steam doesn't respond)
        :rtype: :class:`list`, :class:`None`

        Sample response:

        .. code:: python

            [{'auth_players': 0, 'server_ip': '1.2.3.4', 'query_port': 27015},
             {'auth_players': 6, 'server_ip': '1:2:3:4::5', 'query_port': 27016},
             ...
            ]
        """
        if 'geo_location_ip' in kw:
            kw['geo_location_ip'] = ip4_to_int(kw['geo_location_ip'])

        kw['filter_text'] = filter_text
        kw['max_servers'] = max_servers

        resp = self._s.send_job_and_wait(
            MsgProto(EMsg.ClientGMSServerQuery),
            kw,
            timeout=timeout,
        )

        if resp is None:
            return None

        resp = proto_to_dict(resp)

        for server in resp['servers']:
            server.pop('deprecated_server_ip', None)  # no point returning this

            if 'v4' in server['server_ip']:
                server['server_ip'] = ip4_from_int(server['server_ip']['v4'])
            else:
                server['server_ip'] = ip6_from_bytes(server['server_ip']['v6'])

        return resp['servers']
예제 #3
0
 def get_product_changes(self, since_change_number):
     resp = self.steam.send_job_and_wait(MsgProto(
         EMsg.ClientPICSChangesSinceRequest), {
             'since_change_number': since_change_number,
             'send_app_info_changes': True,
             'send_package_info_changes': True,
         },
                                         timeout=10)
     return proto_to_dict(resp) or {}
예제 #4
0
 def get_product_changes(self, since_change_number):
     try:
         resp = self.steam.send_job_and_wait(MsgProto(EMsg.ClientPICSChangesSinceRequest),
                                             {
             'since_change_number': since_change_number,
             'send_app_info_changes': True,
             'send_package_info_changes': True,
         },
             timeout=10
         )
         return proto_to_dict(resp) or {}
     except Exception as e:
         print('get_product_changes() exception: ' + str(e))
         return {}
예제 #5
0
    def test_proto_from_dict_to_dict(self):
        DATA = {
            'buffers': [{
                'data':
                b'some data',
                'flags': [{
                    'flag': True
                }, {
                    'flag': False
                }, {
                    'flag': False
                }]
            }, {
                'data':
                b'\x01\x02\x03\x04',
                'flags': [{
                    'flag': False
                }, {
                    'flag': True
                }, {
                    'flag': True
                }]
            }],
            'list_number32': [
                4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576,
                4194304, 16777216, 67108864, 268435456, 1073741824
            ],
            'list_number64': [
                4, 64, 1024, 16384, 262144, 1125899906842624,
                18014398509481984, 288230376151711744, 4611686018427387904
            ],
            'messages': [{
                'text': 'test string'
            }, {
                'text': 'another one'
            }, {
                'text': 'third'
            }],
            'number32':
            16777216,
            'number64':
            72057594037927936
        }

        utp.proto_fill_from_dict(self.msg, DATA)

        RESULT = utp.proto_to_dict(self.msg)

        self.assertEqual(DATA, RESULT)
예제 #6
0
    def _send_request(self, action, params):
        backend = self.backend

        if isinstance(backend, MobileWebAuth):
            if not backend.logged_on:
                raise SteamAuthenticatorError(
                    "MobileWebAuth instance not logged in")

            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))

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

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

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

            resp = proto_to_dict(resp.body)

            if action == 'AddAuthenticator':
                for key in ['shared_secret', 'identity_secret', 'secret_1']:
                    resp[key] = b64encode(resp[key]).decode('ascii')

        return resp
예제 #7
0
 def get_player_count(self, appid):
     resp = self.steam.send_job_and_wait(MsgProto(
         EMsg.ClientGetNumberOfCurrentPlayersDP), {'appid': appid},
                                         timeout=10)
     return proto_to_dict(resp) or {}
예제 #8
0
    def get_server_list(self, filter_text, max_servers=10, timeout=20):
        """
        Get list of servers. Works similiarly to :meth:`query`, but the response has more details.

        :param filter_text: filter for servers
        :type  filter_text: str
        :param max_servers: (optional) number of servers to return
        :type  max_servers: int
        :param timeout: (optional) timeout for request in seconds
        :type  timeout: int
        :returns: list of servers, see below. (``None`` is returned steam doesn't respond)
        :rtype: :class:`list`, :class:`None`
        :raises: :class:`.SteamError`


        Sample response:

        .. code:: python

            [{'addr': '1.2.3.4:27067',
              'appid': 730,
              'bots': 0,
              'dedicated': True,
              'gamedir': 'csgo',
              'gameport': 27067,
              'gametype': 'valve_ds,empty,secure',
              'map': 'de_dust2',
              'max_players': 10,
              'name': 'Valve CS:GO Asia Server (srcdsXXX.XXX.XXX)',
              'os': 'l',
              'players': 0,
              'product': 'csgo',
              'region': 5,
              'secure': True,
              'steamid': SteamID(id=3279818759, type='AnonGameServer', universe='Public', instance=7011),
              'version': '1.35.4.0'}
            ]
        """
        resp = self._s.send_um_and_wait(
            "GameServers.GetServerList#1",
            {
                "filter": filter_text,
                "limit": max_servers,
            },
            timeout=20,
        )

        if resp is None:
            return None
        if resp.header.eresult != EResult.OK:
            raise SteamError(resp.header.error_message, resp.header.eresult)

        resp = proto_to_dict(resp.body)

        if not resp:
            return []
        else:
            for server in resp['servers']:
                server['steamid'] = SteamID(server['steamid'])

            return resp['servers']