From f4ab736ed9608323f2ea8db4400fd87d5e1eb4aa Mon Sep 17 00:00:00 2001 From: Todd Lucas Date: Sun, 27 Oct 2024 14:29:27 -0500 Subject: [PATCH] [ 1.0.62 ] * Added service `get_track_recommendations` to get track recommendations for specified criteria. * Added the following extra state attribute: `sp_track_is_explicit` - denotes the nowplaying track contains explicit lyrics (true) or not (false). --- CHANGELOG.md | 5 + README.md | 4 +- custom_components/spotifyplus/__init__.py | 135 ++++++- custom_components/spotifyplus/manifest.json | 2 +- custom_components/spotifyplus/media_player.py | 381 +++++++++++++++++- custom_components/spotifyplus/services.yaml | 347 ++++++++++++++++ custom_components/spotifyplus/strings.json | 198 +++++++++ .../spotifyplus/translations/en.json | 198 +++++++++ 8 files changed, 1262 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f89707..89f7e6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ Change are listed in reverse chronological order (newest to oldest). +###### [ 1.0.62 ] - 2024/10/27 + + * Added service `get_track_recommendations` to get track recommendations for specified criteria. + * Added the following extra state attribute: `sp_track_is_explicit` - denotes the nowplaying track contains explicit lyrics (true) or not (false). + ###### [ 1.0.61 ] - 2024/10/22 * Added service `get_audiobook_chapters` to get Spotify catalog information about an audiobook's chapters. diff --git a/README.md b/README.md index 09dbbb3..2d637fd 100644 --- a/README.md +++ b/README.md @@ -75,11 +75,11 @@ Check out the [SmartInspect Logging Configuration wiki page](https://github.com/ ## Reporting a Problem -Submit a [Bug Report](https://github.com/thlucas1/homeassistantcomponent_spotifyplus/issues/new?assignees=&labels=Bug&projects=&template=bug.yml) to bring the issue to my attention. I receive a notification when a new issue is opened, and will do my best to address it in a prompt and professional manner. +Submit a [Bug Report](https://github.com/thlucas1/homeassistantcomponent_spotifyplus/issues/new?assignees=&labels=bug&projects=&template=bug.yml) to bring the issue to my attention. I receive a notification when a new issue is opened, and will do my best to address it in a prompt and professional manner. ## Request a New Feature -Do you have an idea for a new feature that could be added to the integration? Submit a [Feature Request](https://github.com/thlucas1/homeassistantcomponent_spotifyplus/issues/new?assignees=&labels=Feature%2BRequest&projects=&template=feature_request.yml) to get your idea into the queue. I receive a notification when a new request is opened, and will do my best to turn your idea into the latest and greatest feature. +Do you have an idea for a new feature that could be added to the integration? Submit a [Feature Request](https://github.com/thlucas1/homeassistantcomponent_spotifyplus/issues/new?assignees=&labels=enhancement&projects=&template=feature_request.yml) to get your idea into the queue. I receive a notification when a new request is opened, and will do my best to turn your idea into the latest and greatest feature. ## Contributions are welcome! diff --git a/custom_components/spotifyplus/__init__.py b/custom_components/spotifyplus/__init__.py index 09ce990..35e2c6f 100644 --- a/custom_components/spotifyplus/__init__.py +++ b/custom_components/spotifyplus/__init__.py @@ -127,6 +127,7 @@ SERVICE_SPOTIFY_GET_SPOTIFY_CONNECT_DEVICES:str = 'get_spotify_connect_devices' SERVICE_SPOTIFY_GET_TRACK:str = 'get_track' SERVICE_SPOTIFY_GET_TRACK_FAVORITES:str = 'get_track_favorites' +SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS:str = 'get_track_recommendations' SERVICE_SPOTIFY_GET_TRACKS_AUDIO_FEATURES:str = 'get_tracks_audio_features' SERVICE_SPOTIFY_GET_USERS_TOP_ARTISTS:str = 'get_users_top_artists' SERVICE_SPOTIFY_GET_USERS_TOP_TRACKS:str = 'get_users_top_tracks' @@ -544,6 +545,59 @@ } ) +SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS_SCHEMA = vol.Schema( + { + vol.Required("entity_id"): cv.entity_id, + vol.Optional("limit", default=20): vol.All(vol.Range(min=0,max=50)), + vol.Optional("market"): cv.string, + vol.Optional("seed_artists"): cv.string, + vol.Optional("seed_genres"): cv.string, + vol.Optional("seed_tracks"): cv.string, + vol.Optional("min_acousticness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_acousticness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_acousticness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_danceability", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_danceability", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_danceability", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_duration_ms", default=0): vol.All(vol.Range(min=0,max=999999999)), + vol.Optional("max_duration_ms", default=0): vol.All(vol.Range(min=0,max=999999999)), + vol.Optional("target_duration_ms", default=0): vol.All(vol.Range(min=0,max=999999999)), + vol.Optional("min_energy", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_energy", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_energy", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_instrumentalness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_instrumentalness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_instrumentalness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_key", default=0): vol.All(vol.Range(min=0,max=11)), + vol.Optional("max_key", default=0): vol.All(vol.Range(min=0,max=11)), + vol.Optional("target_key", default=0): vol.All(vol.Range(min=0,max=11)), + vol.Optional("min_liveness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_liveness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_liveness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_loudness", default=0): vol.All(vol.Range(min=-1000.0,max=1000.0)), + vol.Optional("max_loudness", default=0): vol.All(vol.Range(min=-1000.0,max=1000.0)), + vol.Optional("target_loudness", default=0): vol.All(vol.Range(min=-1000.0,max=1000.0)), + vol.Optional("min_mode", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_mode", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_mode", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_popularity", default=0): vol.All(vol.Range(min=0,max=100)), + vol.Optional("max_popularity", default=0): vol.All(vol.Range(min=0,max=100)), + vol.Optional("target_popularity", default=0): vol.All(vol.Range(min=0,max=100)), + vol.Optional("min_speechiness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_speechiness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_speechiness", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("min_tempo", default=0): vol.All(vol.Range(min=0,max=99999)), + vol.Optional("max_tempo", default=0): vol.All(vol.Range(min=0,max=99999)), + vol.Optional("target_tempo", default=0): vol.All(vol.Range(min=0,max=99999)), + vol.Optional("min_time_signature", default=0): vol.All(vol.Range(min=0,max=99999)), + vol.Optional("max_time_signature", default=0): vol.All(vol.Range(min=0,max=99999)), + vol.Optional("target_time_signature", default=0): vol.All(vol.Range(min=0,max=99999)), + vol.Optional("min_valence", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("max_valence", default=0): vol.All(vol.Range(min=0,max=1.0)), + vol.Optional("target_valence", default=0): vol.All(vol.Range(min=-0,max=1.0)), + } +) + SERVICE_SPOTIFY_GET_TRACKS_AUDIO_FEATURES_SCHEMA = vol.Schema( { vol.Required("entity_id"): cv.entity_id, @@ -1669,7 +1723,7 @@ async def service_handle_spotify_serviceresponse(service: ServiceCall) -> Servic elif service.service == SERVICE_SPOTIFY_GET_TRACK_FAVORITES: - # get spotify album favorites. + # get spotify track favorites. limit = service.data.get("limit") offset = service.data.get("offset") market = service.data.get("market") @@ -1678,6 +1732,76 @@ async def service_handle_spotify_serviceresponse(service: ServiceCall) -> Servic _logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name)) response = await hass.async_add_executor_job(entity.service_spotify_get_track_favorites, limit, offset, market, limit_total, sort_result) + elif service.service == SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS: + + # get spotify track recommendations. + limit = service.data.get("limit") + market = service.data.get("market") + seed_artists = service.data.get("seed_artists") + seed_genres = service.data.get("seed_genres") + seed_tracks = service.data.get("seed_tracks") + min_acousticness = service.data.get("min_acousticness") + max_acousticness = service.data.get("max_acousticness") + target_acousticness = service.data.get("target_acousticness") + min_danceability = service.data.get("min_danceability") + max_danceability = service.data.get("max_danceability") + target_danceability = service.data.get("target_danceability") + min_duration_ms = service.data.get("min_duration_ms") + max_duration_ms = service.data.get("max_duration_ms") + target_duration_ms = service.data.get("target_duration_ms") + min_energy = service.data.get("min_energy") + max_energy = service.data.get("max_energy") + target_energy = service.data.get("target_energy") + min_instrumentalness = service.data.get("min_instrumentalness") + max_instrumentalness = service.data.get("max_instrumentalness") + target_instrumentalness = service.data.get("target_instrumentalness") + min_key = service.data.get("min_key") + max_key = service.data.get("max_key") + target_key = service.data.get("target_key") + min_liveness = service.data.get("min_liveness") + max_liveness = service.data.get("max_liveness") + target_liveness = service.data.get("target_liveness") + min_loudness = service.data.get("min_loudness") + max_loudness = service.data.get("max_loudness") + target_loudness = service.data.get("target_loudness") + min_mode = service.data.get("min_mode") + max_mode = service.data.get("max_mode") + target_mode = service.data.get("target_mode") + min_popularity = service.data.get("min_popularity") + max_popularity = service.data.get("max_popularity") + target_popularity = service.data.get("target_popularity") + min_speechiness = service.data.get("min_speechiness") + max_speechiness = service.data.get("max_speechiness") + target_speechiness = service.data.get("target_speechiness") + min_tempo = service.data.get("min_tempo") + max_tempo = service.data.get("max_tempo") + target_tempo = service.data.get("target_tempo") + min_time_signature = service.data.get("min_time_signature") + max_time_signature = service.data.get("max_time_signature") + target_time_signature = service.data.get("target_time_signature") + min_valence = service.data.get("min_valence") + max_valence = service.data.get("max_valence") + target_valence = service.data.get("target_valence") + _logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name)) + response = await hass.async_add_executor_job( + entity.service_spotify_get_track_recommendations, + limit, market, + seed_artists, seed_genres, seed_tracks, + min_acousticness, max_acousticness, target_acousticness, + min_danceability, max_danceability, target_danceability, + min_duration_ms, max_duration_ms, target_duration_ms, + min_energy, max_energy, target_energy, + min_instrumentalness, max_instrumentalness, target_instrumentalness, + min_key, max_key, target_key, + min_liveness, max_liveness, target_liveness, + min_loudness, max_loudness, target_loudness, + min_mode, max_mode, target_mode, + min_popularity, max_popularity, target_popularity, + min_speechiness, max_speechiness, target_speechiness, + min_tempo, max_tempo, target_tempo, + min_time_signature, max_time_signature, target_time_signature, + min_valence, max_valence, target_valence) + elif service.service == SERVICE_SPOTIFY_GET_TRACKS_AUDIO_FEATURES: # get spotify album favorites. @@ -2308,6 +2432,15 @@ def _GetEntityFromServiceData(hass:HomeAssistant, service:ServiceCall, field_id: supports_response=SupportsResponse.ONLY, ) + _logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS, SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS_SCHEMA) + hass.services.async_register( + DOMAIN, + SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS, + service_handle_spotify_serviceresponse, + schema=SERVICE_SPOTIFY_GET_TRACK_RECOMMENDATIONS_SCHEMA, + supports_response=SupportsResponse.ONLY, + ) + _logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_GET_TRACKS_AUDIO_FEATURES, SERVICE_SPOTIFY_GET_TRACKS_AUDIO_FEATURES_SCHEMA) hass.services.async_register( DOMAIN, diff --git a/custom_components/spotifyplus/manifest.json b/custom_components/spotifyplus/manifest.json index 9bea5fa..b86ab63 100644 --- a/custom_components/spotifyplus/manifest.json +++ b/custom_components/spotifyplus/manifest.json @@ -22,6 +22,6 @@ "urllib3>=1.21.1,<1.27", "zeroconf>=0.132.2" ], - "version": "1.0.61", + "version": "1.0.62", "zeroconf": [ "_spotify-connect._tcp.local." ] } diff --git a/custom_components/spotifyplus/media_player.py b/custom_components/spotifyplus/media_player.py index b610514..b723a26 100644 --- a/custom_components/spotifyplus/media_player.py +++ b/custom_components/spotifyplus/media_player.py @@ -59,6 +59,7 @@ SpotifyConnectDevice, SpotifyConnectDevices, Track, + TrackRecommendations, TrackSaved, TrackPage, TrackPageSaved, @@ -137,6 +138,7 @@ ATTR_SPOTIFYPLUS_ITEM_TYPE = "sp_item_type" ATTR_SPOTIFYPLUS_PLAYLIST_NAME = "sp_playlist_name" ATTR_SPOTIFYPLUS_PLAYLIST_URI = "sp_playlist_uri" +ATTR_SPOTIFYPLUS_TRACK_IS_EXPLICIT = "sp_track_is_explicit" ATTR_SPOTIFYPLUS_USER_COUNTRY = "sp_user_country" ATTR_SPOTIFYPLUS_USER_DISPLAY_NAME = "sp_user_display_name" ATTR_SPOTIFYPLUS_USER_EMAIL = "sp_user_email" @@ -429,8 +431,7 @@ def extra_state_attributes(self) -> dict: attributes[ATTR_SPOTIFYPLUS_DEVICE_NAME] = ATTRVALUE_NO_DEVICE attributes[ATTR_SPOTIFYPLUS_DEVICE_IS_BRAND_SONOS] = False attributes[ATTR_SPOTIFYPLUS_ITEM_TYPE] = ATTRVALUE_UNKNOWN - # attributes[ATTR_SPOTIFYPLUS_PLAYLIST_NAME] = ATTRVALUE_UNKNOWN - # attributes[ATTR_SPOTIFYPLUS_PLAYLIST_URI] = ATTRVALUE_UNKNOWN + attributes[ATTR_SPOTIFYPLUS_TRACK_IS_EXPLICIT] = False attributes[ATTR_SPOTIFYPLUS_USER_COUNTRY] = ATTRVALUE_UNKNOWN attributes[ATTR_SPOTIFYPLUS_USER_DISPLAY_NAME] = ATTRVALUE_UNKNOWN attributes[ATTR_SPOTIFYPLUS_USER_EMAIL] = ATTRVALUE_UNKNOWN @@ -440,7 +441,7 @@ def extra_state_attributes(self) -> dict: self.data.spotifyClient.UserProfile.DisplayName - # get currently active device id. + # add currently active playstate information. if self._playerState is not None: if self._playerState.Device is not None: attributes[ATTR_SPOTIFYPLUS_DEVICE_ID] = self._playerState.Device.Id @@ -452,6 +453,10 @@ def extra_state_attributes(self) -> dict: attributes[ATTR_SPOTIFYPLUS_ITEM_TYPE] = self._playerState.ItemType if self._spotifyConnectDevice is not None: attributes[ATTR_SPOTIFYPLUS_DEVICE_IS_BRAND_SONOS] = self._spotifyConnectDevice.DeviceInfo.IsBrandSonos + if self._playerState.Item is not None: + track:Track = self._playerState.Item + if track.Explicit: + attributes[ATTR_SPOTIFYPLUS_TRACK_IS_EXPLICIT] = track.Explicit # add currently active playlist information. if self._playlist is not None: @@ -4530,7 +4535,7 @@ def service_spotify_get_track_favorites( Returns: A dictionary that contains the following keys: - user_profile: A (partial) user profile that retrieved the result. - - result: A `TrackPageSaved` object that contains playlist information. + - result: A `TrackPageSaved` object that contains track favorites. """ apiMethodName:str = 'service_spotify_get_track_favorites' apiMethodParms:SIMethodParmListContext = None @@ -4570,6 +4575,374 @@ def service_spotify_get_track_favorites( _logsi.LeaveMethod(SILevel.Debug, apiMethodName) + def service_spotify_get_track_recommendations( + self, + limit:int=20, + market:str=None, + seedArtists:str=None, + seedGenres:str=None, + seedTracks:str=None, + minAcousticness:float=None, maxAcousticness:float=None, targetAcousticness:float=None, + minDanceability:float=None, maxDanceability:float=None, targetDanceability:float=None, + minDurationMS:int=None, maxDurationMS:int=None, targetDurationMS:int=None, + minEnergy:float=None, maxEnergy:float=None, targetEnergy:float=None, + minInstrumentalness:float=None, maxInstrumentalness:float=None, targetInstrumentalness:float=None, + minKey:int=None, maxKey:int=None, targetKey:int=None, + minLiveness:float=None, maxLiveness:float=None, targetLiveness:float=None, + minLoudness:float=None, maxLoudness:float=None, targetLoudness:float=None, + minMode:float=None, maxMode:float=None, targetMode:float=None, + minPopularity:int=None, maxPopularity:int=None, targetPopularity:int=None, + minSpeechiness:float=None, maxSpeechiness:float=None, targetSpeechiness:float=None, + minTempo:int=None, maxTempo:int=None, targetTempo:int=None, + minTimeSignature:int=None, maxTimeSignature:int=None, targetTimeSignature:int=None, + minValence:float=None, maxValence:float=None, targetValence:float=None + ) -> dict: + """ + Get track recommendations for specified criteria. + + Args: + limit (int): + The maximum number of items to return in a page of items. + Default: 20, Range: 1 to 50. + market (str): + An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that + is available in that market will be returned. If a valid user access token is specified + in the request header, the country associated with the user account will take priority over + this parameter. + Note: If neither market or user country are provided, the content is considered unavailable for the client. + Users can view the country that is associated with their account in the account settings. + Example: `ES` + seedArtists (str): + A comma separated list of Spotify IDs for seed artists. + Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres. + Note: only required if seedGenres and seedTracks are not set. + Example: `4NHQUGzhtTLFvgF5SZesLK` + seedGenres (str): + A comma separated list of any genres in the set of available genre seeds. + Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres. + Note: only required if seedArtists and seedTracks are not set. + Example: `classical,country` + seedTracks (str): + A comma separated list of Spotify IDs for a seed track. + Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres. + Note: only required if seedArtists and seedGenres are not set. + Example: `0c6xIDDpzE81m2q797ordA` + minAcousticness (float): + Restrict results to only those tracks whose acousticness level is greater than the specified value. + Range: `0` - `1` + maxAcousticness (float): + Restrict results to only those tracks whose acousticness level is less than the specified value. + Range: `0` - `1` + targetAcousticness (float): + Restrict results to only those tracks whose acousticness level is equal to the specified value. + Range: `0` - `1` + minDanceability (float): + Restrict results to only those tracks whose danceability level is greater than the specified value. + Range: `0` - `1` + maxDanceability (float): + Restrict results to only those tracks whose danceability level is less than the specified value. + Range: `0` - `1` + targetDanceability (float): + Restrict results to only those tracks whose acousticness is equal to the specified value. + Range: `0` - `1` + minDurationMS (int): + Restrict results to only those tracks whose duration is greater than the specified value in milliseconds. + maxDurationMS (int): + Restrict results to only those tracks whose duration is less than the specified value in milliseconds. + targetDurationMS (int): + Restrict results to only those tracks whose duration is equal to the specified value in milliseconds. + minEnergy (float): + Restrict results to only those tracks whose energy level is greater than the specified value. + Range: `0` - `1` + maxEnergy (float): + Restrict results to only those tracks whose energy level is less than the specified value. + Range: `0` - `1` + targetEnergy (float): + Restrict results to only those tracks whose energy level is equal to the specified value. + Range: `0` - `1` + minInstrumentalness (float): + Restrict results to only those tracks whose instrumentalness level is greater than the specified value. + Range: `0` - `1` + maxInstrumentalness (float): + Restrict results to only those tracks whose instrumentalness level is less than the specified value. + Range: `0` - `1` + targetInstrumentalness (float): + Restrict results to only those tracks whose instrumentalness level is equal to the specified value. + Range: `0` - `1` + minKey (int): + Restrict results to only those tracks whose key level is greater than the specified value. + Range: `0` - `11` + maxKey (int): + Restrict results to only those tracks whose key level is less than the specified value. + Range: `0` - `11` + targetKey (int): + Restrict results to only those tracks whose key level is equal to the specified value. + Range: `0` - `11` + minLiveness (float): + Restrict results to only those tracks whose liveness level is greater than the specified value. + Range: `0` - `1` + maxLiveness (float): + Restrict results to only those tracks whose liveness level is less than the specified value. + Range: `0` - `1` + targetLiveness (float): + Restrict results to only those tracks whose liveness level is equal to the specified value. + Range: `0` - `1` + minLoudness (float): + Restrict results to only those tracks whose loudness level is greater than the specified value. + maxLoudness (float): + Restrict results to only those tracks whose loudness level is less than the specified value. + targetLoudness (float): + Restrict results to only those tracks whose loudness level is equal to the specified value. + minMode (float): + Restrict results to only those tracks whose mode level is greater than the specified value. + Range: `0` - `1` + maxMode (float): + Restrict results to only those tracks whose mode level is less than the specified value. + Range: `0` - `1` + targetMode (float): + Restrict results to only those tracks whose mode level is equal to the specified value. + Range: `0` - `1` + minPopularity (int): + Restrict results to only those tracks whose popularity level is greater than the specified value. + Range: `0` - `100` + maxPopularity (int): + Restrict results to only those tracks whose popularity level is less than the specified value. + Range: `0` - `100` + targetPopularity (int): + Restrict results to only those tracks whose popularity level is equal to the specified value. + Range: `0` - `100` + minSpeechiness (float): + Restrict results to only those tracks whose speechiness level is greater than the specified value. + Range: `0` - `1` + maxSpeechiness (float): + Restrict results to only those tracks whose speechiness level is less than the specified value. + Range: `0` - `1` + targetSpeechiness (float): + Restrict results to only those tracks whose speechiness level is equal to the specified value. + Range: `0` - `1` + minTempo (int): + Restrict results to only those tracks with a tempo greater than the specified number of beats per minute. + maxTempo (int): + Restrict results to only those tracks with a tempo less than the specified number of beats per minute. + targetTempo (int): + Restrict results to only those tracks with a tempo equal to the specified number of beats per minute. + minTimeSignature (int): + Restrict results to only those tracks whose time signature is greater than the specified value. + Maximum value: 11 + maxTimeSignature (int): + Restrict results to only those tracks whose time signature is less than the specified value. + targetTimeSignature (int): + Restrict results to only those tracks whose time signature is equal to the specified value. + minValence (float): + Restrict results to only those tracks whose valence level is greater than the specified value. + Range: `0` - `1` + maxValence (float): + Restrict results to only those tracks whose valence level is less than the specified value. + Range: `0` - `1` + targetValence (float): + Restrict results to only those tracks whose valence level is equal to the specified value. + Range: `0` - `1` + + Returns: + A dictionary that contains the following keys: + - user_profile: A (partial) user profile that retrieved the result. + - result: A `TrackRecommendations` object that contains track information. + """ + apiMethodName:str = 'service_spotify_get_track_recommendations' + apiMethodParms:SIMethodParmListContext = None + result:TrackRecommendations = TrackRecommendations() + + try: + + # trace. + apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName) + apiMethodParms.AppendKeyValue("limit", limit) + apiMethodParms.AppendKeyValue("market", market) + apiMethodParms.AppendKeyValue("seedArtists", seedArtists) + apiMethodParms.AppendKeyValue("seedGenres", seedGenres) + apiMethodParms.AppendKeyValue("seedTracks", seedTracks) + apiMethodParms.AppendKeyValue("minAcousticness", minAcousticness) + apiMethodParms.AppendKeyValue("maxAcousticness", maxAcousticness) + apiMethodParms.AppendKeyValue("targetAcousticness", targetAcousticness) + apiMethodParms.AppendKeyValue("minDanceability", minDanceability) + apiMethodParms.AppendKeyValue("maxDanceability", maxDanceability) + apiMethodParms.AppendKeyValue("targetDanceability", targetDanceability) + apiMethodParms.AppendKeyValue("minDurationMS", minDurationMS) + apiMethodParms.AppendKeyValue("maxDurationMS", maxDurationMS) + apiMethodParms.AppendKeyValue("targetDurationMS", targetDurationMS) + apiMethodParms.AppendKeyValue("minEnergy", minEnergy) + apiMethodParms.AppendKeyValue("maxEnergy", maxEnergy) + apiMethodParms.AppendKeyValue("targetEnergy", targetEnergy) + apiMethodParms.AppendKeyValue("minInstrumentalness", minInstrumentalness) + apiMethodParms.AppendKeyValue("maxInstrumentalness", maxInstrumentalness) + apiMethodParms.AppendKeyValue("targetInstrumentalness", targetInstrumentalness) + apiMethodParms.AppendKeyValue("minKey", minKey) + apiMethodParms.AppendKeyValue("maxKey", maxKey) + apiMethodParms.AppendKeyValue("targetKey", targetKey) + apiMethodParms.AppendKeyValue("minLiveness", minLiveness) + apiMethodParms.AppendKeyValue("maxLiveness", maxLiveness) + apiMethodParms.AppendKeyValue("targetLiveness", targetLiveness) + apiMethodParms.AppendKeyValue("minLoudness", minLoudness) + apiMethodParms.AppendKeyValue("maxLoudness", maxLoudness) + apiMethodParms.AppendKeyValue("targetLoudness", targetLoudness) + apiMethodParms.AppendKeyValue("minMode", minMode) + apiMethodParms.AppendKeyValue("maxMode", maxMode) + apiMethodParms.AppendKeyValue("targetMode", targetMode) + apiMethodParms.AppendKeyValue("minPopularity", minPopularity) + apiMethodParms.AppendKeyValue("maxPopularity", maxPopularity) + apiMethodParms.AppendKeyValue("targetPopularity", targetPopularity) + apiMethodParms.AppendKeyValue("minSpeechiness", minSpeechiness) + apiMethodParms.AppendKeyValue("maxSpeechiness", maxSpeechiness) + apiMethodParms.AppendKeyValue("targetSpeechiness", targetSpeechiness) + apiMethodParms.AppendKeyValue("minTempo", minTempo) + apiMethodParms.AppendKeyValue("maxTempo", maxTempo) + apiMethodParms.AppendKeyValue("targetTempo", targetTempo) + apiMethodParms.AppendKeyValue("minTimeSignature", minTimeSignature) + apiMethodParms.AppendKeyValue("maxTimeSignature", maxTimeSignature) + apiMethodParms.AppendKeyValue("targetTimeSignature", targetTimeSignature) + apiMethodParms.AppendKeyValue("minValence", minValence) + apiMethodParms.AppendKeyValue("maxValence", maxValence) + apiMethodParms.AppendKeyValue("targetValence", targetValence) + _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Get Track Recommendations Service", apiMethodParms) + + # reset default values to None so they are processed correctly by the api. + if minAcousticness == 0: + minAcousticness = None + if maxAcousticness == 0: + maxAcousticness = None + if targetAcousticness == 0: + targetAcousticness = None + + if minDanceability == 0: + minDanceability = None + if maxDanceability == 0: + maxDanceability = None + if targetDanceability == 0: + targetDanceability = None + + if minDurationMS == 0: + minDurationMS = None + if maxDurationMS == 0: + maxDurationMS = None + if targetDurationMS == 0: + targetDurationMS = None + + if minEnergy == 0: + minEnergy = None + if maxEnergy == 0: + maxEnergy = None + if targetEnergy == 0: + targetEnergy = None + + if minInstrumentalness == 0: + minInstrumentalness = None + if maxInstrumentalness == 0: + maxInstrumentalness = None + if targetInstrumentalness == 0: + targetInstrumentalness = None + + if minKey == 0: + minKey = None + if maxKey == 0: + maxKey = None + if targetKey == 0: + targetKey = None + + if minLiveness == 0: + minLiveness = None + if maxLiveness == 0: + maxLiveness = None + if targetLiveness == 0: + targetLiveness = None + + if minLoudness == 0: + minLoudness = None + if maxLoudness == 0: + maxLoudness = None + if targetLoudness == 0: + targetLoudness = None + + if minMode == 0: + minMode = None + if maxMode == 0: + maxMode = None + if targetMode == 0: + targetMode = None + + if minPopularity == 0: + minPopularity = None + if maxPopularity == 0: + maxPopularity = None + if targetPopularity == 0: + targetPopularity = None + + if minSpeechiness == 0: + minSpeechiness = None + if maxSpeechiness == 0: + maxSpeechiness = None + if targetSpeechiness == 0: + targetSpeechiness = None + + if minTempo == 0: + minTempo = None + if maxTempo == 0: + maxTempo = None + if targetTempo == 0: + targetTempo = None + + if minTimeSignature == 0: + minTimeSignature = None + if maxTimeSignature == 0: + maxTimeSignature = None + if targetTimeSignature == 0: + targetTimeSignature = None + + if minValence == 0: + minValence = None + if maxValence == 0: + maxValence = None + if targetValence == 0: + targetValence = None + + # request information from Spotify Web API. + _logsi.LogVerbose(STAppMessages.MSG_SERVICE_QUERY_WEB_API) + result:TrackPageSaved = self.data.spotifyClient.GetTrackRecommendations( + limit, market, + seedArtists, seedGenres, seedTracks, + minAcousticness, maxAcousticness, targetAcousticness, + minDanceability, maxDanceability, targetDanceability, + minDurationMS, maxDurationMS, targetDurationMS, + minEnergy, maxEnergy, targetEnergy, + minInstrumentalness, maxInstrumentalness, targetInstrumentalness, + minKey, maxKey, targetKey, + minLiveness, maxLiveness, targetLiveness, + minLoudness, maxLoudness, targetLoudness, + minMode, maxMode, targetMode, + minPopularity, maxPopularity, targetPopularity, + minSpeechiness, maxSpeechiness, targetSpeechiness, + minTempo, maxTempo, targetTempo, + minTimeSignature, maxTimeSignature, targetTimeSignature, + minValence, maxValence, targetValence) + + # return the (partial) user profile that retrieved the result, as well as the result itself. + return { + "user_profile": self._GetUserProfilePartialDictionary(self.data.spotifyClient.UserProfile), + "result": result.ToDictionary() + } + + # the following exceptions have already been logged, so we just need to + # pass them back to HA for display in the log (or service UI). + except SpotifyApiError as ex: + raise HomeAssistantError(ex.Message) + except SpotifyWebApiError as ex: + raise HomeAssistantError(ex.Message) + + finally: + + # trace. + _logsi.LeaveMethod(SILevel.Debug, apiMethodName) + + def service_spotify_get_tracks_audio_features( self, ids:str, diff --git a/custom_components/spotifyplus/services.yaml b/custom_components/spotifyplus/services.yaml index 801ebd7..2469d8e 100644 --- a/custom_components/spotifyplus/services.yaml +++ b/custom_components/spotifyplus/services.yaml @@ -1571,6 +1571,353 @@ get_track_favorites: selector: boolean: +get_track_recommendations: + name: Get Track Recommendations + description: Get track recommendations for specified criteria. + fields: + entity_id: + name: Entity ID + description: Entity ID of the SpotifyPlus device that will make the request to the Spotify Web API. + example: "media_player.spotifyplus_username" + required: true + selector: + entity: + integration: spotifyplus + domain: media_player + limit: + name: Limit + description: The maximum number of items to return in a page of items. Default is 20, Range is 1 to 50. + example: 20 + required: false + selector: + number: + min: 1 + max: 50 + mode: box + market: + name: Market / Country Code + description: An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that is available in that market will be returned. The country associated with the Spotify user account will take priority over this parameter. + example: "ES" + required: false + selector: + text: + seed_artists: + name: Seed Artists + description: A comma separated list of Spotify IDs for seed artists (e.g. 4NHQUGzhtTLFvgF5SZesLK). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedGenres and seedTracks are not set. + required: false + selector: + text: + seed_genres: + name: Seed Genres + description: A comma separated list of any genres in the set of available genre seeds (e.g. rock,hard-rock,rock-n-roll). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedArtists and seedTracks are not set. + example: "rock,hard-rock,rock-n-roll" + required: false + selector: + text: + seed_tracks: + name: Seed Tracks + description: A comma separated list of Spotify IDs for a seed track (e.g. 0c6xIDDpzE81m2q797ordA). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedArtists and seedGenres are not set. + required: false + selector: + text: + min_acousticness: + name: Minimum Acousticness + description: Restrict results to only those tracks whose acousticness level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_acousticness: + name: Maximum Acousticness + description: Restrict results to only those tracks whose acousticness level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_acousticness: + name: Target Acousticness + description: Restrict results to only those tracks whose acousticness level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_danceability: + name: Minimum Danceability + description: Restrict results to only those tracks whose danceability level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_danceability: + name: Maximum Danceability + description: Restrict results to only those tracks whose danceability level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_danceability: + name: Target Danceability + description: Restrict results to only those tracks whose acousticness is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_duration_ms: + name: Minimum Duration MS + description: Restrict results to only those tracks whose duration is greater than the specified value in milliseconds. + required: false + selector: + number: + mode: box + max_duration_ms: + name: Maximum Duration MS + description: Restrict results to only those tracks whose duration is less than the specified value in milliseconds. + required: false + selector: + number: + mode: box + target_duration_ms: + name: Target Duration MS + description: Restrict results to only those tracks whose duration is equal to the specified value in milliseconds. + required: false + selector: + number: + mode: box + min_energy: + name: Minimum Energy + description: Restrict results to only those tracks whose energy level is greater than the specified value. Range is `0` - `1`. + example: 0.975 + required: false + selector: + number: + mode: box + max_energy: + name: Maximum Energy + description: Restrict results to only those tracks whose energy level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_energy: + name: Target Energy + description: Restrict results to only those tracks whose energy level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_instrumentalness: + name: Minimum Instrumentalness + description: Restrict results to only those tracks whose instrumentalness level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_instrumentalness: + name: Maximum Instrumentalness + description: Restrict results to only those tracks whose instrumentalness level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_instrumentalness: + name: Target Instrumentalness + description: Restrict results to only those tracks whose instrumentalness level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_key: + name: Minimum Key + description: Restrict results to only those tracks whose key level is greater than the specified value. Range is `0` - `11`. + required: false + selector: + number: + mode: box + max_key: + name: Maximum Key + description: Restrict results to only those tracks whose key level is less than the specified value. Range is `0` - `11`. + required: false + selector: + number: + mode: box + target_key: + name: Target Key + description: Restrict results to only those tracks whose key level is equal to the specified value. Range is `0` - `11`. + required: false + selector: + number: + mode: box + min_liveness: + name: Minimum Liveness + description: Restrict results to only those tracks whose liveness level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_liveness: + name: Maximum Liveness + description: Restrict results to only those tracks whose liveness level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_liveness: + name: Target Liveness + description: Restrict results to only those tracks whose liveness level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_loudness: + name: Minimum Loudness + description: Restrict results to only those tracks whose loudness level is greater than the specified value. + example: -9.201 + required: false + selector: + number: + mode: box + max_loudness: + name: Maximum Loudness + description: Restrict results to only those tracks whose loudness level is less than the specified value. + required: false + selector: + number: + mode: box + target_loudness: + name: Target Loudness + description: Restrict results to only those tracks whose loudness level is equal to the specified value. + required: false + selector: + number: + mode: box + min_mode: + name: Minimum Mode + description: Restrict results to only those tracks whose mode level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_mode: + name: Maximum Mode + description: Restrict results to only those tracks whose mode level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_mode: + name: Target Mode + description: Restrict results to only those tracks whose mode level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_popularity: + name: Minimum Popularity + description: Restrict results to only those tracks whose popularity level is greater than the specified value. Range is `0` - `100`. + required: false + selector: + number: + mode: box + max_popularity: + name: Maximum Popularity + description: Restrict results to only those tracks whose popularity level is less than the specified value. Range is `0` - `100`. + required: false + selector: + number: + mode: box + target_popularity: + name: Target Popularity + description: Restrict results to only those tracks whose popularity level is equal to the specified value. Range is `0` - `100`. + required: false + selector: + number: + mode: box + min_speechiness: + name: Minimum Speechiness + description: Restrict results to only those tracks whose speechiness level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_speechiness: + name: Maximum Speechiness + description: Restrict results to only those tracks whose speechiness level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_speechiness: + name: Target Speechiness + description: Restrict results to only those tracks whose speechiness level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + min_tempo: + name: Minimum Tempo + description: Restrict results to only those tracks with a tempo greater than the specified number of beats per minute. + required: false + selector: + number: + mode: box + max_tempo: + name: Maximum Tempo + description: Restrict results to only those tracks with a tempo less than the specified number of beats per minute. + required: false + selector: + number: + mode: box + target_tempo: + name: Target Tempo + description: Restrict results to only those tracks with a tempo equal to the specified number of beats per minute. + required: false + selector: + number: + mode: box + min_time_signature: + name: Minimum Time Signature + description: Restrict results to only those tracks whose time signature is greater than the specified value. Range is `0` - `11`. + example: 4 + required: false + selector: + number: + mode: box + max_time_signature: + name: Maximum Time Signature + description: Restrict results to only those tracks whose time signature is less than the specified value. Range is `0` - `11`. + required: false + selector: + number: + mode: box + target_time_signature: + name: Target Time Signature + description: Restrict results to only those tracks whose time signature is equal to the specified value. Range is `0` - `11`. + required: false + selector: + number: + mode: box + min_valence: + name: Minimum Valence + description: Restrict results to only those tracks whose valence level is greater than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + max_valence: + name: Maximum Valence + description: Restrict results to only those tracks whose valence level is less than the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + target_valence: + name: Target Valence + description: Restrict results to only those tracks whose valence level is equal to the specified value. Range is `0` - `1`. + required: false + selector: + number: + mode: box + get_tracks_audio_features: name: Get Tracks Audio Features description: Get audio features for multiple tracks based on their Spotify IDs. diff --git a/custom_components/spotifyplus/strings.json b/custom_components/spotifyplus/strings.json index 7d95938..8353991 100644 --- a/custom_components/spotifyplus/strings.json +++ b/custom_components/spotifyplus/strings.json @@ -976,6 +976,204 @@ } } }, + "get_track_recommendations": { + "name": "Get Track Recommendations", + "description": "Get track recommendations for specified criteria.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Entity ID of the SpotifyPlus device that will make the request to the Spotify Web API." + }, + "limit": { + "name": "Limit", + "description": "The maximum number of items to return in a page of items when manual paging is used. Default is 20, Range is 1 to 50. See the limit_total argument for automatic paging option." + }, + "market": { + "name": "Market / Country Code", + "description": "An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that is available in that market will be returned. The country associated with the user account will take priority over this parameter." + }, + "seed_artists": { + "name": "Seed Artists", + "description": "A comma separated list of Spotify IDs for seed artists (e.g. 4NHQUGzhtTLFvgF5SZesLK). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedGenres and seedTracks are not set." + }, + "seed_genres": { + "name": "Seed Genres", + "description": "A comma separated list of any genres in the set of available genre seeds (e.g. classical,country). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedArtists and seedTracks are not set." + }, + "seed_tracks": { + "name": "Seed Tracks", + "description": "A comma separated list of Spotify IDs for a seed track (e.g. 0c6xIDDpzE81m2q797ordA). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedArtists and seedGenres are not set." + }, + "min_acousticness": { + "name": "Minimum Acousticness", + "description": "Restrict results to only those tracks whose acousticness level is greater than the specified value. Range is `0` - `1`." + }, + "max_acousticness": { + "name": "Maximum Acousticness", + "description": "Restrict results to only those tracks whose acousticness level is less than the specified value. Range is `0` - `1`." + }, + "target_acousticness": { + "name": "Target Acousticness", + "description": "Restrict results to only those tracks whose acousticness level is equal to the specified value. Range is `0` - `1`." + }, + "min_danceability": { + "name": "Minimum Danceability", + "description": "Restrict results to only those tracks whose danceability level is greater than the specified value. Range is `0` - `1`." + }, + "max_danceability": { + "name": "Maximum Danceability", + "description": "Restrict results to only those tracks whose danceability level is less than the specified value. Range is `0` - `1`." + }, + "target_danceability": { + "name": "Target Danceability", + "description": "Restrict results to only those tracks whose acousticness is equal to the specified value. Range is `0` - `1`." + }, + "min_duration_ms": { + "name": "Minimum Duration MS", + "description": "Restrict results to only those tracks whose duration is greater than the specified value in milliseconds." + }, + "max_duration_ms": { + "name": "Maximum Duration MS", + "description": "Restrict results to only those tracks whose duration is less than the specified value in milliseconds." + }, + "target_duration_ms": { + "name": "Target Duration MS", + "description": "Restrict results to only those tracks whose duration is equal to the specified value in milliseconds." + }, + "min_energy": { + "name": "Minimum Energy", + "description": "Restrict results to only those tracks whose energy level is greater than the specified value. Range is `0` - `1`." + }, + "max_energy": { + "name": "Maximum Energy", + "description": "Restrict results to only those tracks whose energy level is less than the specified value. Range is `0` - `1`." + }, + "target_energy": { + "name": "Target Energy", + "description": "Restrict results to only those tracks whose energy level is equal to the specified value. Range is `0` - `1`." + }, + "min_instrumentalness": { + "name": "Minimum Instrumentalness", + "description": "Restrict results to only those tracks whose instrumentalness level is greater than the specified value. Range is `0` - `1`." + }, + "max_instrumentalness": { + "name": "Maximum Instrumentalness", + "description": "Restrict results to only those tracks whose instrumentalness level is less than the specified value. Range is `0` - `1`." + }, + "target_instrumentalness": { + "name": "Target Instrumentalness", + "description": "Restrict results to only those tracks whose instrumentalness level is equal to the specified value. Range is `0` - `1`." + }, + "min_key": { + "name": "Minimum Key", + "description": "Restrict results to only those tracks whose key level is greater than the specified value. Range is `0` - `11`." + }, + "max_key": { + "name": "Maximum Key", + "description": "Restrict results to only those tracks whose key level is less than the specified value. Range is `0` - `11`." + }, + "target_key": { + "name": "Target Key", + "description": "Restrict results to only those tracks whose key level is equal to the specified value. Range is `0` - `11`." + }, + "min_liveness": { + "name": "Minimum Liveness", + "description": "Restrict results to only those tracks whose liveness level is greater than the specified value. Range is `0` - `1`." + }, + "max_liveness": { + "name": "Maximum Liveness", + "description": "Restrict results to only those tracks whose liveness level is less than the specified value. Range is `0` - `1`." + }, + "target_liveness": { + "name": "Target Liveness", + "description": "Restrict results to only those tracks whose liveness level is equal to the specified value. Range is `0` - `1`." + }, + "min_loudness": { + "name": "Minimum Loudness", + "description": "Restrict results to only those tracks whose loudness level is greater than the specified value." + }, + "max_loudness": { + "name": "Maximum Loudness", + "description": "Restrict results to only those tracks whose loudness level is less than the specified value." + }, + "target_loudness": { + "name": "Target Loudness", + "description": "Restrict results to only those tracks whose loudness level is equal to the specified value." + }, + "min_mode": { + "name": "Minimum Mode", + "description": "Restrict results to only those tracks whose mode level is greater than the specified value. Range is `0` - `1`." + }, + "max_mode": { + "name": "Maximum Mode", + "description": "Restrict results to only those tracks whose mode level is less than the specified value. Range is `0` - `1`." + }, + "target_mode": { + "name": "Target Mode", + "description": "Restrict results to only those tracks whose mode level is equal to the specified value. Range is `0` - `1`." + }, + "min_popularity": { + "name": "Minimum Popularity", + "description": "Restrict results to only those tracks whose popularity level is greater than the specified value. Range is `0` - `100`." + }, + "max_popularity": { + "name": "Maximum Popularity", + "description": "Restrict results to only those tracks whose popularity level is less than the specified value. Range is `0` - `100`." + }, + "target_popularity": { + "name": "Target Popularity", + "description": "Restrict results to only those tracks whose popularity level is equal to the specified value. Range is `0` - `100`." + }, + "min_speechiness": { + "name": "Minimum Speechiness", + "description": "Restrict results to only those tracks whose speechiness level is greater than the specified value. Range is `0` - `1`." + }, + "max_speechiness": { + "name": "Maximum Speechiness", + "description": "Restrict results to only those tracks whose speechiness level is less than the specified value. Range is `0` - `1`." + }, + "target_speechiness": { + "name": "Target Speechiness", + "description": "Restrict results to only those tracks whose speechiness level is equal to the specified value. Range is `0` - `1`." + }, + "min_tempo": { + "name": "Minimum Tempo", + "description": "Restrict results to only those tracks with a tempo greater than the specified number of beats per minute." + }, + "max_tempo": { + "name": "Maximum Tempo", + "description": "Restrict results to only those tracks with a tempo less than the specified number of beats per minute." + }, + "target_tempo": { + "name": "Target Tempo", + "description": "Restrict results to only those tracks with a tempo equal to the specified number of beats per minute." + }, + "min_time_signature": { + "name": "Minimum Time Signature", + "description": "Restrict results to only those tracks whose time signature is greater than the specified value. Range is `0` - `11`." + }, + "max_time_signature": { + "name": "Maximum Time Signature", + "description": "Restrict results to only those tracks whose time signature is less than the specified value. Range is `0` - `11`." + }, + "target_time_signature": { + "name": "Target Time Signature", + "description": "Restrict results to only those tracks whose time signature is equal to the specified value. Range is `0` - `11`." + }, + "min_valence": { + "name": "Minimum Valence", + "description": "Restrict results to only those tracks whose valence level is greater than the specified value. Range is `0` - `1`." + }, + "max_valence": { + "name": "Maximum Valence", + "description": "Restrict results to only those tracks whose valence level is less than the specified value. Range is `0` - `1`." + }, + "target_valence": { + "name": "Target Valence", + "description": "Restrict results to only those tracks whose valence level is equal to the specified value. Range is `0` - `1`." + } + } + }, "get_tracks_audio_features": { "name": "Get Tracks Audio Features", "description": "Get audio features for multiple tracks based on their Spotify IDs.", diff --git a/custom_components/spotifyplus/translations/en.json b/custom_components/spotifyplus/translations/en.json index 7d95938..8353991 100644 --- a/custom_components/spotifyplus/translations/en.json +++ b/custom_components/spotifyplus/translations/en.json @@ -976,6 +976,204 @@ } } }, + "get_track_recommendations": { + "name": "Get Track Recommendations", + "description": "Get track recommendations for specified criteria.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Entity ID of the SpotifyPlus device that will make the request to the Spotify Web API." + }, + "limit": { + "name": "Limit", + "description": "The maximum number of items to return in a page of items when manual paging is used. Default is 20, Range is 1 to 50. See the limit_total argument for automatic paging option." + }, + "market": { + "name": "Market / Country Code", + "description": "An ISO 3166-1 alpha-2 country code. If a country code is specified, only content that is available in that market will be returned. The country associated with the user account will take priority over this parameter." + }, + "seed_artists": { + "name": "Seed Artists", + "description": "A comma separated list of Spotify IDs for seed artists (e.g. 4NHQUGzhtTLFvgF5SZesLK). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedGenres and seedTracks are not set." + }, + "seed_genres": { + "name": "Seed Genres", + "description": "A comma separated list of any genres in the set of available genre seeds (e.g. classical,country). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedArtists and seedTracks are not set." + }, + "seed_tracks": { + "name": "Seed Tracks", + "description": "A comma separated list of Spotify IDs for a seed track (e.g. 0c6xIDDpzE81m2q797ordA). Up to 5 seed values may be provided in any combination of seedArtists, seedTracks and seedGenres; only required if seedArtists and seedGenres are not set." + }, + "min_acousticness": { + "name": "Minimum Acousticness", + "description": "Restrict results to only those tracks whose acousticness level is greater than the specified value. Range is `0` - `1`." + }, + "max_acousticness": { + "name": "Maximum Acousticness", + "description": "Restrict results to only those tracks whose acousticness level is less than the specified value. Range is `0` - `1`." + }, + "target_acousticness": { + "name": "Target Acousticness", + "description": "Restrict results to only those tracks whose acousticness level is equal to the specified value. Range is `0` - `1`." + }, + "min_danceability": { + "name": "Minimum Danceability", + "description": "Restrict results to only those tracks whose danceability level is greater than the specified value. Range is `0` - `1`." + }, + "max_danceability": { + "name": "Maximum Danceability", + "description": "Restrict results to only those tracks whose danceability level is less than the specified value. Range is `0` - `1`." + }, + "target_danceability": { + "name": "Target Danceability", + "description": "Restrict results to only those tracks whose acousticness is equal to the specified value. Range is `0` - `1`." + }, + "min_duration_ms": { + "name": "Minimum Duration MS", + "description": "Restrict results to only those tracks whose duration is greater than the specified value in milliseconds." + }, + "max_duration_ms": { + "name": "Maximum Duration MS", + "description": "Restrict results to only those tracks whose duration is less than the specified value in milliseconds." + }, + "target_duration_ms": { + "name": "Target Duration MS", + "description": "Restrict results to only those tracks whose duration is equal to the specified value in milliseconds." + }, + "min_energy": { + "name": "Minimum Energy", + "description": "Restrict results to only those tracks whose energy level is greater than the specified value. Range is `0` - `1`." + }, + "max_energy": { + "name": "Maximum Energy", + "description": "Restrict results to only those tracks whose energy level is less than the specified value. Range is `0` - `1`." + }, + "target_energy": { + "name": "Target Energy", + "description": "Restrict results to only those tracks whose energy level is equal to the specified value. Range is `0` - `1`." + }, + "min_instrumentalness": { + "name": "Minimum Instrumentalness", + "description": "Restrict results to only those tracks whose instrumentalness level is greater than the specified value. Range is `0` - `1`." + }, + "max_instrumentalness": { + "name": "Maximum Instrumentalness", + "description": "Restrict results to only those tracks whose instrumentalness level is less than the specified value. Range is `0` - `1`." + }, + "target_instrumentalness": { + "name": "Target Instrumentalness", + "description": "Restrict results to only those tracks whose instrumentalness level is equal to the specified value. Range is `0` - `1`." + }, + "min_key": { + "name": "Minimum Key", + "description": "Restrict results to only those tracks whose key level is greater than the specified value. Range is `0` - `11`." + }, + "max_key": { + "name": "Maximum Key", + "description": "Restrict results to only those tracks whose key level is less than the specified value. Range is `0` - `11`." + }, + "target_key": { + "name": "Target Key", + "description": "Restrict results to only those tracks whose key level is equal to the specified value. Range is `0` - `11`." + }, + "min_liveness": { + "name": "Minimum Liveness", + "description": "Restrict results to only those tracks whose liveness level is greater than the specified value. Range is `0` - `1`." + }, + "max_liveness": { + "name": "Maximum Liveness", + "description": "Restrict results to only those tracks whose liveness level is less than the specified value. Range is `0` - `1`." + }, + "target_liveness": { + "name": "Target Liveness", + "description": "Restrict results to only those tracks whose liveness level is equal to the specified value. Range is `0` - `1`." + }, + "min_loudness": { + "name": "Minimum Loudness", + "description": "Restrict results to only those tracks whose loudness level is greater than the specified value." + }, + "max_loudness": { + "name": "Maximum Loudness", + "description": "Restrict results to only those tracks whose loudness level is less than the specified value." + }, + "target_loudness": { + "name": "Target Loudness", + "description": "Restrict results to only those tracks whose loudness level is equal to the specified value." + }, + "min_mode": { + "name": "Minimum Mode", + "description": "Restrict results to only those tracks whose mode level is greater than the specified value. Range is `0` - `1`." + }, + "max_mode": { + "name": "Maximum Mode", + "description": "Restrict results to only those tracks whose mode level is less than the specified value. Range is `0` - `1`." + }, + "target_mode": { + "name": "Target Mode", + "description": "Restrict results to only those tracks whose mode level is equal to the specified value. Range is `0` - `1`." + }, + "min_popularity": { + "name": "Minimum Popularity", + "description": "Restrict results to only those tracks whose popularity level is greater than the specified value. Range is `0` - `100`." + }, + "max_popularity": { + "name": "Maximum Popularity", + "description": "Restrict results to only those tracks whose popularity level is less than the specified value. Range is `0` - `100`." + }, + "target_popularity": { + "name": "Target Popularity", + "description": "Restrict results to only those tracks whose popularity level is equal to the specified value. Range is `0` - `100`." + }, + "min_speechiness": { + "name": "Minimum Speechiness", + "description": "Restrict results to only those tracks whose speechiness level is greater than the specified value. Range is `0` - `1`." + }, + "max_speechiness": { + "name": "Maximum Speechiness", + "description": "Restrict results to only those tracks whose speechiness level is less than the specified value. Range is `0` - `1`." + }, + "target_speechiness": { + "name": "Target Speechiness", + "description": "Restrict results to only those tracks whose speechiness level is equal to the specified value. Range is `0` - `1`." + }, + "min_tempo": { + "name": "Minimum Tempo", + "description": "Restrict results to only those tracks with a tempo greater than the specified number of beats per minute." + }, + "max_tempo": { + "name": "Maximum Tempo", + "description": "Restrict results to only those tracks with a tempo less than the specified number of beats per minute." + }, + "target_tempo": { + "name": "Target Tempo", + "description": "Restrict results to only those tracks with a tempo equal to the specified number of beats per minute." + }, + "min_time_signature": { + "name": "Minimum Time Signature", + "description": "Restrict results to only those tracks whose time signature is greater than the specified value. Range is `0` - `11`." + }, + "max_time_signature": { + "name": "Maximum Time Signature", + "description": "Restrict results to only those tracks whose time signature is less than the specified value. Range is `0` - `11`." + }, + "target_time_signature": { + "name": "Target Time Signature", + "description": "Restrict results to only those tracks whose time signature is equal to the specified value. Range is `0` - `11`." + }, + "min_valence": { + "name": "Minimum Valence", + "description": "Restrict results to only those tracks whose valence level is greater than the specified value. Range is `0` - `1`." + }, + "max_valence": { + "name": "Maximum Valence", + "description": "Restrict results to only those tracks whose valence level is less than the specified value. Range is `0` - `1`." + }, + "target_valence": { + "name": "Target Valence", + "description": "Restrict results to only those tracks whose valence level is equal to the specified value. Range is `0` - `1`." + } + } + }, "get_tracks_audio_features": { "name": "Get Tracks Audio Features", "description": "Get audio features for multiple tracks based on their Spotify IDs.",