mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-09-17 06:32:30 +02:00
movetv fixes
This commit is contained in:
@@ -170,6 +170,16 @@ class EPGEntry:
|
||||
writers: Optional[List[str]] = None
|
||||
"""List of writer names. C++ expects 'writers' array."""
|
||||
|
||||
producers: Optional[List[str]] = None
|
||||
"""
|
||||
List of producer names. Note: unlike cast/directors/writers, Kodi's
|
||||
PVREPGTag C++ interface has no dedicated producer slot, so this field
|
||||
is not rendered by the Kodi frontend today. It is still captured here
|
||||
for JSON/API consumers and providers (e.g. MoveTV's channel-based EPG
|
||||
endpoint) that return producer data as part of a single one-shot
|
||||
fetch with no separate enrichment pass to fall back on.
|
||||
"""
|
||||
|
||||
# Optional fields - Genre/Category
|
||||
genre: Optional[int] = None
|
||||
"""
|
||||
@@ -191,6 +201,14 @@ class EPGEntry:
|
||||
Used when genre=EPGGenre.USE_STRING or for custom genres not in DVB-SI standard.
|
||||
"""
|
||||
|
||||
genres: Optional[List[str]] = None
|
||||
"""
|
||||
List of text genre/category labels (e.g. ["Komedija", "Drama", "Romansa"]),
|
||||
distinct from the single numeric DVB-SI `genre` field and from the single
|
||||
`genre_description` string above. Named to match EPGProgramDetails.genres
|
||||
so the two line up if this ever gets pulled into a shared merge field.
|
||||
"""
|
||||
|
||||
# Optional fields - Episode Information
|
||||
season_number: Optional[int] = None
|
||||
"""Season/series number (1-based). C++ expects 'season_number' key."""
|
||||
@@ -278,8 +296,10 @@ class EPGEntry:
|
||||
"cast",
|
||||
"directors",
|
||||
"writers",
|
||||
"producers",
|
||||
"genre",
|
||||
"genre_description",
|
||||
"genres",
|
||||
"season_number",
|
||||
"episode_number",
|
||||
"episode_part_number",
|
||||
@@ -803,12 +823,17 @@ def merge_content(entry: "EPGEntry", details: "EPGProgramDetails") -> "EPGEntry"
|
||||
this title) will not clobber a value already present on `entry`.
|
||||
|
||||
Fields that exist on EPGProgramDetails but NOT in EPGContent (e.g.
|
||||
provider_vod_id, genres, backdrop/poster, producers/presenter/
|
||||
composers/contributors, the *_details enriched-person fields) are
|
||||
intentionally NOT copied here - EPGEntry has no matching field for
|
||||
them. Callers that need that richer data should keep the
|
||||
EPGProgramDetails instance itself rather than expecting it to appear
|
||||
on the merged EPGEntry.
|
||||
provider_vod_id, genres, backdrop/poster, presenter/composers/
|
||||
contributors, the *_details enriched-person fields) are intentionally
|
||||
NOT copied here - EPGEntry has no matching field for them. Callers
|
||||
that need that richer data should keep the EPGProgramDetails instance
|
||||
itself rather than expecting it to appear on the merged EPGEntry.
|
||||
|
||||
Note: EPGEntry.producers is the one exception - it exists directly on
|
||||
EPGEntry (not via EPGContent/merge) for providers like MoveTV that
|
||||
return producer data in a single one-shot grid fetch with no separate
|
||||
detail-fetch step to enrich later. It is set at parse time, not
|
||||
merged in here.
|
||||
|
||||
A new EPGEntry is returned (rather than mutating in place) because
|
||||
EPGEntry is not frozen, but merge_content should behave predictably
|
||||
|
||||
@@ -44,27 +44,34 @@ class MoveTvEpgManager:
|
||||
so the provider can still be recovered from
|
||||
the broadcast_id alone for catchup lookups)
|
||||
title (cleaned) -> title
|
||||
title (raw, S/E) -> episode_name (only when season/episode parsed)
|
||||
(raw title's S/E marker is now fully captured by season_number/
|
||||
episode_number below, so episode_name is left None — MoveTV
|
||||
doesn't provide a distinct episode subtitle)
|
||||
originalTitle -> original_title
|
||||
epgDesc -> description
|
||||
start / end (ms) -> start / end (seconds)
|
||||
tagInfo.name -> genre_description
|
||||
categories[].name -> genres (list)
|
||||
director -> directors (single-item list)
|
||||
actor -> cast (list, comma-split)
|
||||
producer -> producers (list, comma-split)
|
||||
year -> year
|
||||
rating -> star_rating
|
||||
rating -> parental_rating (age/content classification,
|
||||
e.g. 12, 0=unrestricted — not a 0-10 star score)
|
||||
picture.background-> icon
|
||||
season/episode -> season_number / episode_number (+ IS_SERIES flag)
|
||||
|
||||
Known lossy fields
|
||||
------------------
|
||||
EPGEntry has no slots for: schedule_id, live_id, live_name, content_id,
|
||||
producer, multiple categories/category_ids/category_images, genre_id,
|
||||
or the secondary images (poster, square_logo, poster_mark,
|
||||
original_title_logo). These were present in the old dict-based return
|
||||
value and are now dropped. Confirm nothing else in the MoveTV pipeline
|
||||
(e.g. catchup/manifest matching) reads those keys before relying on
|
||||
this contract.
|
||||
category_ids, category_images/genre_id (per-category numeric IDs and
|
||||
their picture objects — always null in observed data), or the
|
||||
secondary images (poster, square_logo, poster_mark,
|
||||
original_title_logo) — confirmed always null in observed MoveTV
|
||||
responses, so not wired up. These were present in the old dict-based
|
||||
return value and are now dropped. Confirm nothing else in the MoveTV
|
||||
pipeline (e.g. catchup/manifest matching) reads those keys before
|
||||
relying on this contract.
|
||||
"""
|
||||
|
||||
def __init__(self, authenticator: Any) -> None:
|
||||
@@ -374,8 +381,9 @@ class MoveTvEpgManager:
|
||||
# Native backwards/forwards — anchor to now
|
||||
return datetime.now(tz=timezone.utc), backwards, forwards
|
||||
|
||||
@staticmethod
|
||||
def _parse_items(
|
||||
self, items: List[Dict[str, Any]], channel_id: str
|
||||
items: List[Dict[str, Any]], channel_id: str
|
||||
) -> List[EPGEntry]:
|
||||
"""
|
||||
Normalise raw API programme objects into EPGEntry objects.
|
||||
@@ -414,6 +422,18 @@ class MoveTvEpgManager:
|
||||
else []
|
||||
)
|
||||
|
||||
producer_raw: Optional[str] = item.get("producer")
|
||||
producers: List[str] = (
|
||||
[p.strip() for p in producer_raw.split(",") if p.strip()]
|
||||
if producer_raw
|
||||
else []
|
||||
)
|
||||
|
||||
categories_raw: List[Dict[str, Any]] = item.get("categories") or []
|
||||
genres: List[str] = [
|
||||
c["name"] for c in categories_raw if c.get("name")
|
||||
]
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Parse season and episode from title.
|
||||
# Supports multiple patterns:
|
||||
@@ -480,16 +500,18 @@ class MoveTvEpgManager:
|
||||
end=end_s,
|
||||
program_id=str(epg_id_raw) if epg_id_raw else None,
|
||||
description=item.get("epgDesc"),
|
||||
episode_name=raw_title if season_num else None,
|
||||
episode_name=None,
|
||||
original_title=item.get("originalTitle"),
|
||||
year=item.get("year"),
|
||||
icon=icon,
|
||||
cast=cast,
|
||||
directors=[item["director"]] if item.get("director") else [],
|
||||
producers=producers,
|
||||
genre_description=(item.get("tagInfo") or {}).get("name"),
|
||||
genres=genres,
|
||||
season_number=season_num,
|
||||
episode_number=episode_num,
|
||||
star_rating=item.get("rating") or None,
|
||||
parental_rating=item.get("rating") or None,
|
||||
)
|
||||
|
||||
if season_num is not None:
|
||||
|
||||
Reference in New Issue
Block a user