import json from datetime import datetime, timezone from core.dal.base_repository import BaseRepository class PlayerRepository(BaseRepository): def get_all(self, server_id: int) -> list[dict]: return self._fetchall( "SELECT * FROM players WHERE server_id = :sid ORDER BY slot_id", {"sid": server_id}, ) def count(self, server_id: int) -> int: row = self._fetchone( "SELECT COUNT(*) as cnt FROM players WHERE server_id = :sid", {"sid": server_id}, ) return row["cnt"] if row else 0 def upsert(self, server_id: int, player: dict) -> None: now = datetime.now(timezone.utc).isoformat() self._execute( """ INSERT INTO players (server_id, slot_id, name, guid, ip, ping, game_data, joined_at, updated_at) VALUES (:sid, :slot, :name, :guid, :ip, :ping, :gd, :now, :now) ON CONFLICT(server_id, slot_id) DO UPDATE SET name = excluded.name, guid = excluded.guid, ping = excluded.ping, game_data = excluded.game_data, updated_at = excluded.updated_at """, { "sid": server_id, "slot": str(player.get("slot_id", "")), "name": player.get("name", ""), "guid": player.get("guid"), "ip": player.get("ip"), "ping": player.get("ping"), "gd": json.dumps(player.get("game_data", {})), "now": now, }, ) def get_by_slot(self, server_id: int, slot_id: int) -> dict | None: return self._fetchone( "SELECT * FROM players WHERE server_id = :sid AND slot_id = :slot", {"sid": server_id, "slot": str(slot_id)}, ) def clear(self, server_id: int) -> None: self._execute("DELETE FROM players WHERE server_id = :sid", {"sid": server_id}) def get_history( self, server_id: int, limit: int = 50, offset: int = 0, search: str | None = None, ) -> tuple[int, list[dict]]: conditions = ["server_id = :sid"] params: dict = {"sid": server_id, "limit": limit, "offset": offset} if search: conditions.append("name LIKE :search") params["search"] = f"%{search}%" where = " AND ".join(conditions) total_row = self._fetchone( f"SELECT COUNT(*) as cnt FROM player_history WHERE {where}", params ) total = total_row["cnt"] if total_row else 0 rows = self._fetchall( f"SELECT * FROM player_history WHERE {where} ORDER BY left_at DESC LIMIT :limit OFFSET :offset", params, ) return total, rows