import logging from typing import Optional from config import BotConfig, HARDCODED_USERNAME, HARDCODED_PASSWORD from browser_session import BrowserSession from auth_handler import AuthHandler from modify_listings_updater import update_wo_case_listing_prices import queue logger = logging.getLogger("bot") class QueueLoggingHandler(logging.Handler): def __init__(self, q: queue.Queue): super().__init__() self.q = q def emit(self, record: logging.LogRecord) -> None: try: msg = self.format(record) self.q.put(msg) except Exception: pass class BotRunner: def __init__( self, target_url: str, log_queue: Optional[queue.Queue] = None, stop_event=None, ): self.target_url = target_url self.log_queue = log_queue or queue.Queue() self.stop_event = stop_event def _log(self, msg: str): try: self.log_queue.put(msg) except Exception: pass def run(self): # attach logging handler so module logs appear in GUI q_handler = QueueLoggingHandler(self.log_queue) q_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s: %(message)s")) root_logger = logging.getLogger() root_logger.addHandler(q_handler) logging.getLogger("bot").addHandler(q_handler) self._log("Phase 0 ▶ Preparing session") config = BotConfig() session = BrowserSession(headless=False, state_dir=config.state_dir) try: session.start() self._log("Phase 1 ▶ Authentication") auth = AuthHandler(session, HARDCODED_USERNAME, HARDCODED_PASSWORD) if not auth.ensure_authenticated(): self._log("Authentication failed") return self._log("Phase 2 ▶ Opening target page") if session.goto(self.target_url): self._log(f"Opened: {self.target_url}") else: self._log("Failed to open target page") return self._log("Phase 3 - Updating w/o case listing prices") result = update_wo_case_listing_prices( session.page, dashboard_url=self.target_url, stop_event=self.stop_event, ) self._log( "Update complete: " f"matched={result['matched']}, updated={result['updated']}, " f"failed={result['failed']}, pages={result['pages_scanned']}" ) self._log(f"CSV saved: {result['csv_path']}") except Exception as e: logger.exception("Unexpected error in BotRunner") self._log(f"Error: {e}") finally: try: root_logger.removeHandler(q_handler) logging.getLogger("bot").removeHandler(q_handler) except Exception: pass session.stop()