Files
languard-servers-manager/backend/core/servers/players_router.py
Tran G. (Revernomad) Khoa 5a62d21def feat: implement phases 3-5 of Arma 3 UX enhancement plan
Phase 3 - Mod display names + split-pane selector:
- Parse mod.cpp/meta.cpp for display_name and workshop_id
- Rewrite ModList as two-pane available/selected interface

Phase 4 - Player kick/ban from Players tab:
- Add get_by_slot() to PlayerRepository
- Add get_rcon_client() class method to ThreadRegistry
- Add /players/{slot_id}/kick and /ban endpoints
- Rewrite PlayerTable with kick/ban modals and ban presets

Phase 5 - Historical log file browser:
- Add list_log_files() and get_log_file_path() to RPTParser
- Add logfiles_router with GET/download/DELETE endpoints
- Update LogViewer with collapsible log files section (download + delete)
2026-04-17 20:47:37 +07:00

94 lines
2.7 KiB
Python

"""Player endpoints — list current players for a running server."""
from __future__ import annotations
import logging
from typing import Annotated
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from sqlalchemy.engine import Connection
from core.dal.player_repository import PlayerRepository
from core.servers.service import ServerService
from database import get_db
from dependencies import get_current_user, require_admin
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/servers/{server_id}/players", tags=["players"])
class KickRequest(BaseModel):
reason: str = "Kicked by admin"
class BanFromPlayerRequest(BaseModel):
reason: str = "Banned by admin"
duration_minutes: int | None = None
def _ok(data):
return {"success": True, "data": data, "error": None}
@router.get("")
def list_players(
server_id: int,
db: Annotated[Connection, Depends(get_db)],
_user: Annotated[dict, Depends(get_current_user)],
) -> dict:
"""List current players (cached from RemoteAdminPollerThread)."""
ServerService(db).get_server(server_id) # raises 404 if not found
player_repo = PlayerRepository(db)
players = player_repo.get_all(server_id=server_id)
count = player_repo.count(server_id=server_id)
return _ok({
"server_id": server_id,
"player_count": count,
"players": players,
})
@router.get("/history")
def player_history(
server_id: int,
db: Annotated[Connection, Depends(get_db)],
_user: Annotated[dict, Depends(get_current_user)],
limit: int = 100,
offset: int = 0,
search: str | None = None,
) -> dict:
"""Get historical player sessions."""
ServerService(db).get_server(server_id) # raises 404 if not found
player_repo = PlayerRepository(db)
total, rows = player_repo.get_history(
server_id=server_id, limit=limit, offset=offset, search=search,
)
return _ok({"total": total, "items": rows})
@router.post("/{slot_id}/kick")
def kick_player(
server_id: int,
slot_id: int,
body: KickRequest,
db: Annotated[Connection, Depends(get_db)],
_admin: Annotated[dict, Depends(require_admin)],
) -> dict:
ServerService(db).kick_player(server_id, slot_id, body.reason)
return _ok({"message": f"Player {slot_id} kicked"})
@router.post("/{slot_id}/ban")
def ban_player_from_list(
server_id: int,
slot_id: int,
body: BanFromPlayerRequest,
db: Annotated[Connection, Depends(get_db)],
admin: Annotated[dict, Depends(require_admin)],
) -> dict:
ban = ServerService(db).ban_from_player(
server_id, slot_id, body.reason, body.duration_minutes,
banned_by=admin["username"],
)
return _ok(ban)