from fastapi.responses import StreamingResponse from fastapi import HTTPException from mcstatus import JavaServer from dotenv import load_dotenv from fastapi import FastAPI from mcrcon import MCRcon from os import environ from lib import CommandModel, LogsModel, sse_from_iterator from handler import ServerHandler load_dotenv() MCSMGR_PASSWORD = environ.get("MCSMGR_PASSWORD", "SuperSecretPassword") MINECRAFT_SERVER_COMMAND = environ.get( "MINECRAFT_SERVER_COMMAND", "java -jar fabric.jar nogui") MINECRAFT_SERVER_ADDRESS = environ.get("MINECRAFT_SERVER_ADDRESS", "localhost") MINECRAFT_SERVER_RCON_PASSWORD = environ.get( "MINECRAFT_SERVER_RCON_PASSWORD", "SuperSecretPassword") app = FastAPI() handler = ServerHandler(MINECRAFT_SERVER_COMMAND.split()) server = JavaServer(MINECRAFT_SERVER_ADDRESS) @app.get("/status") async def status(): try: info = server.status() except: return {"online": False} return { "online": True, "latency": info.latency, "motd": info.motd, "players": { "list": info.players.sample, "online": info.players.online, "max": info.players.max, }, } @app.post("/command") async def command(data: CommandModel): if data.password != MCSMGR_PASSWORD: raise HTTPException(403, "Invalid password") try: with MCRcon(MINECRAFT_SERVER_ADDRESS, MINECRAFT_SERVER_RCON_PASSWORD) as mcr: return mcr.command(data.cmd) except: raise HTTPException(500, "Unable to reach Server") @app.post("/start") async def start(): await handler.start() @app.get("/logs") async def logs(data: LogsModel): if data.password != MCSMGR_PASSWORD: raise HTTPException(401, "Invalid password") generator = sse_from_iterator(handler.reader()) return StreamingResponse(generator, media_type="text/event-stream")