spotifywebapiPython 1.0.262__py3-none-any.whl → 1.0.264__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. spotifywebapipython/const.py +1 -1
  2. spotifywebapipython/docs/__init__.html +15 -2
  3. spotifywebapipython/docs/index.html +2 -2
  4. spotifywebapipython/docs/search.js +1 -1
  5. spotifywebapipython/docs/spotifywebapipython/const.html +3 -3
  6. spotifywebapipython/docs/spotifywebapipython/saappmessages.html +2 -2
  7. spotifywebapipython/docs/spotifywebapipython/sautils.html +2 -2
  8. spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +2 -2
  9. spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +2 -2
  10. spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +2 -2
  11. spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +13 -65
  12. spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +2 -2
  13. spotifywebapipython/docs/spotifywebapipython/spotifymediatypes.html +2 -2
  14. spotifywebapipython/docs/spotifywebapipython/spotifytypeprefixes.html +2 -2
  15. spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +2 -2
  16. spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +2 -2
  17. spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +2 -2
  18. spotifywebapipython/models/playerlastplayedinfo.py +3 -2
  19. spotifywebapipython/oauthcli/authclient.py +2 -1
  20. spotifywebapipython/spotifyclient.py +272 -250
  21. {spotifywebapipython-1.0.262.dist-info → spotifywebapipython-1.0.264.dist-info}/METADATA +1 -1
  22. {spotifywebapipython-1.0.262.dist-info → spotifywebapipython-1.0.264.dist-info}/RECORD +25 -25
  23. {spotifywebapipython-1.0.262.dist-info → spotifywebapipython-1.0.264.dist-info}/LICENSE +0 -0
  24. {spotifywebapipython-1.0.262.dist-info → spotifywebapipython-1.0.264.dist-info}/WHEEL +0 -0
  25. {spotifywebapipython-1.0.262.dist-info → spotifywebapipython-1.0.264.dist-info}/top_level.txt +0 -0
@@ -67,6 +67,10 @@ from .const import (
67
67
 
68
68
  CACHE_SOURCE_CACHED:str = "cached"
69
69
  CACHE_SOURCE_CURRENT:str = "current"
70
+ CACHE_KEY_GETSPOTIFYCONNECTDEVICES:str = "GetSpotifyConnectDevices"
71
+
72
+ MUSIC_SOURCE_SPOTIFY_LOCAL_QUEUE:str = "SPOTIFY_LOCAL_QUEUE"
73
+ MUSIC_SOURCE_SPOTIFY_CONNECT:str = "SPOTIFY_CONNECT"
70
74
 
71
75
  DELAY_DISCONNECT:float = 0.350
72
76
  """
@@ -1084,6 +1088,10 @@ class SpotifyClient:
1084
1088
  # Spotify Connect devices on the local network.
1085
1089
  self._SpotifyConnectDirectory.WaitForInitComplete.wait()
1086
1090
 
1091
+ # load initial configuration cache with devices we have found thus far.
1092
+ # no need to refresh, since they were just loaded (just loads the cache).
1093
+ self.GetSpotifyConnectDevices(refresh=False)
1094
+
1087
1095
  # trace.
1088
1096
  _logsi.LogVerbose("Spotify Connect Directory task was started and initialized successfully")
1089
1097
 
@@ -3834,14 +3842,6 @@ class SpotifyClient:
3834
3842
  market:str=None,
3835
3843
  ) -> list[Album]:
3836
3844
  """
3837
- <span class="deprecated">
3838
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
3839
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
3840
- More information about the deprecated functionality can be found on the
3841
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
3842
- page.
3843
- </span>
3844
-
3845
3845
  Get Spotify catalog information for multiple albums.
3846
3846
 
3847
3847
  Args:
@@ -3887,37 +3887,42 @@ class SpotifyClient:
3887
3887
  apiMethodParms.AppendKeyValue("market", market)
3888
3888
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple albums", apiMethodParms)
3889
3889
 
3890
- # are spotify web player credentials configured? if so, then we will use them to create
3891
- # an elevated authorization access token for the Spotify Web API endpoint call.
3892
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
3893
-
3894
- # if spotify web player credentials not configured then we are done; the Spotify Web API
3895
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
3896
- if (accessTokenHeaderValue is None):
3897
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
3898
-
3899
3890
  # ensure we have a market value, in order to return track relinking (e.g. `linked_from`) data.
3900
3891
  market = self._ValidateMarket(market, forceReturnValue=True)
3901
3892
 
3902
- # build spotify web api request parameters.
3903
- urlParms:dict = \
3904
- {
3905
- 'ids': ids,
3906
- }
3907
- if market is not None:
3908
- urlParms['market'] = market
3909
-
3910
- # execute spotify web api request.
3911
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/albums')
3912
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3913
- msg.UrlParameters = urlParms
3914
- self.MakeRequest('GET', msg)
3893
+ # if ids not specified, then we are done.
3894
+ if (ids is None) or (len(ids.strip()) == 0):
3895
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
3915
3896
 
3916
- # process results.
3917
- items = msg.ResponseData.get('albums',None)
3918
- if items is not None:
3919
- for item in items:
3920
- result.append(Album(root=item))
3897
+ # build list of all input item id's, and retrieve them one-by-one.
3898
+ ids = ids.replace(" ", "")
3899
+ arrIds:list[str] = ids.split(',')
3900
+ for strId in arrIds:
3901
+ result.append(self.GetAlbum(strId, market))
3902
+
3903
+ # ------------------------------------------------------------------------------------------
3904
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
3905
+ # ------------------------------------------------------------------------------------------
3906
+
3907
+ # # build spotify web api request parameters.
3908
+ # urlParms:dict = \
3909
+ # {
3910
+ # 'ids': ids,
3911
+ # }
3912
+ # if market is not None:
3913
+ # urlParms['market'] = market
3914
+
3915
+ # # execute spotify web api request.
3916
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/albums')
3917
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3918
+ # msg.UrlParameters = urlParms
3919
+ # self.MakeRequest('GET', msg)
3920
+
3921
+ # # process results.
3922
+ # items = msg.ResponseData.get('albums',None)
3923
+ # if items is not None:
3924
+ # for item in items:
3925
+ # result.append(Album(root=item))
3921
3926
 
3922
3927
  # trace.
3923
3928
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[Album]'), result)
@@ -4834,14 +4839,6 @@ class SpotifyClient:
4834
4839
  ids:list[str],
4835
4840
  ) -> list[Artist]:
4836
4841
  """
4837
- <span class="deprecated">
4838
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
4839
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
4840
- More information about the deprecated functionality can be found on the
4841
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
4842
- page.
4843
- </span>
4844
-
4845
4842
  Get Spotify catalog information for several artists based on their Spotify IDs.
4846
4843
 
4847
4844
  Args:
@@ -4878,32 +4875,37 @@ class SpotifyClient:
4878
4875
  apiMethodParms.AppendKeyValue("ids", ids)
4879
4876
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple artists", apiMethodParms)
4880
4877
 
4881
- # are spotify web player credentials configured? if so, then we will use them to create
4882
- # an elevated authorization access token for the Spotify Web API endpoint call.
4883
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
4878
+ # if ids not specified, then we are done.
4879
+ if (ids is None) or (len(ids.strip()) == 0):
4880
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
4884
4881
 
4885
- # if spotify web player credentials not configured then we are done; the Spotify Web API
4886
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
4887
- if (accessTokenHeaderValue is None):
4888
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
4882
+ # build list of all input item id's, and retrieve them one-by-one.
4883
+ ids = ids.replace(" ", "")
4884
+ arrIds:list[str] = ids.split(',')
4885
+ for strId in arrIds:
4886
+ result.append(self.GetArtist(strId))
4889
4887
 
4890
- # build spotify web api request parameters.
4891
- urlParms:dict = \
4892
- {
4893
- 'ids': ids
4894
- }
4888
+ # ------------------------------------------------------------------------------------------
4889
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
4890
+ # ------------------------------------------------------------------------------------------
4895
4891
 
4896
- # execute spotify web api request.
4897
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/artists')
4898
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4899
- msg.UrlParameters = urlParms
4900
- self.MakeRequest('GET', msg)
4892
+ # # build spotify web api request parameters.
4893
+ # urlParms:dict = \
4894
+ # {
4895
+ # 'ids': ids
4896
+ # }
4901
4897
 
4902
- # process results.
4903
- items = msg.ResponseData.get('artists',None)
4904
- if items is not None:
4905
- for item in items:
4906
- result.append(Artist(root=item))
4898
+ # # execute spotify web api request.
4899
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/artists')
4900
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
4901
+ # msg.UrlParameters = urlParms
4902
+ # self.MakeRequest('GET', msg)
4903
+
4904
+ # # process results.
4905
+ # items = msg.ResponseData.get('artists',None)
4906
+ # if items is not None:
4907
+ # for item in items:
4908
+ # result.append(Artist(root=item))
4907
4909
 
4908
4910
  # trace.
4909
4911
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[Artist]'), result)
@@ -5658,14 +5660,6 @@ class SpotifyClient:
5658
5660
  market:str=None,
5659
5661
  ) -> list[AudiobookSimplified]:
5660
5662
  """
5661
- <span class="deprecated">
5662
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
5663
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
5664
- More information about the deprecated functionality can be found on the
5665
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
5666
- page.
5667
- </span>
5668
-
5669
5663
  Get Spotify catalog information for several audiobooks based on their Spotify IDs.
5670
5664
 
5671
5665
  Args:
@@ -5692,6 +5686,8 @@ class SpotifyClient:
5692
5686
  SpotifyApiError:
5693
5687
  If the method fails for any other reason.
5694
5688
 
5689
+ Note that `AudiobookSimplified` details do not contain chapter data.
5690
+
5695
5691
  Important policy notes:
5696
5692
  - Spotify content may not be downloaded.
5697
5693
  - Keep visual content in its original form.
@@ -5716,37 +5712,45 @@ class SpotifyClient:
5716
5712
  apiMethodParms.AppendKeyValue("market", market)
5717
5713
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple audiobooks", apiMethodParms)
5718
5714
 
5719
- # are spotify web player credentials configured? if so, then we will use them to create
5720
- # an elevated authorization access token for the Spotify Web API endpoint call.
5721
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
5722
-
5723
- # if spotify web player credentials not configured then we are done; the Spotify Web API
5724
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
5725
- if (accessTokenHeaderValue is None):
5726
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
5727
-
5728
5715
  # ensure market was either supplied or implied; default if neither.
5729
5716
  market = self._ValidateMarket(market)
5730
5717
 
5731
- # build spotify web api request parameters.
5732
- urlParms:dict = \
5733
- {
5734
- 'ids': ids,
5735
- }
5736
- if market is not None:
5737
- urlParms['market'] = market
5738
-
5739
- # execute spotify web api request.
5740
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/audiobooks')
5741
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5742
- msg.UrlParameters = urlParms
5743
- self.MakeRequest('GET', msg)
5718
+ # if ids not specified, then we are done.
5719
+ if (ids is None) or (len(ids.strip()) == 0):
5720
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
5744
5721
 
5745
- # process results.
5746
- items = msg.ResponseData.get('audiobooks',None)
5747
- if items is not None:
5748
- for item in items:
5749
- result.append(AudiobookSimplified(root=item))
5722
+ # build list of all input item id's, and retrieve them one-by-one.
5723
+ ids = ids.replace(" ", "")
5724
+ arrIds:list[str] = ids.split(',')
5725
+ for strId in arrIds:
5726
+ dataObj = self.GetAudiobook(strId, market)
5727
+ # convert Audiobook object to a AudiobookSimplified object.
5728
+ dataObj._Chapters = None
5729
+ result.append(dataObj)
5730
+
5731
+ # ------------------------------------------------------------------------------------------
5732
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
5733
+ # ------------------------------------------------------------------------------------------
5734
+
5735
+ # # build spotify web api request parameters.
5736
+ # urlParms:dict = \
5737
+ # {
5738
+ # 'ids': ids,
5739
+ # }
5740
+ # if market is not None:
5741
+ # urlParms['market'] = market
5742
+
5743
+ # # execute spotify web api request.
5744
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/audiobooks')
5745
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
5746
+ # msg.UrlParameters = urlParms
5747
+ # self.MakeRequest('GET', msg)
5748
+
5749
+ # # process results.
5750
+ # items = msg.ResponseData.get('audiobooks',None)
5751
+ # if items is not None:
5752
+ # for item in items:
5753
+ # result.append(AudiobookSimplified(root=item))
5750
5754
 
5751
5755
  # trace.
5752
5756
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[AudiobookSimplified]'), result)
@@ -6530,14 +6534,6 @@ class SpotifyClient:
6530
6534
  market:str=None,
6531
6535
  ) -> list[Chapter]:
6532
6536
  """
6533
- <span class="deprecated">
6534
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
6535
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
6536
- More information about the deprecated functionality can be found on the
6537
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
6538
- page.
6539
- </span>
6540
-
6541
6537
  Get Spotify catalog information for several chapters based on their Spotify IDs.
6542
6538
 
6543
6539
  Args:
@@ -6588,37 +6584,42 @@ class SpotifyClient:
6588
6584
  apiMethodParms.AppendKeyValue("market", market)
6589
6585
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple chapters", apiMethodParms)
6590
6586
 
6591
- # are spotify web player credentials configured? if so, then we will use them to create
6592
- # an elevated authorization access token for the Spotify Web API endpoint call.
6593
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
6594
-
6595
- # if spotify web player credentials not configured then we are done; the Spotify Web API
6596
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
6597
- if (accessTokenHeaderValue is None):
6598
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
6599
-
6600
6587
  # ensure market was either supplied or implied; default if neither.
6601
6588
  market = self._ValidateMarket(market)
6602
6589
 
6603
- # build spotify web api request parameters.
6604
- urlParms:dict = \
6605
- {
6606
- 'ids': ids,
6607
- }
6608
- if market is not None:
6609
- urlParms['market'] = market
6610
-
6611
- # execute spotify web api request.
6612
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/chapters')
6613
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6614
- msg.UrlParameters = urlParms
6615
- self.MakeRequest('GET', msg)
6590
+ # if ids not specified, then we are done.
6591
+ if (ids is None) or (len(ids.strip()) == 0):
6592
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
6616
6593
 
6617
- # process results.
6618
- items = msg.ResponseData.get('chapters',None)
6619
- if items is not None:
6620
- for item in items:
6621
- result.append(Chapter(root=item))
6594
+ # build list of all input item id's, and retrieve them one-by-one.
6595
+ ids = ids.replace(" ", "")
6596
+ arrIds:list[str] = ids.split(',')
6597
+ for strId in arrIds:
6598
+ result.append(self.GetChapter(strId, market))
6599
+
6600
+ # ------------------------------------------------------------------------------------------
6601
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
6602
+ # ------------------------------------------------------------------------------------------
6603
+
6604
+ # # build spotify web api request parameters.
6605
+ # urlParms:dict = \
6606
+ # {
6607
+ # 'ids': ids,
6608
+ # }
6609
+ # if market is not None:
6610
+ # urlParms['market'] = market
6611
+
6612
+ # # execute spotify web api request.
6613
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/chapters')
6614
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
6615
+ # msg.UrlParameters = urlParms
6616
+ # self.MakeRequest('GET', msg)
6617
+
6618
+ # # process results.
6619
+ # items = msg.ResponseData.get('chapters',None)
6620
+ # if items is not None:
6621
+ # for item in items:
6622
+ # result.append(Chapter(root=item))
6622
6623
 
6623
6624
  # trace.
6624
6625
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[Chapter]'), result)
@@ -6844,9 +6845,17 @@ class SpotifyClient:
6844
6845
  # get Sonos playback state via Sonos Controller instance.
6845
6846
  playerStateSonos:PlayerPlayState = self.GetPlayerPlaybackStateSonos(scDevice)
6846
6847
 
6847
- # return the device playstate.
6848
- _logsi.LogVerbose("Sonos device %s playstate will be returned" % (scDevice.Title))
6849
- result = playerStateSonos
6848
+ # is the device still playing spotify content?
6849
+ if (playerStateSonos.DeviceMusicSource in [MUSIC_SOURCE_SPOTIFY_CONNECT, MUSIC_SOURCE_SPOTIFY_LOCAL_QUEUE]):
6850
+
6851
+ # yes - return the device playstate.
6852
+ _logsi.LogVerbose("Sonos device %s playstate will be returned (music source=\"%s\")" % (scDevice.Title, playerStateSonos.DeviceMusicSource))
6853
+ result = playerStateSonos
6854
+
6855
+ else:
6856
+
6857
+ # no - return an empty playstate.
6858
+ _logsi.LogVerbose("Sonos device %s music source (%s) is not Spotify; an empty playstate will be returned" % (scDevice.Title, playerStateSonos.DeviceMusicSource))
6850
6859
 
6851
6860
  # did Sonos Controller instance return a playstate?
6852
6861
  # if so, then update the player last played info if something is playing.
@@ -7141,14 +7150,6 @@ class SpotifyClient:
7141
7150
  market:str=None,
7142
7151
  ) -> list[Episode]:
7143
7152
  """
