import re from datetime import datetime from typing import List, Dict, Optional class ConsoleHandler: def __init__(self, server_manager): self.server_manager = server_manager self.command_history = [] self.max_history = 100 # Pre-defined command templates self.quick_commands = { 'say': 'say {message}', 'give': 'give {player} {item} {amount}', 'tp': 'tp {player} {target}', 'gamemode': 'gamemode {mode} {player}', 'time': 'time set {value}', 'weather': 'weather {type}', 'difficulty': 'difficulty {level}', 'whitelist_add': 'whitelist add {player}', 'whitelist_remove': 'whitelist remove {player}', 'ban': 'ban {player} {reason}', 'pardon': 'pardon {player}', 'kick': 'kick {player} {reason}', 'op': 'op {player}', 'deop': 'deop {player}', 'save': 'save-all', 'stop': 'stop', 'list': 'list' } def execute(self, command: str) -> Dict: """Execute a command and log it""" if not command.strip(): return {'success': False, 'message': 'Empty command'} # Add to history self.command_history.append({ 'command': command, 'timestamp': datetime.now().isoformat() }) if len(self.command_history) > self.max_history: self.command_history = self.command_history[-self.max_history:] # Send to server return self.server_manager.send_command(command) def execute_quick(self, cmd_type: str, **kwargs) -> Dict: """Execute a quick command template""" if cmd_type not in self.quick_commands: return {'success': False, 'message': f'Unknown command type: {cmd_type}'} template = self.quick_commands[cmd_type] try: command = template.format(**kwargs) return self.execute(command) except KeyError as e: return {'success': False, 'message': f'Missing parameter: {e}'} def get_history(self, limit: int = 50) -> List[Dict]: """Get command history""" return self.command_history[-limit:] def clear_history(self): """Clear command history""" self.command_history = [] def parse_log_line(self, line: str) -> Dict: """Parse a log line into structured data""" result = { 'raw': line, 'timestamp': None, 'level': 'INFO', 'thread': None, 'message': line, 'type': 'general' } # Parse timestamp and level: [HH:MM:SS] [Thread/LEVEL] match = re.match( r'\[(\d{2}:\d{2}:\d{2})\]\s*\[([^/]+)/(\w+)\]:\s*(.*)', line ) if match: result['timestamp'] = match.group(1) result['thread'] = match.group(2) result['level'] = match.group(3) result['message'] = match.group(4) # Detect message type if 'joined the game' in line: result['type'] = 'player_join' elif 'left the game' in line: result['type'] = 'player_leave' elif 'logged in' in line: result['type'] = 'player_login' elif '<' in line and '>' in line: result['type'] = 'chat' elif 'WARN' in line or 'WARNING' in line: result['type'] = 'warning' result['level'] = 'WARN' elif 'ERROR' in line or 'Exception' in line: result['type'] = 'error' result['level'] = 'ERROR' elif 'Done' in line: result['type'] = 'server_ready' elif 'Starting minecraft server' in line.lower(): result['type'] = 'server_start' return result def filter_logs(self, logs: List[Dict], level: Optional[str] = None, type_filter: Optional[str] = None, search: Optional[str] = None) -> List[Dict]: """Filter log entries""" filtered = logs if level: filtered = [l for l in filtered if l.get('level') == level] if type_filter: filtered = [l for l in filtered if l.get('type') == type_filter] if search: search_lower = search.lower() filtered = [l for l in filtered if search_lower in l.get('message', '').lower()] return filtered