From 541527be322a73e4ecdef215e04dc0a040250063 Mon Sep 17 00:00:00 2001 From: Robert Honz Date: Sun, 7 Sep 2025 18:27:30 +0200 Subject: [PATCH] =?UTF-8?q?feat(tidal):=20=E2=9C=A8=20add=20url=5Fending?= =?UTF-8?q?=5Fclean=20function=20and=20refactor=20URL=20handling.=20Fixes?= =?UTF-8?q?=20#523?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduced `url_ending_clean` to sanitize URLs by removing trailing "/u" or "?u". * Updated `_process_url` and GUI search logic to utilize cleaned URLs for better validation and processing. --- tidal_dl_ng/cli.py | 33 ++++++++++++++++++--------------- tidal_dl_ng/gui.py | 12 +++++++----- tidal_dl_ng/helper/tidal.py | 13 +++++++++++++ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/tidal_dl_ng/cli.py b/tidal_dl_ng/cli.py index 78e0049..ce8dc3d 100644 --- a/tidal_dl_ng/cli.py +++ b/tidal_dl_ng/cli.py @@ -28,6 +28,7 @@ from tidal_dl_ng.helper.tidal import ( get_tidal_media_id, get_tidal_media_type, instantiate_media, + url_ending_clean, ) from tidal_dl_ng.helper.wrapper import LoggerWrapped from tidal_dl_ng.model.cfg import HelpSettings @@ -147,7 +148,7 @@ def _process_url( dl: Download, ctx: typer.Context, handling_app: HandlingApp, - item: str, + url: str, idx: int, urls_pos_last: int, ) -> bool: @@ -157,8 +158,8 @@ def _process_url( dl (Download): The Download instance. ctx (typer.Context): Typer context object. handling_app (HandlingApp): The HandlingApp instance. - item (str): The URL or identifier to process. - idx (int): The index of the item in the list. + url (str): The URL or identifier to process. + idx (int): The index of the url in the list. urls_pos_last (int): The last index in the URLs list. Returns: @@ -169,35 +170,37 @@ def _process_url( if handling_app.event_abort.is_set(): return False - if "http" not in item: - print(f"It seems like that you have supplied an invalid URL: {item}") + if "http" not in url: + print(f"It seems like that you have supplied an invalid URL: {url}") return True - media_type = get_tidal_media_type(item) + url_clean: str = url_ending_clean(url) + + media_type = get_tidal_media_type(url_clean) if not isinstance(media_type, MediaType): - print(f"Could not determine media type for: {item}") + print(f"Could not determine media type for: {url_clean}") return True - item_id = get_tidal_media_id(item) - if not isinstance(item_id, str): - print(f"Could not determine media id for: {item}") + url_clean_id = get_tidal_media_id(url_clean) + if not isinstance(url_clean_id, str): + print(f"Could not determine media id for: {url_clean}") return True file_template = get_format_template(media_type, settings) if not isinstance(file_template, str): - print(f"Could not determine file template for: {item}") + print(f"Could not determine file template for: {url_clean}") return True try: - media = instantiate_media(ctx.obj[CTX_TIDAL].session, media_type, item_id) + media = instantiate_media(ctx.obj[CTX_TIDAL].session, media_type, url_clean_id) except Exception: - print(f"Media not found (ID: {item_id}). Maybe it is not available anymore.") + print(f"Media not found (ID: {url_clean_id}). Maybe it is not available anymore.") return True if media_type in [MediaType.TRACK, MediaType.VIDEO]: - _handle_track_or_video(dl, ctx, item, media, file_template, idx, urls_pos_last) + _handle_track_or_video(dl, ctx, url_clean, media, file_template, idx, urls_pos_last) elif media_type in [MediaType.ALBUM, MediaType.PLAYLIST, MediaType.MIX, MediaType.ARTIST]: - return _handle_album_playlist_mix_artist(ctx, dl, handling_app, media_type, media, item_id, file_template) + return _handle_album_playlist_mix_artist(ctx, dl, handling_app, media_type, media, url_clean_id, file_template) return True diff --git a/tidal_dl_ng/gui.py b/tidal_dl_ng/gui.py index 6263c76..20742a2 100644 --- a/tidal_dl_ng/gui.py +++ b/tidal_dl_ng/gui.py @@ -77,6 +77,7 @@ from tidal_dl_ng.helper.tidal import ( name_builder_title, quality_audio_highest, search_results_all, + url_ending_clean, user_media_lists, ) @@ -743,12 +744,13 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): Returns: list[ResultItem]: The search results. """ - query = query.strip() + query_clean: str = query.strip() # If a direct link was searched for, skip search and create the object from the link directly. - if "http" in query: - media_type = get_tidal_media_type(query) - item_id = get_tidal_media_id(query) + if "http" in query_clean: + query_clean: str = url_ending_clean(query_clean) + media_type = get_tidal_media_type(query_clean) + item_id = get_tidal_media_id(query_clean) try: media = instantiate_media(self.tidal.session, media_type, item_id) @@ -760,7 +762,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): result_search = {"direct": [media]} else: result_search: dict[str, list[SearchTypes]] = search_results_all( - session=self.tidal.session, needle=query, types_media=types_media + session=self.tidal.session, needle=query_clean, types_media=types_media ) result: list[ResultItem] = [] diff --git a/tidal_dl_ng/helper/tidal.py b/tidal_dl_ng/helper/tidal.py index 3896fa6..96348f2 100644 --- a/tidal_dl_ng/helper/tidal.py +++ b/tidal_dl_ng/helper/tidal.py @@ -41,6 +41,7 @@ def name_builder_item(media: Track | Video) -> str: def get_tidal_media_id(url_or_id_media: str) -> str: + id_dirty = url_or_id_media.rsplit("/", 1)[-1] id_media = id_dirty.rsplit("?", 1)[0] @@ -70,6 +71,18 @@ def get_tidal_media_type(url_media: str) -> MediaType | bool: return result +def url_ending_clean(url: str) -> str: + """Checks if a link ends with "/u" or "?u" and removes that part. + + Args: + url (str): The URL to clean. + + Returns: + str: The cleaned URL. + """ + return url[:-2] if url.endswith("/u") or url.endswith("?u") else url + + def search_results_all(session: Session, needle: str, types_media: SearchTypes = None) -> dict[str, [SearchTypes]]: limit: int = 300 offset: int = 0