Add full application source

This commit is contained in:
Dr Jones
2026-05-22 12:47:24 -07:00
parent 53138fdd1e
commit c958a06b96
37 changed files with 6642 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
"""
Browser automation controller for CAPTCHA solving workflows.
Supports Playwright and Selenium when installed; otherwise operates in manual mode.
"""
import logging
from dataclasses import dataclass
from typing import Any, Optional, Tuple
logger = logging.getLogger(__name__)
@dataclass
class BrowserConfig:
engine: str = "Playwright"
headless: bool = False
viewport: Tuple[int, int] = (1280, 720)
mouse_delay_ms: int = 50
retry_limit: int = 3
class BrowserController:
"""Launches and controls a browser session for CAPTCHA automation."""
def __init__(self, config: Optional[BrowserConfig] = None):
self.config = config or BrowserConfig()
self._driver: Any = None
self._playwright: Any = None
self._browser: Any = None
self._page: Any = None
@property
def is_running(self) -> bool:
return self._driver is not None or self._page is not None
@property
def active_driver(self) -> Any:
"""Return the active Playwright page or Selenium WebDriver."""
return self._page or self._driver
def launch(self, url: Optional[str] = None) -> bool:
engine = (self.config.engine or "None (Manual)").lower()
if "playwright" in engine:
return self._launch_playwright(url)
if "selenium" in engine:
return self._launch_selenium(url)
logger.info("Browser automation disabled — manual mode")
return False
def _launch_playwright(self, url: Optional[str]) -> bool:
try:
from playwright.sync_api import sync_playwright
except ImportError:
logger.warning("Playwright not installed. Install with: pip install playwright")
return False
try:
self._playwright = sync_playwright().start()
self._browser = self._playwright.chromium.launch(headless=self.config.headless)
context = self._browser.new_context(
viewport={
"width": self.config.viewport[0],
"height": self.config.viewport[1],
}
)
self._page = context.new_page()
if url:
self._page.goto(url, wait_until="domcontentloaded")
logger.info("Playwright browser launched")
return True
except Exception as e:
logger.error(f"Failed to launch Playwright: {e}")
self.close()
return False
def _launch_selenium(self, url: Optional[str]) -> bool:
try:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
except ImportError:
logger.warning("Selenium not installed. Install with: pip install selenium")
return False
try:
options = Options()
if self.config.headless:
options.add_argument("--headless=new")
options.add_argument(
f"--window-size={self.config.viewport[0]},{self.config.viewport[1]}"
)
self._driver = webdriver.Chrome(options=options)
if url:
self._driver.get(url)
logger.info("Selenium browser launched")
return True
except Exception as e:
logger.error(f"Failed to launch Selenium: {e}")
self.close()
return False
def navigate(self, url: str) -> bool:
driver = self.active_driver
if not driver:
return False
try:
if self._page is not None:
self._page.goto(url, wait_until="domcontentloaded")
else:
driver.get(url)
return True
except Exception as e:
logger.error(f"Navigation failed: {e}")
return False
def close(self):
try:
if self._page is not None:
self._page.close()
if self._browser is not None:
self._browser.close()
if self._playwright is not None:
self._playwright.stop()
if self._driver is not None:
self._driver.quit()
except Exception as e:
logger.warning(f"Browser shutdown warning: {e}")
finally:
self._driver = None
self._page = None
self._browser = None
self._playwright = None