7144
- <span class="deprecated">
7145
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
7146
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
7147
- More information about the deprecated functionality can be found on the
7148
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
7149
- page.
7150
- </span>
7151
-
7152
7153
  Get Spotify catalog information for several episodes based on their Spotify IDs.
7153
7154
 
7154
7155
  Args:
@@ -7199,37 +7200,42 @@ class SpotifyClient:
7199
7200
  apiMethodParms.AppendKeyValue("market", market)
7200
7201
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple episodes", apiMethodParms)
7201
7202
 
7202
- # are spotify web player credentials configured? if so, then we will use them to create
7203
- # an elevated authorization access token for the Spotify Web API endpoint call.
7204
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
7205
-
7206
- # if spotify web player credentials not configured then we are done; the Spotify Web API
7207
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
7208
- if (accessTokenHeaderValue is None):
7209
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
7210
-
7211
7203
  # ensure market was either supplied or implied; default if neither.
7212
7204
  market = self._ValidateMarket(market)
7213
7205
 
7214
- # build spotify web api request parameters.
7215
- urlParms:dict = \
7216
- {
7217
- 'ids': ids,
7218
- }
7219
- if market is not None:
7220
- urlParms['market'] = market
7221
-
7222
- # execute spotify web api request.
7223
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/episodes')
7224
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
7225
- msg.UrlParameters = urlParms
7226
- self.MakeRequest('GET', msg)
7206
+ # if ids not specified, then we are done.
7207
+ if (ids is None) or (len(ids.strip()) == 0):
7208
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
7227
7209
 
7228
- # process results.
7229
- items = msg.ResponseData.get('episodes',None)
7230
- if items is not None:
7231
- for item in items:
7232
- result.append(Episode(root=item))
7210
+ # build list of all input item id's, and retrieve them one-by-one.
7211
+ ids = ids.replace(" ", "")
7212
+ arrIds:list[str] = ids.split(',')
7213
+ for strId in arrIds:
7214
+ result.append(self.GetEpisode(strId, market))
7215
+
7216
+ # ------------------------------------------------------------------------------------------
7217
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
7218
+ # ------------------------------------------------------------------------------------------
7219
+
7220
+ # # build spotify web api request parameters.
7221
+ # urlParms:dict = \
7222
+ # {
7223
+ # 'ids': ids,
7224
+ # }
7225
+ # if market is not None:
7226
+ # urlParms['market'] = market
7227
+
7228
+ # # execute spotify web api request.
7229
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/episodes')
7230
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
7231
+ # msg.UrlParameters = urlParms
7232
+ # self.MakeRequest('GET', msg)
7233
+
7234
+ # # process results.
7235
+ # items = msg.ResponseData.get('episodes',None)
7236
+ # if items is not None:
7237
+ # for item in items:
7238
+ # result.append(Episode(root=item))
7233
7239
 
7234
7240
  # trace.
