mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-09-21 16:42:18 +02:00
Add discovery
This commit is contained in:
@@ -1333,46 +1333,52 @@ class Magenta2Provider(StreamingProvider):
|
||||
|
||||
def _resolve_gn_id_to_media_id(self, gn_id: str) -> Optional[str]:
|
||||
"""
|
||||
Resolve a Gracenote content id (GN_EP*, GN_MV*, GN_SH*) to the MPX
|
||||
guid needed by the SMIL selector URL (.../media/{guid}).
|
||||
Resolve a Gracenote content id (GN_EP*, GN_MV*, GN_SH*) to the
|
||||
alphanumeric MPX guid needed by the SMIL selector URL (.../media/{guid}).
|
||||
|
||||
The VodItem returned by _fetch_single_episode stores:
|
||||
content_id = numeric mediaId (e.g. 1904600133178)
|
||||
manifest_script = theplatform href (e.g. .../media/zRPPGLNGgPa1)
|
||||
|
||||
The SMIL endpoint requires the alphanumeric guid from the href, not
|
||||
the numeric mediaId.
|
||||
Called at play time only — never during browse. Runs the full chain:
|
||||
VodDetails → productInformationLink → VodPlayer → playbackUrls
|
||||
and extracts the guid from the theplatform href in manifest_script.
|
||||
"""
|
||||
if not self._vod_manager:
|
||||
logger.warning(f"Cannot resolve GN id {gn_id}: VodManager not available")
|
||||
return None
|
||||
try:
|
||||
items = self._vod_manager.get_children(gn_id)
|
||||
# Route to the correct resolver based on GN id prefix.
|
||||
# get_children with the opaque prefix triggers full resolution.
|
||||
if gn_id.startswith(VOD_PREFIX_EPISODE):
|
||||
items = self._vod_manager.get_children(f"episode:{gn_id}")
|
||||
elif gn_id.startswith(VOD_PREFIX_MOVIE_MV) or gn_id.startswith(VOD_PREFIX_MOVIE_SH):
|
||||
items = self._vod_manager.get_children(f"movie:{gn_id}")
|
||||
else:
|
||||
items = self._vod_manager.get_children(gn_id)
|
||||
|
||||
if items:
|
||||
item = items[0]
|
||||
manifest_script = getattr(item, "manifest_script", None)
|
||||
|
||||
# If manifest_script is a vodproductinformation URL the content
|
||||
# is not playable (subscriptionMissing / not entitled).
|
||||
# Stop here rather than passing an unplayable URL to the SMIL chain.
|
||||
# is not entitled (subscriptionMissing). Stop immediately.
|
||||
if manifest_script and "vodproductinformation" in manifest_script:
|
||||
logger.warning(
|
||||
f"{gn_id}: content not entitled (manifest_script is "
|
||||
f"vodproductinformation URL — subscriptionMissing)"
|
||||
f"{gn_id}: content not entitled "
|
||||
f"(subscriptionMissing)"
|
||||
)
|
||||
return None
|
||||
|
||||
if manifest_script:
|
||||
# href format: https://link.theplatform.eu/s/mdeprod/media/zRPPGLNGgPa1
|
||||
# href: https://link.theplatform.eu/s/mdeprod/media/zRPPGLNGgPa1
|
||||
guid = manifest_script.rstrip("/").rsplit("/media/", 1)[-1].split("?")[0]
|
||||
if guid and guid != manifest_script:
|
||||
logger.debug(f"Resolved GN id {gn_id} → guid {guid}")
|
||||
logger.debug(f"Resolved {gn_id} → guid {guid}")
|
||||
return guid
|
||||
# Fallback to content_id if manifest_script is absent
|
||||
|
||||
# Fallback: content_id already IS the guid (set by _fetch_single_item)
|
||||
resolved = getattr(item, "content_id", None)
|
||||
if resolved and resolved != gn_id:
|
||||
logger.debug(f"Resolved GN id {gn_id} → content_id {resolved}")
|
||||
if resolved and resolved not in (gn_id, f"movie:{gn_id}", f"episode:{gn_id}"):
|
||||
logger.debug(f"Resolved {gn_id} → {resolved}")
|
||||
return resolved
|
||||
|
||||
logger.warning(f"GN id {gn_id} resolution returned no usable id")
|
||||
except Exception as exc:
|
||||
logger.warning(f"GN id {gn_id} resolution failed: {exc}")
|
||||
@@ -1380,10 +1386,20 @@ class Magenta2Provider(StreamingProvider):
|
||||
|
||||
def _get_smil_data(self, channel_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get complete SMIL data with caching"""
|
||||
# If the caller passed a Gracenote content id (GN_EP*, GN_MV*, GN_SH*)
|
||||
# rather than a real MPX mediaId, resolve it first. The SMIL/selector
|
||||
# endpoint only accepts MPX mediaIds.
|
||||
if (
|
||||
# Strip opaque prefixes added at browse time — resolution happens here.
|
||||
if channel_id.startswith("movie:") or channel_id.startswith("episode:"):
|
||||
gn_id = channel_id.split(":", 1)[1]
|
||||
resolved = self._resolve_gn_id_to_media_id(gn_id)
|
||||
if resolved:
|
||||
channel_id = resolved
|
||||
else:
|
||||
logger.error(
|
||||
f"Cannot play {channel_id}: failed to resolve to MPX guid"
|
||||
)
|
||||
return None
|
||||
|
||||
# Legacy: bare GN_EP*/GN_MV*/GN_SH* ids (pre-opaque-prefix era)
|
||||
elif (
|
||||
channel_id.startswith(VOD_PREFIX_EPISODE)
|
||||
or channel_id.startswith(VOD_PREFIX_MOVIE_MV)
|
||||
or channel_id.startswith(VOD_PREFIX_MOVIE_SH)
|
||||
|
||||
@@ -825,19 +825,10 @@ class VodManager:
|
||||
fetch_url=details_href,
|
||||
)
|
||||
|
||||
# Movie (or unknown leaf): resolve via _fetch_single_item so we get
|
||||
# the correct MPX mediaId as content_id and a ready manifest_script.
|
||||
items = self._fetch_single_item(content_id, params)
|
||||
if items:
|
||||
return items[0]
|
||||
|
||||
# _fetch_single_item failed — return a minimal unresolved VodItem so
|
||||
# the lane listing still shows the title/artwork, even if playback
|
||||
# will fail later.
|
||||
logger.warning(
|
||||
f"{self._provider}: Could not resolve playback for movie "
|
||||
f"'{title}' ({content_id}); returning unresolved item."
|
||||
)
|
||||
# Movie (or unknown leaf): store opaque "movie:GN_MV..." id.
|
||||
# Playback resolution (VodDetails → productInformation → VodPlayer)
|
||||
# is deferred to get_manifest() / get_drm() — only triggered when the
|
||||
# user actually hits play, not during lane browsing.
|
||||
year_raw = item.get("yearOfProduction")
|
||||
try:
|
||||
release_year: Optional[int] = int(str(year_raw).split("-")[0]) if year_raw else None
|
||||
@@ -846,7 +837,7 @@ class VodManager:
|
||||
duration_raw = item.get("duration")
|
||||
return VodItem.create_movie(
|
||||
name=title,
|
||||
content_id=content_id,
|
||||
content_id=f"movie:{content_id}",
|
||||
provider=self._provider,
|
||||
logo_url=image_url,
|
||||
description=description,
|
||||
@@ -1158,7 +1149,7 @@ class VodManager:
|
||||
|
||||
return VodItem.create_episode(
|
||||
name=title,
|
||||
content_id=content_id,
|
||||
content_id=f"episode:{content_id}",
|
||||
provider=self._provider,
|
||||
season_number=season_number or 0,
|
||||
episode_number=ep_num or 0,
|
||||
|
||||
Reference in New Issue
Block a user