from __future__ import annotations from dataclasses import dataclass from .adapters import adapter_for from .config import AppConfig, default_config from .plan import BrowsePlan, plan_url @dataclass(frozen=True) class OpenPlan: browse_plan: BrowsePlan status: str dry_run: bool consent_granted: bool profile_path: str proxy: str setup_steps: tuple[str, ...] message: str def prepare_open( raw_url: str, *, consent: bool = False, dry_run: bool = True, config: AppConfig | None = None, platform: str | None = None, ) -> OpenPlan: config = config or default_config() browse_plan = plan_url(raw_url, config=config, platform=platform) profile_path = config.profile_path(browse_plan.route.profile) proxy = _proxy_for(browse_plan) if browse_plan.action.startswith("blocked"): return OpenPlan( browse_plan=browse_plan, status="blocked", dry_run=dry_run, consent_granted=consent, profile_path=profile_path, proxy=proxy, setup_steps=(), message=browse_plan.action, ) if browse_plan.requires_consent: setup_steps = _setup_steps(browse_plan) if not consent: return OpenPlan( browse_plan=browse_plan, status="consent-required", dry_run=dry_run, consent_granted=False, profile_path=profile_path, proxy=proxy, setup_steps=setup_steps, message=browse_plan.prompt, ) return OpenPlan( browse_plan=browse_plan, status="setup-approved", dry_run=dry_run, consent_granted=True, profile_path=profile_path, proxy=proxy, setup_steps=setup_steps, message="first-use setup approved; execution is not implemented yet", ) return OpenPlan( browse_plan=browse_plan, status="ready", dry_run=dry_run, consent_granted=consent, profile_path=profile_path, proxy=proxy, setup_steps=(), message="ready to open with isolated profile", ) def _proxy_for(browse_plan: BrowsePlan) -> str: if browse_plan.route.transport in {"tor", "i2p"} and browse_plan.status: return browse_plan.status.endpoint return "-" def _setup_steps(browse_plan: BrowsePlan) -> tuple[str, ...]: if not browse_plan.status: return () adapter = adapter_for(browse_plan.route.transport) if not adapter: return () steps: list[str] = [] platform = browse_plan.platform_capability.platform if platform == "android" and not browse_plan.status.installed: steps.append(f"install or enable Android {browse_plan.route.transport} provider") steps.extend(adapter.setup_steps(installed=True, platform=platform)) return tuple(steps) if platform == "ios" and not browse_plan.status.installed: if browse_plan.route.transport == "tor": steps.append("enable bundled iOS Arti Tor runtime") else: steps.append(f"enable foreground iOS {browse_plan.route.transport} session") steps.extend(adapter.setup_steps(installed=True, platform=platform)) return tuple(steps) steps.extend(adapter.setup_steps(installed=browse_plan.status.installed, platform=platform)) return tuple(steps)