mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-10-28 09:42:33 +01:00
movetv: update version
This commit is contained in:
@@ -109,7 +109,7 @@ def api_post(
|
||||
response: Any = None
|
||||
for attempt in (1, 2):
|
||||
info = session.info(need_profile=need_profile) # raises typed AuthError & co.
|
||||
headers = MoveTVConfig.get_api_headers(info["auth_token"])
|
||||
headers = MoveTVConfig.get_api_headers(info["auth_token"], dev_id=info.get("uid"))
|
||||
try:
|
||||
response = http_manager.post(
|
||||
url, operation=operation, json=build_payload(info), headers=headers
|
||||
|
||||
@@ -96,7 +96,7 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
|
||||
def _get_auth_headers(self) -> Dict[str, str]:
|
||||
"""Headers for the authentication request."""
|
||||
return MoveTVConfig.get_base_headers()
|
||||
return MoveTVConfig.get_base_headers(dev_id=self.get_device_id())
|
||||
|
||||
def _build_auth_payload(self) -> Dict[str, Any]:
|
||||
"""Build the login payload from current credentials."""
|
||||
@@ -110,6 +110,7 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
"deviceName": MoveTVConfig.DEVICE_NAME,
|
||||
"deviceModelId": MoveTVConfig.DEVICE_MODEL_ID,
|
||||
"uid": uid,
|
||||
"debugMac": uid,
|
||||
"appVersion": MoveTVConfig.APP_VERSION,
|
||||
}
|
||||
|
||||
@@ -217,8 +218,10 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
status, f"move.tv: login failed (HTTP {status})", url=self.auth_endpoint
|
||||
) from exc
|
||||
if isinstance(status, int) and status >= 400:
|
||||
body = (getattr(response, "text", "") or "")[:300]
|
||||
logger.warning(f"move.tv: login failed (HTTP {status}): {body}")
|
||||
raise default_error_for_status_heuristic(
|
||||
status, f"move.tv: login failed (HTTP {status})", url=self.auth_endpoint
|
||||
status, f"move.tv: login failed (HTTP {status}): {body}", url=self.auth_endpoint
|
||||
)
|
||||
try:
|
||||
data = response.json()
|
||||
@@ -255,13 +258,11 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
logger.debug("move.tv: validate_token called with empty access_token, skipping")
|
||||
return False
|
||||
|
||||
headers = {
|
||||
**MoveTVConfig.get_base_headers(),
|
||||
"x-auth-token": token.access_token,
|
||||
"x-refresh-token": token.refresh_token or "",
|
||||
}
|
||||
headers = MoveTVConfig.get_base_headers(token.access_token, dev_id=token.device_id)
|
||||
headers[MoveTVConfig.HEADER_REFRESH_TOKEN] = token.refresh_token or ""
|
||||
payload = {
|
||||
"customerId": token.customer_id,
|
||||
"debugMac": token.device_id,
|
||||
"appVersion": MoveTVConfig.APP_VERSION,
|
||||
}
|
||||
|
||||
@@ -279,7 +280,8 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
except Exception as exc:
|
||||
logger.debug(f"move.tv: Token validation request failed: {exc}")
|
||||
status = getattr(getattr(exc, "response", None), "status_code", None)
|
||||
logger.warning(f"move.tv: Token validation request failed (HTTP {status}): {exc}")
|
||||
return False
|
||||
|
||||
if data.get("message") == "Token active.":
|
||||
@@ -312,10 +314,8 @@ class MoveTVAuthenticator(BaseAuthenticator):
|
||||
logger.debug("move.tv: refresh_token called but no refresh_token stored, skipping")
|
||||
return None
|
||||
|
||||
headers = {
|
||||
**MoveTVConfig.get_base_headers(),
|
||||
"x-refresh-token": token.refresh_token,
|
||||
}
|
||||
headers = MoveTVConfig.get_base_headers(dev_id=token.device_id)
|
||||
headers[MoveTVConfig.HEADER_REFRESH_TOKEN] = token.refresh_token
|
||||
payload = {
|
||||
"customerProfileId": token.customer_profile_id,
|
||||
"appVersion": MoveTVConfig.APP_VERSION,
|
||||
|
||||
@@ -58,8 +58,8 @@ class MoveTVConfig:
|
||||
# -------------------------------------------------------------------------
|
||||
PARTNER_ID: int = 2
|
||||
DEVICE_MODEL_ID: int = 10
|
||||
DEVICE_NAME: str = "Chrome 146"
|
||||
APP_VERSION: str = "3.4.8"
|
||||
DEVICE_NAME: str = "Chrome 155"
|
||||
APP_VERSION: str = "3.5.41"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Language / locale defaults
|
||||
@@ -70,9 +70,9 @@ class MoveTVConfig:
|
||||
# HTTP / request defaults
|
||||
# -------------------------------------------------------------------------
|
||||
USER_AGENT: str = (
|
||||
"Mozilla/5.0 (X11; Linux x86_64) "
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/146.0.0.0 Safari/537.36"
|
||||
"Chrome/155.0.0.0 Safari/537.36"
|
||||
)
|
||||
TIMEOUT: int = 30
|
||||
|
||||
@@ -96,6 +96,8 @@ class MoveTVConfig:
|
||||
PLAY_AUTH_EARLY_EXPIRY_SECONDS: int = 60
|
||||
PLAY_AUTH_EXPIRY_PATTERN: str = r"expires-(\d+)"
|
||||
HEADER_PLAY_AUTH: str = "X-Play-Auth"
|
||||
HEADER_DEV_ID: str = "X-Dev-Id"
|
||||
HEADER_REFRESH_TOKEN: str = "X-Refresh-Token"
|
||||
|
||||
# VOD: browse tag per content-type NAME (as in v1)
|
||||
TAG_ID_BY_CONTENT_TYPE_NAME: Dict[str, int] = {"Film": 1, "Serija": 2}
|
||||
@@ -135,27 +137,36 @@ class MoveTVConfig:
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@classmethod
|
||||
def get_base_headers(cls, auth_token: Optional[str] = None) -> Dict[str, str]:
|
||||
def get_base_headers(
|
||||
cls, auth_token: Optional[str] = None, dev_id: Optional[str] = None
|
||||
) -> Dict[str, str]:
|
||||
"""
|
||||
Returns headers shared by every request.
|
||||
|
||||
When *auth_token* is None the unauthenticated sentinel value is used
|
||||
(as observed in the login request capture).
|
||||
(as observed in the login request capture). *dev_id* is the local
|
||||
device uid; the web client sends it as X-Dev-Id on every call.
|
||||
"""
|
||||
return {
|
||||
headers = {
|
||||
"Accept": "*/*",
|
||||
"Accept-Encoding": "gzip, deflate, br, zstd",
|
||||
# Only encodings the HTTP stack is sure to decode (no br / zstd).
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Content-Type": "application/json",
|
||||
"Origin": cls.WEB_ORIGIN,
|
||||
"Referer": cls.WEB_REFERER,
|
||||
"User-Agent": cls.USER_AGENT,
|
||||
"X-Auth-Token": auth_token if auth_token else cls.UNAUTHENTICATED_TOKEN,
|
||||
}
|
||||
if dev_id:
|
||||
headers[cls.HEADER_DEV_ID] = dev_id
|
||||
return headers
|
||||
|
||||
@classmethod
|
||||
def get_api_headers(cls, auth_token: Optional[str] = None) -> Dict[str, str]:
|
||||
def get_api_headers(
|
||||
cls, auth_token: Optional[str] = None, dev_id: Optional[str] = None
|
||||
) -> Dict[str, str]:
|
||||
"""Headers for authenticated JSON API calls (channels, manifest source, VOD)."""
|
||||
return cls.get_base_headers(auth_token)
|
||||
return cls.get_base_headers(auth_token, dev_id=dev_id)
|
||||
|
||||
@classmethod
|
||||
def stream_headers(cls, play_auth: Optional[str] = None) -> Dict[str, str]:
|
||||
|
||||
@@ -67,10 +67,13 @@ class MoveTvSession:
|
||||
return self.authenticator.get_current_token()
|
||||
|
||||
def _ready(self) -> bool:
|
||||
# No local is_expired check: the token's real lifetime is decided by
|
||||
# the server (401 -> recover()). A locally "expired" but server-valid
|
||||
# token would otherwise be re-validated on every call.
|
||||
token = self._token()
|
||||
return bool(
|
||||
self._logged_in and token is not None
|
||||
and getattr(token, "access_token", None) and not token.is_expired
|
||||
and getattr(token, "access_token", None)
|
||||
)
|
||||
|
||||
# ---- failure bookkeeping ---------------------------------------------
|
||||
@@ -165,7 +168,9 @@ class MoveTvSession:
|
||||
return self._token().access_token
|
||||
|
||||
def build_headers(self) -> Dict[str, str]:
|
||||
return self.config.get_api_headers(self.get_access_token())
|
||||
access_token = self.get_access_token()
|
||||
dev_id = getattr(self._token(), "device_id", None)
|
||||
return self.config.get_api_headers(access_token, dev_id=dev_id)
|
||||
|
||||
def invalidate(self) -> None:
|
||||
self.authenticator.invalidate_token() # memory AND persisted storage
|
||||
|
||||
Reference in New Issue
Block a user