From 922b3d265519e38e465b869379a0accfa16431c5 Mon Sep 17 00:00:00 2001 From: Robert Honz Date: Thu, 18 Jan 2024 21:57:35 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Result=20pagination=20implement=20f?= =?UTF-8?q?or=20GUI.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- tidal_dl_ng/gui.py | 14 +++++++--- tidal_dl_ng/helper/tidal.py | 53 ++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 629ed1f..b5fdb89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -168,7 +168,7 @@ profile = "black" multi_line_output = 3 indent = 4 color_output = true -known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"] +known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "helper", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"] [tool.mypy] # https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file diff --git a/tidal_dl_ng/gui.py b/tidal_dl_ng/gui.py index ee90b5b..5d8ee3e 100644 --- a/tidal_dl_ng/gui.py +++ b/tidal_dl_ng/gui.py @@ -2,6 +2,8 @@ import math import sys from collections.abc import Callable +from helper.tidal import items_all_results, search_all_results + from tidal_dl_ng.helper.path import get_format_template try: @@ -250,13 +252,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def populate_tree_results(self, results: [ResultSearch]): self.tr_results.clear() + count_digits: int = int(math.log10(len(results))) + 1 for item in results: # Format seconds to mm:ss. m, s = divmod(item.duration_sec, 60) duration: str = f"{m:02d}:{s:02d}" # Since sorting happens only by string, we need to pad the index and add 1 (to avoid start at 0) - index: str = f"{item.position + 1:03}" + index: str = str(item.position + 1).zfill(count_digits) child = QtWidgets.QTreeWidgetItem() child.setText(0, index) @@ -269,7 +272,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.tr_results.addTopLevelItem(child) def search(self, query: str, types_media: SearchTypes) -> [ResultSearch]: - result_search: [dict[str, SearchTypes]] = self.tidal.session.search(query, models=types_media, limit=999) + result_search: dict[str, [SearchTypes]] = search_all_results( + session=self.tidal.session, needle=query, types_media=types_media + ) result: [ResultSearch] = [] for _media_type, l_media in result_search.items(): @@ -386,8 +391,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): item = self.tr_lists_user.itemAt(point) media_list = item.data(3, QtCore.Qt.ItemDataRole.UserRole) - media_items = media_list.items() - result = self.search_result_to_model(media_items) + # Get all results + media_items: [Track | Video] = items_all_results(media_list) + result: [ResultSearch] = self.search_result_to_model(media_items) self.populate_tree_results(result) diff --git a/tidal_dl_ng/helper/tidal.py b/tidal_dl_ng/helper/tidal.py index 5c73b10..1a1fcc1 100644 --- a/tidal_dl_ng/helper/tidal.py +++ b/tidal_dl_ng/helper/tidal.py @@ -1,4 +1,5 @@ -from tidalapi import Track +from tidalapi import Album, Mix, Playlist, Session, Track, Video +from tidalapi.session import SearchTypes from tidal_dl_ng.constants import MediaType @@ -41,3 +42,53 @@ def get_tidal_media_type(url_media: str) -> MediaType | bool: result = MediaType.MIX return result + + +def search_all_results(session: Session, needle: str, types_media: SearchTypes = None) -> dict[str, [SearchTypes]]: + limit: int = 300 + offset: int = 0 + done: bool = False + result: dict[str, [SearchTypes]] = {} + + while not done: + tmp_result: dict[str, [SearchTypes]] = session.search( + query=needle, models=types_media, limit=limit, offset=offset + ) + tmp_done: bool = True + + for key, value in tmp_result.items(): + # Append pagination results, if there are any + if offset == 0: + result = tmp_result + tmp_done = False + elif bool(value): + result[key] += value + tmp_done = False + + # Next page + offset += limit + done = tmp_done + + return result + + +def items_all_results(media_list: [Mix | Playlist | Album]) -> [Track | Video]: + limit: int = 100 + offset: int = 0 + done: bool = False + result: [Track | Video] = [] + + if isinstance(media_list, Mix): + result = media_list.items() + else: + while not done: + tmp_result: [Track | Video] = media_list.items(limit=limit, offset=offset) + + if bool(tmp_result): + result += tmp_result + # Get the next page in the next iteration. + offset += limit + else: + done = True + + return result