Updated responses and endpoint descriptions
This commit is contained in:
parent
44340f20b0
commit
17fc911290
2 changed files with 169 additions and 20 deletions
162
main.py
162
main.py
|
|
@ -1,5 +1,5 @@
|
|||
from asyncio import create_task
|
||||
from typing import Annotated
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import uvicorn
|
||||
from classes import ProcessStatus
|
||||
|
|
@ -15,42 +15,77 @@ app = FastAPI()
|
|||
|
||||
@app.get("/start")
|
||||
async def start() -> Responses.StartResponse:
|
||||
"Starts the Server process."
|
||||
"""Starts the Server's process if it is not already running.
|
||||
Returns:
|
||||
status: "started" or "running".
|
||||
message: The Server's response.
|
||||
"""
|
||||
|
||||
if Controllers.process.status() == ProcessStatus.RUNNING:
|
||||
return {"status": "running"}
|
||||
return {
|
||||
"status": "running",
|
||||
"message": "The Server was already running.",
|
||||
}
|
||||
|
||||
if Controllers.maintainance.is_set():
|
||||
Controllers.maintainance.unset()
|
||||
|
||||
Controllers.process.start()
|
||||
return {"status": "started"}
|
||||
return {
|
||||
"status": "started",
|
||||
"message": "The Server was started.",
|
||||
}
|
||||
|
||||
|
||||
@app.get("/status")
|
||||
async def status() -> Responses.StatusResponse:
|
||||
"Checks whether the Server is running and returns its information."
|
||||
"""Checks whether the Server is running and returns its information.
|
||||
Returns:
|
||||
status: One of "online", "offline", "crashed", "maintainance", or "starting".
|
||||
message: The Server's response.
|
||||
reason: if status is "maintainance", contains the reason for the Server's maintainance state.
|
||||
motd: if status is "online", contains the Server's MOTD as an HTML string.
|
||||
icon: if status is "online", contains the Server's icon as a base64 string.
|
||||
players: if status is "online", contains:
|
||||
online: the number of online players.
|
||||
max: the number of max allowed players.
|
||||
list: the list of online players' usernames as strings.
|
||||
"""
|
||||
|
||||
process_status = Controllers.process.status()
|
||||
if process_status != ProcessStatus.RUNNING:
|
||||
# Crashed
|
||||
if process_status == ProcessStatus.CRASHED:
|
||||
return {"status": "crashed"}
|
||||
return {
|
||||
"status": "crashed",
|
||||
"message": "The Server has crashed.",
|
||||
}
|
||||
# Maintainance
|
||||
if Controllers.maintainance.is_set():
|
||||
return {"status": "maintainance", "reason": Controllers.maintainance.get()}
|
||||
return {
|
||||
"status": "maintainance",
|
||||
"message": "The Server is offline due to maintainance.",
|
||||
"reason": Controllers.maintainance.get(),
|
||||
}
|
||||
# Offline
|
||||
return {"status": "offline"}
|
||||
return {
|
||||
"status": "offline",
|
||||
"message": "The Server is offline.",
|
||||
}
|
||||
|
||||
server_status = Controllers.server.status()
|
||||
|
||||
# Starting
|
||||
if not server_status["online"]:
|
||||
return {"status": "starting"}
|
||||
return {
|
||||
"status": "starting",
|
||||
"message": "The Server is starting.",
|
||||
}
|
||||
|
||||
# Online
|
||||
return {
|
||||
"status": "online",
|
||||
"message": "The Server is online.",
|
||||
"motd": server_status.get("motd", ""),
|
||||
"icon": server_status.get("icon", None),
|
||||
"players": server_status.get(
|
||||
|
|
@ -65,15 +100,50 @@ async def status() -> Responses.StatusResponse:
|
|||
|
||||
|
||||
@app.get("/stop")
|
||||
async def stop(data: Models.StopModel, authorization: Annotated[str, Header()]):
|
||||
"Stops the Server."
|
||||
async def stop(
|
||||
data: Models.StopModel, authorization: Annotated[str, Header()]
|
||||
) -> Responses.StopResponse:
|
||||
"""Stops the Server.
|
||||
It waits for `countdown` seconds, then runs `/stop` on the Server, and kills it after `timeout` seconds if it's still alive.
|
||||
Args:
|
||||
countdown: the time in seconds to give the players to leave the Server before initiating the shutdown.
|
||||
if set to 0, the shutdown phase is started immediately. Defaults to 60.
|
||||
reason: a brief message explaining why the Server is shutting down. Only shown if countdown is non-zero. Defaults to "".
|
||||
timeout: the time in seconds to wait before killing the Server if its process hasn't stopped. Defaults to 10.
|
||||
Headers:
|
||||
Authorization: the Authorization token.
|
||||
Returns:
|
||||
status: "stopping"
|
||||
message: The Server's response.
|
||||
"""
|
||||
|
||||
check_password(authorization)
|
||||
create_task(stop_server("STOPPING", data.countdown, data.reason, data.timeout))
|
||||
return {
|
||||
"status": "stopping",
|
||||
"message": "The Server is stopping.",
|
||||
}
|
||||
|
||||
|
||||
@app.get("/restart")
|
||||
async def restart(data: Models.RestartModel, authorization: Annotated[str, Header()]):
|
||||
"Restarts the Server."
|
||||
async def restart(
|
||||
data: Models.RestartModel, authorization: Annotated[str, Header()]
|
||||
) -> Responses.RestartResponse:
|
||||
"""Restarts the Server.
|
||||
It waits for `countdown` seconds, then runs `/stop` on the Server, and kills it after `timeout` seconds if it's still alive.
|
||||
Then, it starts the Server again.
|
||||
Args:
|
||||
countdown: the time in seconds to give the players to leave the Server before initiating the shutdown.
|
||||
if set to 0, the shutdown phase is started immediately. Defaults to 60.
|
||||
reason: a brief message explaining why the Server is restarting. Only shown if countdown is non-zero. Defaults to "".
|
||||
timeout: the time in seconds to wait before killing the Server if its process hasn't stopped. Defaults to 10.
|
||||
Headers:
|
||||
Authorization: the Authorization token.
|
||||
Returns:
|
||||
status: "restarting"
|
||||
message: The Server's response.
|
||||
"""
|
||||
|
||||
check_password(authorization)
|
||||
create_task(
|
||||
stop_server(
|
||||
|
|
@ -84,13 +154,30 @@ async def restart(data: Models.RestartModel, authorization: Annotated[str, Heade
|
|||
Controllers.process.start,
|
||||
)
|
||||
)
|
||||
return {
|
||||
"status": "restarting",
|
||||
"message": "The Server is restarting.",
|
||||
}
|
||||
|
||||
|
||||
@app.get("/maintainance")
|
||||
async def maintainance(
|
||||
data: Models.MaintainanceModel, authorization: Annotated[str, Header()]
|
||||
):
|
||||
"Stops the Server and sets it to maintainance status."
|
||||
) -> Responses.MaintainanceResponse:
|
||||
"""Stops the Server and sets it to maintainance status.
|
||||
It waits for `countdown` seconds, then runs `/stop` on the Server, and kills it after `timeout` seconds if it's still alive.
|
||||
Args:
|
||||
countdown: the time in seconds to give the players to leave the Server before initiating the shutdown.
|
||||
if set to 0, the shutdown phase is started immediately. Defaults to 60.
|
||||
reason: a brief message explaining why the Server is entering maintanance mode. Only shown if countdown is non-zero. Defaults to "".
|
||||
timeout: the time in seconds to wait before killing the Server if its process hasn't stopped. Defaults to 10.
|
||||
Headers:
|
||||
Authorization: the Authorization token.
|
||||
Returns:
|
||||
status: "stopping"
|
||||
message: The Server's response.
|
||||
"""
|
||||
|
||||
check_password(authorization)
|
||||
create_task(
|
||||
stop_server(
|
||||
|
|
@ -101,29 +188,64 @@ async def maintainance(
|
|||
Controllers.maintainance.set(data.reason),
|
||||
)
|
||||
)
|
||||
return {
|
||||
"status": "stopping",
|
||||
"message": "The Server is stopping for maintainance.",
|
||||
}
|
||||
|
||||
|
||||
@app.get("/command")
|
||||
async def command(
|
||||
data: Models.CommandModel, authorization: Annotated[str, Header()]
|
||||
) -> str:
|
||||
"Runs a command on the Server and returns its output."
|
||||
) -> Responses.CommandResponse:
|
||||
"""
|
||||
Executes a command on the Server and returns its output.
|
||||
Args:
|
||||
command: The command to execute.
|
||||
Headers:
|
||||
Authorization: the Authorization token.
|
||||
Returns:
|
||||
status: "executed"
|
||||
message: The Server's response.
|
||||
output: The command's output.
|
||||
"""
|
||||
|
||||
check_password(authorization)
|
||||
return Controllers.server.command(data.command)
|
||||
return {
|
||||
"status": "executed",
|
||||
"message": "The command was executed.",
|
||||
"output": Controllers.server.command(data.command),
|
||||
}
|
||||
|
||||
|
||||
@app.get("/logs")
|
||||
@app.get("/logs/stream")
|
||||
async def logs_stream(authorization: Annotated[str, Header()]) -> StreamingResponse:
|
||||
"""Streams Server logs in real-time using SSE.
|
||||
Headers:
|
||||
Authorization: the Authorization token.
|
||||
Returns: text/event-stream
|
||||
"""
|
||||
|
||||
check_password(authorization)
|
||||
return StreamingResponse(Controllers.logs.stream(), media_type="text/event-stream")
|
||||
|
||||
|
||||
@app.get("/logs/tail")
|
||||
async def logs_tail(
|
||||
data: Models.LogsTailModel, authorization: Annotated[str, Header()]
|
||||
authorization: Annotated[str, Header()],
|
||||
data: Optional[Models.LogsTailModel] = None,
|
||||
) -> StreamingResponse:
|
||||
"""Streams the last few lines of the Server's logs.
|
||||
Args:
|
||||
back: The number of lines to stream.
|
||||
Headers:
|
||||
Authorization: the Authorization token.
|
||||
Returns: text/event-stream
|
||||
"""
|
||||
|
||||
check_password(authorization)
|
||||
return StreamingResponse(Controllers.logs.tail(data.back))
|
||||
return StreamingResponse(Controllers.logs.tail(data.back if data else 10))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
27
responses.py
27
responses.py
|
|
@ -5,6 +5,7 @@ from typing_extensions import TypedDict
|
|||
|
||||
class StartResponse(TypedDict):
|
||||
status: Literal["running", "started"]
|
||||
message: str
|
||||
|
||||
|
||||
class StatusResponsePlayers(TypedDict):
|
||||
|
|
@ -15,13 +16,39 @@ class StatusResponsePlayers(TypedDict):
|
|||
|
||||
class StatusResponse(TypedDict):
|
||||
status: Literal["online", "offline", "crashed", "maintainance", "starting"]
|
||||
message: str
|
||||
reason: NotRequired[str]
|
||||
motd: NotRequired[str]
|
||||
icon: NotRequired[str | None]
|
||||
players: NotRequired[StatusResponsePlayers]
|
||||
|
||||
|
||||
class StopResponse(TypedDict):
|
||||
status: Literal["stopping"]
|
||||
message: str
|
||||
|
||||
|
||||
class RestartResponse(TypedDict):
|
||||
status: Literal["restarting"]
|
||||
message: str
|
||||
|
||||
|
||||
class MaintainanceResponse(TypedDict):
|
||||
status: Literal["stopping"]
|
||||
message: str
|
||||
|
||||
|
||||
class CommandResponse(TypedDict):
|
||||
status: Literal["executed"]
|
||||
message: str
|
||||
output: str
|
||||
|
||||
|
||||
class Responses:
|
||||
StartResponse = StartResponse
|
||||
StatusResponsePlayers = StatusResponsePlayers
|
||||
StatusResponse = StatusResponse
|
||||
StopResponse = StopResponse
|
||||
RestartResponse = RestartResponse
|
||||
MaintainanceResponse = MaintainanceResponse
|
||||
CommandResponse = CommandResponse
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue