diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b3e50..9605245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ Change are listed in reverse chronological order (newest to oldest). +###### [ 1.0.60 ] - 2024/10/04 + + * Added service `player_media_seek` to seek to the given absolute or relative position in the user's currently playing track for the specified Spotify Connect device. + * Updated service `get_show_favorites` to include the `exclude_audiobooks` argument, which allows you to limit the results to only podcast items (by default). For some reason, the Spotify Web API returns both audiobook and podcast items. + * Updated Spotify Connect device processing to only require the userid and password configuration options when authenticating to devices that require user and password values. Some devices only require a loginid value (e.g. spotifyd, Spotify Connect AddOn, librespot, Sonos, etc). The user should not have to specify userid and password options if they are not required! + * Updated service description strings to correct HASSFest validation errors on GitHub. + * Updated underlying `spotifywebapiPython` package requirement to version 1.0.106. + ###### [ 1.0.59 ] - 2024/09/28 * Added support for devices that utilize spotifyd / librespot. See the [wiki documentation](https://github.com/thlucas1/homeassistantcomponent_spotifyplus/wiki/Device-Configuration-Options#librespot-and-spotifyd-device-support) for more information on how to configure support for spotifyD / librespot applications. diff --git a/custom_components/spotifyplus/__init__.py b/custom_components/spotifyplus/__init__.py index 316811c..db37bbf 100644 --- a/custom_components/spotifyplus/__init__.py +++ b/custom_components/spotifyplus/__init__.py @@ -128,6 +128,7 @@ SERVICE_SPOTIFY_PLAYER_MEDIA_PLAY_CONTEXT:str = 'player_media_play_context' SERVICE_SPOTIFY_PLAYER_MEDIA_PLAY_TRACK_FAVORITES:str = 'player_media_play_track_favorites' SERVICE_SPOTIFY_PLAYER_MEDIA_PLAY_TRACKS:str = 'player_media_play_tracks' +SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK:str = 'player_media_seek' SERVICE_SPOTIFY_PLAYER_RESOLVE_DEVICE_ID:str = 'player_resolve_device_id' SERVICE_SPOTIFY_PLAYER_SET_REPEAT_MODE:str = 'player_set_repeat_mode' SERVICE_SPOTIFY_PLAYER_SET_SHUFFLE_MODE:str = 'player_set_shuffle_mode' @@ -437,6 +438,7 @@ vol.Optional("offset", default=0): vol.All(vol.Range(min=0,max=500)), vol.Optional("limit_total", default=0): vol.All(vol.Range(min=0,max=9999)), vol.Optional("sort_result"): cv.boolean, + vol.Optional("exclude_audiobooks"): cv.boolean, } ) @@ -548,6 +550,16 @@ } ) +SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK_SCHEMA = vol.Schema( + { + vol.Required("entity_id"): cv.entity_id, + vol.Optional("position_ms", default=-1): vol.All(vol.Range(min=-1,max=999999999)), + vol.Optional("device_id"): cv.string, + vol.Optional("delay", default=0.50): vol.All(vol.Range(min=0,max=10.0)), + vol.Optional("relative_position_ms", default=0): vol.All(vol.Range(min=-999999999,max=999999999)), + } +) + SERVICE_SPOTIFY_PLAYER_RESOLVE_DEVICE_ID_SCHEMA = vol.Schema( { vol.Required("entity_id"): cv.entity_id, @@ -1020,6 +1032,16 @@ 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_player_media_play_tracks, uris, position_ms, device_id, delay) + elif service.service == SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK: + + # seeks to the given position in the currently playing track. + position_ms = service.data.get("position_ms") + device_id = service.data.get("device_id") + delay = service.data.get("delay") + relative_position_ms = service.data.get("relative_position_ms") + _logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name)) + await hass.async_add_executor_job(entity.service_spotify_player_media_seek, position_ms, device_id, delay, relative_position_ms) + elif service.service == SERVICE_SPOTIFY_PLAYER_SET_REPEAT_MODE: # set player repeat mode. @@ -1492,8 +1514,9 @@ async def service_handle_spotify_serviceresponse(service: ServiceCall) -> Servic offset = service.data.get("offset") limit_total = service.data.get("limit_total") sort_result = service.data.get("sort_result") + exclude_audiobooks = service.data.get("exclude_audiobooks") _logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (service.service, entity.name)) - response = await hass.async_add_executor_job(entity.service_spotify_get_show_favorites, limit, offset, limit_total, sort_result) + response = await hass.async_add_executor_job(entity.service_spotify_get_show_favorites, limit, offset, limit_total, sort_result, exclude_audiobooks) elif service.service == SERVICE_SPOTIFY_GET_SPOTIFY_CONNECT_DEVICE: @@ -2172,6 +2195,15 @@ def _GetEntityFromServiceData(hass:HomeAssistant, service:ServiceCall, field_id: supports_response=SupportsResponse.NONE, ) + _logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK, SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK_SCHEMA) + hass.services.async_register( + DOMAIN, + SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK, + service_handle_spotify_command, + schema=SERVICE_SPOTIFY_PLAYER_MEDIA_SEEK_SCHEMA, + supports_response=SupportsResponse.NONE, + ) + _logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_SERVICE_REQUEST_REGISTER % SERVICE_SPOTIFY_PLAYER_RESOLVE_DEVICE_ID, SERVICE_SPOTIFY_PLAYER_RESOLVE_DEVICE_ID_SCHEMA) hass.services.async_register( DOMAIN, diff --git a/custom_components/spotifyplus/manifest.json b/custom_components/spotifyplus/manifest.json index ca9e857..cf10454 100644 --- a/custom_components/spotifyplus/manifest.json +++ b/custom_components/spotifyplus/manifest.json @@ -18,10 +18,10 @@ "requests_oauthlib>=1.3.1", "soco>=0.30.4", "smartinspectPython>=3.0.33", - "spotifywebapiPython>=1.0.101", + "spotifywebapiPython>=1.0.106", "urllib3>=1.21.1,<1.27", "zeroconf>=0.132.2" ], - "version": "1.0.59", + "version": "1.0.60", "zeroconf": [ "_spotify-connect._tcp.local." ] } diff --git a/custom_components/spotifyplus/media_player.py b/custom_components/spotifyplus/media_player.py index 590255a..876eba6 100644 --- a/custom_components/spotifyplus/media_player.py +++ b/custom_components/spotifyplus/media_player.py @@ -3768,6 +3768,7 @@ def service_spotify_get_show_favorites( offset:int=0, limitTotal:int=None, sortResult:bool=True, + excludeAudiobooks:bool=True, ) -> dict: """ Get a list of the shows saved in the current Spotify user's 'Your Library'. @@ -3790,6 +3791,15 @@ def service_spotify_get_show_favorites( True to sort the items by name; otherwise, False to leave the items in the same order they were returned in by the Spotify Web API. Default: True + excludeAudiobooks (bool): + True to exclude audiobook shows from the returned list, leaving only podcast shows; + otherwise, False to include all results returned by the Spotify Web API. + Default: True + + For some reason, Spotify Web API returns audiobooks AND podcasts with the `/me/shows` service. + Spotify Web API returns only audiobooks with the `/me/audiobooks` service. + The reasoning for that is unclear, but the `excludeAudiobooks` argument allows you to + only return podcast shows in the results if desired. Returns: A dictionary that contains the following keys: @@ -3807,11 +3817,12 @@ def service_spotify_get_show_favorites( apiMethodParms.AppendKeyValue("offset", offset) apiMethodParms.AppendKeyValue("limitTotal", limitTotal) apiMethodParms.AppendKeyValue("sortResult", sortResult) + apiMethodParms.AppendKeyValue("excludeAudiobooks", excludeAudiobooks) _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Get Show Favorites Service", apiMethodParms) # request information from Spotify Web API. _logsi.LogVerbose(STAppMessages.MSG_SERVICE_QUERY_WEB_API) - result:ShowPageSaved = self.data.spotifyClient.GetShowFavorites(limit, offset, limitTotal, sortResult) + result:ShowPageSaved = self.data.spotifyClient.GetShowFavorites(limit, offset, limitTotal, sortResult, excludeAudiobooks) # return the (partial) user profile that retrieved the result, as well as the result itself. return { @@ -4819,6 +4830,131 @@ def service_spotify_player_media_play_tracks( _logsi.LeaveMethod(SILevel.Debug, apiMethodName) + @spotify_exception_handler + def service_spotify_player_media_seek( + self, + positionMS:int=-1, + deviceId:str=None, + delay:float=0.50, + relativePositionMS:int=0, + ) -> None: + """ + Seeks to the given absolute or relative position in the user's currently playing track + for the specified Spotify Connect device. + + Args: + positionMS (int): + The absolute position in milliseconds to seek to; must be a positive number. + Passing in a position that is greater than the length of the track will cause the + player to start playing the next song. + Example = `25000` to start playing at the 25 second mark. + deviceId (str): + The id or name of the device this command is targeting. + If not supplied, the user's currently active device is the target. + Example: `0d1841b0976bae2a3a310dd74c0f3df354899bc8` + Example: `Web Player (Chrome)` + delay (float): + Time delay (in seconds) to wait AFTER issuing the command to the player. + This delay will give the spotify web api time to process the change before + another command is issued. + Default is 0.50; value range is 0 - 10. + relativePositionMS (int): + The relative position in milliseconds to seek to; can be a positive or negative number. + Example = `-10000` to seek behind by 10 seconds. + Example = `10000` to seek ahead by 10 seconds. + """ + apiMethodName:str = 'service_spotify_player_media_seek' + apiMethodParms:SIMethodParmListContext = None + + try: + + # trace. + apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName) + apiMethodParms.AppendKeyValue("positionMS", positionMS) + apiMethodParms.AppendKeyValue("deviceId", deviceId) + apiMethodParms.AppendKeyValue("delay", delay) + apiMethodParms.AppendKeyValue("relativePositionMS", positionMS) + _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Player Media Seek Service", apiMethodParms) + + # validations. + if positionMS == -1: + positionMS = None + if relativePositionMS == 0: + relativePositionMS = None + + # validations. + delay = validateDelay(delay, 0.50, 10) + if deviceId == '': + deviceId = None + if deviceId is None or deviceId == "*": + deviceId = PlayerDevice.GetIdFromSelectItem(self.data.OptionDeviceDefault) + + # get selected device reference from cached list of Spotify Connect devices. + scDevices:SpotifyConnectDevices = self.data.spotifyClient.GetSpotifyConnectDevices(refresh=False) + scDevice:SpotifyConnectDevice = scDevices.GetDeviceByName(deviceId) + if scDevice is None: + scDevice = scDevices.GetDeviceById(deviceId) + + # get current track position. + # ignore what we get for device from _GetPlayerPlaybackState, as it's the active device + # and may be NOT what the user asked for (via deviceId argument). + playerState:PlayerPlayState + spotifyConnectDevice:SpotifyConnectDevice + sonosDevice:SoCo + + # get current track position. + playerState, spotifyConnectDevice, sonosDevice = self._GetPlayerPlaybackState() + + # set seek position based on device type. + if (sonosDevice is not None): + + # was relative seeking specified? + if (relativePositionMS != 0) and ((positionMS is None) or (positionMS <= 0)): + + newPositionMS:int = playerState.ProgressMS + if (newPositionMS is not None) and (newPositionMS > 0): + + # calculate new position; if less than zero, then force it to zero. + newPositionMS += relativePositionMS + if (newPositionMS < 0): + newPositionMS = 0 + positionMS = newPositionMS + + # for Sonos, use the SoCo API command. + sonosPosition:str = positionHMS_fromMilliSeconds(positionMS) # convert from milliseconds to Sonos H:MM:SS format + _logsi.LogVerbose("'%s': Issuing command to Sonos device '%s' ('%s'): SEEK (position=%s)" % (self.name, sonosDevice.ip_address, sonosDevice.player_name, sonosPosition)) + sonosDevice.seek(position=sonosPosition) + + # give SoCo api time to process the change. + if delay > 0: + _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE_SONOS % delay) + time.sleep(delay) + + else: + + # for everything else, just use the Spotify Web API command. + self.data.spotifyClient.PlayerMediaSeek(positionMS, deviceId, delay, relativePositionMS) + + # update ha state. + self.schedule_update_ha_state(force_refresh=False) + + # media player command was processed, so force a scan window at the next interval. + _logsi.LogVerbose("'%s': Processed a media player command - forcing a playerState scan window for the next %d updates" % (self.name, SPOTIFY_SCAN_INTERVAL_COMMAND - 1)) + self._commandScanInterval = SPOTIFY_SCAN_INTERVAL_COMMAND + + # 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_player_resolve_device_id( self, deviceValue:str, diff --git a/custom_components/spotifyplus/services.yaml b/custom_components/spotifyplus/services.yaml index a56008b..6f94906 100644 --- a/custom_components/spotifyplus/services.yaml +++ b/custom_components/spotifyplus/services.yaml @@ -237,7 +237,7 @@ get_album_favorites: domain: media_player 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. + 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. example: 20 required: false selector: @@ -247,7 +247,7 @@ get_album_favorites: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -257,7 +257,7 @@ get_album_favorites: 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. + 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: @@ -293,7 +293,7 @@ get_album_new_releases: domain: media_player 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. + 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. example: 20 required: false selector: @@ -303,7 +303,7 @@ get_album_new_releases: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -313,7 +313,7 @@ get_album_new_releases: mode: box country: 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. + 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: @@ -384,7 +384,7 @@ get_artist_albums: text: 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. + 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. example: 20 required: false selector: @@ -394,7 +394,7 @@ get_artist_albums: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -404,7 +404,7 @@ get_artist_albums: 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. + 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: @@ -447,7 +447,7 @@ get_artists_followed: text: 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. + 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. example: 20 required: false selector: @@ -486,7 +486,7 @@ get_audiobook_favorites: domain: media_player 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. + 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. example: 20 required: false selector: @@ -496,7 +496,7 @@ get_audiobook_favorites: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -577,7 +577,7 @@ get_category_playlists: text: 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. + 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. example: 20 required: false selector: @@ -587,7 +587,7 @@ get_category_playlists: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -661,7 +661,7 @@ get_episode_favorites: domain: media_player 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. + 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. example: 20 required: false selector: @@ -671,7 +671,7 @@ get_episode_favorites: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -710,7 +710,7 @@ get_featured_playlists: domain: media_player 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. + 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. example: 20 required: false selector: @@ -720,7 +720,7 @@ get_featured_playlists: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -815,7 +815,7 @@ get_player_now_playing: text: additional_types: name: Additional Types - description: A comma-separated list of item types that your client supports besides the default track type. Valid types are 'track' and 'episode'. + description: A comma-separated list of item types that your client supports besides the default track type. Valid types are 'track' and 'episode'. example: "episode" required: false selector: @@ -843,7 +843,7 @@ get_player_playback_state: text: additional_types: name: Additional Types - description: A comma-separated list of item types that your client supports besides the default track type. Valid types are 'track' and 'episode'. + description: A comma-separated list of item types that your client supports besides the default track type. Valid types are 'track' and 'episode'. example: "episode" required: false selector: @@ -878,7 +878,7 @@ get_player_recent_tracks: domain: media_player 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. + 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. example: 20 required: false selector: @@ -951,7 +951,7 @@ get_playlist: text: additional_types: name: Additional Types - description: A comma-separated list of item types that your client supports besides the default track type. Valid types are 'track' and 'episode'. + description: A comma-separated list of item types that your client supports besides the default track type. Valid types are 'track' and 'episode'. example: "episode" required: false selector: @@ -972,7 +972,7 @@ get_playlist_favorites: domain: media_player 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. + 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. example: 20 required: false selector: @@ -982,7 +982,7 @@ get_playlist_favorites: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -1056,7 +1056,7 @@ get_show_episodes: text: 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. + 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. example: 20 required: false selector: @@ -1066,7 +1066,7 @@ get_show_episodes: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -1105,7 +1105,7 @@ get_show_favorites: domain: media_player 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. + 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. example: 20 required: false selector: @@ -1115,7 +1115,7 @@ get_show_favorites: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -1138,6 +1138,13 @@ get_show_favorites: required: false selector: boolean: + exclude_audiobooks: + name: Exclude Audiobooks? + description: True (default) to exclude audiobook shows from the returned list, leaving only podcast shows; otherwise, False to include all results returned by the Spotify Web API. + example: "True" + required: false + selector: + boolean: get_spotify_connect_device: name: Get Spotify Connect Device @@ -1265,7 +1272,7 @@ get_track_favorites: domain: media_player 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. + 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. example: 20 required: false selector: @@ -1275,7 +1282,7 @@ get_track_favorites: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -1285,7 +1292,7 @@ get_track_favorites: 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. + 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: @@ -1349,7 +1356,7 @@ get_users_top_artists: text: 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. + 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. example: 20 required: false selector: @@ -1359,7 +1366,7 @@ get_users_top_artists: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -1405,7 +1412,7 @@ get_users_top_tracks: text: 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. + 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. example: 20 required: false selector: @@ -1415,7 +1422,7 @@ get_users_top_tracks: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -1485,7 +1492,7 @@ player_media_play_context: domain: media_player context_uri: name: Context Uri - description: Spotify URI of the context to play (e.g. `spotify:album:6vc9OTcyd3hyzabCmsdnwE`). Valid contexts are albums, artists & playlists. + description: Spotify URI of the context to play (e.g. `spotify:album:6vc9OTcyd3hyzabCmsdnwE`). Valid contexts are albums, artists & playlists. example: "spotify:album:6vc9OTcyd3hyzabCmsdnwE" required: true selector: @@ -1574,7 +1581,7 @@ player_media_play_track_favorites: mode: box resolve_device_id: name: Resolve Device Id? - description: True to resolve the supplied `deviceId` value; otherwise, False not resolve the `deviceId` value as it has already been resolved. Default is True. + description: True to resolve the supplied `deviceId` value; otherwise, False not resolve the `deviceId` value as it has already been resolved. Default is True. example: "True" required: false selector: @@ -1636,6 +1643,57 @@ player_media_play_tracks: max: 10.0 mode: box +player_media_seek: + name: Player Media Seek + description: Seeks to the given absolute or relative position in the user's currently playing track for the specified Spotify Connect device. + 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 + position_ms: + name: Absolute Seek Position + description: The absolute position in milliseconds to seek to; must be a positive number or zero if the `relativePositionMS` argument is specified. Passing in a position that is greater than the length of the track will cause the player to start playing the next song. Example = `25000` to start playing at the 25 second mark. + example: 25000 + required: false + selector: + number: + min: 0 + max: 999999999 + mode: box + device_id: + name: Device ID + description: The id or name of the Spotify Connect Player device this command is targeting. If not supplied, the user's currently active device is the target. If no device is active (or an "*" is specified), then the SpotifyPlus default device is activated. + example: "0d1841b0976bae2a3a310dd74c0f337465899bc8" + required: false + selector: + text: + delay: + name: Delay + description: Time delay (in seconds) to wait AFTER issuing the final Connect command (if necessary). This delay will give the spotify web api time to process the device list change before another command is issued. Default is 0.50; value range is 0 - 10. + example: "0.50" + required: false + selector: + number: + min: 0.0 + max: 10.0 + mode: box + relative_position_ms: + name: Relative Seek Position + description: The relative position in milliseconds to seek to; can be a positive or negative number, or zero if the `positionMS` argument is specified. Example = `-10000` to seek behind by 10 seconds; `10000` to seek ahead by 10 seconds. + example: 10000 + required: false + selector: + number: + min: -999999999 + max: 999999999 + mode: box + player_resolve_device_id: name: Player Resolve Device ID description: Resolves a Spotify Connect device identifier from a specified device id, name, alias id, or alias name. This will ensure that the device id can be found on the network, as well as connect to the device if necessary with the current user context. @@ -1842,7 +1900,7 @@ player_transfer_playback: boolean: force_activate_device: name: Force Activate Device? - description: True to issue a Spotify Connect Disconnect call prior to transfer, which will force the device to reconnect to Spotify Connect; otherwise, False to not disconnect. Default is True. + description: True to issue a Spotify Connect Disconnect call prior to transfer, which will force the device to reconnect to Spotify Connect; otherwise, False to not disconnect. Default is True. example: "True" required: false selector: @@ -2017,7 +2075,7 @@ playlist_items_add: text: position: name: Position - description: The position to insert the items, a zero-based index. For example, to insert the items in the first position use a value of 0; to insert the items in the third position use a value of 2. Omit the parameter to append the items to the end of the playlist. + description: The position to insert the items, a zero-based index. For example, to insert the items in the first position use a value of 0; to insert the items in the third position use a value of 2. Omit the parameter to append the items to the end of the playlist. example: "0" required: false selector: @@ -2314,7 +2372,7 @@ search_albums: text: 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. + 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. example: 20 required: false selector: @@ -2324,7 +2382,7 @@ search_albums: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2334,7 +2392,7 @@ search_albums: 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. + 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: @@ -2377,7 +2435,7 @@ search_artists: text: 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. + 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. example: 20 required: false selector: @@ -2387,7 +2445,7 @@ search_artists: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2397,7 +2455,7 @@ search_artists: 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. + 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: @@ -2440,7 +2498,7 @@ search_audiobooks: text: 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. + 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. example: 20 required: false selector: @@ -2450,7 +2508,7 @@ search_audiobooks: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2460,7 +2518,7 @@ search_audiobooks: 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. + 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: @@ -2503,7 +2561,7 @@ search_episodes: text: 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. + 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. example: 20 required: false selector: @@ -2513,7 +2571,7 @@ search_episodes: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2523,7 +2581,7 @@ search_episodes: 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. + 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: @@ -2566,7 +2624,7 @@ search_playlists: text: 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. + 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. example: 20 required: false selector: @@ -2576,7 +2634,7 @@ search_playlists: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2586,7 +2644,7 @@ search_playlists: 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. + 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: @@ -2629,7 +2687,7 @@ search_shows: text: 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. + 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. example: 20 required: false selector: @@ -2639,7 +2697,7 @@ search_shows: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2649,7 +2707,7 @@ search_shows: 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. + 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: @@ -2692,7 +2750,7 @@ search_tracks: text: 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. + 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. example: 20 required: false selector: @@ -2702,7 +2760,7 @@ search_tracks: mode: box offset: name: Offset - description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). + description: The page index offset of the first item to return. Use with limit to get the next set of items. Default is 0 (the first item). example: 0 required: false selector: @@ -2712,7 +2770,7 @@ search_tracks: 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. + 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: @@ -2863,7 +2921,7 @@ zeroconf_device_connect: text: loginid: name: Spotify Login ID - description: Spotify Connect login id to login with (e.g. "31l77fd87g8h9j00k89f07jf87ge"). This is also known as the canonical user id value. This MUST be the value that relates to the `username` argument. + description: Spotify Connect login id to login with (e.g. "31l77fd87g8h9j00k89f07jf87ge"). This is also known as the canonical user id value. This MUST be the value that relates to the `username` argument. example: "31l77y75hfnhk79f7gk6jkk878mg" required: false selector: diff --git a/custom_components/spotifyplus/strings.json b/custom_components/spotifyplus/strings.json index 48eff8c..9d30244 100644 --- a/custom_components/spotifyplus/strings.json +++ b/custom_components/spotifyplus/strings.json @@ -725,6 +725,10 @@ "sort_result": { "name": "Sort Result?", "description": "True to sort result items by name prior to returning to the caller; otherwise, False to return results in the order that the Spotify Web API returned them." + }, + "exclude_audiobooks": { + "name": "Exclude Audiobooks?", + "description": "True (default) to exclude audiobook shows from the returned list, leaving only podcast shows; otherwise, False to include all results returned by the Spotify Web API." } } }, @@ -1006,9 +1010,35 @@ } } }, + "player_media_seek": { + "name": "Player Media Seek", + "description": "Seeks to the given absolute or relative position in the user's currently playing track for the specified Spotify Connect device.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Entity ID of the SpotifyPlus device that will make the request to the Spotify Web API." + }, + "position_ms": { + "name": "Absolute Seek Position", + "description": "The absolute position in milliseconds to seek to; must be a positive number or zero if the `relativePositionMS` argument is specified. Passing in a position that is greater than the length of the track will cause the player to start playing the next song. Example = `25000` to start playing at the 25 second mark." + }, + "device_id": { + "name": "Device ID", + "description": "The id or name of the Spotify Connect Player device this command is targeting. If not supplied, the user's currently active device is the target. If no device is active (or an '*' is specified), then the SpotifyPlus default device is activated." + }, + "delay": { + "name": "Delay", + "description": "Time delay (in seconds) to wait AFTER issuing the final Connect command (if necessary). This delay will give the spotify web api time to process the device list change before another command is issued. Default is 0.50; value range is 0 - 10." + }, + "relative_position_ms": { + "name": "Relative Seek Position", + "description": "The relative position in milliseconds to seek to; can be a positive or negative number, or zero if the `positionMS` argument is specified. Example = `-10000` to seek behind by 10 seconds; `10000` to seek ahead by 10 seconds." + } + } + }, "player_resolve_device_id": { "name": "Player Resolve Device ID", - "description": "Resolves a Spotify Connect device identifier from a specified device id, name, alias id, or alias name. This will ensure that the device id can be found on the network, as well as connect to the device if necessary with the current user context. ", + "description": "Resolves a Spotify Connect device identifier from a specified device id, name, alias id, or alias name. This will ensure that the device id can be found on the network, as well as connect to the device if necessary with the current user context.", "fields": { "entity_id": { "name": "Entity ID", diff --git a/custom_components/spotifyplus/translations/en.json b/custom_components/spotifyplus/translations/en.json index 48eff8c..9d30244 100644 --- a/custom_components/spotifyplus/translations/en.json +++ b/custom_components/spotifyplus/translations/en.json @@ -725,6 +725,10 @@ "sort_result": { "name": "Sort Result?", "description": "True to sort result items by name prior to returning to the caller; otherwise, False to return results in the order that the Spotify Web API returned them." + }, + "exclude_audiobooks": { + "name": "Exclude Audiobooks?", + "description": "True (default) to exclude audiobook shows from the returned list, leaving only podcast shows; otherwise, False to include all results returned by the Spotify Web API." } } }, @@ -1006,9 +1010,35 @@ } } }, + "player_media_seek": { + "name": "Player Media Seek", + "description": "Seeks to the given absolute or relative position in the user's currently playing track for the specified Spotify Connect device.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Entity ID of the SpotifyPlus device that will make the request to the Spotify Web API." + }, + "position_ms": { + "name": "Absolute Seek Position", + "description": "The absolute position in milliseconds to seek to; must be a positive number or zero if the `relativePositionMS` argument is specified. Passing in a position that is greater than the length of the track will cause the player to start playing the next song. Example = `25000` to start playing at the 25 second mark." + }, + "device_id": { + "name": "Device ID", + "description": "The id or name of the Spotify Connect Player device this command is targeting. If not supplied, the user's currently active device is the target. If no device is active (or an '*' is specified), then the SpotifyPlus default device is activated." + }, + "delay": { + "name": "Delay", + "description": "Time delay (in seconds) to wait AFTER issuing the final Connect command (if necessary). This delay will give the spotify web api time to process the device list change before another command is issued. Default is 0.50; value range is 0 - 10." + }, + "relative_position_ms": { + "name": "Relative Seek Position", + "description": "The relative position in milliseconds to seek to; can be a positive or negative number, or zero if the `positionMS` argument is specified. Example = `-10000` to seek behind by 10 seconds; `10000` to seek ahead by 10 seconds." + } + } + }, "player_resolve_device_id": { "name": "Player Resolve Device ID", - "description": "Resolves a Spotify Connect device identifier from a specified device id, name, alias id, or alias name. This will ensure that the device id can be found on the network, as well as connect to the device if necessary with the current user context. ", + "description": "Resolves a Spotify Connect device identifier from a specified device id, name, alias id, or alias name. This will ensure that the device id can be found on the network, as well as connect to the device if necessary with the current user context.", "fields": { "entity_id": { "name": "Entity ID", diff --git a/requirements.txt b/requirements.txt index 2b5ff06..ad95b5b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,4 @@ homeassistant==2024.5.0 ruff==0.1.3 soco>=0.30.4 smartinspectPython>=3.0.33 -spotifywebapiPython>=1.0.101 +spotifywebapiPython>=1.0.106