diff --git a/README.md b/README.md index 56528f1..974689d 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Descarga el archivo .zip generado por Github e instálalo. ## Roadmap ### Funciones agregadas * Autorización -* Reproducción con DRM y sin DRM, pudiendo elegir audio y subtítulos +* Reproducción con y sin DRM, pudiendo elegir audio y subtítulos * Búsqueda * Highlights * Colecciones diff --git a/resources/lib/api.py b/resources/lib/api.py index 2c53e96..b782026 100644 --- a/resources/lib/api.py +++ b/resources/lib/api.py @@ -35,6 +35,8 @@ class Api: }, } + LIMIT = 20 + client_id = "" client_secret = "" @@ -153,6 +155,7 @@ def genres(self): def catalog( self, + page: int, item_type: str = "", genre: int = -1, subgenre: int = -1 @@ -165,15 +168,20 @@ def catalog( if item_type: query["type"] = item_type + # Picked both genre and subgenre if genre != -1 and subgenre != -1: query["filter_entity"] = "tag" query["filter_id"] = subgenre + # Picked genre only if genre != -1 and subgenre == -1: query["filter_entity"] = "genre" query["filter_id"] = genre - res = self._req(endpoint="/media/catalog", query=query) + res = self._req( + endpoint="/media/catalog", + query=self._paginated_query(query, page) + ) return res["data"] def search(self, term: str) -> list: @@ -181,10 +189,12 @@ def search(self, term: str) -> list: Search by title using a term """ - res = self._req(endpoint="/searcher", query={"q": term}) + res = self._req(endpoint="/search", query={ + "query": term + }, uapi=True) - # Return only allowed items (tvshows, movies...) - return [item for item in res["data"] if "type" in item] + # Return only media + return [o for o in res["data"]["items"] if o.get('_type') == 'Media'] def purchased(self) -> list: """ @@ -215,12 +225,15 @@ def collections(self) -> list: res = self._req(endpoint="/collections") return res["data"] - def collection(self, collection_id: int) -> list: + def collection(self, collection_id: int, page: int) -> list: """ Get all media from a specific collection """ - res = self._req(endpoint=f"/collections/{collection_id}/medias") + res = self._req( + endpoint=f"/collections/{collection_id}/medias", + query=self._paginated_query({}, page) + ) return res["data"] def watching(self) -> list: @@ -334,3 +347,12 @@ def set_profile_id(self, profile_id: str): """ self.s.headers["x-user-profile-id"] = profile_id + + def _paginated_query(self, query: dict, page: int) -> dict: + newQuery = { + **query, + 'page': page, + 'limit': self.LIMIT + } + + return newQuery diff --git a/resources/lib/helpers/render.py b/resources/lib/helpers/render.py index 8bf7cf9..7028b63 100644 --- a/resources/lib/helpers/render.py +++ b/resources/lib/helpers/render.py @@ -34,6 +34,7 @@ def videos(items: list) -> list: """ Render videos fetched from Filmin API """ + listing = [] for item in items: url = build_kodi_url(_URL, { @@ -46,10 +47,14 @@ def videos(items: list) -> list: return listing @staticmethod - def folders(items: list, route: str = "") -> list: + def folders( + items: list, + route: str = "" + ) -> list: """ Render folders fetched from Filmin API """ + listing = [] for item in items: if not route: @@ -72,7 +77,10 @@ def folders(items: list, route: str = "") -> list: return listing @staticmethod - def mix(items: list, go_to: str = "") -> list: + def mix( + items: list, + go_to: str = "" + ) -> list: """ Render folder containing both folders and videos """ diff --git a/resources/lib/views/base.py b/resources/lib/views/base.py index 07fbf70..d2b7564 100644 --- a/resources/lib/views/base.py +++ b/resources/lib/views/base.py @@ -1,10 +1,17 @@ """ Base view """ from ..helpers.render import Render +from ..helpers.misc import build_kodi_url +from ..common import _PARAMS, _URL +from xbmcgui import ListItem class Base: """Main view class, skeleton for all views""" + items = [] + """All items""" + + # -- View type -- # static = False """True if is an static route with predefined items""" @@ -14,43 +21,79 @@ class Base: has_dirs = False """True if the directory is recursive""" - items = [] - """All items""" - folders_goTo = "" """Path that kodi will assign to all folder items""" + # -- Pagination utils -- # pagination = False - """Set to True if the endpoint has a pagination system - TODO: Make it work + """Set to True if the endpoint has a pagination system""" + + page = 1 + """Current page""" + + extra_query: dict = None + """ + If not an empty string, + it will tell Kodi to append this query to the next folder + Used for pagination only """ + def set_state(self): + """Set attributes used later for the API request""" + def set_items(self): """Set items using API if necessary""" def show(self): """Renders folder into Kodi""" + if self.extra_query is None: + self.extra_query = {} + listing = [] # Render static route if self.static: listing = Render.static(self.items) - else: - # Has both videos and dirs - if self.has_dirs and self.has_videos: - listing = Render.mix(self.items, self.folders_goTo) - # Only has dirs - elif self.has_dirs and not self.has_videos: - listing = Render.folders(self.items, self.folders_goTo) - # Only has videos - elif self.has_videos and not self.has_dirs: - listing = Render.videos(self.items) + # Has both videos and dirs + elif self.has_dirs and self.has_videos: + listing = Render.mix( + self.items, + self.folders_goTo + ) + # Only has dirs + elif self.has_dirs and not self.has_videos: + listing = Render.folders( + self.items, + self.folders_goTo + ) + # Only has videos + elif self.has_videos and not self.has_dirs: + listing = Render.videos(self.items) + # Handle pagination + if self.pagination: + nextUrl = build_kodi_url(_URL, { + **_PARAMS, + **self.extra_query, + "page": self.page + 1 + }) + nextItem = ListItem("Next", path=nextUrl) + + listing.append((nextUrl, nextItem, True)) + + # Append to Kodi Render.create_directory(listing) def run(self): """ Run view, this will set items and render them in Kodi """ + if self.pagination: + self.page = self._get_page() + self.set_state() self.set_items() self.show() + + def _get_page(self) -> int: + """ Get current page from _PARAMS """ + return int(_PARAMS.get('page', 1)) diff --git a/resources/lib/views/catalog.py b/resources/lib/views/catalog.py index 1af5686..c38279e 100644 --- a/resources/lib/views/catalog.py +++ b/resources/lib/views/catalog.py @@ -1,7 +1,7 @@ """ Catalog module """ import xbmcgui from .base import Base -from ..common import api, settings +from ..common import api, settings, _PARAMS class Catalog(Base): @@ -9,59 +9,85 @@ class Catalog(Base): has_dirs = True has_videos = True + pagination = True - def set_items(self): - # TYPE (show or film) - allowed_types = [ - ("", settings.get_localized_string(40043)), - ("serie", settings.get_localized_string(40044)), - ("film", settings.get_localized_string(40045)), - ("short", settings.get_localized_string(40046)), - ] - allowed_types_listitem = [] - for allowed_type in allowed_types: - listitem = xbmcgui.ListItem(label=allowed_type[1]) - allowed_types_listitem.append(listitem) - - index = xbmcgui.Dialog().select( - settings.get_localized_string(40040), allowed_types_listitem - ) - item_type = allowed_types[index][0] - - # GENRE (Action, adventure...) - genres = [ - {"id": -1, "name": settings.get_localized_string(40043)} - ] + api.genres() - genres_listitem = [] - for genre in genres: - listitem = xbmcgui.ListItem(label=genre["name"]) - genres_listitem.append(listitem) - - index = xbmcgui.Dialog().select( - settings.get_localized_string(40041), genres_listitem - ) - genre_picked = genres[index] + item_type: str + genre_id: int + subgenre_id: int + + def set_state(self): + item_type = _PARAMS.get("item_type") + genre_id = int(_PARAMS.get("genre_id", -1)) + subgenre_id = int(_PARAMS.get("subgenre_id", -1)) + + if item_type is None: + # TYPE (show or film) + allowed_types = [ + ("", settings.get_localized_string(40043)), + ("serie", settings.get_localized_string(40044)), + ("film", settings.get_localized_string(40045)), + ("short", settings.get_localized_string(40046)), + ] + allowed_types_listitem = [] + for allowed_type in allowed_types: + listitem = xbmcgui.ListItem(label=allowed_type[1]) + allowed_types_listitem.append(listitem) + + index = xbmcgui.Dialog().select( + settings.get_localized_string(40040), allowed_types_listitem + ) - # Allow picking subgenre only if there is a genre chosen - if genre_picked["id"] != -1: - subgenres = [ + item_type = allowed_types[index][0] + + # GENRE (Action, adventure...) + genres = [ {"id": -1, "name": settings.get_localized_string(40043)} - ] + genre_picked["subgenres"]["data"] - subgenres_listitem = [] - for subgenre in subgenres: - listitem = xbmcgui.ListItem(label=subgenre["name"]) - subgenres_listitem.append(listitem) + ] + api.genres() + genres_listitem = [] + for genre in genres: + listitem = xbmcgui.ListItem(label=genre["name"]) + genres_listitem.append(listitem) index = xbmcgui.Dialog().select( - settings.get_localized_string(40042), subgenres_listitem + settings.get_localized_string(40041), genres_listitem ) + genre_picked = genres[index] + + # Allow picking subgenre only if there is a genre chosen + if genre_picked["id"] != -1: + subgenres = [ + {"id": -1, "name": settings.get_localized_string(40043)} + ] + genre_picked["subgenres"]["data"] + subgenres_listitem = [] + for subgenre in subgenres: + listitem = xbmcgui.ListItem(label=subgenre["name"]) + subgenres_listitem.append(listitem) + + index = xbmcgui.Dialog().select( + settings.get_localized_string(40042), subgenres_listitem + ) + + subgenre_picked = subgenres[index] + else: + subgenre_picked = {"id": -1} - subgenre_picked = subgenres[index] - else: - subgenre_picked = {"id": -1} + genre_id = genre_picked['id'] + subgenre_id = subgenre_picked['id'] + self.item_type = item_type + self.genre_id = genre_id + self.subgenre_id = subgenre_id + + self.extra_query = { + "item_type": self.item_type, + "genre_id": self.genre_id, + "subgenre_id": self.subgenre_id + } + + def set_items(self): self.items = api.catalog( - item_type=item_type, - genre=genre_picked["id"], - subgenre=subgenre_picked["id"], + page=self.page, + item_type=self.item_type, + genre=self.genre_id, + subgenre=self.subgenre_id ) diff --git a/resources/lib/views/collection.py b/resources/lib/views/collection.py index 635c79c..18530dd 100644 --- a/resources/lib/views/collection.py +++ b/resources/lib/views/collection.py @@ -8,10 +8,11 @@ class Collection(Base): has_dirs = True has_videos = True + pagination = True collection_id = 0 def __init__(self, col_id: int): self.collection_id = col_id def set_items(self): - self.items = api.collection(self.collection_id) + self.items = api.collection(self.collection_id, self.page) diff --git a/resources/lib/views/search.py b/resources/lib/views/search.py index 6236600..5c885d7 100644 --- a/resources/lib/views/search.py +++ b/resources/lib/views/search.py @@ -2,7 +2,7 @@ import xbmcgui from .base import Base -from ..common import api, settings +from ..common import api, settings, _PARAMS class Search(Base): @@ -11,9 +11,21 @@ class Search(Base): has_dirs = True has_videos = True + term = '' + + def set_state(self): + self.term = _PARAMS.get('term', "") + if self.term == "": + self.term = xbmcgui.Dialog().input( + settings.get_localized_string(40020), + type=xbmcgui.INPUT_ALPHANUM + ) + + if self.term != "": + self.extra_query = { + "term": self.term + } + def set_items(self): - search_term = xbmcgui.Dialog().input( - settings.get_localized_string(40020), type=xbmcgui.INPUT_ALPHANUM - ) - if search_term: - self.items = api.search(search_term) + if self.term != "": + self.items = api.search(self.term)