Spaces:
Sleeping
Sleeping
| 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() | |