From 8e4eeaf4a50e4d0ffcb9d67e8b250994534aa247 Mon Sep 17 00:00:00 2001 From: Marvin Schenkel Date: Sat, 2 Jul 2022 19:36:18 +0200 Subject: [PATCH] Add serach for artist and album --- examples/ytmusic.py | 8 +++- music_assistant/music_providers/ytmusic.py | 54 +++++++++++++++++++++- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/examples/ytmusic.py b/examples/ytmusic.py index c62b3366..d5b82799 100644 --- a/examples/ytmusic.py +++ b/examples/ytmusic.py @@ -10,7 +10,7 @@ path.insert(1, dirname(dirname(abspath(__file__)))) from music_assistant.mass import MusicAssistant from music_assistant.models.config import MassConfig, MusicProviderConfig -from music_assistant.models.enums import ProviderType +from music_assistant.models.enums import MediaType, ProviderType from music_assistant.models.player import Player, PlayerState from music_assistant.models.player_queue import RepeatMode @@ -108,7 +108,11 @@ async def main(): yt = mass.music.get_provider(ProviderType.YTMUSIC) track = await yt.get_track("pE3ju1qS848") await yt.get_album("MPREb_AYetWMZunqA") - await yt.get_artist("UCU2d6Vg6hp0vJb8K0krR5_g") + artist = await yt.get_artist("UC-T-wUsgssr7Vy-BiJD4-2g") + #print(artist) + for album in await yt.search("dark side of the moon", [MediaType.ALBUM]): + print(album) + print("**********") #test_player1 = TestPlayer("test1") #await mass.players.register_player(test_player1) diff --git a/music_assistant/music_providers/ytmusic.py b/music_assistant/music_providers/ytmusic.py index 49f366cf..56cd4ce7 100644 --- a/music_assistant/music_providers/ytmusic.py +++ b/music_assistant/music_providers/ytmusic.py @@ -60,6 +60,53 @@ class YTMusic(MusicProvider): self._cookies = {'CONSENT': 'YES+1'} return True + async def search( + self, search_query: str, media_types=Optional[List[MediaType]], limit: int = 5 + ) -> List[MediaItemType]: + """ + Perform search on musicprovider. + :param search_query: Search query. + :param media_types: A list of media_types to include. All types if None. + :param limit: Number of items to return in the search (per type). + """ + data = {'query': search_query} + filter = None + if len(media_types) == 1: + # YTM does not support multiple searchtypes, falls back to all if no type given + if media_types[0] == MediaType.ARTIST: + filter = "artists" + if media_types[0] == MediaType.ALBUM: + filter = "albums" + if media_types[0] == MediaType.TRACK: + filter = "songs" + if media_types[0] == MediaType.PLAYLIST: + filter = "playlists" + params = ytmusicapi.parsers.search_params.get_search_params(filter=filter, scope=None, ignore_spelling=False) + data["params"] = params + search_results = await self._post_data(endpoint="search", data=data) + if 'tabbedSearchResultsRenderer' in search_results['contents']: + results = search_results['contents']['tabbedSearchResultsRenderer']['tabs'][0][ + 'tabRenderer']['content'] + else: + results = search_results['contents'] + parsed_results = [] + for result in results["sectionListRenderer"]["contents"]: + if "musicShelfRenderer" in result: + category = result["musicShelfRenderer"]["title"]["runs"][0]["text"] + if category == "Artists": + for artist in result['musicShelfRenderer']['contents']: + artist_id = artist["musicResponsiveListItemRenderer"]["navigationEndpoint"]["browseEndpoint"]["browseId"] + parsed_results.append(await self.get_artist(artist_id)) + elif category == "Albums": + for album in result['musicShelfRenderer']['contents']: + album_id = album["musicResponsiveListItemRenderer"]["navigationEndpoint"]["browseEndpoint"]["browseId"] + parsed_results.append(await self.get_album(album_id)) + + else: + print(category) + return parsed_results + + async def get_album(self, prov_album_id) -> Album: """Get full album details by id.""" data = {"browseId": prov_album_id} @@ -180,7 +227,8 @@ class YTMusic(MusicProvider): for thumb in parsed_album["thumbnails"]: images.append(MediaItemImage(ImageType.THUMB, thumb["url"])) album.metadata.images = images - album.metadata.description = unquote(parsed_album["description"]) + if "description" in parsed_album: + album.metadata.description = unquote(parsed_album["description"]) artists = [] for artist in parsed_album["artists"]: artists.append(await self.get_artist(artist["id"])) @@ -189,12 +237,14 @@ class YTMusic(MusicProvider): async def _parse_artist(self, artist_obj: dict) -> Artist: """Parse a YT Artist response to Artist model object""" + print(json.dumps(artist_obj)) name = artist_obj["header"]["musicImmersiveHeaderRenderer"]["title"]["runs"][0]["text"] id = artist_obj["header"]["musicImmersiveHeaderRenderer"]["subscriptionButton"]["subscribeButtonRenderer"]["channelId"] artist = Artist( item_id=str(id), provider=self.type, name=name ) - artist.metadata.description = unquote(artist_obj["header"]["musicImmersiveHeaderRenderer"]["description"]["runs"][0]["text"]) + if "description" in artist_obj["header"]["musicImmersiveHeaderRenderer"]: + artist.metadata.description = unquote(artist_obj["header"]["musicImmersiveHeaderRenderer"]["description"]["runs"][0]["text"]) images = [] for thumb in artist_obj["header"]["musicImmersiveHeaderRenderer"]["thumbnail"]["musicThumbnailRenderer"]["thumbnail"]["thumbnails"]: images.append(MediaItemImage(ImageType.THUMB, thumb["url"])) -- 2.34.1