mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Support browsing multiple Spotify accounts (#66256)
* Support browsing multiple Spotify accounts * Fix rebase mistakes * Address review comments * Return root spotify node with config entries as children * Add util to get spotify URI for media browser URL * Only support browsing spotify with config entry specified
This commit is contained in:
parent
370832f527
commit
dbd26c7faf
@ -30,7 +30,11 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
|
||||
from . import config_flow
|
||||
from .browse_media import async_browse_media
|
||||
from .const import DOMAIN, LOGGER, SPOTIFY_SCOPES
|
||||
from .util import is_spotify_media_type, resolve_spotify_media_type
|
||||
from .util import (
|
||||
is_spotify_media_type,
|
||||
resolve_spotify_media_type,
|
||||
spotify_uri_from_media_browser_url,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
@ -50,6 +54,7 @@ PLATFORMS = [Platform.MEDIA_PLAYER]
|
||||
__all__ = [
|
||||
"async_browse_media",
|
||||
"DOMAIN",
|
||||
"spotify_uri_from_media_browser_url",
|
||||
"is_spotify_media_type",
|
||||
"resolve_spotify_media_type",
|
||||
]
|
||||
|
@ -6,11 +6,13 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from spotipy import Spotify
|
||||
import yarl
|
||||
|
||||
from homeassistant.backports.enum import StrEnum
|
||||
from homeassistant.components.media_player import BrowseError, BrowseMedia
|
||||
from homeassistant.components.media_player.const import (
|
||||
MEDIA_CLASS_ALBUM,
|
||||
MEDIA_CLASS_APP,
|
||||
MEDIA_CLASS_ARTIST,
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_CLASS_EPISODE,
|
||||
@ -137,15 +139,53 @@ class UnknownMediaType(BrowseError):
|
||||
|
||||
async def async_browse_media(
|
||||
hass: HomeAssistant,
|
||||
media_content_type: str,
|
||||
media_content_id: str,
|
||||
media_content_type: str | None,
|
||||
media_content_id: str | None,
|
||||
*,
|
||||
can_play_artist: bool = True,
|
||||
) -> BrowseMedia:
|
||||
"""Browse Spotify media."""
|
||||
if not (info := next(iter(hass.data[DOMAIN].values()), None)):
|
||||
raise BrowseError("No Spotify accounts available")
|
||||
return await async_browse_media_internal(
|
||||
parsed_url = None
|
||||
info = None
|
||||
|
||||
# Check if caller is requesting the root nodes
|
||||
if media_content_type is None and media_content_id is None:
|
||||
children = []
|
||||
for config_entry_id, info in hass.data[DOMAIN].items():
|
||||
config_entry = hass.config_entries.async_get_entry(config_entry_id)
|
||||
assert config_entry is not None
|
||||
children.append(
|
||||
BrowseMedia(
|
||||
title=config_entry.title,
|
||||
media_class=MEDIA_CLASS_APP,
|
||||
media_content_id=f"{MEDIA_PLAYER_PREFIX}{config_entry_id}",
|
||||
media_content_type=f"{MEDIA_PLAYER_PREFIX}library",
|
||||
thumbnail="https://brands.home-assistant.io/_/spotify/logo.png",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
)
|
||||
)
|
||||
return BrowseMedia(
|
||||
title="Spotify",
|
||||
media_class=MEDIA_CLASS_APP,
|
||||
media_content_id=MEDIA_PLAYER_PREFIX,
|
||||
media_content_type="spotify",
|
||||
thumbnail="https://brands.home-assistant.io/_/spotify/logo.png",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children=children,
|
||||
)
|
||||
|
||||
if media_content_id is None or not media_content_id.startswith(MEDIA_PLAYER_PREFIX):
|
||||
raise BrowseError("Invalid Spotify URL specified")
|
||||
|
||||
# Check for config entry specifier, and extract Spotify URI
|
||||
parsed_url = yarl.URL(media_content_id)
|
||||
if (info := hass.data[DOMAIN].get(parsed_url.host)) is None:
|
||||
raise BrowseError("Invalid Spotify account specified")
|
||||
media_content_id = parsed_url.name
|
||||
|
||||
result = await async_browse_media_internal(
|
||||
hass,
|
||||
info.client,
|
||||
info.session,
|
||||
@ -155,6 +195,13 @@ async def async_browse_media(
|
||||
can_play_artist=can_play_artist,
|
||||
)
|
||||
|
||||
# Build new URLs with config entry specifyers
|
||||
result.media_content_id = str(parsed_url.with_name(result.media_content_id))
|
||||
if result.children:
|
||||
for child in result.children:
|
||||
child.media_content_id = str(parsed_url.with_name(child.media_content_id))
|
||||
return result
|
||||
|
||||
|
||||
async def async_browse_media_internal(
|
||||
hass: HomeAssistant,
|
||||
|
@ -3,6 +3,8 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import yarl
|
||||
|
||||
from .const import MEDIA_PLAYER_PREFIX
|
||||
|
||||
|
||||
@ -22,3 +24,11 @@ def fetch_image_url(item: dict[str, Any], key="images") -> str | None:
|
||||
return item.get(key, [])[0].get("url")
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
|
||||
def spotify_uri_from_media_browser_url(media_content_id: str) -> str:
|
||||
"""Extract spotify URI from media browser URL."""
|
||||
if media_content_id and media_content_id.startswith(MEDIA_PLAYER_PREFIX):
|
||||
parsed_url = yarl.URL(media_content_id)
|
||||
media_content_id = parsed_url.name
|
||||
return media_content_id
|
||||
|
Loading…
x
Reference in New Issue
Block a user