Skip to content

Commit

Permalink
Feat: Add missing helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt committed Oct 30, 2024
1 parent 0e1b6d3 commit d6f4da6
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 1 deletion.
43 changes: 43 additions & 0 deletions music_assistant_client/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Several generic/basic helpers and utilities complementing the Music Assistant Client."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from music_assistant_models.media_items import SearchResults


def compact_media_item_dict(item: dict[str, Any]) -> dict[str, Any]:
"""Return compacted MediaItem dict."""
for key in (
"metadata",
"provider_mappings",
"favorite",
"timestamp_added",
"timestamp_modified",
"mbid",
):
item.pop(key, None)
for key, value in item.items():
if isinstance(value, dict):
item[key] = compact_media_item_dict(value)
elif isinstance(value, list):
for subitem in value:
if not isinstance(subitem, dict):
continue
compact_media_item_dict(subitem)
return item


def searchresults_as_compact_dict(search_results: SearchResults) -> dict[str, Any]:
"""Return compacted search result dict."""
dict_result: dict[str, list[dict[str, Any]]] = search_results.to_dict()
for media_type_key in dict_result:
for item in dict_result[media_type_key]:
if not isinstance(item, dict):
# guards against invalid data
continue # type: ignore[unreachable]
# return limited result to prevent it being too verbose
compact_media_item_dict(item)
return dict_result
66 changes: 66 additions & 0 deletions music_assistant_client/music.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,3 +570,69 @@ def get_media_item_image(
if type == ImageType.THUMB:
return self.get_media_item_image(item, ImageType.LANDSCAPE)
return None

async def get_item_by_name(
self,
name: str,
artist: str | None = None,
album: str | None = None,
media_type: MediaType | None = None,
) -> MediaItemType | None:
"""Try to find a media item (such as a playlist) by name."""
# pylint: disable=too-many-nested-blocks
searchname = name.lower()
library_functions = [
x
for x in (
self.get_library_playlists,
self.get_library_radios,
self.get_library_tracks,
self.get_library_albums,
self.get_library_artists,
)
if not media_type or media_type.value.lower() in x.__name__
]
# prefer (exact) lookup in the library by name
for func in library_functions:
result = await func(search=searchname)
for item in result:
# handle optional artist filter
if (
artist
and (artists := getattr(item, "artists", None))
and not any(x for x in artists if x.name.lower() == artist.lower())
):
continue
# handle optional album filter
if (
album
and (item_album := getattr(item, "album", None))
and item_album.name.lower() != album.lower()
):
continue
if searchname == item.name.lower():
return item
# nothing found in the library, fallback to global search
search_name = name
if album and artist:
search_name = f"{artist} - {album} - {name}"
elif album:
search_name = f"{album} - {name}"
elif artist:
search_name = f"{artist} - {name}"
search_results = await self.search(
search_query=search_name,
media_types=[media_type] if media_type else MediaType.ALL,
limit=5,
)
for results in (
search_results.tracks,
search_results.albums,
search_results.playlists,
search_results.artists,
search_results.radio,
):
for item in results:
# simply return the first item because search is already sorted by best match
return item
return None
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = ["aiohttp>=3.10", "music_assistant_models==1.0.0"]
dependencies = ["aiohttp>=3.10", "music_assistant_models==1.0.2"]
description = "Music Assistant Client"
license = {text = "Apache-2.0"}
name = "music_assistant_client"
Expand Down

0 comments on commit d6f4da6

Please sign in to comment.