mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-09-25 02:22:44 +02:00
Restructure stream routes
This commit is contained in:
+48
-42
@@ -16,6 +16,8 @@ helpers:
|
||||
_build_drm_header(content_type, provider, content_id, ...)
|
||||
Fetches DRM configs via the correct manager method and attaches them as a
|
||||
base64-encoded response header. Non-fatal — logs a warning on failure.
|
||||
Returns the fetched DRMConfig list (or [] on failure) so callers that
|
||||
also need the configs don't have to fetch them a second time.
|
||||
|
||||
_resolve_stream(content_type, provider, content_id, ...)
|
||||
The single place that understands how to turn (type, provider, id) into a
|
||||
@@ -50,11 +52,14 @@ def setup_stream_routes(app, manager, service):
|
||||
from .vod import setup_vod_routes
|
||||
from .recordings import setup_recording_routes
|
||||
|
||||
# Pass manager and service to all submodules
|
||||
setup_channel_routes(app, manager, service)
|
||||
setup_event_routes(app, manager, service)
|
||||
setup_vod_routes(app, manager, service)
|
||||
setup_recording_routes(app, manager, service)
|
||||
# Build the shared helpers once and hand the same dict to every submodule,
|
||||
# rather than each submodule creating its own independent closure set.
|
||||
helpers = make_helpers(manager, service)
|
||||
|
||||
setup_channel_routes(app, manager, service, helpers)
|
||||
setup_event_routes(app, manager, service, helpers)
|
||||
setup_vod_routes(app, manager, service, helpers)
|
||||
setup_recording_routes(app, manager, service, helpers)
|
||||
|
||||
# =========================================================================
|
||||
# ORIGINAL MANIFEST ENDPOINT (shared across content types)
|
||||
@@ -79,8 +84,6 @@ def setup_stream_routes(app, manager, service):
|
||||
try:
|
||||
country = request.query.get("country")
|
||||
|
||||
# Create helpers to use the manager methods
|
||||
helpers = make_helpers(manager, service)
|
||||
_get_manifest_url = helpers["_get_manifest_url"]
|
||||
|
||||
# Map content_type string to constant
|
||||
@@ -125,6 +128,22 @@ def setup_stream_routes(app, manager, service):
|
||||
return {"error": f"Failed to fetch manifest: {str(e)}"}
|
||||
|
||||
|
||||
def _serialize_drm_configs(drm_configs) -> dict:
|
||||
"""
|
||||
Merge a list of DRMConfig objects (or plain dicts) into a single dict,
|
||||
keyed by DRM scheme (e.g. 'org.w3.clearkey', 'none').
|
||||
|
||||
Shared by every call site that needs to turn a list of DRM configs into
|
||||
the merged dict shape used for the response header and for ClearKey
|
||||
keyid lookups.
|
||||
"""
|
||||
merged = {}
|
||||
for config in drm_configs:
|
||||
config_dict = config.to_dict() if hasattr(config, "to_dict") else config
|
||||
merged.update(config_dict)
|
||||
return merged
|
||||
|
||||
|
||||
def make_helpers(manager, service):
|
||||
"""
|
||||
Factory function that creates helper functions with manager and service
|
||||
@@ -223,12 +242,17 @@ def make_helpers(manager, service):
|
||||
"""
|
||||
Fetch DRM configs, serialise to JSON and attach as a base64-encoded
|
||||
response header (x-kodi-drm-configs). Non-fatal: logs a warning and
|
||||
returns None on any error.
|
||||
returns [] on any error.
|
||||
|
||||
Args:
|
||||
drm_variant: 'auto' or 'software'. Forwarded to the DRM config
|
||||
fetch so the provider can return ClearKey configs when
|
||||
the software-DRM variant is requested.
|
||||
|
||||
Returns:
|
||||
The list of DRMConfig objects that were fetched (or [] on failure).
|
||||
Callers that also need the raw configs (e.g. _resolve_stream) can
|
||||
reuse this instead of fetching them again.
|
||||
"""
|
||||
try:
|
||||
if is_catchup and content_type == CONTENT_TYPE_CHANNEL:
|
||||
@@ -247,24 +271,21 @@ def make_helpers(manager, service):
|
||||
country=country, drm_variant=drm_variant,
|
||||
)
|
||||
|
||||
merged = {}
|
||||
for config in drm_configs:
|
||||
config_dict = config.to_dict() if hasattr(config, "to_dict") else config
|
||||
merged.update(config_dict)
|
||||
merged = _serialize_drm_configs(drm_configs)
|
||||
|
||||
encoded = base64.b64encode(
|
||||
json.dumps(merged).encode("utf-8")
|
||||
).decode("ascii")
|
||||
|
||||
response.headers["x-kodi-drm-configs"] = encoded
|
||||
return encoded
|
||||
return drm_configs
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Could not build x-kodi-drm-configs header for "
|
||||
f"{content_type} {provider}/{content_id} (variant={drm_variant}): {e}"
|
||||
)
|
||||
return None
|
||||
return []
|
||||
|
||||
def _build_stream_headers(
|
||||
content_type: str,
|
||||
@@ -410,8 +431,10 @@ def make_helpers(manager, service):
|
||||
software-decodable DRM). Threaded through to all helpers so
|
||||
providers can return the correct manifest URL and DRM configs.
|
||||
"""
|
||||
# --- DRM header (best-effort, never fatal) ---
|
||||
_build_drm_header(
|
||||
# --- DRM header (best-effort, never fatal). Also returns the DRM
|
||||
# configs it fetched so the proxy branch below can reuse them instead
|
||||
# of fetching from the provider a second time. ---
|
||||
drm_configs_for_header = _build_drm_header(
|
||||
content_type, provider, content_id,
|
||||
country=country,
|
||||
is_catchup=is_catchup,
|
||||
@@ -459,22 +482,12 @@ def make_helpers(manager, service):
|
||||
# Check for ClearKey DRM — if present, rewrite manifest with ClearKey signaling
|
||||
# so the receiver can decrypt itself, rather than serving a plain proxy stream
|
||||
# with stripped ContentProtection that the player cannot handle.
|
||||
try:
|
||||
drm_configs = _get_drm_configs(
|
||||
content_type, provider, content_id,
|
||||
country=country, drm_variant=drm_variant,
|
||||
)
|
||||
drm_dict = {}
|
||||
for config in drm_configs:
|
||||
drm_dict.update(
|
||||
config.to_dict() if hasattr(config, "to_dict") else config
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Could not fetch DRM configs for {content_type} "
|
||||
f"{provider}/{content_id} during proxy resolution: {e}"
|
||||
)
|
||||
drm_dict = {}
|
||||
#
|
||||
# Reuse the configs _build_drm_header already fetched above rather than
|
||||
# calling the provider again. This branch is only reached when
|
||||
# is_catchup is False, so drm_configs_for_header always corresponds to
|
||||
# the non-catchup fetch performed above.
|
||||
drm_dict = _serialize_drm_configs(drm_configs_for_header)
|
||||
|
||||
keyids = (
|
||||
drm_dict.get("org.w3.clearkey", {})
|
||||
@@ -620,11 +633,7 @@ def make_helpers(manager, service):
|
||||
epg_id=epg_id,
|
||||
country=country,
|
||||
)
|
||||
catchup_drm_dict = {}
|
||||
for config in catchup_drm_configs:
|
||||
catchup_drm_dict.update(
|
||||
config.to_dict() if hasattr(config, "to_dict") else config
|
||||
)
|
||||
catchup_drm_dict = _serialize_drm_configs(catchup_drm_configs)
|
||||
|
||||
is_unencrypted = "none" in catchup_drm_dict
|
||||
keyids = (
|
||||
@@ -658,11 +667,7 @@ def make_helpers(manager, service):
|
||||
content_type, provider, content_id, country=country
|
||||
)
|
||||
|
||||
drm_dict = {}
|
||||
for config in drm_configs:
|
||||
drm_dict.update(
|
||||
config.to_dict() if hasattr(config, "to_dict") else config
|
||||
)
|
||||
drm_dict = _serialize_drm_configs(drm_configs)
|
||||
|
||||
has_clearkey = "org.w3.clearkey" in drm_dict
|
||||
is_unencrypted = "none" in drm_dict
|
||||
@@ -746,4 +751,5 @@ def make_helpers(manager, service):
|
||||
"_inject_base_url": _inject_base_url,
|
||||
"_resolve_stream": _resolve_stream,
|
||||
"_resolve_decrypted_stream": _resolve_decrypted_stream,
|
||||
"_serialize_drm_configs": _serialize_drm_configs,
|
||||
}
|
||||
@@ -11,15 +11,10 @@ import time
|
||||
from bottle import HTTPResponse, request, response
|
||||
from streaming_providers.base.utils import logger
|
||||
|
||||
from . import make_helpers
|
||||
|
||||
|
||||
def setup_channel_routes(app, manager, service):
|
||||
def setup_channel_routes(app, manager, service, helpers):
|
||||
"""Setup all channel-related stream routes."""
|
||||
|
||||
# Create helpers with manager and service closures
|
||||
helpers = make_helpers(manager, service)
|
||||
|
||||
CONTENT_TYPE_CHANNEL = helpers["CONTENT_TYPE_CHANNEL"]
|
||||
_build_drm_header = helpers["_build_drm_header"]
|
||||
_build_stream_headers = helpers["_build_stream_headers"]
|
||||
|
||||
@@ -9,15 +9,10 @@ share the same transport pattern as channels but without catchup support.
|
||||
from bottle import HTTPResponse, request, response
|
||||
from streaming_providers.base.utils import logger
|
||||
|
||||
from . import make_helpers
|
||||
|
||||
|
||||
def setup_event_routes(app, manager, service):
|
||||
def setup_event_routes(app, manager, service, helpers):
|
||||
"""Setup all event-related stream routes."""
|
||||
|
||||
# Create helpers with manager and service closures
|
||||
helpers = make_helpers(manager, service)
|
||||
|
||||
CONTENT_TYPE_EVENT = helpers["CONTENT_TYPE_EVENT"]
|
||||
_build_drm_header = helpers["_build_drm_header"]
|
||||
_build_stream_headers = helpers["_build_stream_headers"]
|
||||
|
||||
@@ -11,15 +11,10 @@ Recordings are always on-demand (pre-captured), so:
|
||||
from bottle import HTTPResponse, request, response
|
||||
from streaming_providers.base.utils import logger
|
||||
|
||||
from . import make_helpers
|
||||
|
||||
|
||||
def setup_recording_routes(app, manager, service):
|
||||
def setup_recording_routes(app, manager, service, helpers):
|
||||
"""Setup all recording-related stream routes."""
|
||||
|
||||
# Create helpers with manager and service closures
|
||||
helpers = make_helpers(manager, service)
|
||||
|
||||
CONTENT_TYPE_RECORDING = helpers["CONTENT_TYPE_RECORDING"]
|
||||
_build_drm_header = helpers["_build_drm_header"]
|
||||
_build_stream_headers = helpers["_build_stream_headers"]
|
||||
|
||||
@@ -9,15 +9,10 @@ IDs (paths like "clip_1417600/stream") and without catchup support.
|
||||
from bottle import HTTPResponse, request, response
|
||||
from streaming_providers.base.utils import logger
|
||||
|
||||
from . import make_helpers
|
||||
|
||||
|
||||
def setup_vod_routes(app, manager, service):
|
||||
def setup_vod_routes(app, manager, service, helpers):
|
||||
"""Setup all VOD-related stream routes."""
|
||||
|
||||
# Create helpers with manager and service closures
|
||||
helpers = make_helpers(manager, service)
|
||||
|
||||
CONTENT_TYPE_VOD = helpers["CONTENT_TYPE_VOD"]
|
||||
_build_drm_header = helpers["_build_drm_header"]
|
||||
_build_stream_headers = helpers["_build_stream_headers"]
|
||||
|
||||
Reference in New Issue
Block a user