diff --git a/resources/lib/managers/catchup_manager.py b/resources/lib/managers/catchup_manager.py index c786540..505015a 100644 --- a/resources/lib/managers/catchup_manager.py +++ b/resources/lib/managers/catchup_manager.py @@ -14,38 +14,13 @@ def __init__(self): """Initialize Catchup Manager object.""" self.provider = get_provider() - def get_channels(self) -> list: - """Return channels available for catchup TV.""" - channels = self.provider.get_catchup_channels() - - for channel in channels: - xbmcplugin.addDirectoryItem(router.handle, channel["path"], create_list_item(channel, True), True) - - xbmcplugin.endOfDirectory(router.handle) - - def get_categories(self, catchup_channel_id: str) -> list: - """Return content categories for the required channel.""" - categories = self.provider.get_catchup_categories(catchup_channel_id) - - for category in categories: - xbmcplugin.addDirectoryItem(router.handle, category["path"], create_list_item(category, True), True) - - xbmcplugin.endOfDirectory(router.handle) - - def get_articles(self, catchup_channel_id: str, category_id: str) -> list: - """Return content (TV show, movie, etc) for the required channel and category.""" - articles = self.provider.get_catchup_articles(catchup_channel_id, category_id) - - for article in articles: - xbmcplugin.addDirectoryItem(router.handle, article["path"], create_list_item(article, True), True) - - xbmcplugin.endOfDirectory(router.handle) - - def get_videos(self, catchup_channel_id: str, article_id: str) -> list: - """Return the video list for the required show.""" - videos = self.provider.get_catchup_videos(catchup_channel_id, article_id) - - for video in videos: - xbmcplugin.addDirectoryItem(router.handle, video["path"], create_list_item(video)) + def build_directory(self, levels: str = None) -> None: + """Build catchup TV directory.""" + levels = levels.split("/") if levels else [] + items = self.provider.get_catchup_items(levels) + + for item in items: + is_folder = item.get("is_folder") + xbmcplugin.addDirectoryItem(router.handle, item["path"], create_list_item(item, is_folder), is_folder) xbmcplugin.endOfDirectory(router.handle) diff --git a/resources/lib/providers/abstract_orange_provider.py b/resources/lib/providers/abstract_orange_provider.py index d5a8011..c3af58b 100644 --- a/resources/lib/providers/abstract_orange_provider.py +++ b/resources/lib/providers/abstract_orange_provider.py @@ -5,6 +5,7 @@ import re from abc import ABC from datetime import date, datetime, timedelta +from typing import List from urllib.parse import urlencode import xbmc @@ -18,7 +19,7 @@ _PROGRAMS_ENDPOINT = "https://rp-ott-mediation-tv.woopic.com/api-gw/live/v3/applications/STB4PC/programs?period={period}&epgIds=all&mco={mco}" _CATCHUP_CHANNELS_ENDPOINT = "https://rp-ott-mediation-tv.woopic.com/api-gw/catchup/v4/applications/PC/channels" -_CATCHUP_ARTICLES_ENDPOINT = "https://rp-ott-mediation-tv.woopic.com/api-gw/catchup/v4/applications/PC/channels/{catchup_channel_id}/categories/{category_id}" +_CATCHUP_ARTICLES_ENDPOINT = "https://rp-ott-mediation-tv.woopic.com/api-gw/catchup/v4/applications/PC/channels/{channel_id}/categories/{category_id}" _CATCHUP_VIDEOS_ENDPOINT = "https://rp-ott-mediation-tv.woopic.com/api-gw/catchup/v4/applications/PC/groups/{group_id}" _CHANNELS_ENDPOINT = "https://rp-ott-mediation-tv.woopic.com/api-gw/pds/v1/live/ew?everywherePopulation=OTT_Metro" @@ -43,6 +44,7 @@ def get_live_stream_info(self, stream_id: str) -> dict: return self._get_stream_info(auth_url, _LIVE_STREAM_ENDPOINT, stream_id) def get_catchup_stream_info(self, stream_id: str) -> dict: + """Get catchup stream info.""" auth_url = _CATCHUP_VIDEO_URL.format(stream_id=stream_id) return self._get_stream_info(auth_url, _CATCHUP_STREAM_ENDPOINT, stream_id) @@ -59,7 +61,7 @@ def get_streams(self) -> list: "name": channel["name"], "preset": str(channel["displayOrder"]), "logo": self._extract_logo(channel["logos"]), - "stream": build_addon_url(f"/live-streams/{channel['idEPG']}"), + "stream": build_addon_url(f"/stream/live/{channel['idEPG']}"), "group": [group_name for group_name in self.groups if int(channel["idEPG"]) in self.groups[group_name]], } for channel in channels @@ -124,55 +126,72 @@ def get_epg(self) -> dict: return epg - def get_catchup_channels(self) -> list: + def get_catchup_items(self, levels: List[str]) -> list: + """Return a list of directory items for the specified levels.""" + depth = len(levels) + + if depth == 0: + return self._get_catchup_channels() + elif depth == 1: + return self._get_catchup_categories(levels[0]) + elif depth == 2: + return self._get_catchup_articles(levels[0], levels[1]) + elif depth == 3: + return self._get_catchup_videos(levels[0], levels[1], levels[2]) + + def _get_catchup_channels(self) -> list: """Load available catchup channels.""" channels = request_json(_CATCHUP_CHANNELS_ENDPOINT, default=[]) return [ { + "is_folder": True, "label": str(channel["name"]).upper(), - "path": build_addon_url(f"/channels/{channel['id']}/categories"), + "path": build_addon_url(f"/catchup/{channel['id']}"), "art": {"thumb": channel["logos"]["ref_millenials_partner_white_logo"]}, } for channel in channels ] - def get_catchup_categories(self, catchup_channel_id: str) -> list: + def _get_catchup_categories(self, channel_id: str) -> list: """Return a list of catchup categories for the specified channel id.""" - url = _CATCHUP_CHANNELS_ENDPOINT + "/" + catchup_channel_id + url = _CATCHUP_CHANNELS_ENDPOINT + "/" + channel_id categories = request_json(url, default={"categories": {}})["categories"] return [ { + "is_folder": True, "label": category["name"][0].upper() + category["name"][1:], - "path": build_addon_url(f"/channels/{catchup_channel_id}/categories/{category['id']}/articles"), + "path": build_addon_url(f"/catchup/{channel_id}/{category['id']}"), } for category in categories ] - def get_catchup_articles(self, catchup_channel_id: str, category_id: str) -> list: + def _get_catchup_articles(self, channel_id: str, category_id: str) -> list: """Return a list of catchup groups for the specified channel id and category id.""" - url = _CATCHUP_ARTICLES_ENDPOINT.format(catchup_channel_id=catchup_channel_id, category_id=category_id) + url = _CATCHUP_ARTICLES_ENDPOINT.format(channel_id=channel_id, category_id=category_id) articles = request_json(url, default={"articles": {}})["articles"] return [ { + "is_folder": True, "label": article["title"], - "path": build_addon_url(f"/channels/{catchup_channel_id}/articles/{article['id']}/videos"), + "path": build_addon_url(f"/catchup/{channel_id}/{category_id}/{article['id']}"), "art": {"poster": article["covers"]["ref_16_9"]}, } for article in articles ] - def get_catchup_videos(self, catchup_channel_id: str, article_id: str) -> list: + def _get_catchup_videos(self, channel_id: str, category_id: str, article_id: str) -> list: """Return a list of catchup videos for the specified channel id and article id.""" url = _CATCHUP_VIDEOS_ENDPOINT.format(group_id=article_id) videos = request_json(url, default={"videos": {}})["videos"] return [ { + "is_folder": False, "label": video["title"], - "path": build_addon_url(f"/catchup-streams/{video['id']}"), + "path": build_addon_url(f"/stream/catchup/{video['id']}"), "art": {"poster": video["covers"]["ref_16_9"]}, "info": { "duration": int(video["duration"]) * 60, diff --git a/resources/lib/providers/abstract_provider.py b/resources/lib/providers/abstract_provider.py index 767def0..6925e59 100644 --- a/resources/lib/providers/abstract_provider.py +++ b/resources/lib/providers/abstract_provider.py @@ -1,6 +1,7 @@ """Abstract TV Provider.""" from abc import ABC, abstractmethod +from typing import List class AbstractProvider(ABC): @@ -27,21 +28,6 @@ def get_epg(self) -> dict: pass @abstractmethod - def get_catchup_channels(self) -> list: - """Return a list of available catchup channels.""" - pass - - @abstractmethod - def get_catchup_categories(self, catchup_channel_id: str) -> list: - """Return a list of catchup categories for the specified channel id.""" - pass - - @abstractmethod - def get_catchup_articles(self, catchup_channel_id: str, category_id: str) -> list: - """Return a list of catchup articles for the specified channel id and category id.""" - pass - - @abstractmethod - def get_catchup_videos(self, catchup_channel_id: str, article_id: str) -> list: - """Return a list of catchup videos for the specified channel id and article id.""" + def get_catchup_items(self, levels: List[str]) -> list: + """Return a list of directory items for the specified levels.""" pass diff --git a/resources/lib/providers/fr/orange_france.py b/resources/lib/providers/fr/orange_france.py index 360c7e6..af9f2dd 100644 --- a/resources/lib/providers/fr/orange_france.py +++ b/resources/lib/providers/fr/orange_france.py @@ -1,4 +1,3 @@ -# ruff: noqa: D102 """Orange France.""" from lib.providers.abstract_orange_provider import AbstractOrangeProvider diff --git a/resources/lib/routes.py b/resources/lib/routes.py index af19a68..41be96d 100644 --- a/resources/lib/routes.py +++ b/resources/lib/routes.py @@ -9,41 +9,27 @@ @router.route("/") def index(): - """Display catchup TV channels.""" - log("Display index", xbmc.LOGINFO) - CatchupManager().get_channels() + """Display catchup service index.""" + log("Display catchup index", xbmc.LOGINFO) + CatchupManager().build_directory() -@router.route("/channels//categories") -def channel_categories(catchup_channel_id: str): - """Return catchup category listitems for the required channel id.""" - log(f"Loading catchup categories for channel {catchup_channel_id}", xbmc.LOGINFO) - CatchupManager().get_categories(catchup_channel_id) +@router.route("/catchup/") +def catchup_(levels: str): + """Display catchup service directory.""" + log(f"Display catchup directory {levels}", xbmc.LOGINFO) + CatchupManager().build_directory(levels) -@router.route("/channels//categories//articles") -def channel_category_articles(catchup_channel_id: str, category_id: str): - """Return catchup category article listitems.""" - log(f"Loading catchup articles for category {category_id}", xbmc.LOGINFO) - CatchupManager().get_articles(catchup_channel_id, category_id) - - -@router.route("/channels//articles//videos") -def channel_article_videos(catchup_channel_id: str, article_id: str): - """Return catchup article video listitems.""" - log(f"Loading catchup videos for article {article_id}", xbmc.LOGINFO) - CatchupManager().get_videos(catchup_channel_id, article_id) - - -@router.route("/live-streams/") -def live_stream(stream_id: str): +@router.route("/stream/live/") +def stream_live(stream_id: str): """Load live stream for the required channel id.""" log(f"Loading live stream {stream_id}", xbmc.LOGINFO) StreamManager().load_live_stream(stream_id) -@router.route("/catchup-streams/") -def catchup_stream(stream_id: str): +@router.route("/stream/catchup/") +def stream_catchup(stream_id: str): """Load live stream for the required video id.""" log(f"Loading catchup stream {stream_id}", xbmc.LOGINFO) StreamManager().load_chatchup_stream(stream_id)