7235
7241
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[Episode]'), result)
@@ -8705,18 +8711,25 @@ class SpotifyClient:
8705
8711
  else:
8706
8712
  result.ItemType = SpotifyMediaTypes.PODCAST.value
8707
8713
 
8708
- # check for a restricted device; if found, then grab the device id from the
8709
- # cached list of spotify connect devices (if present).
8714
+ # if device id is not present (e.g. a restricted device), then get the device id
8715
+ # from the cached list of spotify connect devices (if present).
8710
8716
  if (not result.IsEmpty):
8711
8717
  device:Device = result.Device
8712
8718
  if (device is not None) and (device.Id is None or device.Id == ''):
8713
- cacheKey:str = 'GetSpotifyConnectDevices'
8719
+ cacheKey:str = CACHE_KEY_GETSPOTIFYCONNECTDEVICES
8714
8720
  if (cacheKey in self._ConfigurationCache):
8715
8721
  devices:SpotifyConnectDevices = self._ConfigurationCache[cacheKey]
8716
8722
  scDevice:SpotifyConnectDevice = devices.GetDeviceByName(device.Name)
8717
8723
  if scDevice is not None:
8718
8724
  device.Id = scDevice.DeviceInfo.DeviceId
8719
-
8725
+ # is this a Sonos device? if so, then update the music source.
8726
+ # at this point, it will probably be "SPOTIFY_CONNECT" since it was
8727
+ # detected in the Spotify Web API device list.
8728
+ if (scDevice.IsSonos):
8729
+ sonosPlayer = self._SpotifyConnectDirectory.GetSonosPlayer(scDevice)
8730
+ if (sonosPlayer):
8731
+ result.DeviceMusicSource = sonosPlayer.music_source
8732
+
8720
8733
  # did Spotify return a playstate?
8721
8734
  # if so, then update the player last played info if something is playing.
8722
8735
  if (not result.IsEmpty):
@@ -8796,6 +8809,16 @@ class SpotifyClient:
8796
8809
  playerState.IsDeviceState = True
8797
8810
  playerState.DeviceMusicSource = "" + str(sonosPlayer.music_source)
8798
8811
 
8812
+ # at this point, the the device music_source is probably set to one of the following:
8813
+ # - "UNKNOWN": indicates that Spotify is POSSIBLY playing from the Sonos local queue.
8814
+ # - "SPOTIFY_CONNECT": indicates that Spotify is playing via Spotify Connect using Spotify App.
8815
+ # if not SPOTIFY_CONNECT, then check the currently playing track info to see if it's
8816
+ # a Spotify uri; if so, then it's (probably) playing Spotify from the local queue, so
8817
+ # we will set the music source to the "SPOTIFY_LOCAL_QUEUE" custom value.
8818
+ if (playerState.DeviceMusicSource != MUSIC_SOURCE_SPOTIFY_CONNECT):
8819
+ if (sonosTrackInfo.get('uri','').startswith("x-sonos-spotify:")):
8820
+ playerState.DeviceMusicSource = MUSIC_SOURCE_SPOTIFY_LOCAL_QUEUE
8821
+
8799
8822
  # update Spotify Web API player state with Sonos player state.
8800
8823
  playerState._Device._Id = scDevice.Id
8801
8824
  playerState._Device._Name = sonosPlayer.player_name
@@ -10492,14 +10515,6 @@ class SpotifyClient:
10492
10515
  market:str=None,
10493
10516
  ) -> list[ShowSimplified]:
