Skip to content

Commit

Permalink
[ 1.0.52 ] * Changed storage location of authorization Token Cache fi…
Browse files Browse the repository at this point in the history
…le to prevent data loss on version updates. The file was moved from `\config\custom_components\spotifyplus\data\tokens.json` to `\config\.storage\spotifyplus_tokens.json`, which will allow it to persist between version updates. Note that you can simply copy the Token Cache file from the old location to the new location prior to this update, so that you don't have to re-run the AuthTokenGenerator.py script again.

  * Added service `remove_audiobook_favorites` to remove one or more audiobooks (or the currently playing audiobook) from the current user's 'Your Library' favorites.
  * Added service `remove_episode_favorites` to remove one or more show episodes (or the currently playing episode) from the current user's 'Your Library' favorites.
  * Added service `remove_show_favorites` to remove one or more shows (or the currently playing show) from the current user's 'Your Library' favorites.
  * Added service `save_audiobook_favorites` to save one or more audiobooks (or the currently playing audiobook) to the current user's 'Your Library' favorites.
  * Added service `save_episode_favorites` to save one or more show episodes (or the currently playing episode) to the current user's 'Your Library' favorites.
  * Added service `save_show_favorites` to save one or more shows (or the currently playing show) to the current user's 'Your Library' favorites.
  * Updated underlying `spotifywebapiPython` package requirement to version 1.0.86.
  • Loading branch information
thlucas1 committed Aug 20, 2024
1 parent f9fc000 commit 9fef192
Show file tree
Hide file tree
Showing 9 changed files with 917 additions and 100 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ Change are listed in reverse chronological order (newest to oldest).

<span class="changelog">

###### [ 1.0.52 ] - 2024/08/19

* Changed storage location of authorization Token Cache file to prevent data loss on version updates. The file was moved from `\config\custom_components\spotifyplus\data\tokens.json` to `\config\.storage\spotifyplus_tokens.json`, which will allow it to persist between version updates. Note that you can simply copy the Token Cache file from the old location to the new location prior to this update, so that you don't have to re-run the AuthTokenGenerator.py script again.
* Added service `remove_audiobook_favorites` to remove one or more audiobooks (or the currently playing audiobook) from the current user's 'Your Library' favorites.
* Added service `remove_episode_favorites` to remove one or more show episodes (or the currently playing episode) from the current user's 'Your Library' favorites.
* Added service `remove_show_favorites` to remove one or more shows (or the currently playing show) from the current user's 'Your Library' favorites.
* Added service `save_audiobook_favorites` to save one or more audiobooks (or the currently playing audiobook) to the current user's 'Your Library' favorites.
* Added service `save_episode_favorites` to save one or more show episodes (or the currently playing episode) to the current user's 'Your Library' favorites.
* Added service `save_show_favorites` to save one or more shows (or the currently playing show) to the current user's 'Your Library' favorites.
* Updated underlying `spotifywebapiPython` package requirement to version 1.0.86.

###### [ 1.0.51 ] - 2024/08/18

* Updated service `player_transfer_playback` to check Sonos transport status after transferring playback to the target device, and play / pause the transport as designated by the `play` argument.
Expand All @@ -19,7 +30,7 @@ Change are listed in reverse chronological order (newest to oldest).
###### [ 1.0.49 ] - 2024/08/16

* Updated service `zeroconf_device_connect` to correctly process Spotify Connect requests for token type `authorization_code` devices. This requires you to setup a seperate OAuth2 authorization access token outside of Home Assistant in order to activate these devices. This (currently) only affects Sonos devices, as they are the only manufacturer (that I am aware of) that implements the `authorization_code` token type. More information can be found in the [wiki documentation](https://github.com/thlucas1/homeassistantcomponent_spotifyplus/wiki/Device-Configuration-Options#oauth2-token-for-tokentypeauthorization_code-devices).
* Added service `get_spotify_connect_device` to Get information about a specific Spotify Connect player device, and (optionally) activate the device if it requires it.
* Added service `get_spotify_connect_device` to get information about a specific Spotify Connect player device, and (optionally) activate the device if it requires it.
* Updated service `player_resolve_device_id` with deprecated status, as the `get_spotify_connect_device` service offers the same (and more) functionality.
* Updated service descriptions for services that specify a `limit` argument.
* Added `sortResult` argument to the various services that return lists that can be sorted. If True (default), result items are sorted by name prior to returning to the caller; otherwise, results are left in the order that the Spotify Web API returned them.
Expand Down
150 changes: 148 additions & 2 deletions custom_components/spotifyplus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,14 @@
SERVICE_SPOTIFY_PLAYLIST_ITEMS_CLEAR:str = 'playlist_items_clear'
SERVICE_SPOTIFY_PLAYLIST_ITEMS_REMOVE:str = 'playlist_items_remove'
SERVICE_SPOTIFY_REMOVE_ALBUM_FAVORITES:str = 'remove_album_favorites'
SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES:str = 'remove_audiobook_favorites'
SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES:str = 'remove_episode_favorites'
SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES:str = 'remove_show_favorites'
SERVICE_SPOTIFY_REMOVE_TRACK_FAVORITES:str = 'remove_track_favorites'
SERVICE_SPOTIFY_SAVE_ALBUM_FAVORITES:str = 'save_album_favorites'
SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES:str = 'save_audiobook_favorites'
SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES:str = 'save_episode_favorites'
SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES:str = 'save_show_favorites'
SERVICE_SPOTIFY_SAVE_TRACK_FAVORITES:str = 'save_track_favorites'
SERVICE_SPOTIFY_SEARCH_ALBUMS:str = 'search_albums'
SERVICE_SPOTIFY_SEARCH_ARTISTS:str = 'search_artists'
Expand Down Expand Up @@ -558,6 +564,27 @@
}
)

SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
vol.Optional("ids"): cv.string,
}
)

SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
vol.Optional("ids"): cv.string,
}
)

SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
vol.Optional("ids"): cv.string,
}
)

SERVICE_SPOTIFY_REMOVE_TRACK_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
Expand All @@ -572,6 +599,27 @@
}
)

SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
vol.Optional("ids"): cv.string,
}
)

SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
vol.Optional("ids"): cv.string,
}
)

SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
vol.Optional("ids"): cv.string,
}
)

SERVICE_SPOTIFY_SAVE_TRACK_FAVORITES_SCHEMA = vol.Schema(
{
vol.Required("entity_id"): cv.entity_id,
Expand Down Expand Up @@ -966,6 +1014,27 @@ async def service_handle_spotify_command(service: ServiceCall) -> None:
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_remove_album_favorites, ids)

elif service.service == SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES:

# remove audiobook(s) from favorites.
ids = service.data.get("ids")
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_remove_audiobook_favorites, ids)

elif service.service == SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES:

# remove episode(s) from favorites.
ids = service.data.get("ids")
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_remove_episode_favorites, ids)

elif service.service == SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES:

# remove show(s) from favorites.
ids = service.data.get("ids")
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_remove_show_favorites, ids)

elif service.service == SERVICE_SPOTIFY_REMOVE_TRACK_FAVORITES:

# remove track(s) from favorites.
Expand All @@ -980,6 +1049,27 @@ async def service_handle_spotify_command(service: ServiceCall) -> None:
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_save_album_favorites, ids)

elif service.service == SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES:

# save audiobook(s) to favorites.
ids = service.data.get("ids")
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_save_audiobook_favorites, ids)

elif service.service == SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES:

# save episode(s) to favorites.
ids = service.data.get("ids")
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_save_episode_favorites, ids)

elif service.service == SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES:

# save show(s) to favorites.
ids = service.data.get("ids")
_logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name))
await hass.async_add_executor_job(entity.service_spotify_save_show_favorites, ids)

elif service.service == SERVICE_SPOTIFY_SAVE_TRACK_FAVORITES:

