mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-10-06 07:52:26 +02:00
133 lines
4.4 KiB
Python
133 lines
4.4 KiB
Python
# streaming_providers/providers/_template/catchup_manager.py
|
|
"""
|
|
{TODO: Provider name} catchup manager (optional).
|
|
|
|
Include this file only if the provider supports timeshift / restart.
|
|
Providers without catchup don't create a catchup manager -- the
|
|
provider's implements_catchup is False and calls to
|
|
get_catchup_manifest return None.
|
|
|
|
See ../_template/README.md for the contract.
|
|
|
|
Reference implementations
|
|
-------------------------
|
|
MoveTV's provider (providers/movetv/provider.py) implements catchup
|
|
by resolving an EPG entry, then POSTing to a catchup-source endpoint
|
|
that returns a URL + a play-auth header. The URL and header are
|
|
coupled, so the manager needs a reference to the EPG manager (to
|
|
resolve epg_id) and to the channel manager (for the channel's stream
|
|
uid).
|
|
|
|
Magenta EU's provider (providers/magentaeu/provider.py) implements
|
|
catchup by appending start/end query parameters to the live manifest
|
|
URL via build_catchup_url().
|
|
|
|
simpliTV's catchup only takes a start bound: it passes end_time=None
|
|
through and documents that it ignores it. The router parses the
|
|
"catchup:<codename>@<ts>" id (an explicit branch above _route) and
|
|
hands the parsed arguments to this manager.
|
|
|
|
HRTi has no catchup -- its VOD and EPG are separate domains, and
|
|
authorize_session's session id is not reused for timeshift.
|
|
|
|
State sharing
|
|
-------------
|
|
The catchup step often shares state with the channel manager (the live
|
|
manifest URL) or the EPG manager (the epg_id for the requested window).
|
|
Pass those collaborators as explicit keyword-only arguments rather than
|
|
reaching back to the provider (the provider's _build_catchup does this).
|
|
|
|
Do NOT fall back to the live manifest
|
|
-------------------------------------
|
|
If get_catchup_manifest cannot resolve catchup for the given window,
|
|
return None. Do not return the live manifest URL as a "catchup"
|
|
manifest -- the DRM pipeline would extract PSSH from the live stream,
|
|
which may differ from the catchup stream's encryption context. Callers
|
|
that want the live manifest on failure call provider.get_manifest().
|
|
|
|
end_time is Optional[int]
|
|
-------------------------
|
|
If the provider's API takes only a start bound, accept None and document
|
|
that it is ignored. If the API needs both bounds, raise BadRequestError
|
|
on None. Never pass a sentinel (0, start_time + 1800) when the ABC
|
|
accepts None.
|
|
"""
|
|
|
|
from typing import List, Optional
|
|
|
|
from ...base.managers import CatchupManager
|
|
from ...base.models import DRMConfig
|
|
from ...base.utils.logger import logger
|
|
|
|
# from ...base.errors import BadRequestError
|
|
|
|
|
|
class YourCatchupManager(CatchupManager):
|
|
"""Catchup for {TODO: provider name}."""
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
http_manager,
|
|
auth,
|
|
country,
|
|
config,
|
|
channels=None,
|
|
epg=None,
|
|
):
|
|
super().__init__(
|
|
http_manager=http_manager,
|
|
auth=auth,
|
|
country=country,
|
|
config=config,
|
|
)
|
|
# Common collaborators. Catchup often needs one or both.
|
|
# - channels: for resolving a channel's live manifest URL
|
|
# (Magenta, simpliTV) or its stream uid (MoveTV).
|
|
# - epg: for resolving an epg_id from a start_time
|
|
# (MoveTV).
|
|
self._channels = channels
|
|
self._epg = epg
|
|
|
|
# ----- Capability -----
|
|
|
|
@property
|
|
def catchup_window_hours(self) -> int:
|
|
"""Return the catchup window in hours. 0 means no catchup."""
|
|
return 0 # TODO: e.g. 168 for 7 days
|
|
|
|
# ----- Abstract method -----
|
|
|
|
def get_catchup_manifest(
|
|
self,
|
|
content_id: str,
|
|
start_time: int,
|
|
end_time: Optional[int] = None,
|
|
epg_id: Optional[str] = None,
|
|
**kw,
|
|
) -> Optional[str]:
|
|
"""
|
|
Return the catchup manifest URL, or None if not resolvable.
|
|
|
|
start_time / end_time are integer epoch seconds. end_time may be
|
|
None (see module docstring).
|
|
|
|
Do NOT fall back to the live manifest URL here.
|
|
"""
|
|
raise NotImplementedError("YourCatchupManager.get_catchup_manifest")
|
|
|
|
# ----- Concrete methods (override when needed) -----
|
|
|
|
# def get_catchup_drm(
|
|
# self,
|
|
# content_id: str,
|
|
# start_time: int,
|
|
# end_time: Optional[int] = None,
|
|
# epg_id: Optional[str] = None,
|
|
# **kw,
|
|
# ) -> List[DRMConfig]:
|
|
# """
|
|
# Override only if catchup uses a different DRM config from live.
|
|
# The default returns [] -- the caller falls back to live DRM.
|
|
# """
|
|
# return [] |