from fastapi import FastAPI from fastapi.responses import JSONResponse, Response import os, argparse from a2s import ainfo as VALVE_SERVER_INFO from a2s import aplayers as VALVE_SERVER_PLAYERS from rcon.source import rcon as VALVE_SERVER_RCON from time import time from pydantic import BaseModel from RCONPlayerModel import * import traceback class A2S_request(BaseModel): server: str = None @property def address(self): return self.server.split(":")[0] @property def port(self): return int(self.server.split(":")[1]) @property def tuple_address(self): return (self.address, self.port) class RCON_Request(A2S_request): password: str = None command: str = None @property def fulled_data(self): return self.server and self.password and self.command class SourceBackend: app = None def __init__(self): self.app = FastAPI() self.setup_routes() def run(self, host = "0.0.0.0", port = 45353): import uvicorn uvicorn.run(self.app, host = host, port = port) def setup_routes(self): @self.app.get("/api/ping") async def get_ping(): return {"pong":int(time())} @self.app.post("/api/rcon") async def execute_rcon(request: RCON_Request): if not request.fulled_data: return Response(status_code=409) try: return await VALVE_SERVER_RCON( request.command, host = request.address, port = request.port, passwd = request.password ) except: return Response(status_code = 400) @self.app.post("/api/a2s/info") async def get_a2s_info(request: A2S_request): if not request.address: return Response(status_code=409) try: return JSONResponse(content=dict(await VALVE_SERVER_INFO(request.tuple_address))) except: traceback.print_exc() return Response(status_code = 400) @self.app.post("/api/a2s/players") async def get_a2s_players(request: A2S_request): if not request.address: return Response(status_code=409) try: return JSONResponse(content=dict(await VALVE_SERVER_PLAYERS(request.tuple_address))) except: traceback.print_exc() return Response(status_code = 400) @self.app.post("/api/players") async def get_players(request: RCON_Request): a2s_players = await VALVE_SERVER_PLAYERS(request.tuple_address) status_lines:str = await VALVE_SERVER_RCON( "status", host = request.address, port = request.port, passwd = request.password ) try: start_index = status_lines.index("# userid") except: return Response(status_code = 400) skip_table_header = True players:list[RCONPlayer] = [] for line in status_lines[start_index:].split("\n"): if skip_table_header or line.__len__() < 1: skip_table_header = False continue try: players.append(RCONPlayer(line).__dict__) except: traceback.print_exc() pass for a2s_player in a2s_players: for rcon_player in players: if rcon_player["name"] == a2s_player.name: rcon_player["score"] = a2s_player.score break return JSONResponse(content=players) if __name__ == "__main__": SourceBackend().run(port = 8082)