""" Entry point for DirtyLeague Bot. Handles configuration loading, logging initialization, and global Kill Switch. """ import json import logging import os import sys import threading import time import keyboard CONFIG_FILE = "config.json" def setup_logging(log_level_str: str = "INFO"): os.makedirs("logs", exist_ok=True) log_file = os.path.join("logs", f"bot_{time.strftime('%Y%m%d_%H%M%S')}.log") # Ensure stdout handles unicode properly on Windows if hasattr(sys.stdout, "reconfigure"): try: sys.stdout.reconfigure(encoding="utf-8", errors="replace") except Exception: pass level = getattr(logging, log_level_str.upper(), logging.INFO) logging.basicConfig( level=level, format="%(asctime)s [%(levelname)s] %(message)s", handlers=[ logging.FileHandler(log_file, encoding="utf-8"), logging.StreamHandler(sys.stdout) ] ) logging.info(f"Logging initialized. Log file: {log_file}") def load_config(): if not os.path.exists(CONFIG_FILE): raise FileNotFoundError(f"Configuration file '{CONFIG_FILE}' not found.") with open(CONFIG_FILE, "r", encoding="utf-8") as f: return json.load(f) def main(): import argparse parser = argparse.ArgumentParser(description="DirtyLeague Autonomous FSM Bot") parser.add_argument("--duration", type=int, default=None, help="Stop after N seconds") parser.add_argument("--cycles", type=int, default=None, help="Stop after N battles/cycles") args = parser.parse_args() config = load_config() bot_conf = config.get("bot", {}) setup_logging(config.get("log_level", "INFO")) kill_key = bot_conf.get("kill_switch_key", "q") logging.info(f"Starting DirtyLeague Bot. Press '{kill_key.upper()}' at ANY time for Emergency Stop (Kill Switch).") from bot_core import DirtyLeagueBot bot = DirtyLeagueBot(config=config) stop_event = threading.Event() def kill_switch_listener(): while not stop_event.is_set(): if keyboard.is_pressed(kill_key): logging.warning(f"!!! KILL SWITCH '{kill_key.upper()}' PRESSED! Stopping bot immediately... !!!") bot.stop() stop_event.set() break time.sleep(0.05) listener_thread = threading.Thread(target=kill_switch_listener, daemon=True) listener_thread.start() try: bot.start(max_duration_sec=args.duration, max_cycles=args.cycles) except KeyboardInterrupt: logging.info("Bot interrupted by User (Ctrl+C).") except Exception as e: logging.exception(f"Unexpected error in bot execution: {e}") finally: stop_event.set() bot.stop() logging.info("Bot stopped successfully.") if __name__ == "__main__": main()