10494
10517
  """
10495
- <span class="deprecated">
10496
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
10497
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
10498
- More information about the deprecated functionality can be found on the
10499
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
10500
- page.
10501
- </span>
10502
-
10503
10518
  Get Spotify catalog information for several shows based on their Spotify IDs.
10504
10519
 
10505
10520
  Args:
@@ -10526,6 +10541,8 @@ class SpotifyClient:
10526
10541
  SpotifyApiError:
10527
10542
  If the method fails for any other reason.
10528
10543
 
10544
+ Note that `ShowSimplified` details do not contain episode data.
10545
+
10529
10546
  Important policy notes:
10530
10547
  - Spotify content may not be downloaded.
10531
10548
  - Keep visual content in its original form.
@@ -10550,37 +10567,45 @@ class SpotifyClient:
10550
10567
  apiMethodParms.AppendKeyValue("market", market)
10551
10568
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple shows", apiMethodParms)
10552
10569
 
10553
- # are spotify web player credentials configured? if so, then we will use them to create
10554
- # an elevated authorization access token for the Spotify Web API endpoint call.
10555
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
10556
-
10557
- # if spotify web player credentials not configured then we are done; the Spotify Web API
10558
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
10559
- if (accessTokenHeaderValue is None):
10560
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
10561
-
10562
10570
  # ensure market was either supplied or implied; default if neither.
10563
10571
  market = self._ValidateMarket(market)
10564
10572
 
10565
- # build spotify web api request parameters.
10566
- urlParms:dict = \
10567
- {
10568
- 'ids': ids,
10569
- }
10570
- if market is not None:
10571
- urlParms['market'] = market
10572
-
10573
- # execute spotify web api request.
10574
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/shows')
10575
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
10576
- msg.UrlParameters = urlParms
10577
- self.MakeRequest('GET', msg)
10573
+ # if ids not specified, then we are done.
10574
+ if (ids is None) or (len(ids.strip()) == 0):
10575
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
10578
10576
 
10579
- # process results.
10580
- items = msg.ResponseData.get('shows',None)
10581
- if items is not None:
10582
- for item in items:
10583
- result.append(ShowSimplified(root=item))
10577
+ # build list of all input item id's, and retrieve them one-by-one.
10578
+ ids = ids.replace(" ", "")
10579
+ arrIds:list[str] = ids.split(',')
10580
+ for strId in arrIds:
10581
+ dataObj = self.GetShow(strId, market)
10582
+ # convert Show object to a ShowSimplified object.
10583
+ dataObj._Episodes = None
10584
+ result.append(dataObj)
10585
+
10586
+ # ------------------------------------------------------------------------------------------
10587
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
10588
+ # ------------------------------------------------------------------------------------------
10589
+
10590
+ # # build spotify web api request parameters.
10591
+ # urlParms:dict = \
10592
+ # {
10593
+ # 'ids': ids,
10594
+ # }
10595
+ # if market is not None:
10596
+ # urlParms['market'] = market
10597
+
10598
+ # # execute spotify web api request.
10599
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/shows')
10600
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
10601
+ # msg.UrlParameters = urlParms
10602
+ # self.MakeRequest('GET', msg)
10603
+
10604
+ # # process results.
10605
+ # items = msg.ResponseData.get('shows',None)
10606
+ # if items is not None:
10607
+ # for item in items:
10608
+ # result.append(ShowSimplified(root=item))
10584
10609
 
10585
10610
  # trace.
10586
10611
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[ShowSimplified]'), result)
@@ -10869,7 +10894,7 @@ class SpotifyClient:
10869
10894
  # was the Sonos device music source set to SPOTIFY_CONNECT?
10870
10895
  # if not, then issue a Disconnect to (hopefully) reset the music source. this should allow
10871
10896
  # the subsequent Connect to re-establish a SPOTIFY_CONNECT music source on the Sonos device.
10872
- if sonosMusicSource != "SPOTIFY_CONNECT":
10897
+ if sonosMusicSource != MUSIC_SOURCE_SPOTIFY_CONNECT:
10873
10898
  _logsi.LogVerbose("Issuing Disconnect to Sonos Spotify Connect device %s" % (scDevice.Title))
10874
10899
  zcfResult = zconn.Disconnect(ignoreStatusResult=True)
10875
10900
 
@@ -10893,7 +10918,7 @@ class SpotifyClient:
10893
10918
 
10894
10919
  # was the Sonos device music source set to Spotify Connect?
10895
10920
  # if not, then it's a lost cause at this point since it's probably in an UNKNOWN state.
10896
- if sonosMusicSource != "SPOTIFY_CONNECT":
10921
+ if sonosMusicSource != MUSIC_SOURCE_SPOTIFY_CONNECT:
10897
10922
  _logsi.LogVerbose("Sonos device %s music source after Connect is not SPOTIFY_CONNECT; it will probably fail to play" % (scDevice.Title))
10898
10923
  elif (self.HasSpotifyWebPlayerCredentials):
10899
10924
  # if using Spotify Web Player credentials, then we don't have to wait for device.
@@ -11048,7 +11073,7 @@ class SpotifyClient:
11048
11073
  result = self._SpotifyConnectDirectory.GetDevices()
11049
11074
 
11050
11075
  # update cache.
11051
- self._ConfigurationCache[apiMethodName] = result
11076
+ self._ConfigurationCache[CACHE_KEY_GETSPOTIFYCONNECTDEVICES] = result
11052
11077
 
11053
11078
  # trace.
11054
11079
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE_CACHED % (apiMethodName, type(result).__name__, cacheDesc), result)
@@ -11491,14 +11516,6 @@ class SpotifyClient:
11491
11516
  market:str=None,
11492
11517
  ) -> list[Track]:
11493
11518
  """
