mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-09-29 04:22:42 +02:00
Add discovery
This commit is contained in:
@@ -21,6 +21,7 @@ from .constants import (
|
||||
SUPPORTED_COUNTRIES,
|
||||
CHANNEL_COLLECTIONS,
|
||||
CHANNEL_ITEM_TYPES,
|
||||
DISCOVERY_USERS_ME_URL,
|
||||
StreamingMode,
|
||||
CDMMode,
|
||||
VideoQuality,
|
||||
@@ -75,6 +76,7 @@ __all__ = [
|
||||
"SUPPORTED_COUNTRIES",
|
||||
"CHANNEL_COLLECTIONS",
|
||||
"CHANNEL_ITEM_TYPES",
|
||||
"DISCOVERY_USERS_ME_URL",
|
||||
|
||||
# Constants - Enums
|
||||
"StreamingMode",
|
||||
|
||||
@@ -72,6 +72,10 @@ DISCOVERY_LOGO: Final[
|
||||
DISCOVERY_BOOTSTRAP_URL: Final[
|
||||
str] = "https://default.any-any.prd.api.discoveryplus.com/session-context/headwaiter/v1/bootstrap"
|
||||
|
||||
# User profile endpoint — returns currentLocationTerritory for country detection
|
||||
DISCOVERY_USERS_ME_URL: Final[
|
||||
str] = "https://default.dplus-emea.prd.api.discoveryplus.com/users/me"
|
||||
|
||||
# Default realm
|
||||
DEFAULT_REALM: Final[str] = "bolt"
|
||||
|
||||
@@ -89,10 +93,9 @@ SUPPORTED_AUTH_TYPES: Final[List[str]] = [
|
||||
# Country/Region Configuration
|
||||
# ============================================================================
|
||||
|
||||
# Supported countries (EMEA region)
|
||||
SUPPORTED_COUNTRIES: Final[List[str]] = [
|
||||
"de", "at", "ch", "dk", "fi", "no", "se", "it", "nl", "es", "uk", "ie",
|
||||
]
|
||||
# Wildcard sentinel — Discovery+ accepts any country; the user's actual country
|
||||
# is determined at runtime via the /users/me endpoint (currentLocationTerritory).
|
||||
SUPPORTED_COUNTRIES: Final[str] = "*"
|
||||
|
||||
# Home market mapping (immutable)
|
||||
HOME_MARKET_MAPPING: Final[Dict[str, str]] = {
|
||||
|
||||
@@ -28,6 +28,7 @@ from .constants import (
|
||||
DEFAULT_TENANT,
|
||||
DEFAULT_PLATFORM_OS,
|
||||
DISCOVERY_LOGO,
|
||||
DISCOVERY_USERS_ME_URL,
|
||||
DRMSystem as DiscoveryDRMSystem,
|
||||
DRM_SYSTEM_PLAYREADY,
|
||||
PlatformOS,
|
||||
@@ -71,7 +72,7 @@ class DiscoveryProvider(StreamingProvider):
|
||||
PROVIDER_LABEL: ClassVar[str] = "Discovery+"
|
||||
SUPPORTED_AUTH_TYPES: ClassVar[List[str]] = SUPPORTED_AUTH_TYPES
|
||||
PROVIDER_LOGO: ClassVar[str] = DISCOVERY_LOGO
|
||||
SUPPORTED_COUNTRIES: ClassVar[List[str]] = SUPPORTED_COUNTRIES
|
||||
SUPPORTED_COUNTRIES: ClassVar[str] = SUPPORTED_COUNTRIES # "*" = all countries
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -106,9 +107,9 @@ class DiscoveryProvider(StreamingProvider):
|
||||
ValueError: If country not supported or credentials missing
|
||||
"""
|
||||
if not self.validate_country(country):
|
||||
supported = ", ".join(self.SUPPORTED_COUNTRIES)
|
||||
raise ValueError(
|
||||
f"Unsupported country: {country}. Discovery+ supports: {supported}"
|
||||
f"Unsupported country: {country}. "
|
||||
f"Provide a valid ISO-3166-1 alpha-2 country code (e.g. 'de', 'uk')."
|
||||
)
|
||||
|
||||
super().__init__(country=country)
|
||||
@@ -300,6 +301,64 @@ class DiscoveryProvider(StreamingProvider):
|
||||
return self.token_info.get("anonymous", True)
|
||||
return True
|
||||
|
||||
def validate_country(self, country: str) -> bool:
|
||||
"""
|
||||
Override base validation.
|
||||
|
||||
Discovery+ supports all countries (SUPPORTED_COUNTRIES == "*"),
|
||||
so any non-empty lowercase alpha-2 code is accepted.
|
||||
The user's actual serving country is determined at runtime via
|
||||
get_user_country().
|
||||
"""
|
||||
if self.SUPPORTED_COUNTRIES == "*":
|
||||
return bool(country and country.isalpha() and len(country) == 2)
|
||||
# Fallback to standard list-based check if constant is ever changed back
|
||||
return country.lower() in [c.lower() for c in self.SUPPORTED_COUNTRIES]
|
||||
|
||||
def get_user_country(self) -> Optional[str]:
|
||||
"""
|
||||
Detect the user's current country by calling the /users/me endpoint.
|
||||
|
||||
The API returns ``currentLocationTerritory`` (e.g. ``"DE"``) inside
|
||||
``data.attributes``. This method normalises the value to lowercase
|
||||
so it is consistent with the rest of the codebase (e.g. ``"de"``).
|
||||
|
||||
Returns:
|
||||
Two-letter lowercase country code (e.g. ``"de"``, ``"uk"``) or
|
||||
``None`` if the request fails or the field is absent.
|
||||
|
||||
Example::
|
||||
|
||||
provider = DiscoveryProvider(country="de")
|
||||
country = provider.get_user_country()
|
||||
# → "de" (or whatever territory the server reports)
|
||||
"""
|
||||
try:
|
||||
headers = self._get_auth_headers()
|
||||
response = self.http_manager.get(
|
||||
DISCOVERY_USERS_ME_URL,
|
||||
operation="users_me",
|
||||
headers=headers,
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
territory = (
|
||||
data.get("data", {})
|
||||
.get("attributes", {})
|
||||
.get("currentLocationTerritory")
|
||||
)
|
||||
if territory:
|
||||
country_code = territory.lower()
|
||||
logger.debug(
|
||||
f"Detected user country from /users/me: {country_code}"
|
||||
)
|
||||
return country_code
|
||||
logger.warning("/users/me response missing currentLocationTerritory")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to fetch user country from /users/me: {e}")
|
||||
return None
|
||||
|
||||
def get_channels(
|
||||
self,
|
||||
fetch_manifests: bool = False,
|
||||
|
||||
@@ -17,6 +17,7 @@ class RTLPlusDefaults:
|
||||
# Device information
|
||||
DEVICE_ID = "8c3f37cc-13a3-4141-bd0f-e4b3673fe5e4"
|
||||
DEVICE_NAME = "Linux Chrome"
|
||||
PLAYREADY_DEVICE_NAME = "Windows Edge"
|
||||
|
||||
# User Agent components
|
||||
USER_AGENT = f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{CHROME_VERSION} Safari/537.36"
|
||||
@@ -132,7 +133,7 @@ class RTLPlusHeaders:
|
||||
"User-Agent": RTLPlusDefaults.PLAYREADY_USER_AGENT,
|
||||
"X-Auth-Token": access_token,
|
||||
"X-Device-Id": device_id or RTLPlusDefaults.DEVICE_ID,
|
||||
"X-Device-Name": RTLPlusDefaults.DEVICE_NAME,
|
||||
"X-Device-Name": RTLPlusDefaults.PLAYREADY_DEVICE_NAME,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user