82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
"""Worker configuration, parsed once from the environment.
|
|
|
|
All env knobs the workers honor live here so there's a single source of truth (the
|
|
two market workers used to each re-parse the same ~15 vars). Frozen dataclass — read
|
|
it, don't mutate it.
|
|
"""
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
|
|
|
|
def _int(name: str, default: int) -> int:
|
|
return int(os.environ.get(name, str(default)))
|
|
|
|
|
|
def _float(name: str, default: float) -> float:
|
|
return float(os.environ.get(name, str(default)))
|
|
|
|
|
|
def _flag(name: str) -> bool:
|
|
return os.environ.get(name) == "1"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Settings:
|
|
# C2
|
|
c2_url: str
|
|
token: str
|
|
# Session / pacing
|
|
market_url: str # "" => use the worker's own default page
|
|
solve_seconds: int
|
|
delay: float
|
|
jitter: float
|
|
idle_seconds: int
|
|
# Browser
|
|
browser_path: str | None
|
|
load_images: bool
|
|
chrome_no_sandbox: bool
|
|
# Proxy (auth-free fallback)
|
|
proxy: str | None
|
|
# IPRoyal residential gateway
|
|
iproyal_host: str
|
|
iproyal_port: int
|
|
iproyal_username: str | None
|
|
iproyal_password: str | None
|
|
iproyal_country: str
|
|
iproyal_lifetime_min: int
|
|
# Logging
|
|
log_level: str
|
|
log_json: bool
|
|
|
|
@property
|
|
def use_iproyal(self) -> bool:
|
|
"""IPRoyal takes priority over a plain PROXY when its creds are set."""
|
|
return bool(self.iproyal_username and self.iproyal_password)
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "Settings":
|
|
return cls(
|
|
c2_url=os.environ.get("C2_URL", "http://localhost:5080").rstrip("/"),
|
|
token=os.environ.get("WORKER_TOKEN", "dev-worker-token"),
|
|
market_url=os.environ.get("MARKET_URL", ""),
|
|
solve_seconds=_int("SOLVE_SECONDS", 30),
|
|
delay=_float("DELAY", 2.0),
|
|
jitter=_float("JITTER", 1.5),
|
|
idle_seconds=_int("IDLE_SECONDS", 10),
|
|
browser_path=os.environ.get("BROWSER_PATH") or None,
|
|
# Residential proxy is metered per GB; Cloudflare gates on JS, not images, and
|
|
# the market APIs are pure JSON — so block images unless explicitly debugging.
|
|
load_images=_flag("LOAD_IMAGES"),
|
|
chrome_no_sandbox=_flag("CHROME_NO_SANDBOX"),
|
|
proxy=os.environ.get("PROXY") or None,
|
|
iproyal_host=os.environ.get("IPROYAL_HOST", "geo.iproyal.com"),
|
|
iproyal_port=_int("IPROYAL_PORT", 12321),
|
|
iproyal_username=os.environ.get("IPROYAL_USERNAME") or None,
|
|
iproyal_password=os.environ.get("IPROYAL_PASSWORD") or None,
|
|
iproyal_country=os.environ.get("IPROYAL_COUNTRY", "us").strip().lower(),
|
|
iproyal_lifetime_min=_int("IPROYAL_LIFETIME_MIN", 60),
|
|
log_level=os.environ.get("LOG_LEVEL", "INFO").upper(),
|
|
log_json=_flag("LOG_JSON"),
|
|
)
|