mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-10-27 09:12:43 +01:00
Add movetv
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# streaming_providers/providers/movetv/auth.py
|
||||
import time
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
@@ -24,6 +25,7 @@ class MoveTVAuthToken(BaseAuthToken):
|
||||
- customer_profile_id active profile id (needed in manifest requests)
|
||||
- dedicated_server CDN base URL (e.g. https://edge-mts-si-2.mts-si.tv)
|
||||
- device_id server-assigned device identifier
|
||||
- uid client-generated unique identifier (UUID)
|
||||
- widevine_url Widevine license server URL (from drm_server block)
|
||||
- playready_url PlayReady license server URL (from drm_server block)
|
||||
"""
|
||||
@@ -33,6 +35,7 @@ class MoveTVAuthToken(BaseAuthToken):
|
||||
customer_profile_id: int = 0
|
||||
dedicated_server: str = ""
|
||||
device_id: int = 0
|
||||
uid: str = ""
|
||||
widevine_url: str = ""
|
||||
playready_url: str = ""
|
||||
|
||||
@@ -51,6 +54,7 @@ class MoveTVAuthToken(BaseAuthToken):
|
||||
"customer_profile_id": self.customer_profile_id,
|
||||
"dedicated_server": self.dedicated_server,
|
||||
"device_id": self.device_id,
|
||||
"uid": self.uid,
|
||||
"widevine_url": self.widevine_url,
|
||||
"playready_url": self.playready_url,
|
||||
}
|
||||
@@ -72,6 +76,7 @@ class MoveTVAuthToken(BaseAuthToken):
|
||||
customer_profile_id=data.get("customer_profile_id", 0),
|
||||
dedicated_server=data.get("dedicated_server", ""),
|
||||
device_id=data.get("device_id", 0),
|
||||
uid=data.get("uid", ""),
|
||||
widevine_url=data.get("widevine_url", ""),
|
||||
playready_url=data.get("playready_url", ""),
|
||||
)
|
||||
@@ -93,19 +98,20 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
- refresh_token → used to renew the session without re-entering credentials
|
||||
- dedicated_server → CDN base URL; manifest URLs are derived from it
|
||||
- customer_id / device_id / profile.id → required for manifest source requests
|
||||
- t → token lifetime in seconds (32400 = 9 hours)
|
||||
3. All of the above is stored on MoveTVAuthToken and persisted via the
|
||||
base-class settings_manager.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
proxy_config=None,
|
||||
http_manager=None,
|
||||
settings_manager=None,
|
||||
credentials: Optional[UserPasswordCredentials] = None,
|
||||
country: Optional[str] = None,
|
||||
config_dir: Optional[str] = None,
|
||||
enable_kodi_integration: bool = True,
|
||||
self,
|
||||
proxy_config=None,
|
||||
http_manager=None,
|
||||
settings_manager=None,
|
||||
credentials: Optional[UserPasswordCredentials] = None,
|
||||
country: Optional[str] = None,
|
||||
config_dir: Optional[str] = None,
|
||||
enable_kodi_integration: bool = True,
|
||||
):
|
||||
super().__init__(
|
||||
provider_name="movetv",
|
||||
@@ -117,6 +123,30 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
)
|
||||
self._proxy_config = proxy_config
|
||||
self._http_manager = http_manager
|
||||
self._uid = None # Will be loaded from stored token or generated
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# UID management
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _get_or_generate_uid(self) -> str:
|
||||
"""
|
||||
Get existing UID from stored token or generate a new UUID.
|
||||
The UID is persisted across sessions via the token storage.
|
||||
"""
|
||||
if self._uid:
|
||||
return self._uid
|
||||
|
||||
# Try to load from existing token if available
|
||||
if self._current_token and hasattr(self._current_token, 'uid'):
|
||||
self._uid = self._current_token.uid
|
||||
if self._uid:
|
||||
return self._uid
|
||||
|
||||
# Generate new UUID
|
||||
self._uid = str(uuid.uuid4())
|
||||
logger.debug(f"move.tv: Generated new UID: {self._uid}")
|
||||
return self._uid
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# BaseAuthenticator abstract contract
|
||||
@@ -137,7 +167,7 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
Called by the base class only when credentials are already validated,
|
||||
so self.credentials is safe to access here.
|
||||
"""
|
||||
uid = self.get_device_id()
|
||||
uid = self._get_or_generate_uid()
|
||||
return {
|
||||
"username": self.credentials.username,
|
||||
"password": self.credentials.password,
|
||||
@@ -158,8 +188,8 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
|
||||
def has_user_credentials(self) -> bool:
|
||||
return (
|
||||
isinstance(self.credentials, UserPasswordCredentials)
|
||||
and self.credentials.validate()
|
||||
isinstance(self.credentials, UserPasswordCredentials)
|
||||
and self.credentials.validate()
|
||||
)
|
||||
|
||||
def get_current_token_level(self) -> TokenAuthLevel:
|
||||
@@ -232,16 +262,18 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
"""
|
||||
Map the raw /api/v2/login JSON response onto a MoveTVAuthToken.
|
||||
|
||||
The API does not return a numeric expires_in; the auth_token contains
|
||||
an 'expires-<unix>' component in the protection header of manifest
|
||||
responses (typically ~24 h). We default to 86 400 s (24 h) so the
|
||||
base-class expiry logic behaves sensibly.
|
||||
The API returns token lifetime in the 't' field (in seconds).
|
||||
If not present, defaults to 32400 (9 hours) based on observed responses.
|
||||
"""
|
||||
auth_token: str = data.get("auth_token", "")
|
||||
refresh_token: str = data.get("refresh_token", "")
|
||||
customer_id: int = data.get("customer_id", 0)
|
||||
device_id: int = data.get("device_id", 0)
|
||||
dedicated_server: str = data.get("dedicated_server", "")
|
||||
uid: str = data.get("uid", "")
|
||||
|
||||
# Get token expiry from 't' field (in seconds)
|
||||
token_expiry: int = data.get("t", 32400) # Default to 9 hours if not present
|
||||
|
||||
profile: Dict = data.get("profile", {})
|
||||
customer_profile_id: int = profile.get("id", 0)
|
||||
@@ -252,14 +284,15 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
|
||||
logger.info(
|
||||
f"move.tv: Login successful – customer_id={customer_id}, "
|
||||
f"device_id={device_id}, dedicated_server={dedicated_server}"
|
||||
f"device_id={device_id}, uid={uid}, dedicated_server={dedicated_server}, "
|
||||
f"token_expires_in={token_expiry}s"
|
||||
)
|
||||
|
||||
return MoveTVAuthToken(
|
||||
# BaseAuthToken fields
|
||||
access_token=auth_token, # used as bearer / X-Auth-Token
|
||||
access_token=auth_token, # used as bearer / X-Auth-Token
|
||||
token_type="token",
|
||||
expires_in=86400, # 24 h default; no numeric TTL in response
|
||||
expires_in=token_expiry, # Use actual token lifetime from API
|
||||
issued_at=time.time(),
|
||||
refresh_token=refresh_token if refresh_token else None,
|
||||
refresh_expires_in=0,
|
||||
@@ -271,6 +304,7 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
customer_profile_id=customer_profile_id,
|
||||
dedicated_server=dedicated_server,
|
||||
device_id=device_id,
|
||||
uid=uid,
|
||||
widevine_url=widevine_url,
|
||||
playready_url=playready_url,
|
||||
)
|
||||
@@ -299,6 +333,7 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
"customer_id": t.customer_id,
|
||||
"customer_profile_id": t.customer_profile_id,
|
||||
"device_id": t.device_id,
|
||||
"uid": t.uid,
|
||||
"dedicated_server": t.dedicated_server,
|
||||
"auth_token": t.auth_token,
|
||||
}
|
||||
Reference in New Issue
Block a user