diff --git a/discordgsm/protocols/asa.py b/discordgsm/protocols/asa.py index 1415cc7..a5d6fae 100644 --- a/discordgsm/protocols/asa.py +++ b/discordgsm/protocols/asa.py @@ -1,6 +1,7 @@ import time from typing import TYPE_CHECKING +import aiohttp import opengsq from discordgsm.protocols.protocol import Protocol @@ -36,29 +37,76 @@ async def query(self): await self.pre_query() host, port = str(self.kv["host"]), int(str(self.kv["port"])) - eos = opengsq.EOS( - host, port, self._deployment_id, ASA._access_token, self.timeout - ) start = time.time() - info = await eos.get_info() - ping = int((time.time() - start) * 1000) + + # Try EOS first + try: + eos = opengsq.EOS( + host, port, self._deployment_id, ASA._access_token, self.timeout + ) + info = await eos.get_info() + ping = int((time.time() - start) * 1000) + + # Credits: @dkoz https://github.com/DiscordGSM/GameServerMonitor/pull/54/files + attributes = dict(info.get("attributes", {})) + settings = dict(info.get("settings", {})) - # Credits: @dkoz https://github.com/DiscordGSM/GameServerMonitor/pull/54/files - attributes = dict(info.get("attributes", {})) - settings = dict(info.get("settings", {})) + result: GamedigResult = { + "name": attributes.get("CUSTOMSERVERNAME_s", ""), + "map": attributes.get("MAPNAME_s", ""), + "password": attributes.get("SERVERPASSWORD_b", False), + "numplayers": info.get("totalPlayers", 0), + "numbots": 0, + "maxplayers": settings.get("maxPublicPlayers", 0), + "players": None, + "bots": None, + "connect": f"{host}:{port}", + "ping": ping, + "raw": info, + } - result: GamedigResult = { - "name": attributes.get("CUSTOMSERVERNAME_s", ""), - "map": attributes.get("MAPNAME_s", ""), - "password": attributes.get("SERVERPASSWORD_b", False), - "numplayers": info.get("totalPlayers", 0), - "numbots": 0, - "maxplayers": settings.get("maxPublicPlayers", 0), - "players": None, - "bots": None, - "connect": f"{host}:{port}", - "ping": ping, - "raw": info, - } + return result + except Exception: + # EOS failed, fallback to BattleMetrics + start = time.time() # Restart timer for BattleMetrics query + + # Fallback: Query BattleMetrics API by IP:port + async with aiohttp.ClientSession() as session: + url = f"https://api.battlemetrics.com/servers?filter[game]=arksa&filter[search]={host}:{port}" + async with session.get(url, timeout=aiohttp.ClientTimeout(total=self.timeout)) as response: + if response.status != 200: + raise Exception(f"BattleMetrics API returned {response.status}") + + data = await response.json() + servers = data.get("data", []) + + # Find the online server matching our IP:port + server_info = None + for server in servers: + attrs = server.get("attributes", {}) + if attrs.get("ip") == host and attrs.get("port") == port and attrs.get("status") == "online": + server_info = server + break + + if not server_info: + raise Exception(f"No online server found on BattleMetrics for {host}:{port}") + + ping = int((time.time() - start) * 1000) + attrs = server_info.get("attributes", {}) + details = attrs.get("details", {}) + + result: GamedigResult = { + "name": attrs.get("name", ""), + "map": details.get("map", ""), + "password": details.get("password", False), + "numplayers": attrs.get("players", 0), + "numbots": 0, + "maxplayers": attrs.get("maxPlayers", 0), + "players": None, + "bots": None, + "connect": f"{host}:{port}", + "ping": ping, + "raw": attrs, + } - return result + return result