11494
- <span class="deprecated">
11495
- DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
11496
- The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
11497
- More information about the deprecated functionality can be found on the
11498
- <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
11499
- page.
11500
- </span>
11501
-
11502
11519
  Get Spotify catalog information for multiple tracks based on their Spotify IDs.
11503
11520
 
11504
11521
  Args:
@@ -11544,37 +11561,42 @@ class SpotifyClient:
11544
11561
  apiMethodParms.AppendKeyValue("market", market)
11545
11562
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple tracks", apiMethodParms)
11546
11563
 
11547
- # are spotify web player credentials configured? if so, then we will use them to create
11548
- # an elevated authorization access token for the Spotify Web API endpoint call.
11549
- accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
11550
-
11551
- # if spotify web player credentials not configured then we are done; the Spotify Web API
11552
- # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
11553
- if (accessTokenHeaderValue is None):
11554
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
11555
-
11556
11564
  # ensure we have a market value, in order to return track relinking (e.g. `linked_from`) data.
11557
11565
  market = self._ValidateMarket(market, forceReturnValue=True)
11558
11566
 
11559
- # build spotify web api request parameters.
11560
- urlParms:dict = \
11561
- {
11562
- 'ids': ids
11563
- }
11564
- if market is not None:
11565
- urlParms['market'] = market
11566
-
11567
- # execute spotify web api request.
11568
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/tracks')
11569
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11570
- msg.UrlParameters = urlParms
11571
- self.MakeRequest('GET', msg)
11567
+ # if ids not specified, then we are done.
11568
+ if (ids is None) or (len(ids.strip()) == 0):
11569
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
11572
11570
 
11573
- # process results.
11574
- items = msg.ResponseData.get('tracks',None)
11575
- if items is not None:
11576
- for item in items:
11577
- result.append(Track(root=item))
11571
+ # build list of all input item id's, and retrieve them one-by-one.
11572
+ ids = ids.replace(" ", "")
11573
+ arrIds:list[str] = ids.split(',')
11574
+ for strId in arrIds:
11575
+ result.append(self.GetTrack(strId, market))
11576
+
11577
+ # ------------------------------------------------------------------------------------------
11578
+ # the following is the pre-2026/02/11 endpoint for retrieving this information.
11579
+ # ------------------------------------------------------------------------------------------
11580
+
11581
+ # # build spotify web api request parameters.
11582
+ # urlParms:dict = \
11583
+ # {
11584
+ # 'ids': ids
11585
+ # }
11586
+ # if market is not None:
11587
+ # urlParms['market'] = market
11588
+
11589
+ # # execute spotify web api request.
11590
+ # msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/tracks')
11591
+ # msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11592
+ # msg.UrlParameters = urlParms
11593
+ # self.MakeRequest('GET', msg)
11594
+
11595
+ # # process results.
11596
+ # items = msg.ResponseData.get('tracks',None)
11597
+ # if items is not None:
11598
+ # for item in items:
11599
+ # result.append(Track(root=item))
11578
11600
 
11579
11601
  # trace.
11580
11602
  _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, 'list[Track]'), result)