From: Marcel van der Veldt Date: Mon, 8 Dec 2025 13:31:46 +0000 (+0100) Subject: Fix several issues in Browse X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=45f2d57b867015717a8243b00aab500825041a9b;p=music-assistant-server.git Fix several issues in Browse --- diff --git a/music_assistant/models/music_provider.py b/music_assistant/models/music_provider.py index fdc45506..57b51a82 100644 --- a/music_assistant/models/music_provider.py +++ b/music_assistant/models/music_provider.py @@ -481,7 +481,7 @@ class MusicProvider(Provider): return await self.get_podcast_episode(prov_item_id) return await self.get_track(prov_item_id) - async def browse(self, path: str) -> Sequence[MediaItemType | ItemMapping | BrowseFolder]: + async def browse(self, path: str) -> Sequence[MediaItemType | ItemMapping | BrowseFolder]: # noqa: PLR0911 """Browse this provider's items. :param path: The path to browse, (e.g. provider_id://artists). @@ -490,36 +490,82 @@ class MusicProvider(Provider): # we may NOT use the default implementation if the provider does not support browse raise NotImplementedError - subpath = path.split("://", 1)[1] + path_parts = path.split("://")[1].split("/") + subpath = path_parts[0] if len(path_parts) > 0 else None + sub_subpath = path_parts[1] if len(path_parts) > 1 else None # this reference implementation can be overridden with a provider specific approach if subpath == "artists": - return await self.mass.music.artists.library_items( + if artists := await self.mass.music.artists.library_items( provider=self.instance_id, - ) + ): + return artists + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_artists()] if subpath == "albums": - return await self.mass.music.albums.library_items( + if albums := await self.mass.music.albums.library_items( provider=self.instance_id, - ) + ): + return albums + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_albums()] if subpath == "tracks": - return await self.mass.music.tracks.library_items( + if tracks := await self.mass.music.tracks.library_items( provider=self.instance_id, - ) + ): + return tracks + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_tracks()] if subpath == "radios": - return await self.mass.music.radio.library_items( + if radios := await self.mass.music.radio.library_items( provider=self.instance_id, - ) + ): + return radios + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_radios()] if subpath == "playlists": - return await self.mass.music.playlists.library_items( + if playlists := await self.mass.music.playlists.library_items( provider=self.instance_id, - ) + ): + return playlists + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_playlists()] if subpath == "audiobooks": - return await self.mass.music.audiobooks.library_items( + if audiobooks := await self.mass.music.audiobooks.library_items( provider=self.instance_id, - ) + ): + return audiobooks + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_audiobooks()] if subpath == "podcasts": - return await self.mass.music.podcasts.library_items( + if podcasts := await self.mass.music.podcasts.library_items( provider=self.instance_id, - ) + ): + return podcasts + # library items not (yet) synced, fallback to direct retrieval + return [x async for x in self.get_library_podcasts()] + if subpath == "recommendations" and sub_subpath: + # recommendations contents listing + recommendations = await self.recommendations() + for rec in recommendations: + if rec.item_id == sub_subpath: + return rec.items + if subpath == "recommendations": + # Main recommendations listing + result: list[BrowseFolder] = [] + recommendations = await self.recommendations() + for rec in recommendations: + result.append( + BrowseFolder( + item_id=rec.item_id, + provider=self.instance_id, + name=rec.name, + is_playable=rec.is_playable, + image=rec.image, + path=f"{path}/{rec.item_id}", + ) + ) + return result + if subpath: # unknown path msg = "Invalid subpath" @@ -533,7 +579,7 @@ class MusicProvider(Provider): item_id="artists", provider=self.instance_id, path=path + "artists", - name="Artists", + name="", translation_key="artists", is_playable=True, ) @@ -544,7 +590,7 @@ class MusicProvider(Provider): item_id="albums", provider=self.instance_id, path=path + "albums", - name="Albums", + name="", translation_key="albums", is_playable=True, ) @@ -555,7 +601,7 @@ class MusicProvider(Provider): item_id="tracks", provider=self.domain, path=path + "tracks", - name="Tracks", + name="", translation_key="tracks", is_playable=True, ) @@ -566,7 +612,7 @@ class MusicProvider(Provider): item_id="playlists", provider=self.instance_id, path=path + "playlists", - name="Playlists", + name="", translation_key="playlists", is_playable=True, ) @@ -577,7 +623,7 @@ class MusicProvider(Provider): item_id="radios", provider=self.instance_id, path=path + "radios", - name="Radio", + name="", translation_key="radios", ) ) @@ -587,7 +633,7 @@ class MusicProvider(Provider): item_id="audiobooks", provider=self.instance_id, path=path + "audiobooks", - name="Audiobooks", + name="", translation_key="audiobooks", ) ) @@ -597,10 +643,20 @@ class MusicProvider(Provider): item_id="podcasts", provider=self.instance_id, path=path + "podcasts", - name="Podcasts", + name="", translation_key="podcasts", ) ) + if ProviderFeature.RECOMMENDATIONS in self.supported_features: + folders.append( + BrowseFolder( + item_id="recommendations", + provider=self.instance_id, + path=path + "recommendations", + name="", + translation_key="recommendations", + ) + ) if len(folders) == 1: # only one level, return the items directly return await self.browse(folders[0].path)