# save track(s) to favorites.
Expand Down Expand Up @@ -1910,6 +2000,33 @@ def _GetEntityFromServiceData(hass:HomeAssistant, service:ServiceCall, field_id:
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES, SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES,
service_handle_spotify_command,
schema=SERVICE_SPOTIFY_REMOVE_AUDIOBOOK_FAVORITES_SCHEMA,
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES, SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES,
service_handle_spotify_command,
schema=SERVICE_SPOTIFY_REMOVE_EPISODE_FAVORITES_SCHEMA,
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES, SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES,
service_handle_spotify_command,
schema=SERVICE_SPOTIFY_REMOVE_SHOW_FAVORITES_SCHEMA,
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_REMOVE_TRACK_FAVORITES, SERVICE_SPOTIFY_REMOVE_TRACK_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
Expand All @@ -1928,6 +2045,33 @@ def _GetEntityFromServiceData(hass:HomeAssistant, service:ServiceCall, field_id:
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES, SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES,
service_handle_spotify_command,
schema=SERVICE_SPOTIFY_SAVE_AUDIOBOOK_FAVORITES_SCHEMA,
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES, SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES,
service_handle_spotify_command,
schema=SERVICE_SPOTIFY_SAVE_EPISODE_FAVORITES_SCHEMA,
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES, SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES,
service_handle_spotify_command,
schema=SERVICE_SPOTIFY_SAVE_SHOW_FAVORITES_SCHEMA,
supports_response=SupportsResponse.NONE,
)

_logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_SAVE_TRACK_FAVORITES, SERVICE_SPOTIFY_SAVE_TRACK_FAVORITES_SCHEMA)
hass.services.async_register(
DOMAIN,
Expand Down Expand Up @@ -2255,17 +2399,19 @@ def _TokenUpdater() -> dict:

# create new spotify web api python client instance - "SpotifyClient()".
_logsi.LogVerbose("'%s': Component async_setup_entry is creating SpotifyClient instance" % entry.title)
tokenStorageDir:str = "%s/custom_components/%s/data" % (hass.config.config_dir, DOMAIN)
tokenStorageDir:str = "%s/.storage" % (hass.config.config_dir)
tokenStorageFile:str = "%s_tokens.json" % (DOMAIN)
spotifyClient:SpotifyClient = await hass.async_add_executor_job(
SpotifyClient,
None, # manager:PoolManager=None,
tokenStorageDir, # tokenStorageDir:str=None,
tokenStorageFile, # tokenStorageFile:str=None,
_TokenUpdater, # tokenUpdater:Callable=None,
zeroconf_instance, # zeroconfClient:Zeroconf=None,
entry.options.get(CONF_OPTION_DEVICE_USERNAME, None),
entry.options.get(CONF_OPTION_DEVICE_PASSWORD, None),
entry.options.get(CONF_OPTION_DEVICE_LOGINID, None),
)
)
_logsi.LogObject(SILevel.Verbose, "'%s': Component async_setup_entry spotifyClient object" % entry.title, spotifyClient)

# set spotify web api python token authorization from HA-managed OAuth2 session token.
Expand Down
6 changes: 4 additions & 2 deletions custom_components/spotifyplus/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,13 @@ async def async_oauth_create_entry(self, data:dict[str,Any]) -> FlowResult:

# create new spotify web api python client instance - "SpotifyClient()".
_logsi.LogVerbose("Creating SpotifyClient instance")
tokenStorageDir:str = "%s/custom_components/%s/data" % (self.hass.config.config_dir, DOMAIN)
tokenStorageDir:str = "%s/.storage" % (self.hass.config.config_dir, DOMAIN)
tokenStorageFile:str = "%s_tokens.json" % (DOMAIN)
spotifyClient:SpotifyClient = await self.hass.async_add_executor_job(
SpotifyClient,
None, # manager:PoolManager=None,
tokenStorageDir, # tokenStorageDir:str=None,
tokenStorageFile, # tokenStorageFile:str=None,
None, # tokenUpdater:Callable=None,
zeroconf_instance # zeroconfClient:Zeroconf=None,
)
Expand Down Expand Up @@ -403,7 +405,7 @@ async def async_step_init(self, user_input:dict[str,Any]=None) -> FlowResult:
device_default:str = self._Options.get(CONF_OPTION_DEVICE_DEFAULT, None)
_logsi.LogVerbose("'%s': OptionsFlow option '%s' - SELECTED value: '%s'" % (self._name, CONF_OPTION_DEVICE_DEFAULT, device_default))
device_loginid:str = self._Options.get(CONF_OPTION_DEVICE_LOGINID, None)
_logsi.LogVerbose("'%s': OptionsFlow option '%s' - SELECTED value: '%s'" % (self._name, CONF_OPTION_DEVICE_USERNAME, device_loginid))
_logsi.LogVerbose("'%s': OptionsFlow option '%s' - SELECTED value: '%s'" % (self._name, CONF_OPTION_DEVICE_LOGINID, device_loginid))
device_username:str = self._Options.get(CONF_OPTION_DEVICE_USERNAME, None)
_logsi.LogVerbose("'%s': OptionsFlow option '%s' - SELECTED value: '%s'" % (self._name, CONF_OPTION_DEVICE_USERNAME, device_username))

Expand Down
4 changes: 2 additions & 2 deletions custom_components/spotifyplus/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
"requests>=2.31.0",
"requests_oauthlib>=1.3.1",
"smartinspectPython>=3.0.33",
"spotifywebapiPython>=1.0.84",
"spotifywebapiPython>=1.0.86",
"urllib3>=1.21.1,<1.27",
"zeroconf>=0.132.2"
],
"version": "1.0.51",
"version": "1.0.52",
"zeroconf": [ "_spotify-connect._tcp.local." ]
}
Loading

0 comments on commit 9fef192

Please sign in to comment.