From 56542bb84d8870aca94ca1d508e84ff77b5c04ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Lavaud-Wernert?= Date: Wed, 24 Jul 2024 00:39:34 +0200 Subject: [PATCH 1/4] Add IPTV setting and display catchup data --- .../resource.language.en_gb/strings.po | 22 ++++++---- .../resource.language.fr_fr/strings.po | 26 +++++++----- resources/lib/managers/catchup_manager.py | 7 ---- .../lib/providers/abstract_orange_provider.py | 42 +++++++++---------- resources/lib/router.py | 2 +- resources/lib/routes.py | 7 ---- resources/lib/utils/gui.py | 37 ++++++++++++---- resources/lib/utils/request.py | 30 ++++++++++++- resources/settings.xml | 4 +- 9 files changed, 108 insertions(+), 69 deletions(-) diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index de3256e..3d2cf75 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -1,13 +1,13 @@ # Kodi Media Center language file # Addon Name: Orange TV France # Addon id: plugin.video.orange.fr -# Addon Provider: BreizhReloaded +# Addon Provider: Flawe msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: BreizhReloaded\n" +"Last-Translator: Flawe\n" "Language-Team: English\n" "Language: en\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -23,17 +23,25 @@ msgid "Install IPTV Manager…" msgstr "" msgctxt "#30102" -msgid "Help 30104" -msgstr " +msgid "Help 30102" +msgstr "" msgctxt "#30103" -msgid "Go to IPTV Manager settings…" +msgid "Enable IPTV Manager integration" msgstr "" msgctxt "#30104" msgid "Help 30104" msgstr "" +msgctxt "#30105" +msgid "Go to IPTV Manager settings…" +msgstr "" + +msgctxt "#30106" +msgid "Help 30106" +msgstr "" + # Provider settings (from 30200 to 30299) msgctxt "#30200" @@ -103,7 +111,3 @@ msgstr "" msgctxt "#30901" msgid "InputStream cannot be loaded." msgstr "" - -msgctxt "#30902" -msgid "Orange TV France must be used from the Kodi TV section." -msgstr "" diff --git a/resources/language/resource.language.fr_fr/strings.po b/resources/language/resource.language.fr_fr/strings.po index 67bcd0e..d64a861 100644 --- a/resources/language/resource.language.fr_fr/strings.po +++ b/resources/language/resource.language.fr_fr/strings.po @@ -1,13 +1,13 @@ # Kodi Media Center language file # Addon Name: Orange TV France # Addon id: plugin.video.orange.fr -# Addon Provider: BreizhReloaded +# Addon Provider: Flawe msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: BreizhReloaded\n" +"Last-Translator: Flawe\n" "Language-Team: Français\n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -23,17 +23,25 @@ msgid "Install IPTV Manager…" msgstr "Installer IPTV Manager…" msgctxt "#30102" -msgid "Help 30104" +msgid "Help 30102" msgstr "" msgctxt "#30103" -msgid "Go to IPTV Manager settings…" -msgstr "Ouvrir les paramètres de IPTV Manager…" +msgid "Enable IPTV Manager integration" +msgstr "Activer l'intégration avec IPTV Manager" msgctxt "#30104" msgid "Help 30104" msgstr "" +msgctxt "#30105" +msgid "Go to IPTV Manager settings…" +msgstr "Ouvrir les paramètres de IPTV Manager…" + +msgctxt "#30106" +msgid "Help 30106" +msgstr "" + # Provider settings (from 30200 to 30299) msgctxt "#30200" @@ -63,8 +71,8 @@ msgid "Proxy" msgstr "Proxy" msgctxt "#30301" -msgid "Activer" -msgstr "" +msgid "Enable" +msgstr "Activer" msgctxt "#30302" msgid "Help 30302" @@ -103,7 +111,3 @@ msgstr "Cette chaîne ne fait pas partie de votre abonnement." msgctxt "#30901" msgid "InputStream cannot be loaded." msgstr "InputStream n'a pas pu être chargé." - -msgctxt "#30902" -msgid "Orange TV France must be used from the Kodi TV section." -msgstr "Orange TV France doit être utilisé depuis la section TV de Kodi." diff --git a/resources/lib/managers/catchup_manager.py b/resources/lib/managers/catchup_manager.py index 86cf859..21dc40a 100644 --- a/resources/lib/managers/catchup_manager.py +++ b/resources/lib/managers/catchup_manager.py @@ -1,12 +1,10 @@ """Catchup TV Manager.""" -import xbmc import xbmcplugin from lib.providers import get_provider from lib.router import router from lib.utils.gui import create_directory_items -from lib.utils.kodi import build_addon_url class CatchupManager: @@ -47,8 +45,3 @@ def get_videos(self, catchup_channel_id: str, article_id: str) -> list: succeeded = xbmcplugin.addDirectoryItems(router.handle, directory_items, len(directory_items)) xbmcplugin.endOfDirectory(router.handle, succeeded) - - def play_video(self, video_id: str): - """Play catchup video.""" - player = xbmc.Player() - player.play(build_addon_url(f"/catchup-streams/{video_id}")) diff --git a/resources/lib/providers/abstract_orange_provider.py b/resources/lib/providers/abstract_orange_provider.py index 9972346..70f7138 100644 --- a/resources/lib/providers/abstract_orange_provider.py +++ b/resources/lib/providers/abstract_orange_provider.py @@ -13,7 +13,7 @@ from lib.providers.abstract_provider import AbstractProvider from lib.utils.kodi import build_addon_url, get_drm, get_global_setting, log -from lib.utils.request import build_request, get_random_ua +from lib.utils.request import build_request, get_random_ua, open_request _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" @@ -43,9 +43,7 @@ def get_catchup_stream_info(self, stream_id: str) -> dict: def get_streams(self) -> list: """Load stream data from Orange and convert it to JSON-STREAMS format.""" req = build_request(_CHANNELS_ENDPOINT) - - with urlopen(req) as res: - channels = list(json.loads(res.read())["channels"]) + channels = dict(open_request(req, {"channels": {}}))["channels"] log(f"{len(channels)} channels found", xbmc.LOGINFO) channels.sort(key=lambda channel: channel["displayOrder"]) @@ -121,9 +119,7 @@ def get_epg(self) -> dict: def get_catchup_channels(self) -> list: """Load available catchup channels.""" req = build_request(_CATCHUP_CHANNELS_ENDPOINT) - - with urlopen(req) as res: - channels = list(json.loads(res.read())) + channels = open_request(req, []) log(f"{len(channels)} catchup channels found", xbmc.LOGINFO) @@ -140,9 +136,7 @@ def get_catchup_channels(self) -> list: def get_catchup_categories(self, catchup_channel_id: str) -> list: """Return a list of catchup categories for the specified channel id.""" req = build_request(_CATCHUP_CHANNELS_ENDPOINT + "/" + catchup_channel_id) - - with urlopen(req) as res: - categories = list(json.loads(res.read())["categories"]) + categories = dict(open_request(req, {"categories": {}}))["categories"] return [ { @@ -155,18 +149,17 @@ def get_catchup_categories(self, catchup_channel_id: str) -> list: def get_catchup_articles(self, catchup_channel_id: str, category_id: str) -> list: """Return a list of catchup groups for the specified channel id and category id.""" - req = build_request( - _CATCHUP_ARTICLES_ENDPOINT.format(catchup_channel_id=catchup_channel_id, category_id=category_id) - ) + url = _CATCHUP_ARTICLES_ENDPOINT.format(catchup_channel_id=catchup_channel_id, category_id=category_id) + req = build_request(url) - with urlopen(req) as res: - articles = list(json.loads(res.read())["articles"]) + articles = dict(open_request(req, {"articles": {}}))["articles"] return [ { "is_folder": True, "label": article["title"], "path": build_addon_url(f"/channels/{catchup_channel_id}/articles/{article['id']}/videos"), + "art": {"poster": article["covers"]["ref_16_9"]}, } for article in articles ] @@ -174,16 +167,21 @@ def get_catchup_articles(self, catchup_channel_id: str, category_id: str) -> lis 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.""" req = build_request(_CATCHUP_VIDEOS_ENDPOINT.format(group_id=article_id)) - - with urlopen(req) as res: - videos = list(json.loads(res.read())["videos"]) + videos = dict(open_request(req, {"videos": {}}))["videos"] return [ { "is_folder": False, "label": video["title"], - "path": build_addon_url(f"/videos/{video['id']}"), - "art": {"thumb": video["covers"]["ref_4_3"]}, + "path": build_addon_url(f"/catchup-streams/{video['id']}"), + "art": {"poster": video["covers"]["ref_16_9"]}, + "info": { + "duration": int(video["duration"]) * 60, + "genres": video["genres"], + "plot": video["longSummary"], + "premiered": datetime.fromtimestamp(int(video["broadcastDate"]) / 1000).strftime("%Y-%m-%d"), + "year": int(video["productionDate"]), + }, } for video in videos ] @@ -197,7 +195,7 @@ def _get_stream_info(self, stream_type: str, version: str, item_type: str, strea item_type=item_type, stream_id=stream_id, ) - req, tv_token = self._build_request(url, auth_url=auth_url) + req, tv_token = self._build_auth_request(url, auth_url=auth_url) try: with urlopen(req) as res: @@ -240,7 +238,7 @@ def _get_stream_info(self, stream_type: str, version: str, item_type: str, strea log(stream_info, xbmc.LOGDEBUG) return stream_info - def _build_request(self, url: str, additional_headers: dict = None, auth_url: str = None) -> (Request, str): + def _build_auth_request(self, url: str, additional_headers: dict = None, auth_url: str = None) -> (Request, str): """Build HTTP request.""" tv_token = None diff --git a/resources/lib/router.py b/resources/lib/router.py index b713830..7216e98 100644 --- a/resources/lib/router.py +++ b/resources/lib/router.py @@ -10,5 +10,5 @@ def init_router(): """Init addon router.""" + log("Initializing addon router", xbmc.LOGDEBUG) router.run() - log("Addon router initialized", xbmc.LOGDEBUG) diff --git a/resources/lib/routes.py b/resources/lib/routes.py index e74f32b..a24830a 100644 --- a/resources/lib/routes.py +++ b/resources/lib/routes.py @@ -35,13 +35,6 @@ def channel_article_videos(catchup_channel_id: str, article_id: str): CatchupManager().get_videos(catchup_channel_id, article_id) -@router.route("/videos/") -def video(video_id: str): - """Return catchup video listitem.""" - log(f"Loading catchup video {video_id}", xbmc.LOGINFO) - CatchupManager().play_video(video_id) - - @router.route("/live-streams/") def live_stream(stream_id: str): """Load live stream for the required channel id.""" diff --git a/resources/lib/utils/gui.py b/resources/lib/utils/gui.py index 17a7825..4bb60a0 100644 --- a/resources/lib/utils/gui.py +++ b/resources/lib/utils/gui.py @@ -8,15 +8,36 @@ def create_directory_items(data: list) -> list: items = [] for d in data: - list_item = ListItem(label=d["label"], path=d["path"]) - - # list_item.setLabel2("LABEL2") - # list_item.setInfo("INFO", {"INFO1": "INFO1", "INFO2": "INFO2"}) + is_folder = bool(d["is_folder"]) - if "art" in d and "thumb" in d["art"]: - list_item.setArt({"thumb": d["art"]["thumb"]}) - - items.append((d["path"], list_item, bool(d["is_folder"]))) + list_item = ListItem(label=d["label"], path=d["path"]) + list_item.setIsFolder(is_folder) + + if "art" in d: + list_item.setArt( + { + "poster": d["art"].get("poster", None), + "thumb": d["art"].get("thumb", None), + } + ) + + if not is_folder: + list_item.setProperties( + { + "inputstream": "inputstream.adaptive", + "IsPlayable": "true", + } + ) + + if "info" in d: + video_info_tag = list_item.getVideoInfoTag() + video_info_tag.setDuration(d["info"].get("duration", None)) + video_info_tag.setGenres(d["info"].get("genres", None)) + video_info_tag.setPlot(d["info"].get("plot", None)) + video_info_tag.setYear(d["info"].get("year", None)) + video_info_tag.setPremiered(d["info"].get("premiered", None)) + + items.append((d["path"], list_item, is_folder)) return items diff --git a/resources/lib/utils/request.py b/resources/lib/utils/request.py index 0f61e22..5f487a4 100644 --- a/resources/lib/utils/request.py +++ b/resources/lib/utils/request.py @@ -1,12 +1,17 @@ """Request utils.""" +import gzip +import json from random import randint +from urllib.error import HTTPError, URLError from urllib.parse import urlparse -from urllib.request import Request +from urllib.request import Request, urlopen + +import xbmc # from socks import SOCKS5 # from sockshandler import SocksiPyHandler -from lib.utils.kodi import get_addon_setting +from lib.utils.kodi import get_addon_setting, log, ok_dialog _USER_AGENTS = [ # Chrome @@ -43,6 +48,27 @@ def build_request(url: str, additional_headers: dict = None) -> Request: return Request(url, headers={"User-Agent": get_random_ua(), "Host": urlparse(url).netloc, **additional_headers}) +def open_request(req: Request, value=None): + """Open HTTP request and handle errors.""" + try: + res = urlopen(req) + except HTTPError as e: + log(e.code, xbmc.LOGERROR) + ok_dialog("HTTPError") + return value + except URLError as e: + log(e.reason, xbmc.LOGERROR) + ok_dialog("URLError") + return value + else: + content = res.read() + + if res.headers.get("Content-Encoding") == "gzip": + content = gzip.decompress(content) + + return json.loads(content) + + def install_proxy() -> None: """Install proxy server for the next requests.""" if get_addon_setting("proxy.enabled") != "true": diff --git a/resources/settings.xml b/resources/settings.xml index 404d524..dfd35fe 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -1,11 +1,11 @@ - - + + From 722ee292f73ec00829cdeb026fda6b41da2be947 Mon Sep 17 00:00:00 2001 From: Baptiste Fouques Date: Tue, 23 Jul 2024 16:02:09 +0200 Subject: [PATCH 2/4] Update on new InputStream Helper API see https://github.com/emilsvennesson/script.module.inputstreamhelper/blob/master/README.md\#example --- resources/lib/utils/gui.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/resources/lib/utils/gui.py b/resources/lib/utils/gui.py index 4bb60a0..00ae5e6 100644 --- a/resources/lib/utils/gui.py +++ b/resources/lib/utils/gui.py @@ -1,6 +1,7 @@ """Helpers for Kodi GUI.""" from xbmcgui import ListItem +import inputstreamhelper def create_directory_items(data: list) -> list: @@ -44,13 +45,20 @@ def create_directory_items(data: list) -> list: def create_video_item(stream_info: dict) -> ListItem: """Create a video item from stream data.""" - list_item = ListItem(path=stream_info["path"]) - list_item.setMimeType(stream_info["mime_type"]) - list_item.setContentLookup(False) - list_item.setProperty("inputstream", "inputstream.adaptive") - list_item.setProperty("inputstream.adaptive.play_timeshift_buffer", "true") - list_item.setProperty("inputstream.adaptive.manifest_config", '{"timeshift_bufferlimit":14400}') - list_item.setProperty("inputstream.adaptive.license_type", stream_info["license_type"]) - list_item.setProperty("inputstream.adaptive.license_key", stream_info["license_key"]) + + is_helper = inputstreamhelper.Helper(stream_info['manifest_type'], + drm = stream_info["license_type"]) + + if is_helper.check_inputstream(): + list_item = ListItem(path=stream_info["path"]) + + list_item.setContentLookup(False) + list_item.setMimeType(stream_info["mime_type"]) + + list_item.setProperty('inputstream', is_helper.inputstream_addon) + + list_item.setProperty('inputstream.adaptive.manifest_type', stream_info['manifest_type']) + list_item.setProperty('inputstream.adaptive.license_type', stream_info["license_type"]) + list_item.setProperty("inputstream.adaptive.license_key", stream_info["license_key"]) return list_item From fdf0d2a18c48759970de22deb61d9cf9770b45df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Lavaud-Wernert?= Date: Thu, 25 Jul 2024 15:19:09 +0200 Subject: [PATCH 3/4] Rework GUI utils --- resources/lib/managers/catchup_manager.py | 30 +++--- resources/lib/managers/stream_manager.py | 38 ++++---- .../lib/providers/abstract_orange_provider.py | 5 - resources/lib/utils/gui.py | 93 ++++++++----------- 4 files changed, 73 insertions(+), 93 deletions(-) diff --git a/resources/lib/managers/catchup_manager.py b/resources/lib/managers/catchup_manager.py index 21dc40a..c786540 100644 --- a/resources/lib/managers/catchup_manager.py +++ b/resources/lib/managers/catchup_manager.py @@ -4,7 +4,7 @@ from lib.providers import get_provider from lib.router import router -from lib.utils.gui import create_directory_items +from lib.utils.gui import create_list_item class CatchupManager: @@ -17,31 +17,35 @@ def __init__(self): def get_channels(self) -> list: """Return channels available for catchup TV.""" channels = self.provider.get_catchup_channels() - directory_items = create_directory_items(channels) - succeeded = xbmcplugin.addDirectoryItems(router.handle, directory_items, len(directory_items)) - xbmcplugin.endOfDirectory(router.handle, succeeded) + 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) - directory_items = create_directory_items(categories) - succeeded = xbmcplugin.addDirectoryItems(router.handle, directory_items, len(directory_items)) - xbmcplugin.endOfDirectory(router.handle, succeeded) + 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) - directory_items = create_directory_items(articles) - succeeded = xbmcplugin.addDirectoryItems(router.handle, directory_items, len(directory_items)) - xbmcplugin.endOfDirectory(router.handle, succeeded) + 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) - directory_items = create_directory_items(videos) - succeeded = xbmcplugin.addDirectoryItems(router.handle, directory_items, len(directory_items)) - xbmcplugin.endOfDirectory(router.handle, succeeded) + for video in videos: + xbmcplugin.addDirectoryItem(router.handle, video["path"], create_list_item(video)) + + xbmcplugin.endOfDirectory(router.handle) diff --git a/resources/lib/managers/stream_manager.py b/resources/lib/managers/stream_manager.py index f753c6f..0c1c919 100644 --- a/resources/lib/managers/stream_manager.py +++ b/resources/lib/managers/stream_manager.py @@ -1,12 +1,11 @@ """Video stream manager.""" import inputstreamhelper -import xbmcgui import xbmcplugin from lib.providers import get_provider from lib.router import router -from lib.utils.gui import create_video_item +from lib.utils.gui import create_play_item from lib.utils.kodi import localize, ok_dialog @@ -17,32 +16,29 @@ def __init__(self): """Initialize Stream Manager object.""" self.provider = get_provider() - def load_live_stream(self, stream_id: str) -> xbmcgui.ListItem: + def load_live_stream(self, stream_id: str) -> None: """Load live TV stream.""" stream_info = self.provider.get_live_stream_info(stream_id) - if not stream_info: - ok_dialog(localize(30900)) - return - - is_helper = inputstreamhelper.Helper(stream_info["manifest_type"], drm=stream_info["drm"]) - if not is_helper.check_inputstream(): - ok_dialog(localize(30901)) - return + self._load_stream(stream_info) - list_item = create_video_item(stream_info) - xbmcplugin.setResolvedUrl(router.handle, True, list_item) - - def load_chatchup_stream(self, stream_id: str) -> xbmcgui.ListItem: + def load_chatchup_stream(self, stream_id: str) -> None: """Load catchup TV stream.""" stream_info = self.provider.get_catchup_stream_info(stream_id) - if not stream_info: + self._load_stream(stream_info) + + def _load_stream(self, stream_info: dict = None) -> None: + """Load stream.""" + if stream_info is None: ok_dialog(localize(30900)) + xbmcplugin.setResolvedUrl(router.handle, False) return - is_helper = inputstreamhelper.Helper(stream_info["manifest_type"], drm=stream_info["drm"]) - if not is_helper.check_inputstream(): - ok_dialog(localize(30901)) + is_helper = inputstreamhelper.Helper(stream_info["manifest_type"], drm=stream_info["license_type"]) + + if is_helper.check_inputstream(): + play_item = create_play_item(stream_info, is_helper.inputstream_addon) + xbmcplugin.setResolvedUrl(router.handle, True, play_item) return - list_item = create_video_item(stream_info) - xbmcplugin.setResolvedUrl(router.handle, True, list_item) + ok_dialog(localize(30901)) + xbmcplugin.setResolvedUrl(router.handle, False) diff --git a/resources/lib/providers/abstract_orange_provider.py b/resources/lib/providers/abstract_orange_provider.py index 70f7138..3e27d49 100644 --- a/resources/lib/providers/abstract_orange_provider.py +++ b/resources/lib/providers/abstract_orange_provider.py @@ -125,7 +125,6 @@ def get_catchup_channels(self) -> list: return [ { - "is_folder": True, "label": str(channel["name"]).upper(), "path": build_addon_url(f"/channels/{channel['id']}/categories"), "art": {"thumb": channel["logos"]["ref_millenials_partner_white_logo"]}, @@ -140,7 +139,6 @@ def get_catchup_categories(self, catchup_channel_id: str) -> list: 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"), } @@ -156,7 +154,6 @@ def get_catchup_articles(self, catchup_channel_id: str, category_id: str) -> lis return [ { - "is_folder": True, "label": article["title"], "path": build_addon_url(f"/channels/{catchup_channel_id}/articles/{article['id']}/videos"), "art": {"poster": article["covers"]["ref_16_9"]}, @@ -171,7 +168,6 @@ def get_catchup_videos(self, catchup_channel_id: str, article_id: str) -> list: return [ { - "is_folder": False, "label": video["title"], "path": build_addon_url(f"/catchup-streams/{video['id']}"), "art": {"poster": video["covers"]["ref_16_9"]}, @@ -230,7 +226,6 @@ def _get_stream_info(self, stream_type: str, version: str, item_type: str, strea "path": stream_info["url"], "mime_type": "application/xml+dash", "manifest_type": "mpd", - "drm": drm.name.lower(), "license_type": drm.value, "license_key": f"{license_server_url}|{headers}|{post_data}|{response}", } diff --git a/resources/lib/utils/gui.py b/resources/lib/utils/gui.py index 00ae5e6..1f6838d 100644 --- a/resources/lib/utils/gui.py +++ b/resources/lib/utils/gui.py @@ -1,64 +1,49 @@ """Helpers for Kodi GUI.""" from xbmcgui import ListItem -import inputstreamhelper -def create_directory_items(data: list) -> list: - """Create a list of directory items from data.""" - items = [] +def create_list_item(item_data: dict, is_folder: bool = False) -> ListItem: + """Create a list item from data.""" + list_item = ListItem(label=item_data.get("label"), path=item_data.get("path")) + + if "art" in item_data: + item_art_data: dict = item_data.get("art", {}) + list_item.setArt( + { + "poster": item_art_data.get("poster"), + "thumb": item_art_data.get("thumb"), + } + ) + + if not is_folder: + list_item.setProperties( + { + "IsPlayable": "true", + } + ) + + if "info" in item_data: + item_info_data: dict = item_data.get("info", {}) + video_info_tag = list_item.getVideoInfoTag() + video_info_tag.setDuration(item_info_data.get("duration")) + video_info_tag.setGenres(item_info_data.get("genres")) + video_info_tag.setPlot(item_info_data.get("plot")) + video_info_tag.setYear(item_info_data.get("year")) - for d in data: - is_folder = bool(d["is_folder"]) - - list_item = ListItem(label=d["label"], path=d["path"]) - list_item.setIsFolder(is_folder) - - if "art" in d: - list_item.setArt( - { - "poster": d["art"].get("poster", None), - "thumb": d["art"].get("thumb", None), - } - ) - - if not is_folder: - list_item.setProperties( - { - "inputstream": "inputstream.adaptive", - "IsPlayable": "true", - } - ) - - if "info" in d: - video_info_tag = list_item.getVideoInfoTag() - video_info_tag.setDuration(d["info"].get("duration", None)) - video_info_tag.setGenres(d["info"].get("genres", None)) - video_info_tag.setPlot(d["info"].get("plot", None)) - video_info_tag.setYear(d["info"].get("year", None)) - video_info_tag.setPremiered(d["info"].get("premiered", None)) - - items.append((d["path"], list_item, is_folder)) - - return items - - -def create_video_item(stream_info: dict) -> ListItem: - """Create a video item from stream data.""" - - is_helper = inputstreamhelper.Helper(stream_info['manifest_type'], - drm = stream_info["license_type"]) - - if is_helper.check_inputstream(): - list_item = ListItem(path=stream_info["path"]) + return list_item - list_item.setContentLookup(False) - list_item.setMimeType(stream_info["mime_type"]) - list_item.setProperty('inputstream', is_helper.inputstream_addon) +def create_play_item(stream_info: dict, inputstream_addon: str) -> ListItem: + """Create a play item from stream data.""" + play_item = ListItem(path=stream_info["path"]) + play_item.setContentLookup(False) + play_item.setMimeType(stream_info["mime_type"]) - list_item.setProperty('inputstream.adaptive.manifest_type', stream_info['manifest_type']) - list_item.setProperty('inputstream.adaptive.license_type', stream_info["license_type"]) - list_item.setProperty("inputstream.adaptive.license_key", stream_info["license_key"]) + play_item.setProperty("inputstream", inputstream_addon) + # play_item.setProperty("inputstream.adaptive.play_timeshift_buffer", "true") + # play_item.setProperty("inputstream.adaptive.manifest_config", '{"timeshift_bufferlimit":14400}') + play_item.setProperty("inputstream.adaptive.license_type", stream_info["license_type"]) + play_item.setProperty("inputstream.adaptive.license_key", stream_info["license_key"]) - return list_item + return play_item From 18e178db083d98ee4ed33bb9fb9d69b144b21c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Lavaud-Wernert?= Date: Fri, 9 Aug 2024 15:26:31 +0200 Subject: [PATCH 4/4] 2.1.4 --- CHANGELOG.md | 9 +++++++++ addon.xml | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a71f076..a9c471b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # 2.x +## [2.1.4](https://github.com/f-lawe/plugin.video.orange.fr/releases/tag/v2.1.4) - 2024-08-08 + +## Changed +- Better UI items management + +### Fixed +- InputStream Helper is now called properly ([#50](https://github.com/f-lawe/plugin.video.orange.fr/issues/50)) +- Avoid plugin to be runned twice on catchup TV videos ([#55](https://github.com/f-lawe/plugin.video.orange.fr/issues/55)) + ## [2.1.3](https://github.com/f-lawe/plugin.video.orange.fr/releases/tag/v2.1.3) - 2024-07-21 ### Fixed diff --git a/addon.xml b/addon.xml index 33534a6..b3dcaad 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - +