# ruff: noqa: F401,F403,F405,I001 from ._runtime import * # noqa: F403,F405 from config.subscription_guides_config import ( SubscriptionGuidesConfigError, subscription_guides_status, validate_panel_subscription_guides_config, ) PANEL_DEFAULT_SUBPAGE_CONFIG_UUID = "00000000-0000-0000-0000-000000000000" SUBSCRIPTION_GUIDES_CACHE_ERROR_TTL_SECONDS = 30 async def warm_subscription_guides_config(app: web.Application) -> None: try: await _subscription_guides_status_shared(app) except Exception as exc: logger.warning("Failed to warm subscription guides config: %s", exc) async def subscription_guides_route(request: web.Request) -> web.Response: _require_user_id(request) status = await _subscription_guides_status_shared(request.app) payload = { "enabled": bool(status.get("enabled")), "config": status.get("config") if status.get("enabled") else None, "source": status.get("source"), } if status.get("error"): payload["error"] = status["error"] return web.json_response({"ok": True, **payload}) async def public_subscription_guides_route(request: web.Request) -> web.Response: short_uuid = _normalize_short_uuid(request.match_info.get("short_uuid")) if not short_uuid: return web.json_response({"ok": False, "error": "invalid_short_uuid"}, status=404) status = await _subscription_guides_status_shared(request.app) subscription = await _public_subscription_payload(request, short_uuid) payload = { "enabled": bool(status.get("enabled")), "config": status.get("config") if status.get("enabled") else None, "source": status.get("source"), "subscription": subscription, } if status.get("error"): payload["error"] = status["error"] return web.json_response({"ok": True, **payload}) async def _subscription_guides_status_shared(app: web.Application) -> Dict[str, Any]: settings: Settings = app["settings"] cache = app.setdefault("subscription_guides_config_cache", {}) lock: asyncio.Lock = app.setdefault("subscription_guides_config_lock", asyncio.Lock()) fingerprint = _subscription_guides_settings_fingerprint(settings) now = time.monotonic() cached = cache.get("status") if cached is not None and cache.get("fingerprint") == fingerprint: if cached.get("enabled") or now - float(cache.get("ts", 0.0)) < ( SUBSCRIPTION_GUIDES_CACHE_ERROR_TTL_SECONDS ): return cached async with lock: cached = cache.get("status") if cached is not None and cache.get("fingerprint") == fingerprint: if cached.get("enabled") or now - float(cache.get("ts", 0.0)) < ( SUBSCRIPTION_GUIDES_CACHE_ERROR_TTL_SECONDS ): return cached status = await _load_subscription_guides_status(app, settings) cache["fingerprint"] = fingerprint cache["status"] = status cache["ts"] = time.monotonic() return status async def _load_subscription_guides_status( app: web.Application, settings: Settings, ) -> Dict[str, Any]: if not bool(getattr(settings, "SUBSCRIPTION_GUIDES_ENABLED", False)): return {"enabled": False, "config": None, "source": None, "error": None} admin_json = str(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_JSON", "") or "").strip() json_override_enabled = bool( getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_JSON_OVERRIDE_ENABLED", False) ) if admin_json and json_override_enabled: return subscription_guides_status(settings) if bool(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_PANEL_ENABLED", True)): panel_status = await _subscription_guides_status_from_panel_config(app, settings) if panel_status.get("enabled"): return panel_status return subscription_guides_status(settings) async def _subscription_guides_status_from_panel_config( app: web.Application, settings: Settings, ) -> Dict[str, Any]: panel_service = _panel_service_from_app(app) if panel_service is None: return { "enabled": False, "config": None, "source": "panel", "error": "Panel service is unavailable", } try: config_uuid = str(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_UUID", "") or "").strip() if not config_uuid: config_uuid = await _default_panel_subscription_page_config_uuid(panel_service) config_uuid = config_uuid or PANEL_DEFAULT_SUBPAGE_CONFIG_UUID detail = await panel_service.get_subscription_page_config_by_uuid(config_uuid) if detail is None and config_uuid != PANEL_DEFAULT_SUBPAGE_CONFIG_UUID: detail = await panel_service.get_subscription_page_config_by_uuid( PANEL_DEFAULT_SUBPAGE_CONFIG_UUID ) if detail is None: raise SubscriptionGuidesConfigError( f"Panel subscription page config {config_uuid} is unavailable" ) config = validate_panel_subscription_guides_config(detail) except (SubscriptionGuidesConfigError, Exception) as exc: logger.warning("Failed to load subscription guides config from Remnawave Panel: %s", exc) return {"enabled": False, "config": None, "source": "panel", "error": str(exc)} return {"enabled": True, "config": config, "source": "panel", "error": None} async def _default_panel_subscription_page_config_uuid(panel_service: Any) -> str: get_list = getattr(panel_service, "get_subscription_page_config_list", None) if not callable(get_list): return "" payload = await get_list() configs = (payload or {}).get("configs") if not isinstance(configs, list): return "" candidates: list[Dict[str, Any]] = [item for item in configs if isinstance(item, dict)] for item in candidates: uuid = str(item.get("uuid") or "").strip() if uuid == PANEL_DEFAULT_SUBPAGE_CONFIG_UUID: return uuid candidates.sort(key=lambda item: int(item.get("viewPosition") or 0)) for item in candidates: uuid = str(item.get("uuid") or "").strip() if uuid: return uuid return "" async def _public_subscription_payload( request: web.Request, short_uuid: str, ) -> Dict[str, Any]: settings: Settings = request.app["settings"] panel_service = _panel_service_from_app(request.app) raw_link = "" username = "" resolved_short_uuid = short_uuid async_session_factory: sessionmaker = request.app["async_session_factory"] async with async_session_factory() as session: local_sub = await subscription_dal.get_subscription_by_panel_subscription_uuid( session, short_uuid, ) if ( local_sub and getattr(local_sub, "panel_user_uuid", None) and _local_subscription_is_publicly_active(local_sub) and panel_service ): panel_user = await panel_service.get_user_by_uuid(local_sub.panel_user_uuid) if panel_user: raw_link = str(panel_user.get("subscriptionUrl") or "").strip() username = str(panel_user.get("username") or "").strip() resolved_short_uuid = str(panel_user.get("shortUuid") or short_uuid).strip() display_link, connect_url = await prepare_config_links(settings, raw_link) return { "active": bool(display_link), "config_link": display_link, "connect_url": connect_url or display_link, "panel_short_uuid": resolved_short_uuid, "username": username, "share_url": _public_install_url(request, resolved_short_uuid), } def _panel_service_from_app(app: web.Application) -> Any: subscription_service: Optional[SubscriptionService] = app.get("subscription_service") panel_service = ( getattr(subscription_service, "panel_service", None) if subscription_service else None ) return panel_service or app.get("panel_service") def _subscription_guides_settings_fingerprint(settings: Settings) -> Tuple[Any, ...]: admin_json = str(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_JSON", "") or "") return ( bool(getattr(settings, "SUBSCRIPTION_GUIDES_ENABLED", False)), bool(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_PANEL_ENABLED", True)), bool(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_JSON_OVERRIDE_ENABLED", False)), str(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_PATH", "") or ""), str(getattr(settings, "SUBSCRIPTION_PAGE_CONFIG_UUID", "") or ""), hashlib.sha256(admin_json.encode("utf-8")).hexdigest(), str(getattr(settings, "PANEL_API_URL", "") or ""), bool(getattr(settings, "PANEL_API_KEY", "") or ""), ) def _local_subscription_is_publicly_active(subscription: Any) -> bool: end_date = getattr(subscription, "end_date", None) if end_date and end_date.tzinfo is None: end_date = end_date.replace(tzinfo=timezone.utc) return bool( getattr(subscription, "is_active", False) and end_date and end_date > datetime.now(timezone.utc) ) def _normalize_short_uuid(value: Any) -> str: short_uuid = str(value or "").strip() if not re.fullmatch(r"[A-Za-z0-9_-]{8,128}", short_uuid): return "" return short_uuid def _public_install_url(request: web.Request, short_uuid: str) -> str: settings: Settings = request.app["settings"] configured_base = str(getattr(settings, "SUBSCRIPTION_MINI_APP_URL", "") or "").strip() if configured_base: parts = urlsplit(configured_base) if parts.scheme and parts.netloc: base = urlunsplit((parts.scheme, parts.netloc, "", "", "")) else: base = configured_base.rstrip("/") else: host = ( request.headers.get("X-Forwarded-Host") or request.headers.get("Host") or request.host ) proto = request.headers.get("X-Forwarded-Proto") or request.scheme or "https" base = f"{proto}://{host}" return f"{base.rstrip('/')}/install/share/{quote(short_uuid)}" def _subscription_page_request_headers(request: web.Request) -> Dict[str, str]: headers = request.headers host = headers.get("X-Forwarded-Host") or headers.get("Host") or request.host proto = headers.get("X-Forwarded-Proto") or request.scheme or "https" user_agent = headers.get( "User-Agent", "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome Safari", ) return { "host": host, "x-forwarded-host": host, "x-forwarded-proto": proto, "user-agent": user_agent, "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "accept-language": headers.get("Accept-Language", "ru,en;q=0.9"), "sec-fetch-dest": "document", "sec-fetch-mode": "navigate", "sec-fetch-site": "none", "upgrade-insecure-requests": "1", }