import json import os from pathlib import Path from datetime import datetime from typing import List, Dict, Optional from config import config class PlayerTracker: def __init__(self, server_manager): self.server_manager = server_manager self.players_data_file = config.SERVER_DIR / "players_data.json" self.players_data = self._load_data() def _load_data(self) -> Dict: """Load player data from file""" if self.players_data_file.exists(): try: with open(self.players_data_file, 'r') as f: return json.load(f) except: pass return {'players': {}} def _save_data(self): """Save player data to file""" with open(self.players_data_file, 'w') as f: json.dump(self.players_data, f, indent=2) def record_join(self, player_name: str): """Record player joining""" if player_name not in self.players_data['players']: self.players_data['players'][player_name] = { 'first_seen': datetime.now().isoformat(), 'last_seen': datetime.now().isoformat(), 'join_count': 0, 'play_time': 0, 'is_banned': False, 'is_op': False, 'notes': '' } self.players_data['players'][player_name]['last_seen'] = datetime.now().isoformat() self.players_data['players'][player_name]['join_count'] += 1 self.players_data['players'][player_name]['_join_time'] = datetime.now().isoformat() self._save_data() def record_leave(self, player_name: str): """Record player leaving""" if player_name in self.players_data['players']: player = self.players_data['players'][player_name] player['last_seen'] = datetime.now().isoformat() if '_join_time' in player: join_time = datetime.fromisoformat(player['_join_time']) session_time = (datetime.now() - join_time).total_seconds() player['play_time'] = player.get('play_time', 0) + session_time del player['_join_time'] self._save_data() def get_online_players(self) -> List[Dict]: """Get list of online players with details""" online = [] for name in self.server_manager.players_online: player_data = self.players_data['players'].get(name, {}) online.append({ 'name': name, 'join_count': player_data.get('join_count', 1), 'is_op': player_data.get('is_op', False), 'first_seen': player_data.get('first_seen', 'Now'), 'play_time': self._format_time(player_data.get('play_time', 0)) }) return online def get_all_players(self) -> List[Dict]: """Get all known players""" players = [] for name, data in self.players_data['players'].items(): players.append({ 'name': name, 'online': name in self.server_manager.players_online, 'first_seen': data.get('first_seen', 'Unknown'), 'last_seen': data.get('last_seen', 'Unknown'), 'join_count': data.get('join_count', 0), 'play_time': self._format_time(data.get('play_time', 0)), 'is_banned': data.get('is_banned', False), 'is_op': data.get('is_op', False), 'notes': data.get('notes', '') }) return players def _format_time(self, seconds: float) -> str: """Format seconds to readable time""" hours = int(seconds // 3600) minutes = int((seconds % 3600) // 60) if hours > 0: return f"{hours}h {minutes}m" return f"{minutes}m" def kick_player(self, player_name: str, reason: str = "Kicked by admin") -> Dict: """Kick a player""" if player_name not in self.server_manager.players_online: return {'success': False, 'message': 'Player not online'} return self.server_manager.send_command(f'kick {player_name} {reason}') def ban_player(self, player_name: str, reason: str = "Banned by admin") -> Dict: """Ban a player""" result = self.server_manager.send_command(f'ban {player_name} {reason}') if result['success']: if player_name in self.players_data['players']: self.players_data['players'][player_name]['is_banned'] = True self._save_data() return result def pardon_player(self, player_name: str) -> Dict: """Unban a player""" result = self.server_manager.send_command(f'pardon {player_name}') if result['success']: if player_name in self.players_data['players']: self.players_data['players'][player_name]['is_banned'] = False self._save_data() return result def op_player(self, player_name: str) -> Dict: """Give operator status""" result = self.server_manager.send_command(f'op {player_name}') if result['success']: if player_name in self.players_data['players']: self.players_data['players'][player_name]['is_op'] = True self._save_data() return result def deop_player(self, player_name: str) -> Dict: """Remove operator status""" result = self.server_manager.send_command(f'deop {player_name}') if result['success']: if player_name in self.players_data['players']: self.players_data['players'][player_name]['is_op'] = False self._save_data() return result def update_notes(self, player_name: str, notes: str) -> Dict: """Update player notes""" if player_name not in self.players_data['players']: self.players_data['players'][player_name] = {} self.players_data['players'][player_name]['notes'] = notes self._save_data() return {'success': True, 'message': 'Notes updated'} def get_whitelist(self) -> List[str]: """Get whitelist""" whitelist_file = config.SERVER_DIR / "whitelist.json" if whitelist_file.exists(): try: with open(whitelist_file, 'r') as f: data = json.load(f) return [p.get('name', '') for p in data] except: pass return [] def get_ops(self) -> List[str]: """Get ops list""" ops_file = config.SERVER_DIR / "ops.json" if ops_file.exists(): try: with open(ops_file, 'r') as f: data = json.load(f) return [p.get('name', '') for p in data] except: pass return [] def get_banned(self) -> List[Dict]: """Get banned players""" banned_file = config.SERVER_DIR / "banned-players.json" if banned_file.exists(): try: with open(banned_file, 'r') as f: return json.load(f) except: pass return []