3 changed files with 169 additions and 1 deletions
@ -0,0 +1,159 @@ |
|||
""" |
|||
Game Servers related functionality |
|||
""" |
|||
from steam.steamid import SteamID |
|||
from steam.core.msg import MsgProto |
|||
from steam.enums.emsg import EMsg |
|||
from steam.util import ip_to_int, ip_from_int, proto_to_dict |
|||
|
|||
|
|||
class GameServers(object): |
|||
def __init__(self, *args, **kwargs): |
|||
super(GameServers, self).__init__(*args, **kwargs) |
|||
|
|||
self.gameservers = SteamGameServers(self) #: instance of :class:`SteamGameServers` |
|||
|
|||
|
|||
class SteamGameServers(object): |
|||
def __init__(self, steam): |
|||
self.steam = steam |
|||
|
|||
def query(self, filter_text, max_servers=10, **kwargs): |
|||
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 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', 'server_port': 27015}, |
|||
{'auth_players': 6, 'server_ip': '1.2.3.4', 'server_port': 27016}, |
|||
... |
|||
] |
|||
""" |
|||
if 'geo_location_ip' in kwargs: |
|||
kwargs['geo_location_ip'] = ip_to_int(kwargs['geo_location_ip']) |
|||
|
|||
kwargs['filter_text'] = filter_text |
|||
kwargs['max_servers'] = max_servers |
|||
|
|||
resp = self.steam.send_job_and_wait(MsgProto(EMsg.ClientGMSServerQuery), kwargs, timeout=30) |
|||
|
|||
if resp is None: return None |
|||
|
|||
resp = proto_to_dict(resp) |
|||
|
|||
for server in resp['servers']: |
|||
server['server_ip'] = ip_from_int(server['server_ip']) |
|||
|
|||
return resp['servers'] |
|||
|
|||
def get_server_list(self, filter_text, max_servers=10): |
|||
""" |
|||
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 |
|||
:returns: list of servers, see below. (``None`` is returned steam doesn't respond) |
|||
:rtype: :class:`list`, :class:`None` |
|||
|
|||
|
|||
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.steam.unified_messages.send_and_wait("GameServers.GetServerList#1", { |
|||
"filter": filter_text, |
|||
"limit": max_servers, |
|||
}, timeout=30) |
|||
|
|||
if resp is None: return None |
|||
|
|||
resp = proto_to_dict(resp) |
|||
|
|||
for server in resp['servers']: |
|||
server['steamid'] = SteamID(server['steamid']) |
|||
|
|||
return resp['servers'] |
|||
|
|||
def get_ips_from_steamid(self, server_steam_ids): |
|||
"""Resolve IPs from SteamIDs |
|||
|
|||
:param server_steam_ids: a list of steamids |
|||
:type server_steam_ids: list |
|||
:return: map of ips to steamids |
|||
:rtype: dict |
|||
|
|||
Sample response: |
|||
|
|||
.. code:: python |
|||
|
|||
{SteamID(id=123456, type='AnonGameServer', universe='Public', instance=1234): '1.2.3.4:27060'} |
|||
""" |
|||
resp = self.steam.unified_messages.send_and_wait("GameServers.GetServerIPsBySteamID#1", { |
|||
"server_steamids": server_steam_ids, |
|||
}, timeout=30) |
|||
|
|||
if resp is None: return None |
|||
|
|||
return {SteamID(server.steamid): server.addr for server in resp.servers} |
|||
|
|||
def get_steamids_from_ip(self, server_ips): |
|||
"""Resolve SteamIDs from IPs |
|||
|
|||
:param steam_ids: a list of ips (e.g. ``['1.2.3.4:27015',...]``) |
|||
:type steam_ids: list |
|||
:return: map of steamids to ips |
|||
:rtype: dict |
|||
|
|||
Sample response: |
|||
|
|||
.. code:: python |
|||
|
|||
{'1.2.3.4:27060': SteamID(id=123456, type='AnonGameServer', universe='Public', instance=1234)} |
|||
""" |
|||
resp = self.steam.unified_messages.send_and_wait("GameServers.GetServerSteamIDsByIP#1", { |
|||
"server_ips": server_ips, |
|||
}, timeout=30) |
|||
|
|||
if resp is None: return None |
|||
|
|||
return {server.addr: SteamID(server.steamid) for server in resp.servers} |
Loading…
Reference in new issue