From e0b91e4ecca9393cde429da4c78dcd360eab9300 Mon Sep 17 00:00:00 2001 From: Fabian Munkes <105975993+fmunkes@users.noreply.github.com> Date: Sat, 1 Aug 2026 17:13:02 +0200 Subject: [PATCH] Add username parameter to get_library action in Music Assistant (#177937) --- .../components/music_assistant/services.py | 5 ++ .../components/music_assistant/services.yaml | 4 ++ .../components/music_assistant/strings.json | 4 ++ .../music_assistant/test_services.py | 52 +++++++++++++++++++ 4 files changed, 65 insertions(+) diff --git a/homeassistant/components/music_assistant/services.py b/homeassistant/components/music_assistant/services.py index 64c94bda4655..9a8d1083c061 100644 --- a/homeassistant/components/music_assistant/services.py +++ b/homeassistant/components/music_assistant/services.py @@ -122,6 +122,7 @@ def register_actions(hass: HomeAssistant) -> None: vol.Optional(ATTR_ORDER_BY): cv.string, vol.Optional(ATTR_ALBUM_TYPE): list[MediaType], vol.Optional(ATTR_ALBUM_ARTISTS_ONLY): cv.boolean, + vol.Optional(ATTR_USERNAME): cv.string, } ), supports_response=SupportsResponse.ONLY, @@ -245,12 +246,16 @@ async def handle_get_library(call: ServiceCall) -> ServiceResponse: limit = call.data.get(ATTR_LIMIT, DEFAULT_LIMIT) offset = call.data.get(ATTR_OFFSET, DEFAULT_OFFSET) order_by = call.data.get(ATTR_ORDER_BY, DEFAULT_SORT_ORDER) + username = call.data.get(ATTR_USERNAME) + if username is not None: + await async_verify_mass_username_availability(mass=mass, username=username) base_params = { "favorite": call.data.get(ATTR_FAVORITE), "search": call.data.get(ATTR_SEARCH), "limit": limit, "offset": offset, "order_by": order_by, + "user": username, } library_result: ( list[Album] diff --git a/homeassistant/components/music_assistant/services.yaml b/homeassistant/components/music_assistant/services.yaml index 55a581fafe4b..45033c722440 100644 --- a/homeassistant/components/music_assistant/services.yaml +++ b/homeassistant/components/music_assistant/services.yaml @@ -250,3 +250,7 @@ get_library: default: false selector: boolean: + username: + example: "john" + selector: + text: diff --git a/homeassistant/components/music_assistant/strings.json b/homeassistant/components/music_assistant/strings.json index 456492b45d03..d7374f1ce4b7 100644 --- a/homeassistant/components/music_assistant/strings.json +++ b/homeassistant/components/music_assistant/strings.json @@ -363,6 +363,10 @@ "search": { "description": "Optional search string to search through this library.", "name": "Search" + }, + "username": { + "description": "Music Assistant username used for this request. Providing the username will respect the user's configured provider filters.", + "name": "Username" } }, "name": "Get library items", diff --git a/tests/components/music_assistant/test_services.py b/tests/components/music_assistant/test_services.py index 8655b2f19a4a..bed611b830fe 100644 --- a/tests/components/music_assistant/test_services.py +++ b/tests/components/music_assistant/test_services.py @@ -136,3 +136,55 @@ async def test_get_library_action( return_response=True, ) assert response == snapshot + + +@pytest.mark.parametrize( + "media_type", + [ + "artist", + "album", + "track", + "playlist", + "audiobook", + "podcast", + "radio", + ], +) +async def test_get_library_action_with_username( + hass: HomeAssistant, + music_assistant_client: MagicMock, + media_type: str, +) -> None: + """Test music assistant get_library action with username.""" + entry = await setup_integration_from_fixtures(hass, music_assistant_client) + # username supported from schema 35 and above + music_assistant_client.server_info.schema_version = 35 + + # invalid users + for username in ("non_existing_user", "party_guest", "user_disabled"): + with pytest.raises(ServiceValidationError): + await hass.services.async_call( + DOMAIN, + SERVICE_GET_LIBRARY, + { + ATTR_CONFIG_ENTRY_ID: entry.entry_id, + ATTR_FAVORITE: False, + ATTR_MEDIA_TYPE: media_type, + ATTR_USERNAME: username, + }, + blocking=True, + return_response=True, + ) + # valid user + await hass.services.async_call( + DOMAIN, + SERVICE_GET_LIBRARY, + { + ATTR_CONFIG_ENTRY_ID: entry.entry_id, + ATTR_FAVORITE: False, + ATTR_MEDIA_TYPE: media_type, + ATTR_USERNAME: "user_user", + }, + blocking=True, + return_response=True, + )