Skip to content

Commit

Permalink
Handle n levels within catchup directories
Browse files Browse the repository at this point in the history
  • Loading branch information
f-lawe committed Oct 12, 2024
1 parent b93a677 commit ffef5a7
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 89 deletions.
41 changes: 8 additions & 33 deletions resources/lib/managers/catchup_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
43 changes: 31 additions & 12 deletions resources/lib/providers/abstract_orange_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"

Expand All @@ -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)

Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down
20 changes: 3 additions & 17 deletions resources/lib/providers/abstract_provider.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Abstract TV Provider."""

from abc import ABC, abstractmethod
from typing import List


class AbstractProvider(ABC):
Expand All @@ -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
1 change: 0 additions & 1 deletion resources/lib/providers/fr/orange_france.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# ruff: noqa: D102
"""Orange France."""

from lib.providers.abstract_orange_provider import AbstractOrangeProvider
Expand Down
38 changes: 12 additions & 26 deletions resources/lib/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/<catchup_channel_id>/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/<path:levels>")
def catchup_(levels: str):
"""Display catchup service directory."""
log(f"Display catchup directory {levels}", xbmc.LOGINFO)
CatchupManager().build_directory(levels)


@router.route("/channels/<catchup_channel_id>/categories/<category_id>/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/<catchup_channel_id>/articles/<article_id>/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/<stream_id>")
def live_stream(stream_id: str):
@router.route("/stream/live/<stream_id>")
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/<stream_id>")
def catchup_stream(stream_id: str):
@router.route("/stream/catchup/<stream_id>")
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)
Expand Down

0 comments on commit ffef5a7

Please sign in to comment.