From 0cf0883723443dc3296f93196ab2b0cc342dfcc6 Mon Sep 17 00:00:00 2001 From: sigma67 <16363825+sigma67@users.noreply.github.com> Date: Mon, 20 May 2024 21:45:02 +0200 Subject: [PATCH] fix #582 (#583) * fix #582 * fix result type heuristics --- tests/mixins/test_search.py | 4 ++++ ytmusicapi/mixins/search.py | 18 ++++++++++++------ ytmusicapi/parsers/search.py | 8 +++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/mixins/test_search.py b/tests/mixins/test_search.py index 4e4a645..bfc2978 100644 --- a/tests/mixins/test_search.py +++ b/tests/mixins/test_search.py @@ -40,6 +40,10 @@ def test_search_localized(self): yt_local = YTMusic(language="it") results = yt_local.search("ABBA") assert all(result["resultType"] in ALL_RESULT_TYPES for result in results) + assert len([x for x in results if x["resultType"] == "album"]) <= 10 # album is default fallback + + results = yt_local.search("ABBA", filter="songs") + assert all(item["resultType"] == "song" for item in results) def test_search_filters(self, yt_auth): query = "hip hop playlist" diff --git a/ytmusicapi/mixins/search.py b/ytmusicapi/mixins/search.py index 8113e4d..22e974d 100644 --- a/ytmusicapi/mixins/search.py +++ b/ytmusicapi/mixins/search.py @@ -205,6 +205,9 @@ def search( filter = scopes[1] for res in section_list: + result_type = category = None + search_result_types = self.parser.get_search_result_types() + if "musicCardShelfRenderer" in res: top_result = parse_top_result( res["musicCardShelfRenderer"], self.parser.get_search_result_types() @@ -212,7 +215,6 @@ def search( search_results.append(top_result) if not (shelf_contents := nav(res, ["musicCardShelfRenderer", "contents"], True)): continue - type = category = None # if "more from youtube" is present, remove it - it's not parseable if "messageRenderer" in shelf_contents[0]: category = nav(shelf_contents.pop(0), ["messageRenderer", *TEXT_RUN_TEXT]) @@ -220,15 +222,19 @@ def search( elif "musicShelfRenderer" in res: shelf_contents = res["musicShelfRenderer"]["contents"] category = nav(res, MUSIC_SHELF + TITLE_TEXT, True) - type_filter = filter or category - type = type_filter[:-1].lower() if type_filter else None + # if we know the filter it's easy to set the result type + # unfortunately uploads is modeled as a filter (historical reasons), + # so we take care to not set the result type for that scope + if filter and not scope == scopes[1]: + result_type = filter[:-1].lower() else: continue - search_result_types = self.parser.get_search_result_types() - search_results.extend(parse_search_results(shelf_contents, search_result_types, type, category)) + search_results.extend( + parse_search_results(shelf_contents, search_result_types, result_type, category) + ) if filter: # if filter is set, there are continuations @@ -236,7 +242,7 @@ def request_func(additionalParams): return self._send_request(endpoint, body, additionalParams) def parse_func(contents): - return parse_search_results(contents, search_result_types, type, category) + return parse_search_results(contents, search_result_types, result_type, category) search_results.extend( get_continuations( diff --git a/ytmusicapi/parsers/search.py b/ytmusicapi/parsers/search.py index 4088662..eab2e39 100644 --- a/ytmusicapi/parsers/search.py +++ b/ytmusicapi/parsers/search.py @@ -61,21 +61,19 @@ def parse_search_result(data, search_result_types, result_type, category): search_result = {"category": category} video_type = nav(data, [*PLAY_BUTTON, "playNavigationEndpoint", *NAVIGATION_VIDEO_TYPE], True) - # try to determine the result type based on the first run - if result_type not in ALL_RESULT_TYPES: # i.e. localized result_type - result_type = get_search_result_type(get_item_text(data, 1), search_result_types) - # determine result type based on browseId # if there was no category title (i.e. for extra results in Top Result) if not result_type: if browse_id := nav(data, NAVIGATION_BROWSE_ID, True): mapping = { - "VMPL": "playlist", + "VM": "playlist", "RD": "playlist", + "VL": "playlist", "MPLA": "artist", "MPRE": "album", "MPSP": "podcast", "MPED": "episode", + "UC": "artist", } result_type = next( iter(type for prefix, type in mapping.items() if browse_id.startswith(prefix)), None