Files
script.service.ultimate/lib/streaming_providers/providers/eon/persistence.py
T
2026-10-20 07:21:18 +02:00

102 lines
4.0 KiB
Python

# streaming_providers/providers/eon/persistence.py
"""
Glue between EonAuth and the framework's storage managers.
SessionStore -- EonStore on top of SessionManager: one dict at
session.json[<provider>][<country>] (country LOWER-case, as
the managers key by it). Read once, written through.
default_persistence() -- finds a SessionManager and a credentials loader the
way BaseAuthenticator does (injected settings manager, else
a SettingsManager of its own); anything missing degrades to
the non-durable MemoryStore / no stored credentials, with a
warning, never to an exception.
SessionManager logs every value of keys it does not know at INFO
(`Saving session data ...`): never hand this store a secret that can be
re-derived. EonAuth persists device identity and the refresh token only (the
refresh token is on SessionManager's mask list).
"""
import threading
from typing import Any, Callable, Dict, Optional, Tuple
from ...base.utils.logger import logger
from .auth import EonStore, MemoryStore
class SessionStore:
def __init__(self, session_manager: Any, provider: str, country: Optional[str]):
self._sm = session_manager
self._provider = provider
self._country = country or None
self._lock = threading.RLock()
self._cache: Optional[Dict[str, str]] = None
def _data(self) -> Dict[str, str]:
if self._cache is None:
loaded = self._sm.load_session(self._provider, self._country)
self._cache = {k: v for k, v in (loaded or {}).items() if isinstance(v, str)}
return self._cache
def get(self, key: str) -> Optional[str]:
with self._lock:
return self._data().get(key)
def set(self, key: str, value: str) -> None:
self.set_many({key: value})
def set_many(self, values: Dict[str, str]) -> None:
with self._lock:
data = self._data()
if all(data.get(k) == v for k, v in values.items()):
return
data.update(values)
self._save()
def delete(self, key: str) -> None:
with self._lock:
data = self._data()
if key in data:
del data[key]
self._save()
def _save(self) -> None:
# save_session REPLACES the dict at that path: write the whole cache.
if not self._sm.save_session(self._provider, dict(self._data()), self._country):
logger.warning(f"{self._provider}: could not persist the session")
def default_persistence(
*, provider: str, country: str, settings_manager: Any = None,
) -> Tuple[EonStore, Optional[Callable[[], Any]]]:
"""(store, credentials_loader); never raises."""
manager = settings_manager
if manager is None:
try:
from ...base.settings.settings_manager import SettingsManager
manager = SettingsManager(config_dir=None, enable_kodi_integration=True)
except Exception as exc:
logger.warning(f"{provider}: no settings manager ({exc!r})")
if manager is not None and hasattr(manager, "register_provider"):
try:
manager.register_provider(provider)
except Exception as exc:
logger.warning(f"{provider}: could not register with the settings manager: {exc!r}")
session_manager = getattr(manager, "session_manager", None)
if session_manager is None:
try:
from ...base.auth.session_manager import SessionManager
session_manager = SessionManager()
except Exception as exc:
logger.warning(f"{provider}: no SessionManager ({exc!r}); device identity is NOT persisted")
store: EonStore = (
SessionStore(session_manager, provider, country) if session_manager is not None
else MemoryStore()
)
loader: Optional[Callable[[], Any]] = None
if manager is not None and hasattr(manager, "get_provider_credentials"):
loader = lambda: manager.get_provider_credentials(provider, country) # noqa: E731
return store, loader