"""Central configuration, all overridable via environment variables. Anything user- or machine-specific lives here so the rest of the code never reads os.environ directly. """ import os from pathlib import Path try: from dotenv import load_dotenv load_dotenv() except Exception: # dotenv is optional pass def _env(name: str, default: str) -> str: return os.environ.get(name, default) BASE_DIR = Path(__file__).resolve().parent # --- Storage ----------------------------------------------------------------- DATA_DIR = Path(_env("SCREEN_LEADS_DATA", str(BASE_DIR / "data"))) DATA_DIR.mkdir(parents=True, exist_ok=True) SCREENSHOT_DIR = DATA_DIR / "screenshots" SCREENSHOT_DIR.mkdir(parents=True, exist_ok=True) DB_PATH = Path(_env("SCREEN_LEADS_DB", str(DATA_DIR / "leads.db"))) # --- AI ---------------------------------------------------------------------- # Vision model used for extraction. Defaults to the most capable Claude model; # override with SCREEN_LEADS_MODEL=claude-sonnet-5 for a cheaper high-volume run. ANTHROPIC_MODEL = _env("SCREEN_LEADS_MODEL", "claude-opus-4-8") MAX_IMAGES_PER_CALL = int(_env("SCREEN_LEADS_MAX_IMAGES", "8")) # --- Capture ----------------------------------------------------------------- # Grace period after Start before the first capture, so you can focus the # browser window on the profile. Set to 0 to disable. START_DELAY = float(_env("SCREEN_LEADS_START_DELAY", "5")) SCROLL_STEPS = int(_env("SCREEN_LEADS_SCROLL_STEPS", "6")) # screenshots per profile SCROLL_AMOUNT = int(_env("SCREEN_LEADS_SCROLL_AMOUNT", "800")) # pyautogui scroll clicks SCROLL_PAUSE = float(_env("SCREEN_LEADS_SCROLL_PAUSE", "0.8")) # settle time (s) WATCH_INTERVAL = float(_env("SCREEN_LEADS_WATCH_INTERVAL", "2.0")) # loop tick (s) # Auto-advance: after capturing a profile, look for a "Next" control, click it, # scroll back to the top, and keep going — walking paginated results hands-free. AUTO_NEXT = _env("SCREEN_LEADS_AUTO_NEXT", "true").lower() in ("1", "true", "yes", "on") NEXT_LOAD_PAUSE = float(_env("SCREEN_LEADS_NEXT_LOAD_PAUSE", "2.5")) # wait after click (s) MAX_AUTO_NEXT = int(_env("SCREEN_LEADS_MAX_AUTO_NEXT", "25")) # safety cap per run # What to do when the front tab is not an enabled site's target page. # "stop" -> end the run (the requested behaviour) # "wait" -> pause and keep polling until a valid page appears ON_INVALID_PAGE = _env("SCREEN_LEADS_ON_INVALID_PAGE", "stop").lower() # --- Server ------------------------------------------------------------------ HOST = _env("SCREEN_LEADS_HOST", "127.0.0.1") PORT = int(_env("SCREEN_LEADS_PORT", "8000"))