import asyncio import random from typing import Any _SCROLL_DISTANCES = {"slow": 1500, "normal": 3000, "fast": 5000} class BehaviorEmulator: """Simulates human-like browser interaction. All timings scale with delay_factor.""" def __init__( self, human: bool = True, delay_factor: float = 1.0, scroll_speed: str = "normal", ) -> None: self.human = human self.delay_factor = delay_factor self._scroll_base = _SCROLL_DISTANCES.get(scroll_speed, 3000) async def human_delay(self, base: float = 2.0, variance: float = 1.0) -> None: delay = ( (base + random.uniform(-variance / 2, variance / 2)) * self.delay_factor if self.human else 0.3 ) await asyncio.sleep(max(0.3, delay)) async def scroll(self, page: Any, distance: int | None = None) -> None: dist = distance if distance is not None else self._scroll_base if self.human: steps = random.randint(2, 4) per_step = dist // steps for _ in range(steps): jitter = random.randint(-150, 150) await page.mouse.wheel(0, per_step + jitter) await asyncio.sleep(random.uniform(0.2, 0.7) * self.delay_factor) else: await page.mouse.wheel(0, dist) async def pause_for_reading(self) -> None: delay = random.uniform(1.0, 2.5) * self.delay_factor if self.human else 0.2 await asyncio.sleep(delay)