Skip to content

Commit

Permalink
get_album: parse more data from response + correct keys on other_vers… (
Browse files Browse the repository at this point in the history
#523)

* get_album: parse more data from response + correct keys on other_versions

* keys: fair point

* navigation, browsing: removed duplicate SUBTITLE

---------

Co-authored-by: sigma67 <[email protected]>
  • Loading branch information
jcbirdwell and sigma67 committed Jan 21, 2024
1 parent de651c4 commit 123eae7
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 20 deletions.
56 changes: 38 additions & 18 deletions tests/mixins/test_browsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,44 @@ def test_get_album_browse_id_issue_470(self, yt):
assert escaped_browse_id == "MPREb_scJdtUCpPE2"

def test_get_album(self, yt, yt_auth, sample_album):
results = yt_auth.get_album(sample_album)
assert len(results) >= 9
assert results["tracks"][0]["isExplicit"]
assert all(item["views"] is not None for item in results["tracks"])
assert all(item["album"] is not None for item in results["tracks"])
assert results["tracks"][0]["trackNumber"] == 1
assert "feedbackTokens" in results["tracks"][0]
assert len(results["other_versions"]) >= 1 # appears to be regional
results = yt.get_album("MPREb_BQZvl3BFGay")
assert len(results["tracks"]) == 7
assert len(results["tracks"][0]["artists"]) == 1
results = yt.get_album("MPREb_rqH94Zr3NN0")
assert len(results["tracks"][0]["artists"]) == 2
results = yt.get_album("MPREb_TPH4WqN5pUo") # album with tracks completely removed/missing
assert results["tracks"][0]["trackNumber"] == 3
assert results["tracks"][13]["trackNumber"] == 18
results = yt.get_album("MPREb_YuigcYm2erf") # album with track (#8) disabled/greyed out
assert results["tracks"][7]["trackNumber"] is None
album = yt_auth.get_album(sample_album)
assert len(album) >= 9
assert "isExplicit" in album
assert album["tracks"][0]["isExplicit"]
assert all(item["views"] is not None for item in album["tracks"])
assert all(item["album"] is not None for item in album["tracks"])
assert album["tracks"][0]["trackNumber"] == 1
assert "feedbackTokens" in album["tracks"][0]
album = yt.get_album("MPREb_BQZvl3BFGay")
assert len(album["tracks"]) == 7
assert len(album["tracks"][0]["artists"]) == 1
album = yt.get_album("MPREb_rqH94Zr3NN0")
assert len(album["tracks"][0]["artists"]) == 2
album = yt.get_album("MPREb_TPH4WqN5pUo") # album with tracks completely removed/missing
assert album["tracks"][0]["trackNumber"] == 3
assert album["tracks"][13]["trackNumber"] == 18
album = yt.get_album("MPREb_YuigcYm2erf") # album with track (#8) disabled/greyed out
assert album["tracks"][7]["trackNumber"] is None

def test_get_album_other_versions(self, yt):
# Eminem - Curtain Call: The Hits (Explicit Variant)
album = yt.get_album("MPREb_LQCAymzbaKJ")
assert len(variants := album["other_versions"]) >= 1 # appears to be regional
assert (variant := variants[0])["type"] == "Album"
assert len(variant["artists"]) == 1
assert variant["artists"][0] == {"name": "Eminem", "id": "UCedvOgsKFzcK3hA5taf3KoQ"}
assert variant["audioPlaylistId"] is not None

# album that's multi-artist, a single, and has clean version
# Cassö & RAYE - Prada
album = yt.get_album("MPREb_of3qfisa0yU")
assert not album["isExplicit"]
assert (variant := album["other_versions"][0])["type"] == "Single"
assert variant["isExplicit"]
assert len(variant["artists"]) == 3
assert variant["artists"][0]["id"] == "UCGWMNnI1Ky5bMcRlr73Cj2Q"
assert variant["artists"][1]["name"] == "RAYE"
assert variant["artists"][2] == {"id": "UCb7jnkQW94hzOoWkG14zs4w", "name": "D-Block Europe"}

def test_get_song(self, config, yt, yt_oauth, sample_video):
song = yt_oauth.get_song(config["uploads"]["private_upload_id"]) # private upload
Expand Down
7 changes: 5 additions & 2 deletions ytmusicapi/navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@
MENU_LIKE_STATUS = [*MENU, "topLevelButtons", 0, "likeButtonRenderer", "likeStatus"]
MENU_SERVICE = ["menuServiceItemRenderer", "serviceEndpoint"]
TOGGLE_MENU = "toggleMenuServiceItemRenderer"
PLAY_BUTTON = ["overlay", "musicItemThumbnailOverlayRenderer", "content", "musicPlayButtonRenderer"]
OVERLAY_RENDERER = ["musicItemThumbnailOverlayRenderer", "content", "musicPlayButtonRenderer"]
PLAY_BUTTON = ["overlay", *OVERLAY_RENDERER]
NAVIGATION_BROWSE = ["navigationEndpoint", "browseEndpoint"]
NAVIGATION_BROWSE_ID = [*NAVIGATION_BROWSE, "browseId"]
PAGE_TYPE = ["browseEndpointContextSupportedConfigs", "browseEndpointContextMusicConfig", "pageType"]
WATCH_VIDEO_ID = ["watchEndpoint", "videoId"]
NAVIGATION_VIDEO_ID = ["navigationEndpoint", *WATCH_VIDEO_ID]
QUEUE_VIDEO_ID = ["queueAddEndpoint", "queueTarget", "videoId"]
NAVIGATION_PLAYLIST_ID = ["navigationEndpoint", "watchEndpoint", "playlistId"]
NAVIGATION_WATCH_PLAYLIST_ID = ["navigationEndpoint", "watchPlaylistEndpoint", "playlistId"]
WATCH_PID = ["watchPlaylistEndpoint", "playlistId"]
NAVIGATION_WATCH_PLAYLIST_ID = ["navigationEndpoint", *WATCH_PID]
NAVIGATION_VIDEO_TYPE = [
"watchEndpoint",
"watchEndpointMusicSupportedConfigs",
Expand All @@ -50,6 +52,7 @@
THUMBNAIL = ["thumbnail", "thumbnails"]
THUMBNAILS = ["thumbnail", "musicThumbnailRenderer", *THUMBNAIL]
THUMBNAIL_RENDERER = ["thumbnailRenderer", "musicThumbnailRenderer", *THUMBNAIL]
THUMBNAIL_OVERLAY = ["thumbnailOverlay", *OVERLAY_RENDERER, "playNavigationEndpoint", *WATCH_PID]
THUMBNAIL_CROPPED = ["thumbnail", "croppedSquareThumbnailRenderer", *THUMBNAIL]
FEEDBACK_TOKEN = ["feedbackEndpoint", "feedbackToken"]
BADGE_PATH = [0, "musicInlineBadgeRenderer", "accessibilityData", "accessibilityData", "label"]
Expand Down
2 changes: 2 additions & 0 deletions ytmusicapi/parsers/albums.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ def parse_album_header(response):
"title": nav(header, TITLE_TEXT),
"type": nav(header, SUBTITLE),
"thumbnails": nav(header, THUMBNAIL_CROPPED),
"isExplicit": nav(header, SUBTITLE_BADGE_LABEL, True) is not None,
}

if "description" in header:
album["description"] = header["description"]["runs"][0]["text"]

Expand Down
10 changes: 10 additions & 0 deletions ytmusicapi/parsers/browsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,23 @@ def parse_content_list(results, parse_func, key=MTRIR):
def parse_album(result):
return {
"title": nav(result, TITLE_TEXT),
"type": nav(result, SUBTITLE),
"year": nav(result, SUBTITLE2, True),
"artists": [parse_id_name(x) for x in nav(result, ["subtitle", "runs"]) if "navigationEndpoint" in x],
"browseId": nav(result, TITLE + NAVIGATION_BROWSE_ID),
"audioPlaylistId": nav(result, THUMBNAIL_OVERLAY, True),
"thumbnails": nav(result, THUMBNAIL_RENDERER),
"isExplicit": nav(result, SUBTITLE_BADGE_LABEL, True) is not None,
}


def parse_id_name(sub_run):
return {
"id": nav(sub_run, NAVIGATION_BROWSE_ID, True),
"name": nav(sub_run, ["text"], True),
}


def parse_single(result):
return {
"title": nav(result, TITLE_TEXT),
Expand Down

0 comments on commit 123eae7

Please sign in to comment.