Skip to content

Commit

Permalink
fix #582 (#583)
Browse files Browse the repository at this point in the history
* fix #582

* fix result type heuristics
  • Loading branch information
sigma67 authored May 20, 2024
1 parent ae966bb commit 0cf0883
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 11 deletions.
4 changes: 4 additions & 0 deletions tests/mixins/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
18 changes: 12 additions & 6 deletions ytmusicapi/mixins/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,38 +205,44 @@ 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()
)
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])

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

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(
Expand Down
8 changes: 3 additions & 5 deletions ytmusicapi/parsers/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 0cf0883

Please sign in to comment.