mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-10-10 18:02:23 +02:00
Add discovery
This commit is contained in:
@@ -264,16 +264,22 @@ class DiscoveryAuthenticator(BaseAuthenticator):
|
||||
http_manager=None,
|
||||
proxy_config: Optional[ProxyConfig] = None,
|
||||
platform_os: Optional[PlatformOS] = None,
|
||||
device_id: Optional[str] = None,
|
||||
):
|
||||
self.country = country
|
||||
self.home_market = HOME_MARKET_MAPPING.get(country, "emea")
|
||||
self.tenant = DEFAULT_TENANT
|
||||
self.env = DEFAULT_ENV
|
||||
self.device_id = DEFAULT_DEVICE_ID
|
||||
|
||||
# OS platform — controls User-Agent, x-disco-client, x-device-info
|
||||
self.platform_os: PlatformOS = platform_os if platform_os is not None else DEFAULT_PLATFORM_OS
|
||||
|
||||
# Device ID — prefer injected value (from provider via settings_manager),
|
||||
# fall back to _load_or_create_device_id() for standalone usage.
|
||||
# Note: set to sentinel now; resolved after super().__init__() below
|
||||
# so that self.settings_manager is available for the fallback path.
|
||||
self._injected_device_id = device_id
|
||||
|
||||
# Session headers storage (from /token 400 response)
|
||||
self._session_state: Optional[str] = None
|
||||
self._disco_id: Optional[str] = None
|
||||
@@ -311,6 +317,15 @@ class DiscoveryAuthenticator(BaseAuthenticator):
|
||||
|
||||
logger.debug(f"Discovery __init__ post-super: self.credentials={type(self.credentials).__name__}")
|
||||
|
||||
# Resolve device_id now that super().__init__() has run and
|
||||
# self.settings_manager (set by BaseAuthenticator) is available.
|
||||
if self._injected_device_id:
|
||||
self.device_id = self._injected_device_id
|
||||
logger.debug(f"Using injected device_id: {self.device_id}")
|
||||
else:
|
||||
self.device_id = self._load_or_create_device_id()
|
||||
del self._injected_device_id # clean up sentinel
|
||||
|
||||
# If no credentials were provided at construction time, attempt to load
|
||||
# from storage. Promote here too — the credential manager always returns
|
||||
# bare base-class instances.
|
||||
@@ -355,6 +370,35 @@ class DiscoveryAuthenticator(BaseAuthenticator):
|
||||
|
||||
return self._http_manager
|
||||
|
||||
def _load_or_create_device_id(self) -> str:
|
||||
"""
|
||||
Return a stable device ID for this installation.
|
||||
|
||||
Intended to be called after the settings_manager is available.
|
||||
In normal operation the provider injects the device_id directly via
|
||||
the constructor, so this is only used as a fallback when the
|
||||
authenticator is constructed standalone (e.g. in tests).
|
||||
|
||||
Falls back to DEFAULT_DEVICE_ID if no settings manager is available.
|
||||
|
||||
Returns:
|
||||
UUID string (with hyphens) to use as device ID
|
||||
"""
|
||||
# BaseAuthenticator stores settings_manager as self.settings_manager
|
||||
# (no underscore prefix) when passed via super().__init__()
|
||||
sm = getattr(self, "settings_manager", None)
|
||||
try:
|
||||
if sm:
|
||||
device_id = sm.get_device_id("discovery", self.country)
|
||||
if device_id:
|
||||
logger.debug(f"Loaded device_id from settings: {device_id}")
|
||||
return device_id
|
||||
except Exception as e:
|
||||
logger.debug(f"Could not load device_id from settings manager: {e}")
|
||||
|
||||
logger.debug("No settings manager available, using DEFAULT_DEVICE_ID")
|
||||
return DEFAULT_DEVICE_ID
|
||||
|
||||
def _discover_endpoints(self, auth_headers: Dict[str, str]) -> None:
|
||||
"""
|
||||
Discover API endpoints from bootstrap using an authenticated session.
|
||||
|
||||
@@ -57,7 +57,7 @@ class PlatformOS(str, Enum):
|
||||
|
||||
# Active platform — change this single constant to switch all OS-dependent behaviour.
|
||||
# LINUX preserves existing behaviour exactly; WINDOWS mirrors a real Edge/Windows client.
|
||||
DEFAULT_PLATFORM_OS: Final[PlatformOS] = PlatformOS.WINDOWS
|
||||
DEFAULT_PLATFORM_OS: Final[PlatformOS] = PlatformOS.LINUX
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -186,6 +186,8 @@ DISCOVERY_DEVICE_INFO_TEMPLATE_LINUX: Final[str] = (
|
||||
DISCOVERY_DEVICE_INFO_TEMPLATE_WINDOWS: Final[str] = (
|
||||
f"dplus/{DISCOVERY_CLIENT_VERSION} (desktop/desktop; Windows/NT 10.0; {{device_id}}/{{session_id}})"
|
||||
)
|
||||
# Backward-compatible alias — resolves to Linux template (original behaviour)
|
||||
DISCOVERY_DEVICE_INFO_TEMPLATE: Final[str] = DISCOVERY_DEVICE_INFO_TEMPLATE_LINUX
|
||||
|
||||
# x-wbd-device-consent header value
|
||||
DISCOVERY_DEVICE_CONSENT: Final[str] = "gpc=0"
|
||||
@@ -228,6 +230,8 @@ DISCOVERY_CLIENT_ID_PREFIX: Final[str] = "web1_prd"
|
||||
# os_version encodes the OS: "0.0.0" for Linux web, "NT 10.0" for Windows
|
||||
DISCOVERY_DISCO_CLIENT_LINUX: Final[str] = f"WEB:0.0.0:dplus:{DISCOVERY_CLIENT_VERSION}"
|
||||
DISCOVERY_DISCO_CLIENT_WINDOWS: Final[str] = f"WEB:NT 10.0:dplus:{DISCOVERY_CLIENT_VERSION}"
|
||||
# Backward-compatible alias — resolves to Linux value (original behaviour)
|
||||
DISCOVERY_DISCO_CLIENT: Final[str] = DISCOVERY_DISCO_CLIENT_LINUX
|
||||
|
||||
# Feature flags endpoint — provides hmacKeys, gisdk clientId, arkose config etc.
|
||||
# x-gisdk clientId comes from the response and is session-specific.
|
||||
@@ -240,7 +244,10 @@ DISCOVERY_FEATURE_FLAGS_PAYLOAD: Final[Dict] = {
|
||||
}
|
||||
|
||||
|
||||
def get_default_device_info(platform_os: Optional[PlatformOS] = None) -> Dict[str, any]:
|
||||
def get_default_device_info(
|
||||
platform_os: Optional[PlatformOS] = None,
|
||||
device_id: Optional[str] = None,
|
||||
) -> Dict[str, any]:
|
||||
"""
|
||||
Return a fresh copy of default device info for the given OS platform.
|
||||
|
||||
@@ -248,6 +255,9 @@ def get_default_device_info(platform_os: Optional[PlatformOS] = None) -> Dict[st
|
||||
platform_os: Target OS platform. Defaults to DEFAULT_PLATFORM_OS.
|
||||
PlatformOS.LINUX → Chrome on Linux (original behaviour)
|
||||
PlatformOS.WINDOWS → Edge on Windows
|
||||
device_id: Device ID to embed. Defaults to DEFAULT_DEVICE_ID.
|
||||
Pass the authenticator's self.device_id so the value
|
||||
matches what the server tracks per session.
|
||||
|
||||
Returns:
|
||||
Dictionary containing device information suitable for the playbackInfo body.
|
||||
@@ -255,6 +265,9 @@ def get_default_device_info(platform_os: Optional[PlatformOS] = None) -> Dict[st
|
||||
if platform_os is None:
|
||||
platform_os = DEFAULT_PLATFORM_OS
|
||||
|
||||
if device_id is None:
|
||||
device_id = DEFAULT_DEVICE_ID
|
||||
|
||||
if platform_os == PlatformOS.WINDOWS:
|
||||
os_info = {"name": "Windows", "version": "NT 10.0"}
|
||||
browser_info = {"name": "Microsoft Edge", "version": "139.0.0.0"}
|
||||
@@ -264,7 +277,7 @@ def get_default_device_info(platform_os: Optional[PlatformOS] = None) -> Dict[st
|
||||
browser_info = {"name": "Chrome", "version": "144.0.0.0"}
|
||||
|
||||
return {
|
||||
"deviceId": DEFAULT_DEVICE_ID,
|
||||
"deviceId": device_id,
|
||||
"browser": browser_info,
|
||||
"make": "desktop",
|
||||
"model": "desktop",
|
||||
|
||||
@@ -189,6 +189,19 @@ class DiscoveryProvider(StreamingProvider):
|
||||
# self-constructs its own SettingsManager via the backward-compat path,
|
||||
# identical to how JoynAuthenticator works. This ensures it always
|
||||
# resolves the correct /config path via the environment variable.
|
||||
# Resolve stable device ID from settings manager before constructing
|
||||
# the authenticator — the authenticator intentionally receives
|
||||
# settings_manager=None so it cannot do this lookup itself.
|
||||
_device_id = None
|
||||
if self._settings_manager:
|
||||
try:
|
||||
_device_id = self._settings_manager.get_device_id(
|
||||
"discovery", country
|
||||
)
|
||||
logger.debug(f"Resolved device_id from settings: {_device_id}")
|
||||
except Exception as e:
|
||||
logger.debug(f"Could not resolve device_id from settings: {e}")
|
||||
|
||||
self.authenticator = DiscoveryAuthenticator(
|
||||
country=country,
|
||||
settings_manager=None,
|
||||
@@ -197,6 +210,7 @@ class DiscoveryProvider(StreamingProvider):
|
||||
proxy_config=self.http_manager.config.proxy_config,
|
||||
credentials=self.credentials,
|
||||
platform_os=self.platform_os,
|
||||
device_id=_device_id,
|
||||
)
|
||||
|
||||
# Authenticate
|
||||
@@ -452,7 +466,10 @@ class DiscoveryProvider(StreamingProvider):
|
||||
"ssaiProvider": {"version": "2.2.0"},
|
||||
},
|
||||
"consumptionType": "streaming",
|
||||
"deviceInfo": get_default_device_info(self.platform_os),
|
||||
"deviceInfo": get_default_device_info(
|
||||
self.platform_os,
|
||||
device_id=self.authenticator.device_id,
|
||||
),
|
||||
"editId": edit_id,
|
||||
"capabilities": get_default_capabilities(self.platform_os),
|
||||
"gdpr": False,
|
||||
|
||||
Reference in New Issue
Block a user