Franck Nijhof 7e4b9adc3d
Rewrite of Spotify integration (#30717)
* Rewrite of Spotify integration

* Update homeassistant/components/spotify/config_flow.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

* Remove configurator dependency

* Strip whitespace from device model in case Spotify product is missing

* Ensure domain dict exists in hass data on setup entry

* Simply config validation for client id and secret

* Abort flow on any exception from spotipy

* Add tests for config flow

* Gen requirements all

* Add test package __init__

* Remove Spotify from coveragerc

* Made alias handling more robuust

* Fix supported_features for Spotify free and open accounts

* Improve error message in the logs

* Re-implement Spotify media_player

* Change media content type when play a playlist

* Process review suggestions

* Move Spotify init, static current user and supported_features

* Remove unneeded me call

* Remove playlist content type due to frontend issues

* Improve playlist handling, when context is missing

* Handle entity disabled correctly

* Handle being offline/unavailable correctly

* Bump Spotipy to 2.7.1

* Update coverage RC, mark integration silver

* Remove URI limitation, lib supports all Spotify URI's now

* Final cleanup

* Addresses Pylint error

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2020-01-24 18:47:22 +01:00

98 lines
3.0 KiB
Python

"""The spotify integration."""
from spotipy import Spotify, SpotifyException
import voluptuous as vol
from homeassistant.components.media_player import DOMAIN as MEDIA_PLAYER_DOMAIN
from homeassistant.components.spotify import config_flow
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_CREDENTIALS
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_entry_oauth2_flow, config_validation as cv
from homeassistant.helpers.config_entry_oauth2_flow import (
OAuth2Session,
async_get_config_entry_implementation,
)
from homeassistant.helpers.typing import ConfigType
from .const import (
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
DATA_SPOTIFY_CLIENT,
DATA_SPOTIFY_ME,
DATA_SPOTIFY_SESSION,
DOMAIN,
)
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Inclusive(CONF_CLIENT_ID, ATTR_CREDENTIALS): cv.string,
vol.Inclusive(CONF_CLIENT_SECRET, ATTR_CREDENTIALS): cv.string,
}
)
},
extra=vol.ALLOW_EXTRA,
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Spotify integration."""
if DOMAIN not in config:
return True
if CONF_CLIENT_ID in config[DOMAIN]:
config_flow.SpotifyFlowHandler.async_register_implementation(
hass,
config_entry_oauth2_flow.LocalOAuth2Implementation(
hass,
DOMAIN,
config[DOMAIN][CONF_CLIENT_ID],
config[DOMAIN][CONF_CLIENT_SECRET],
"https://accounts.spotify.com/authorize",
"https://accounts.spotify.com/api/token",
),
)
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Spotify from a config entry."""
implementation = await async_get_config_entry_implementation(hass, entry)
session = OAuth2Session(hass, entry, implementation)
await session.async_ensure_token_valid()
spotify = Spotify(auth=session.token["access_token"])
try:
current_user = await hass.async_add_executor_job(spotify.me)
except SpotifyException:
raise ConfigEntryNotReady
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {
DATA_SPOTIFY_CLIENT: spotify,
DATA_SPOTIFY_ME: current_user,
DATA_SPOTIFY_SESSION: session,
}
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, MEDIA_PLAYER_DOMAIN)
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload Spotify config entry."""
# Unload entities for this entry/device.
await hass.config_entries.async_forward_entry_unload(entry, MEDIA_PLAYER_DOMAIN)
# Cleanup
del hass.data[DOMAIN][entry.entry_id]
if not hass.data[DOMAIN]:
del hass.data[DOMAIN]
return True