spotifywebapiPython 1.0.259__py3-none-any.whl → 1.0.261__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 (32) hide show
  1. spotifywebapipython/__init__.py +2 -0
  2. spotifywebapipython/const.py +1 -1
  3. spotifywebapipython/docs/__init__.html +23 -2
  4. spotifywebapipython/docs/index.html +8 -2
  5. spotifywebapipython/docs/search.js +1 -1
  6. spotifywebapipython/docs/spotifywebapipython/const.html +3 -3
  7. spotifywebapipython/docs/spotifywebapipython/saappmessages.html +26 -8
  8. spotifywebapipython/docs/spotifywebapipython/sautils.html +2 -2
  9. spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +2 -2
  10. spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +2 -2
  11. spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +2 -2
  12. spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +494 -82
  13. spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +2 -2
  14. spotifywebapipython/docs/spotifywebapipython/spotifymediatypes.html +441 -0
  15. spotifywebapipython/docs/spotifywebapipython/spotifytypeprefixes.html +458 -0
  16. spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +2 -2
  17. spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +2 -2
  18. spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +2 -2
  19. spotifywebapipython/models/zeroconfdiscoveryresult.py +1 -1
  20. spotifywebapipython/saappmessages.py +6 -1
  21. spotifywebapipython/spotifyclient.py +1020 -344
  22. spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py +64 -7
  23. spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py +6 -0
  24. spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py +42 -13
  25. spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py +12 -0
  26. spotifywebapipython/spotifymediatypes.py +10 -10
  27. spotifywebapipython/spotifytypeprefixes.py +65 -0
  28. {spotifywebapipython-1.0.259.dist-info → spotifywebapipython-1.0.261.dist-info}/METADATA +1 -1
  29. {spotifywebapipython-1.0.259.dist-info → spotifywebapipython-1.0.261.dist-info}/RECORD +32 -29
  30. {spotifywebapipython-1.0.259.dist-info → spotifywebapipython-1.0.261.dist-info}/LICENSE +0 -0
  31. {spotifywebapipython-1.0.259.dist-info → spotifywebapipython-1.0.261.dist-info}/WHEEL +0 -0
  32. {spotifywebapipython-1.0.259.dist-info → spotifywebapipython-1.0.261.dist-info}/top_level.txt +0 -0
@@ -31,6 +31,7 @@ from .spotifyapierror import SpotifyApiError
31
31
  from .spotifyapimessage import SpotifyApiMessage
32
32
  from .spotifyauthtoken import SpotifyAuthToken
33
33
  from .spotifymediatypes import SpotifyMediaTypes
34
+ from .spotifytypeprefixes import SpotifyTypePrefixes
34
35
  from .spotifywebapiauthenticationerror import SpotifyWebApiAuthenticationError
35
36
  from .spotifywebapierror import SpotifyWebApiError
36
37
  from .spotifywebplayertoken import SpotifyWebPlayerToken
@@ -251,6 +252,7 @@ class SpotifyClient:
251
252
  # create the zeroconf client if one was not specified.
252
253
  if zeroconfClient is None:
253
254
  _logsi.LogVerbose("Creating new Zeroconf instance for discovery")
255
+ #self._ZeroconfClient = Zeroconf(ip_version=None, interfaces=InterfaceChoice.All) #class IPVersion(enum.Enum): Default=None, V4Only=1, V6Only=2, Any=3
254
256
  self._ZeroconfClient = Zeroconf()
255
257
  else:
256
258
  _logsi.LogObject(SILevel.Verbose, "Using existing Zeroconf instance for discovery", zeroconfClient)
@@ -1691,7 +1693,7 @@ class SpotifyClient:
1691
1693
  break
1692
1694
 
1693
1695
  # execute spotify web api request.
1694
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/images'.format(playlist_id=playlistId))
1696
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/images'.format(id=playlistId))
1695
1697
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
1696
1698
  msg.RequestHeaders['Content-Type'] = 'image/jpeg'
1697
1699
  msg.RequestData = base64.b64encode(fData.getvalue()).decode('utf-8')
@@ -1754,6 +1756,10 @@ class SpotifyClient:
1754
1756
  SpotifyApiError:
1755
1757
  If the method fails for any other reason.
1756
1758
 
1759
+ All specified items are added to the playlist, even if any of the items already exist
1760
+ in the playlist. You must check for duplicates prior to adding items if you want to
1761
+ prevent duplicate items in the list.
1762
+
1757
1763
  <details>
1758
1764
  <summary>Sample Code</summary>
1759
1765
  ```python
@@ -1795,7 +1801,7 @@ class SpotifyClient:
1795
1801
  reqData['position'] = position
1796
1802
 
1797
1803
  # execute spotify web api request.
1798
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/tracks'.format(playlist_id=playlistId))
1804
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/items'.format(id=playlistId))
1799
1805
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
1800
1806
  msg.RequestJson = reqData
1801
1807
  self.MakeRequest('POST', msg)
@@ -1920,7 +1926,7 @@ class SpotifyClient:
1920
1926
  raise ValueError('no details were provided to change.')
1921
1927
 
1922
1928
  # execute spotify web api request.
1923
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}'.format(playlist_id=playlistId))
1929
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}'.format(id=playlistId))
1924
1930
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
1925
1931
  msg.RequestJson = reqData
1926
1932
  self.MakeRequest('PUT', msg)
@@ -1962,8 +1968,8 @@ class SpotifyClient:
1962
1968
 
1963
1969
  Args:
1964
1970
  ids (str):
1965
- A comma-separated list of the Spotify IDs for the albums.
1966
- Maximum: 20 IDs.
1971
+ A comma-separated list of the Spotify ID's (or URI's) for the albums.
1972
+ Maximum: 40 IDs.
1967
1973
  Example: `6vc9OTcyd3hyzabCmsdnwE,2noRn2Aes5aoNVsU6iWThc`
1968
1974
  If null, the currently playing album uri id value is used.
1969
1975
 
@@ -1996,6 +2002,10 @@ class SpotifyClient:
1996
2002
  apiMethodParms.AppendKeyValue("ids", ids)
1997
2003
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if one or more albums are saved in a user's favorites", apiMethodParms)
1998
2004
 
2005
+ # remove any leading / trailing spaces.
2006
+ if ids is not None:
2007
+ ids = ids.replace(' ','')
2008
+
1999
2009
  # if ids not specified, then return currently playing album id value.
2000
2010
  if (ids is None) or (len(ids.strip()) == 0):
2001
2011
  uri = self.GetPlayerNowPlayingAlbumUri()
@@ -2004,25 +2014,29 @@ class SpotifyClient:
2004
2014
  else:
2005
2015
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2006
2016
 
2017
+ # build a list of all item uri's from id values.
2018
+ # remove any leading / trailing spaces in case user put a space between the items.
2019
+ arrUris:list[str] = ids.split(',')
2020
+ for idx in range(0, len(arrUris)):
2021
+ if (arrUris[idx].find(":") == -1):
2022
+ arrUris[idx] = SpotifyTypePrefixes.ALBUM.value + arrUris[idx].strip()
2023
+
2007
2024
  # build spotify web api request parameters.
2008
2025
  urlParms:dict = \
2009
2026
  {
2010
- 'ids': ids
2027
+ 'uris': ",".join(arrUris)
2011
2028
  }
2012
2029
 
2013
2030
  # execute spotify web api request.
2014
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/albums/contains')
2031
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2015
2032
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2016
2033
  msg.UrlParameters = urlParms
2017
2034
  self.MakeRequest('GET', msg)
2018
2035
 
2019
- # build list of all input album id's.
2020
- arrIds:list[str] = ids.split(',')
2021
-
2022
2036
  # process results.
2023
2037
  flags:list[bool] = msg.ResponseData
2024
2038
  flagPtr:int = 0
2025
- for strId in arrIds:
2039
+ for strId in arrUris:
2026
2040
  if strId not in result:
2027
2041
  result[strId] = flags[flagPtr]
2028
2042
  flagPtr = flagPtr + 1
@@ -2057,7 +2071,7 @@ class SpotifyClient:
2057
2071
  Args:
2058
2072
  ids (str):
2059
2073
  A comma-separated list of Spotify artist ID's to check.
2060
- Maximum: 50 ID's.
2074
+ Maximum: 40 ID's.
2061
2075
  Example: `2CIMQHirSU0MQqyYHq0eOx,1IQ2e1buppatiN1bxUVkrk`
2062
2076
  If null, the currently playing artist uri id value is used.
2063
2077
 
@@ -2090,7 +2104,7 @@ class SpotifyClient:
2090
2104
  apiMethodParms.AppendKeyValue("ids", ids)
2091
2105
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if user is following one or more artists", apiMethodParms)
2092
2106
 
2093
- # remove any leading / trailing spaces in case user put a space between the items.
2107
+ # remove any leading / trailing spaces.
2094
2108
  if ids is not None:
2095
2109
  ids = ids.replace(' ','')
2096
2110
 
@@ -2102,30 +2116,33 @@ class SpotifyClient:
2102
2116
  else:
2103
2117
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2104
2118
 
2119
+ # build a list of all item uri's from id values.
2120
+ # remove any leading / trailing spaces in case user put a space between the items.
2121
+ arrUris:list[str] = ids.split(',')
2122
+ for idx in range(0, len(arrUris)):
2123
+ if (arrUris[idx].find(":") == -1):
2124
+ arrUris[idx] = SpotifyTypePrefixes.ARTIST.value + arrUris[idx].strip()
2125
+
2105
2126
  # build spotify web api request parameters.
2106
2127
  urlParms:dict = \
2107
2128
  {
2108
- 'type': SpotifyMediaTypes.ARTIST.value,
2109
- 'ids': ids
2129
+ 'uris': ",".join(arrUris)
2110
2130
  }
2111
2131
 
2112
2132
  # execute spotify web api request.
2113
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following/contains')
2133
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2114
2134
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2115
2135
  msg.UrlParameters = urlParms
2116
2136
  self.MakeRequest('GET', msg)
2117
2137
 
2118
- # build list of all input id's.
2119
- arrIds:list[str] = ids.split(',')
2120
-
2121
- # process results.
2138
+ # process results.
2122
2139
  flags:list[bool] = msg.ResponseData
2123
2140
  flagPtr:int = 0
2124
- for strId in arrIds:
2141
+ for strId in arrUris:
2125
2142
  if strId not in result:
2126
2143
  result[strId] = flags[flagPtr]
2127
2144
  flagPtr = flagPtr + 1
2128
-
2145
+
2129
2146
  # trace.
2130
2147
  _logsi.LogDictionary(SILevel.Verbose, TRACE_METHOD_RESULT % apiMethodName, result)
2131
2148
  return result
@@ -2156,8 +2173,8 @@ class SpotifyClient:
2156
2173
 
2157
2174
  Args:
2158
2175
  ids (str):
2159
- A comma-separated list of the Spotify IDs for the audiobooks.
2160
- Maximum: 50 IDs.
2176
+ A comma-separated list of the Spotify ID's (or URI's) for the audiobooks.
2177
+ Maximum: 40 IDs.
2161
2178
  Example: `74aydHJKgYz3AIq3jjBSv1,4nfQ1hBJWjD0Jq9sK3YRW8,3PFyizE2tGCSRLusl2Qizf`
2162
2179
  If null, the currently playing audiobook uri id value is used.
2163
2180
 
@@ -2190,6 +2207,10 @@ class SpotifyClient:
2190
2207
  apiMethodParms.AppendKeyValue("ids", ids)
2191
2208
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if one or more audiobooks are saved in a user's favorites", apiMethodParms)
2192
2209
 
2210
+ # remove any leading / trailing spaces.
2211
+ if ids is not None:
2212
+ ids = ids.replace(' ','')
2213
+
2193
2214
  # if ids not specified, then return currently playing id value.
2194
2215
  if (ids is None) or (len(ids.strip()) == 0):
2195
2216
  uri = self.GetPlayerNowPlayingAudiobookUri()
@@ -2198,25 +2219,29 @@ class SpotifyClient:
2198
2219
  else:
2199
2220
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2200
2221
 
2222
+ # build a list of all item uri's from id values.
2223
+ # remove any leading / trailing spaces in case user put a space between the items.
2224
+ arrUris:list[str] = ids.split(',')
2225
+ for idx in range(0, len(arrUris)):
2226
+ if (arrUris[idx].find(":") == -1):
2227
+ arrUris[idx] = SpotifyTypePrefixes.SHOW.value + arrUris[idx].strip() # spotify web api considers audiobook a "show"!
2228
+
2201
2229
  # build spotify web api request parameters.
2202
2230
  urlParms:dict = \
2203
2231
  {
2204
- 'ids': ids
2232
+ 'uris': ",".join(arrUris)
2205
2233
  }
2206
2234
 
2207
2235
  # execute spotify web api request.
2208
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/audiobooks/contains')
2236
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2209
2237
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2210
2238
  msg.UrlParameters = urlParms
2211
2239
  self.MakeRequest('GET', msg)
2212
2240
 
2213
- # build list of all input album id's.
2214
- arrIds:list[str] = ids.split(',')
2215
-
2216
2241
  # process results.
2217
2242
  flags:list[bool] = msg.ResponseData
2218
2243
  flagPtr:int = 0
2219
- for strId in arrIds:
2244
+ for strId in arrUris:
2220
2245
  if strId not in result:
2221
2246
  result[strId] = flags[flagPtr]
2222
2247
  flagPtr = flagPtr + 1
@@ -2251,8 +2276,8 @@ class SpotifyClient:
2251
2276
 
2252
2277
  Args:
2253
2278
  ids (str):
2254
- A comma-separated list of the Spotify IDs for the episodes.
2255
- Maximum: 50 IDs.
2279
+ A comma-separated list of the Spotify ID's (or URI's) for the episodes.
2280
+ Maximum: 40 IDs.
2256
2281
  Example: `1kWUud3vY5ij5r62zxpTRy,2takcwOaAZWiXQijPHIx7B`
2257
2282
  If null, the currently playing episode uri id value is used.
2258
2283
 
@@ -2285,6 +2310,10 @@ class SpotifyClient:
2285
2310
  apiMethodParms.AppendKeyValue("ids", ids)
2286
2311
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if one or more episodes are saved in a user's favorites", apiMethodParms)
2287
2312
 
2313
+ # remove any leading / trailing spaces.
2314
+ if ids is not None:
2315
+ ids = ids.replace(' ','')
2316
+
2288
2317
  # if ids not specified, then return currently playing id value.
2289
2318
  if (ids is None) or (len(ids.strip()) == 0):
2290
2319
  uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.EPISODE.value)
@@ -2293,25 +2322,29 @@ class SpotifyClient:
2293
2322
  else:
2294
2323
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2295
2324
 
2325
+ # build a list of all item uri's from id values.
2326
+ # remove any leading / trailing spaces in case user put a space between the items.
2327
+ arrUris:list[str] = ids.split(',')
2328
+ for idx in range(0, len(arrUris)):
2329
+ if (arrUris[idx].find(":") == -1):
2330
+ arrUris[idx] = SpotifyTypePrefixes.EPISODE.value + arrUris[idx].strip()
2331
+
2296
2332
  # build spotify web api request parameters.
2297
2333
  urlParms:dict = \
2298
2334
  {
2299
- 'ids': ids
2335
+ 'uris': ",".join(arrUris)
2300
2336
  }
2301
2337
 
2302
2338
  # execute spotify web api request.
2303
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/episodes/contains')
2339
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2304
2340
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2305
2341
  msg.UrlParameters = urlParms
2306
2342
  self.MakeRequest('GET', msg)
2307
2343
 
2308
- # build list of all input album id's.
2309
- arrIds:list[str] = ids.split(',')
2310
-
2311
2344
  # process results.
2312
2345
  flags:list[bool] = msg.ResponseData
2313
2346
  flagPtr:int = 0
2314
- for strId in arrIds:
2347
+ for strId in arrUris:
2315
2348
  if strId not in result:
2316
2349
  result[strId] = flags[flagPtr]
2317
2350
  flagPtr = flagPtr + 1
@@ -2336,7 +2369,7 @@ class SpotifyClient:
2336
2369
 
2337
2370
  def CheckPlaylistFollowers(
2338
2371
  self,
2339
- playlistId:str,
2372
+ playlistId:str=None,
2340
2373
  userIds:str=None,
2341
2374
  ) -> dict:
2342
2375
  """
@@ -2344,13 +2377,12 @@ class SpotifyClient:
2344
2377
 
2345
2378
  Args:
2346
2379
  playlistId (str):
2347
- The Spotify ID of the playlist.
2380
+ A comma-separated list of Spotify playlist IDs.
2381
+ A maximum of 40 IDs can be sent in one request.
2348
2382
  Example: `3cEYpjA9oz9GiPac4AsH4n`
2383
+ If null, the currently playing playlist uri id value is used.
2349
2384
  userIds (str):
2350
- DEPRECATED - A single item list containing current user's Spotify Username; Maximum of 1 id.
2351
- A comma-separated list of Spotify User ID's to check.
2352
- Maximum: 5 ID's.
2353
- Example: `1kWUud3vY5ij5r62zxpTRy,2takcwOaAZWiXQijPHIx7B`
2385
+ DEPRECATED - no longer used, but left here to maintain compatibility.
2354
2386
 
2355
2387
  Returns:
2356
2388
  Array of boolean, containing a single boolean status that indicates
@@ -2366,7 +2398,6 @@ class SpotifyClient:
2366
2398
  As of (at least) 2024/10/07, Spotify has deprecated the userId's argument;
2367
2399
  only current user can be tested. Any other id's specified on this argument will
2368
2400
  generate a `400 Bad Request` error.
2369
-
2370
2401
 
2371
2402
  <details>
2372
2403
  <summary>Sample Code</summary>
@@ -2387,29 +2418,37 @@ class SpotifyClient:
2387
2418
  apiMethodParms.AppendKeyValue("userIds (DEPRECATED)", userIds)
2388
2419
  _logsi.LogMethodParmList(SILevel.Verbose, "Check to see if users are following a playlist", apiMethodParms)
2389
2420
 
2390
- # validations.
2391
- if (userIds is None):
2392
- userIds = self.UserProfile.Id
2421
+ # if playlistId not specified, then return currently playing playlist id value.
2422
+ if (playlistId is None) or (len(playlistId.strip()) == 0):
2423
+ uri = self.GetPlayerNowPlayingPlaylistUri()
2424
+ if uri is not None:
2425
+ playlistId = SpotifyClient.GetIdFromUri(uri)
2426
+ else:
2427
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'playlistId'), logsi=_logsi)
2428
+
2429
+ # build a list of all item uri's from id values.
2430
+ # remove any leading / trailing spaces in case user put a space between the items.
2431
+ arrUris:list[str] = playlistId.split(',')
2432
+ for idx in range(0, len(arrUris)):
2433
+ if (arrUris[idx].find(":") == -1):
2434
+ arrUris[idx] = SpotifyTypePrefixes.PLAYLIST.value + arrUris[idx].strip()
2393
2435
 
2394
2436
  # build spotify web api request parameters.
2395
2437
  urlParms:dict = \
2396
2438
  {
2397
- 'ids': userIds
2439
+ 'uris': ",".join(arrUris)
2398
2440
  }
2399
2441
 
2400
2442
  # execute spotify web api request.
2401
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/followers/contains'.format(playlist_id=playlistId))
2443
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2402
2444
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2403
2445
  msg.UrlParameters = urlParms
2404
2446
  self.MakeRequest('GET', msg)
2405
2447
 
2406
- # build list of all input id's.
2407
- arrIds:list[str] = userIds.split(',')
2408
-
2409
2448
  # process results.
2410
2449
  flags:list[bool] = msg.ResponseData
2411
2450
  flagPtr:int = 0
2412
- for strId in arrIds:
2451
+ for strId in arrUris:
2413
2452
  if strId not in result:
2414
2453
  result[strId] = flags[flagPtr]
2415
2454
  flagPtr = flagPtr + 1
@@ -2444,8 +2483,8 @@ class SpotifyClient:
2444
2483
 
2445
2484
  Args:
2446
2485
  ids (str):
2447
- A comma-separated list of the Spotify IDs for the shows.
2448
- Maximum: 50 IDs.
2486
+ A comma-separated list of the Spotify ID's (or URI's) for the shows.
2487
+ Maximum: 40 IDs.
2449
2488
  Example: `1kWUud3vY5ij5r62zxpTRy,2takcwOaAZWiXQijPHIx7B`
2450
2489
  If null, the currently playing show uri id value is used.
2451
2490
 
@@ -2478,6 +2517,10 @@ class SpotifyClient:
2478
2517
  apiMethodParms.AppendKeyValue("ids", ids)
2479
2518
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if one or more shows are saved in a user's favorites", apiMethodParms)
2480
2519
 
2520
+ # remove any leading / trailing spaces.
2521
+ if ids is not None:
2522
+ ids = ids.replace(' ','')
2523
+
2481
2524
  # if ids not specified, then return currently playing id value.
2482
2525
  if (ids is None) or (len(ids.strip()) == 0):
2483
2526
  uri = self.GetPlayerNowPlayingShowUri()
@@ -2486,25 +2529,29 @@ class SpotifyClient:
2486
2529
  else:
2487
2530
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2488
2531
 
2532
+ # build a list of all item uri's from id values.
2533
+ # remove any leading / trailing spaces in case user put a space between the items.
2534
+ arrUris:list[str] = ids.split(',')
2535
+ for idx in range(0, len(arrUris)):
2536
+ if (arrUris[idx].find(":") == -1):
2537
+ arrUris[idx] = SpotifyTypePrefixes.SHOW.value + arrUris[idx].strip()
2538
+
2489
2539
  # build spotify web api request parameters.
2490
2540
  urlParms:dict = \
2491
2541
  {
2492
- 'ids': ids
2542
+ 'uris': ",".join(arrUris)
2493
2543
  }
2494
2544
 
2495
2545
  # execute spotify web api request.
2496
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/shows/contains')
2546
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2497
2547
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2498
2548
  msg.UrlParameters = urlParms
2499
2549
  self.MakeRequest('GET', msg)
2500
2550
 
2501
- # build list of all input album id's.
2502
- arrIds:list[str] = ids.split(',')
2503
-
2504
2551
  # process results.
2505
2552
  flags:list[bool] = msg.ResponseData
2506
2553
  flagPtr:int = 0
2507
- for strId in arrIds:
2554
+ for strId in arrUris:
2508
2555
  if strId not in result:
2509
2556
  result[strId] = flags[flagPtr]
2510
2557
  flagPtr = flagPtr + 1
@@ -2539,8 +2586,8 @@ class SpotifyClient:
2539
2586
 
2540
2587
  Args:
2541
2588
  ids (str):
2542
- A comma-separated list of the Spotify IDs for the tracks.
2543
- Maximum: 50 IDs.
2589
+ A comma-separated list of the Spotify ID's (or URI's) for the tracks.
2590
+ Maximum: 40 IDs.
2544
2591
  Example: `1kWUud3vY5ij5r62zxpTRy,2takcwOaAZWiXQijPHIx7B`
2545
2592
  If null, the currently playing track uri id value is used.
2546
2593
 
@@ -2573,6 +2620,10 @@ class SpotifyClient:
2573
2620
  apiMethodParms.AppendKeyValue("ids", ids)
2574
2621
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if one or more tracks are saved in a user's favorites", apiMethodParms)
2575
2622
 
2623
+ # remove any leading / trailing spaces.
2624
+ if ids is not None:
2625
+ ids = ids.replace(' ','')
2626
+
2576
2627
  # if ids not specified, then return currently playing id value.
2577
2628
  if (ids is None) or (len(ids.strip()) == 0):
2578
2629
  uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.TRACK.value)
@@ -2581,25 +2632,122 @@ class SpotifyClient:
2581
2632
  else:
2582
2633
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2583
2634
 
2635
+ # build a list of all item uri's from id values.
2636
+ # remove any leading / trailing spaces in case user put a space between the items.
2637
+ arrUris:list[str] = ids.split(',')
2638
+ for idx in range(0, len(arrUris)):
2639
+ if (arrUris[idx].find(":") == -1):
2640
+ arrUris[idx] = SpotifyTypePrefixes.TRACK.value + arrUris[idx].strip()
2641
+
2584
2642
  # build spotify web api request parameters.
2585
2643
  urlParms:dict = \
2586
2644
  {
2587
- 'ids': ids
2645
+ 'uris': ",".join(arrUris)
2646
+ }
2647
+
2648
+ # execute spotify web api request.
2649
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2650
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2651
+ msg.UrlParameters = urlParms
2652
+ self.MakeRequest('GET', msg)
2653
+
2654
+ # process results.
2655
+ flags:list[bool] = msg.ResponseData
2656
+ flagPtr:int = 0
2657
+ for strId in arrUris:
2658
+ if strId not in result:
2659
+ result[strId] = flags[flagPtr]
2660
+ flagPtr = flagPtr + 1
2661
+
2662
+ # trace.
2663
+ _logsi.LogDictionary(SILevel.Verbose, TRACE_METHOD_RESULT % apiMethodName, result)
2664
+ return result
2665
+
2666
+ except SpotifyApiError: raise # pass handled exceptions on thru
2667
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
2668
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
2669
+ except Exception as ex:
2670
+
2671
+ # format unhandled exception.
2672
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
2673
+
2674
+ finally:
2675
+
2676
+ # trace.
2677
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
2678
+
2679
+
2680
+ def CheckUserFavorites(
2681
+ self,
2682
+ uris:str=None,
2683
+ ) -> dict:
2684
+ """
2685
+ Check if one or more items are already saved in the current user's library.
2686
+ Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, artists, users, and playlists.
2687
+
2688
+ This method requires the `user-library-read`, `user-follow-read`, and `playlist-read-private` scopes.
2689
+
2690
+ Args:
2691
+ uris (str):
2692
+ A comma-separated list of the Spotify URIs for the items.
2693
+ Maximum: 40 URIs.
2694
+ Example: `spotify:artist:6APm8EjxOHSYM5B4i3vT3q,spotify:album:6vc9OTcyd3hyzabCmsdnwE,spotify:track:1kWUud3vY5ij5r62zxpTRy`
2695
+ If null, the currently playing item uri value is used.
2696
+
2697
+ Returns:
2698
+ A dictionary of the uris, along with a boolean status for each that indicates
2699
+ if the item is saved (True) in the users 'Your Library' or not (False).
2700
+
2701
+ Raises:
2702
+ SpotifyWebApiError:
2703
+ If the Spotify Web API request was for a non-authorization service
2704
+ and the response contains error information.
2705
+ SpotifyApiError:
2706
+ If the method fails for any other reason.
2707
+
2708
+ <details>
2709
+ <summary>Sample Code</summary>
2710
+ ```python
2711
+ .. include:: ../docs/include/samplecode/SpotifyClient/CheckUserFavorites.py
2712
+ ```
2713
+ </details>
2714
+ """
2715
+ apiMethodName:str = 'CheckUserFavorites'
2716
+ apiMethodParms:SIMethodParmListContext = None
2717
+ result:dict = {}
2718
+
2719
+ try:
2720
+
2721
+ # trace.
2722
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
2723
+ apiMethodParms.AppendKeyValue("uris", uris)
2724
+ _logsi.LogMethodParmList(SILevel.Verbose, "Check if one or more items are saved in a user's favorites", apiMethodParms)
2725
+
2726
+ # if uris not specified, then return currently playing item uri value.
2727
+ if (uris is None) or (len(uris.strip()) == 0):
2728
+ uris = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.EPISODE.value, False)
2729
+ if uris is None:
2730
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'uris'), logsi=_logsi)
2731
+
2732
+ # build spotify web api request parameters.
2733
+ urlParms:dict = \
2734
+ {
2735
+ 'uris': uris
2588
2736
  }
2589
2737
 
2590
2738
  # execute spotify web api request.
2591
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/tracks/contains')
2739
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2592
2740
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2593
2741
  msg.UrlParameters = urlParms
2594
2742
  self.MakeRequest('GET', msg)
2595
2743
 
2596
- # build list of all input album id's.
2597
- arrIds:list[str] = ids.split(',')
2744
+ # build list of all input item uri's.
2745
+ arrUris:list[str] = uris.split(',')
2598
2746
 
2599
2747
  # process results.
2600
2748
  flags:list[bool] = msg.ResponseData
2601
2749
  flagPtr:int = 0
2602
- for strId in arrIds:
2750
+ for strId in arrUris:
2603
2751
  if strId not in result:
2604
2752
  result[strId] = flags[flagPtr]
2605
2753
  flagPtr = flagPtr + 1
@@ -2666,30 +2814,37 @@ class SpotifyClient:
2666
2814
  apiMethodParms.AppendKeyValue("ids", ids)
2667
2815
  _logsi.LogMethodParmList(SILevel.Verbose, "Check if user is following one or more users", apiMethodParms)
2668
2816
 
2669
- # remove any leading / trailing spaces in case user put a space between the items.
2817
+ # remove any leading / trailing spaces.
2670
2818
  if ids is not None:
2671
2819
  ids = ids.replace(' ','')
2672
2820
 
2821
+ # if ids not specified, then it's an error!
2822
+ if (ids is None) or (len(ids.strip()) == 0):
2823
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
2824
+
2825
+ # build a list of all item uri's from id values.
2826
+ # remove any leading / trailing spaces in case user put a space between the items.
2827
+ arrUris:list[str] = ids.split(',')
2828
+ for idx in range(0, len(arrUris)):
2829
+ if (arrUris[idx].find(":") == -1):
2830
+ arrUris[idx] = SpotifyTypePrefixes.USER.value + arrUris[idx].strip()
2831
+
2673
2832
  # build spotify web api request parameters.
2674
2833
  urlParms:dict = \
2675
2834
  {
2676
- 'type': 'user',
2677
- 'ids': ids
2835
+ 'uris': ",".join(arrUris)
2678
2836
  }
2679
2837
 
2680
2838
  # execute spotify web api request.
2681
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following/contains')
2839
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library/contains')
2682
2840
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2683
2841
  msg.UrlParameters = urlParms
2684
2842
  self.MakeRequest('GET', msg)
2685
2843
 
2686
- # build list of all input id's.
2687
- arrIds:list[str] = ids.split(',')
2688
-
2689
2844
  # process results.
2690
2845
  flags:list[bool] = msg.ResponseData
2691
2846
  flagPtr:int = 0
2692
- for strId in arrIds:
2847
+ for strId in arrUris:
2693
2848
  if strId not in result:
2694
2849
  result[strId] = flags[flagPtr]
2695
2850
  flagPtr = flagPtr + 1
@@ -2788,7 +2943,7 @@ class SpotifyClient:
2788
2943
  }
2789
2944
 
2790
2945
  # execute spotify web api request.
2791
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/tracks'.format(playlist_id=playlistId))
2946
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/items'.format(id=playlistId))
2792
2947
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2793
2948
  msg.RequestJson = reqData
2794
2949
  self.MakeRequest('PUT', msg)
@@ -2816,7 +2971,7 @@ class SpotifyClient:
2816
2971
 
2817
2972
  def CreatePlaylist(
2818
2973
  self,
2819
- userId:str,
2974
+ userId:str=None,
2820
2975
  name:str=None,
2821
2976
  description:str=None,
2822
2977
  public:bool=True,
@@ -2824,15 +2979,14 @@ class SpotifyClient:
2824
2979
  imagePath:str=None
2825
2980
  ) -> Playlist:
2826
2981
  """
2827
- Create an empty playlist for a Spotify user.
2982
+ Create an empty playlist for the current Spotify user.
2828
2983
 
2829
2984
  This method requires the `playlist-modify-public` and `playlist-modify-private` scope.
2830
-
2985
+
2831
2986
  Args:
2832
2987
 
2833
2988
  userId (str):
2834
- The user's Spotify user ID.
2835
- Example: `32k99y2kg5lnn3mxhtmd2bpdkjfu`
2989
+ DEPRECATED - no longer used, but left here to maintain compatibility.
2836
2990
  name (str):
2837
2991
  The name for the new playlist, for example "My Playlist".
2838
2992
  This name does not need to be unique; a user may have several playlists with
@@ -2894,7 +3048,7 @@ class SpotifyClient:
2894
3048
 
2895
3049
  # trace.
2896
3050
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
2897
- apiMethodParms.AppendKeyValue("userId", userId)
3051
+ apiMethodParms.AppendKeyValue("userId (DEPRECATED)", userId)
2898
3052
  apiMethodParms.AppendKeyValue("name", name)
2899
3053
  apiMethodParms.AppendKeyValue("description", description)
2900
3054
  apiMethodParms.AppendKeyValue("public", public)
@@ -2908,10 +3062,6 @@ class SpotifyClient:
2908
3062
  if (collaborative is None):
2909
3063
  collaborative = False
2910
3064
 
2911
- # if userId is not supplied, then use profile value.
2912
- if userId is None or len(userId.strip()) == 0:
2913
- userId = self.UserProfile.Id
2914
-
2915
3065
  # if collaborative is True, then force public to false as Spotify requires it.
2916
3066
  if collaborative:
2917
3067
  public = False
@@ -2919,14 +3069,14 @@ class SpotifyClient:
2919
3069
  # build spotify web api request parameters.
2920
3070
  reqData:dict = \
2921
3071
  {
2922
- 'name': '%s' % name,
2923
- 'description': '%s' % description,
2924
- 'public': public,
2925
- 'collaborative': collaborative,
3072
+ "name": "%s" % name,
3073
+ "description": "%s" % description,
3074
+ "public": public,
3075
+ "collaborative": collaborative
2926
3076
  }
2927
-
3077
+
2928
3078
  # execute spotify web api request.
2929
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{user_id}/playlists'.format(user_id=userId))
3079
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/playlists')
2930
3080
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
2931
3081
  msg.RequestJson = reqData
2932
3082
  self.MakeRequest('POST', msg)
@@ -2971,7 +3121,7 @@ class SpotifyClient:
2971
3121
  Args:
2972
3122
  ids (str):
2973
3123
  A comma-separated list of the Spotify artist IDs.
2974
- A maximum of 50 IDs can be sent in one request.
3124
+ A maximum of 40 IDs can be sent in one request.
2975
3125
  Example: `2CIMQHirSU0MQqyYHq0eOx,1IQ2e1buppatiN1bxUVkrk`
2976
3126
  If null, the currently playing track artist uri id value is used.
2977
3127
 
@@ -3001,6 +3151,10 @@ class SpotifyClient:
3001
3151
  apiMethodParms.AppendKeyValue("ids", ids)
3002
3152
  _logsi.LogMethodParmList(SILevel.Verbose, "Add the current user as a follower of one or more artists", apiMethodParms)
3003
3153
 
3154
+ # remove any leading / trailing spaces.
3155
+ if ids is not None:
3156
+ ids = ids.replace(' ','')
3157
+
3004
3158
  # if ids not specified, then return currently playing artist id value.
3005
3159
  if (ids is None) or (len(ids.strip()) == 0):
3006
3160
  uri = self.GetPlayerNowPlayingArtistUri()
@@ -3009,24 +3163,25 @@ class SpotifyClient:
3009
3163
  else:
3010
3164
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
3011
3165
 
3012
- # build a list of all item id's.
3166
+ # build a list of all item uri's from id values.
3013
3167
  # remove any leading / trailing spaces in case user put a space between the items.
3014
- arrIds:list[str] = ids.split(',')
3015
- for idx in range(0, len(arrIds)):
3016
- arrIds[idx] = arrIds[idx].strip()
3168
+ arrUris:list[str] = ids.split(',')
3169
+ for idx in range(0, len(arrUris)):
3170
+ if (arrUris[idx].find(":") == -1):
3171
+ arrUris[idx] = SpotifyTypePrefixes.ARTIST.value + arrUris[idx].strip()
3017
3172
 
3018
3173
  # build spotify web api request parameters.
3019
- reqData:dict = \
3174
+ urlParms:dict = \
3020
3175
  {
3021
- 'ids': arrIds
3176
+ 'uris': ",".join(arrUris)
3022
3177
  }
3023
3178
 
3024
3179
  # execute spotify web api request.
3025
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following?type=artist')
3180
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
3026
3181
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3027
- msg.RequestJson = reqData
3182
+ msg.UrlParameters = urlParms
3028
3183
  self.MakeRequest('PUT', msg)
3029
-
3184
+
3030
3185
  # process results.
3031
3186
  # no results to process - this is pass or fail.
3032
3187
  return
@@ -3057,13 +3212,12 @@ class SpotifyClient:
3057
3212
 
3058
3213
  Args:
3059
3214
  playlistId (str):
3060
- The Spotify ID of the playlist.
3215
+ A comma-separated list of Spotify playlist IDs.
3216
+ A maximum of 40 IDs can be sent in one request.
3061
3217
  Example: `3cEYpjA9oz9GiPac4AsH4n`
3062
3218
  If null, the currently playing playlist uri id value is used.
3063
3219
  public (bool):
3064
- If true the playlist will be included in user's public playlists, if false it
3065
- will remain private.
3066
- Default is True.
3220
+ DEPRECATED - no longer used, but left here to maintain compatibility.
3067
3221
 
3068
3222
  Raises:
3069
3223
  SpotifyWebApiError:
@@ -3087,13 +3241,13 @@ class SpotifyClient:
3087
3241
  # trace.
3088
3242
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
3089
3243
  apiMethodParms.AppendKeyValue("playlistId", playlistId)
3090
- apiMethodParms.AppendKeyValue("public", public)
3244
+ apiMethodParms.AppendKeyValue("public (DEPRECATED)", public)
3091
3245
  _logsi.LogMethodParmList(SILevel.Verbose, "Add the current user as a follower of a playlist", apiMethodParms)
3092
3246
 
3093
- # validations.
3094
- if (public is None):
3095
- public = True
3096
-
3247
+ # remove any leading / trailing spaces.
3248
+ if playlistId is not None:
3249
+ playlistId = playlistId.replace(' ','')
3250
+
3097
3251
  # if playlistId not specified, then return currently playing playlist id value.
3098
3252
  if (playlistId is None) or (len(playlistId.strip()) == 0):
3099
3253
  uri = self.GetPlayerNowPlayingPlaylistUri()
@@ -3102,17 +3256,25 @@ class SpotifyClient:
3102
3256
  else:
3103
3257
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'playlistId'), logsi=_logsi)
3104
3258
 
3259
+ # build a list of all item uri's from id values.
3260
+ # remove any leading / trailing spaces in case user put a space between the items.
3261
+ arrUris:list[str] = playlistId.split(',')
3262
+ for idx in range(0, len(arrUris)):
3263
+ if (arrUris[idx].find(":") == -1):
3264
+ arrUris[idx] = SpotifyTypePrefixes.PLAYLIST.value + arrUris[idx].strip()
3265
+
3105
3266
  # build spotify web api request parameters.
3106
- reqData:dict = {}
3107
- if public is not None:
3108
- reqData['public'] = public
3267
+ urlParms:dict = \
3268
+ {
3269
+ 'uris': ",".join(arrUris)
3270
+ }
3109
3271
 
3110
3272
  # execute spotify web api request.
3111
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/followers'.format(playlist_id=playlistId))
3273
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
3112
3274
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3113
- msg.RequestJson = reqData
3275
+ msg.UrlParameters = urlParms
3114
3276
  self.MakeRequest('PUT', msg)
3115
-
3277
+
3116
3278
  # process results.
3117
3279
  # no results to process - this is pass or fail.
3118
3280
  return
@@ -3143,7 +3305,7 @@ class SpotifyClient:
3143
3305
  Args:
3144
3306
  ids (str):
3145
3307
  A comma-separated list of the Spotify user IDs.
3146
- A maximum of 50 IDs can be sent in one request.
3308
+ A maximum of 40 IDs can be sent in one request.
3147
3309
  Example: `smedjan`
3148
3310
 
3149
3311
  Raises:
@@ -3172,24 +3334,25 @@ class SpotifyClient:
3172
3334
  apiMethodParms.AppendKeyValue("ids", ids)
3173
3335
  _logsi.LogMethodParmList(SILevel.Verbose, "Add the current user as a follower of one or more users", apiMethodParms)
3174
3336
 
3175
- # build a list of all item id's.
3337
+ # build a list of all item uri's from id values.
3176
3338
  # remove any leading / trailing spaces in case user put a space between the items.
3177
- arrIds:list[str] = ids.split(',')
3178
- for idx in range(0, len(arrIds)):
3179
- arrIds[idx] = arrIds[idx].strip()
3339
+ arrUris:list[str] = ids.split(',')
3340
+ for idx in range(0, len(arrUris)):
3341
+ if (arrUris[idx].find(":") == -1):
3342
+ arrUris[idx] = SpotifyTypePrefixes.USER.value + arrUris[idx].strip()
3180
3343
 
3181
3344
  # build spotify web api request parameters.
3182
- reqData:dict = \
3345
+ urlParms:dict = \
3183
3346
  {
3184
- 'ids': arrIds
3347
+ 'uris': ",".join(arrUris)
3185
3348
  }
3186
3349
 
3187
3350
  # execute spotify web api request.
3188
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following?type=user')
3351
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
3189
3352
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
3190
- msg.RequestJson = reqData
3353
+ msg.UrlParameters = urlParms
3191
3354
  self.MakeRequest('PUT', msg)
3192
-
3355
+
3193
3356
  # process results.
3194
3357
  # no results to process - this is pass or fail.
3195
3358
  return
@@ -3491,6 +3654,14 @@ class SpotifyClient:
3491
3654
  sortResult:bool=True,
3492
3655
  ) -> AlbumPageSimplified:
3493
3656
  """
3657
+ <span class="deprecated">
3658
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
3659
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
3660
+ More information about the deprecated functionality can be found on the
3661
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
3662
+ page.
3663
+ </span>
3664
+
3494
3665
  Get a list of new album releases featured in Spotify (shown, for example, on a
3495
3666
  Spotify player's "Browse" tab).
3496
3667
 
@@ -3557,6 +3728,15 @@ class SpotifyClient:
3557
3728
  apiMethodParms.AppendKeyValue("sortResult", sortResult)
3558
3729
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of new album releases", apiMethodParms)
3559
3730
 
3731
+ # are spotify web player credentials configured? if so, then we will use them to create
3732
+ # an elevated authorization access token for the Spotify Web API endpoint call.
3733
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
3734
+
3735
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
3736
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
3737
+ if (accessTokenHeaderValue is None):
3738
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
3739
+
3560
3740
  # validations.
3561
3741
  if limit is None:
3562
3742
  limit = 20
@@ -3654,6 +3834,14 @@ class SpotifyClient:
3654
3834
  market:str=None,
3655
3835
  ) -> list[Album]:
3656
3836
  """
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
+
3657
3845
  Get Spotify catalog information for multiple albums.
3658
3846
 
3659
3847
  Args:
@@ -3698,6 +3886,15 @@ class SpotifyClient:
3698
3886
  apiMethodParms.AppendKeyValue("ids", ids)
3699
3887
  apiMethodParms.AppendKeyValue("market", market)
3700
3888
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple albums", apiMethodParms)
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)
3701
3898
 
3702
3899
  # ensure we have a market value, in order to return track relinking (e.g. `linked_from`) data.
3703
3900
  market = self._ValidateMarket(market, forceReturnValue=True)
@@ -4584,7 +4781,7 @@ class SpotifyClient:
4584
4781
  # if spotify web player credentials not configured then we are done; the Spotify Web API
4585
4782
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
4586
4783
  if (accessTokenHeaderValue is None):
4587
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
4784
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
4588
4785
 
4589
4786
  # validations.
4590
4787
  if sortResult is None:
@@ -4637,6 +4834,14 @@ class SpotifyClient:
4637
4834
  ids:list[str],
4638
4835
  ) -> list[Artist]:
4639
4836
  """
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
+
4640
4845
  Get Spotify catalog information for several artists based on their Spotify IDs.
4641
4846
 
4642
4847
  Args:
@@ -4673,6 +4878,15 @@ class SpotifyClient:
4673
4878
  apiMethodParms.AppendKeyValue("ids", ids)
4674
4879
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple artists", apiMethodParms)
4675
4880
 
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()
4884
+
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)
4889
+
4676
4890
  # build spotify web api request parameters.
4677
4891
  urlParms:dict = \
4678
4892
  {
@@ -4879,6 +5093,14 @@ class SpotifyClient:
4879
5093
  sortResult:bool=True,
4880
5094
  ) -> list[Track]:
4881
5095
  """
5096
+ <span class="deprecated">
5097
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
5098
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
5099
+ More information about the deprecated functionality can be found on the
5100
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
5101
+ page.
5102
+ </span>
5103
+
4882
5104
  Get Spotify catalog information about an artist's top tracks by country.
4883
5105
 
4884
5106
  Args:
@@ -4930,6 +5152,15 @@ class SpotifyClient:
4930
5152
  apiMethodParms.AppendKeyValue("sortResult", sortResult)
4931
5153
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information about an artist's top tracks", apiMethodParms)
4932
5154
 
5155
+ # are spotify web player credentials configured? if so, then we will use them to create
5156
+ # an elevated authorization access token for the Spotify Web API endpoint call.
5157
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
5158
+
5159
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
5160
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
5161
+ if (accessTokenHeaderValue is None):
5162
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
5163
+
4933
5164
  # validations.
4934
5165
  if sortResult is None:
4935
5166
  sortResult = True
@@ -5427,6 +5658,14 @@ class SpotifyClient:
5427
5658
  market:str=None,
5428
5659
  ) -> list[AudiobookSimplified]:
5429
5660
  """
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
+
5430
5669
  Get Spotify catalog information for several audiobooks based on their Spotify IDs.
5431
5670
 
5432
5671
  Args:
@@ -5477,6 +5716,15 @@ class SpotifyClient:
5477
5716
  apiMethodParms.AppendKeyValue("market", market)
5478
5717
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple audiobooks", apiMethodParms)
5479
5718
 
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
+
5480
5728
  # ensure market was either supplied or implied; default if neither.
5481
5729
  market = self._ValidateMarket(market)
5482
5730
 
@@ -5526,6 +5774,14 @@ class SpotifyClient:
5526
5774
  refresh:bool=True,
5527
5775
  ) -> Playlist:
5528
5776
  """
5777
+ <span class="deprecated">
5778
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
5779
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
5780
+ More information about the deprecated functionality can be found on the
5781
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
5782
+ page.
5783
+ </span>
5784
+
5529
5785
  Get a single category used to tag items in Spotify.
5530
5786
 
5531
5787
  Args:
@@ -5589,6 +5845,15 @@ class SpotifyClient:
5589
5845
  apiMethodParms.AppendKeyValue("locale", locale)
5590
5846
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a single category used to tag items in Spotify", apiMethodParms)
5591
5847
 
5848
+ # are spotify web player credentials configured? if so, then we will use them to create
5849
+ # an elevated authorization access token for the Spotify Web API endpoint call.
5850
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
5851
+
5852
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
5853
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
5854
+ if (accessTokenHeaderValue is None):
5855
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
5856
+
5592
5857
  # validations.
5593
5858
  if (refresh is None):
5594
5859
  refresh = True
@@ -5652,6 +5917,14 @@ class SpotifyClient:
5652
5917
  sortResult:bool=True,
5653
5918
  ) -> CategoryPage:
5654
5919
  """
5920
+ <span class="deprecated">
5921
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
5922
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
5923
+ More information about the deprecated functionality can be found on the
5924
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
5925
+ page.
5926
+ </span>
5927
+
5655
5928
  Get categories used to tag items in Spotify.
5656
5929
 
5657
5930
  Args:
@@ -5728,6 +6001,15 @@ class SpotifyClient:
5728
6001
  apiMethodParms.AppendKeyValue("sortResult", sortResult)
5729
6002
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a page of categories used to tag items in Spotify", apiMethodParms)
5730
6003
 
6004
+ # are spotify web player credentials configured? if so, then we will use them to create
6005
+ # an elevated authorization access token for the Spotify Web API endpoint call.
6006
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
6007
+
6008
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
6009
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
6010
+ if (accessTokenHeaderValue is None):
6011
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
6012
+
5731
6013
  # validations.
5732
6014
  if limit is None:
5733
6015
  limit = 20
@@ -6033,7 +6315,7 @@ class SpotifyClient:
6033
6315
  # if spotify web player credentials not configured then we are done; the Spotify Web API
6034
6316
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
6035
6317
  if (accessTokenHeaderValue is None):
6036
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
6318
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
6037
6319
 
6038
6320
  # validations.
6039
6321
  if limit is None:
@@ -6248,6 +6530,14 @@ class SpotifyClient:
6248
6530
  market:str=None,
6249
6531
  ) -> list[Chapter]:
6250
6532
  """
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
+
6251
6541
  Get Spotify catalog information for several chapters based on their Spotify IDs.
6252
6542
 
6253
6543
  Args:
@@ -6298,6 +6588,15 @@ class SpotifyClient:
6298
6588
  apiMethodParms.AppendKeyValue("market", market)
6299
6589
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple chapters", apiMethodParms)
6300
6590
 
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
+
6301
6600
  # ensure market was either supplied or implied; default if neither.
6302
6601
  market = self._ValidateMarket(market)
6303
6602
 
@@ -6842,6 +7141,14 @@ class SpotifyClient:
6842
7141
  market:str=None,
6843
7142
  ) -> list[Episode]:
6844
7143
  """
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
+
6845
7152
  Get Spotify catalog information for several episodes based on their Spotify IDs.
6846
7153
 
6847
7154
  Args:
@@ -6892,6 +7199,15 @@ class SpotifyClient:
6892
7199
  apiMethodParms.AppendKeyValue("market", market)
6893
7200
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple episodes", apiMethodParms)
6894
7201
 
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
+
6895
7211
  # ensure market was either supplied or implied; default if neither.
6896
7212
  market = self._ValidateMarket(market)
6897
7213
 
@@ -7047,7 +7363,7 @@ class SpotifyClient:
7047
7363
  # if spotify web player credentials not configured then we are done; the Spotify Web API
7048
7364
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
7049
7365
  if (accessTokenHeaderValue is None):
7050
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
7366
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
7051
7367
 
7052
7368
  # validations.
7053
7369
  if limit is None:
@@ -7203,7 +7519,7 @@ class SpotifyClient:
7203
7519
  # if spotify web player credentials not configured then we are done; the Spotify Web API
7204
7520
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
7205
7521
  if (accessTokenHeaderValue is None):
7206
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
7522
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
7207
7523
 
7208
7524
  # validations.
7209
7525
  if (refresh is None):
@@ -7561,6 +7877,14 @@ class SpotifyClient:
7561
7877
  refresh:bool=True
7562
7878
  ) -> list[str]:
7563
7879
  """
7880
+ <span class="deprecated">
7881
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
7882
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
7883
+ More information about the deprecated functionality can be found on the
7884
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
7885
+ page.
7886
+ </span>
7887
+
7564
7888
  Get the list of markets (country codes) where Spotify is available.
7565
7889
 
7566
7890
  Args:
@@ -7599,6 +7923,15 @@ class SpotifyClient:
7599
7923
  _logsi.EnterMethod(SILevel.Debug, apiMethodName)
7600
7924
  _logsi.LogVerbose("Get a sorted list of available markets (country codes)")
7601
7925
 
7926
+ # are spotify web player credentials configured? if so, then we will use them to create
7927
+ # an elevated authorization access token for the Spotify Web API endpoint call.
7928
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
7929
+
7930
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
7931
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
7932
+ if (accessTokenHeaderValue is None):
7933
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
7934
+
7602
7935
  # validations.
7603
7936
  if (refresh is None):
7604
7937
  refresh = True
@@ -8213,6 +8546,7 @@ class SpotifyClient:
8213
8546
  def GetPlayerNowPlayingUri(
8214
8547
  self,
8215
8548
  additionalTypes:str=None,
8549
+ checkSpecificType:bool=True,
8216
8550
  ) -> str:
8217
8551
  """
8218
8552
  Returns the uri value of the currently playing media type if something is
@@ -8223,6 +8557,9 @@ class SpotifyClient:
8223
8557
  An item type that your client supports besides the default track type.
8224
8558
  Valid types are: `track` and `episode`.
8225
8559
  Specify `episode` to get podcast track information.
8560
+ checkSpecificType (bool):
8561
+ If true, the currently playing type MUST match the specified additional type value;
8562
+ otherwise, it will return any uri that is currently playing.
8226
8563
 
8227
8564
  Raises:
8228
8565
  SpotifyApiError:
@@ -8237,7 +8574,7 @@ class SpotifyClient:
8237
8574
  # is anything playing? if so, return the uri value.
8238
8575
  if nowPlaying is not None:
8239
8576
  if nowPlaying.Item is not None:
8240
- if additionalTypes is None:
8577
+ if (additionalTypes is None) or (checkSpecificType == False):
8241
8578
  # if not validating uri type then just return the uri.
8242
8579
  result = nowPlaying.Item.Uri
8243
8580
  elif nowPlaying.CurrentlyPlayingType == additionalTypes:
@@ -8248,7 +8585,7 @@ class SpotifyClient:
8248
8585
  raise SpotifyApiError("Currently playing item is not a %s" % additionalTypes, logsi=_logsi)
8249
8586
  else:
8250
8587
  # otherwise nowplaying item does not contain the desired type!
8251
- if additionalTypes is None:
8588
+ if (additionalTypes is None) or (checkSpecificType == False):
8252
8589
  raise SpotifyApiError("Currently playing item context is not set", logsi=_logsi)
8253
8590
  else:
8254
8591
  raise SpotifyApiError("Currently playing item context is not a %s item" % additionalTypes, logsi=_logsi)
@@ -9082,7 +9419,7 @@ class SpotifyClient:
9082
9419
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'playlistId'), logsi=_logsi)
9083
9420
 
9084
9421
  # execute spotify web api request.
9085
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/images'.format(playlist_id=playlistId))
9422
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/images'.format(id=playlistId))
9086
9423
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
9087
9424
  self.MakeRequest('GET', msg)
9088
9425
 
@@ -9280,7 +9617,7 @@ class SpotifyClient:
9280
9617
  while True:
9281
9618
 
9282
9619
  # execute spotify web api request.
9283
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/tracks'.format(id=playlistId))
9620
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/items'.format(id=playlistId))
9284
9621
  msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
9285
9622
  msg.UrlParameters = urlParms
9286
9623
  self.MakeRequest('GET', msg)
@@ -9514,6 +9851,14 @@ class SpotifyClient:
9514
9851
  sortResult:bool=True,
9515
9852
  ) -> PlaylistPageSimplified:
9516
9853
  """
9854
+ <span class="deprecated">
9855
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
9856
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
9857
+ More information about the deprecated functionality can be found on the
9858
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
9859
+ page.
9860
+ </span>
9861
+
9517
9862
  Get a list of the playlists owned or followed by a Spotify user.
9518
9863
 
9519
9864
  This method requires the `playlist-read-private` and `playlist-read-collaborative` scope.
@@ -9579,6 +9924,15 @@ class SpotifyClient:
9579
9924
  apiMethodParms.AppendKeyValue("sortResult", sortResult)
9580
9925
  _logsi.LogMethodParmList(SILevel.Verbose, "Get a list of the playlists owned or followed by a Spotify user", apiMethodParms)
9581
9926
 
9927
+ # are spotify web player credentials configured? if so, then we will use them to create
9928
+ # an elevated authorization access token for the Spotify Web API endpoint call.
9929
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
9930
+
9931
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
9932
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
9933
+ if (accessTokenHeaderValue is None):
9934
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
9935
+
9582
9936
  # validations.
9583
9937
  if limit is None:
9584
9938
  limit = 20
@@ -9608,7 +9962,7 @@ class SpotifyClient:
9608
9962
  while True:
9609
9963
 
9610
9964
  # execute spotify web api request.
9611
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{user_id}/playlists'.format(user_id=userId))
9965
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{id}/playlists'.format(id=userId))
9612
9966
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
9613
9967
  msg.UrlParameters = urlParms
9614
9968
  self.MakeRequest('GET', msg)
@@ -10138,6 +10492,14 @@ class SpotifyClient:
10138
10492
  market:str=None,
10139
10493
  ) -> list[ShowSimplified]:
10140
10494
  """
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
+
10141
10503
  Get Spotify catalog information for several shows based on their Spotify IDs.
10142
10504
 
10143
10505
  Args:
@@ -10188,6 +10550,15 @@ class SpotifyClient:
10188
10550
  apiMethodParms.AppendKeyValue("market", market)
10189
10551
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple shows", apiMethodParms)
10190
10552
 
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
+
10191
10562
  # ensure market was either supplied or implied; default if neither.
10192
10563
  market = self._ValidateMarket(market)
10193
10564
 
@@ -10448,9 +10819,21 @@ class SpotifyClient:
10448
10819
  # note that `transferPlayback=false`, as transfer should be done after we return to caller.
10449
10820
  if (scDevice.IsChromeCast):
10450
10821
 
10451
- # activate the spotify cast application on the device.
10452
- _logsi.LogVerbose("Activating Chromecast Spotify Connect device: %s on host ip: %s" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle))
10453
- deviceIdActivated:str = self._SpotifyConnectDirectory.ActivateCastAppSpotify(scDevice.Id or scDevice.Name, transferPlayback=False)
10822
+ try:
10823
+
10824
+ # activate the spotify cast application on the device.
10825
+ _logsi.LogVerbose("Activating Chromecast Spotify Connect device: %s on host ip: %s" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle))
10826
+ deviceIdActivated:str = self._SpotifyConnectDirectory.ActivateCastAppSpotify(scDevice.Id or scDevice.Name, transferPlayback=False)
10827
+
10828
+ except Exception as ex:
10829
+
10830
+ # give things time to settle.
10831
+ time.sleep(2.0)
10832
+
10833
+ # try again ...
10834
+ # activate the spotify cast application on the device.
10835
+ _logsi.LogVerbose("Activating Chromecast Spotify Connect device: %s on host ip: %s (attempt #2)" % (scDevice.Title, scDevice.DiscoveryResult.HostIpTitle))
10836
+ deviceIdActivated:str = self._SpotifyConnectDirectory.ActivateCastAppSpotify(scDevice.Id or scDevice.Name, transferPlayback=False)
10454
10837
 
10455
10838
  # re-fetch device instance, as it has updated properties from the activation sequence.
10456
10839
  # do not need to refresh from Spotify Web API, as only zeroconf response data was changed.
@@ -10839,7 +11222,7 @@ class SpotifyClient:
10839
11222
  # if spotify web player credentials not configured then we are done; the Spotify Web API
10840
11223
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
10841
11224
  if (accessTokenHeaderValue is None):
10842
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
11225
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
10843
11226
 
10844
11227
  # if trackId not specified, then return currently playing track id value.
10845
11228
  if (trackId is None) or (len(trackId.strip()) == 0):
@@ -11108,6 +11491,14 @@ class SpotifyClient:
11108
11491
  market:str=None,
11109
11492
  ) -> list[Track]:
11110
11493
  """
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
+
11111
11502
  Get Spotify catalog information for multiple tracks based on their Spotify IDs.
11112
11503
 
11113
11504
  Args:
@@ -11152,7 +11543,16 @@ class SpotifyClient:
11152
11543
  apiMethodParms.AppendKeyValue("ids", ids)
11153
11544
  apiMethodParms.AppendKeyValue("market", market)
11154
11545
  _logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify catalog information for multiple tracks", apiMethodParms)
11155
-
11546
+
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
+
11156
11556
  # ensure we have a market value, in order to return track relinking (e.g. `linked_from`) data.
11157
11557
  market = self._ValidateMarket(market, forceReturnValue=True)
11158
11558
 
@@ -11248,7 +11648,7 @@ class SpotifyClient:
11248
11648
  # if spotify web player credentials not configured then we are done; the Spotify Web API
11249
11649
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
11250
11650
  if (accessTokenHeaderValue is None):
11251
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
11651
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
11252
11652
 
11253
11653
  # execute spotify web api request.
11254
11654
  msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/audio-features')
@@ -11556,7 +11956,7 @@ class SpotifyClient:
11556
11956
  # if spotify web player credentials not configured then we are done; the Spotify Web API
11557
11957
  # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2024/11/27.
11558
11958
  if (accessTokenHeaderValue is None):
11559
- raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT % apiMethodName)
11959
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20241127 % apiMethodName)
11560
11960
 
11561
11961
  # ensure market was either supplied or implied; default if neither.
11562
11962
  market = self._ValidateMarket(market)
@@ -11846,6 +12246,14 @@ class SpotifyClient:
11846
12246
  userId:str,
11847
12247
  ) -> UserProfileSimplified:
11848
12248
  """
12249
+ <span class="deprecated">
12250
+ DEPRECATED - api endpoint no longer supported by Spotify as of 2026/02/11 for unauthorized Spotify Developer Applications.
12251
+ The api endpoint IS still supported by Spotify for authorized Spotify Developer Applications.
12252
+ More information about the deprecated functionality can be found on the
12253
+ <a href="https://developer.spotify.com/blog/2026-02-06-update-on-developer-access-and-platform-security" target="_blank">Spotify Developer Forum Blog</a>
12254
+ page.
12255
+ </span>
12256
+
11849
12257
  Get public profile information about a Spotify user.
11850
12258
 
11851
12259
  Args:
@@ -11881,8 +12289,17 @@ class SpotifyClient:
11881
12289
  apiMethodParms.AppendKeyValue("userId", userId)
11882
12290
  _logsi.LogMethodParmList(SILevel.Verbose, "Get public profile information about a Spotify user", apiMethodParms)
11883
12291
 
12292
+ # are spotify web player credentials configured? if so, then we will use them to create
12293
+ # an elevated authorization access token for the Spotify Web API endpoint call.
12294
+ accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
12295
+
12296
+ # if spotify web player credentials not configured then we are done; the Spotify Web API
12297
+ # endpoint is no longer supported by unauthorized Spotify Developer Applications as of 2026/02/11.
12298
+ if (accessTokenHeaderValue is None):
12299
+ raise SpotifyApiError(SAAppMessages.MSG_SPOTIFY_DEPRECATED_ENDPOINT_20260211 % apiMethodName)
12300
+
11884
12301
  # execute spotify web api request.
11885
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{user_id}'.format(user_id=userId))
12302
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/users/{id}'.format(id=userId))
11886
12303
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11887
12304
  self.MakeRequest('GET', msg)
11888
12305
 
@@ -14524,8 +14941,8 @@ class SpotifyClient:
14524
14941
 
14525
14942
  Args:
14526
14943
  ids (str):
14527
- A comma-separated list of the Spotify IDs for the albums.
14528
- Maximum: 50 IDs.
14944
+ A comma-separated list of the Spotify ID's (or URI's) for the albums.
14945
+ Maximum: 40 IDs.
14529
14946
  Example: `6vc9OTcyd3hyzabCmsdnwE,382ObEPsp2rxGrnsizN5TX`
14530
14947
  If null, the currently playing track album uri id value is used.
14531
14948
 
@@ -14559,6 +14976,10 @@ class SpotifyClient:
14559
14976
  apiMethodParms.AppendKeyValue("ids", ids)
14560
14977
  _logsi.LogMethodParmList(SILevel.Verbose, "Remove album(s) from user favorites", apiMethodParms)
14561
14978
 
14979
+ # remove any leading / trailing spaces.
14980
+ if ids is not None:
14981
+ ids = ids.replace(' ','')
14982
+
14562
14983
  # if ids not specified, then return currently playing album id value.
14563
14984
  if (ids is None) or (len(ids.strip()) == 0):
14564
14985
  uri = self.GetPlayerNowPlayingAlbumUri()
@@ -14567,24 +14988,25 @@ class SpotifyClient:
14567
14988
  else:
14568
14989
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
14569
14990
 
14570
- # build a list of all item id's.
14991
+ # build a list of all item uri's from id values.
14571
14992
  # remove any leading / trailing spaces in case user put a space between the items.
14572
- arrIds:list[str] = ids.split(',')
14573
- for idx in range(0, len(arrIds)):
14574
- arrIds[idx] = arrIds[idx].strip()
14993
+ arrUris:list[str] = ids.split(',')
14994
+ for idx in range(0, len(arrUris)):
14995
+ if (arrUris[idx].find(":") == -1):
14996
+ arrUris[idx] = SpotifyTypePrefixes.ALBUM.value + arrUris[idx].strip()
14575
14997
 
14576
14998
  # build spotify web api request parameters.
14577
- reqData:dict = \
14999
+ urlParms:dict = \
14578
15000
  {
14579
- 'ids': arrIds
15001
+ 'uris': ",".join(arrUris)
14580
15002
  }
14581
15003
 
14582
15004
  # execute spotify web api request.
14583
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/albums')
15005
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
14584
15006
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
14585
- msg.RequestJson = reqData
15007
+ msg.UrlParameters = urlParms
14586
15008
  self.MakeRequest('DELETE', msg)
14587
-
15009
+
14588
15010
  # process results.
14589
15011
  # no results to process - this is pass or fail.
14590
15012
  return
@@ -14614,8 +15036,8 @@ class SpotifyClient:
14614
15036
 
14615
15037
  Args:
14616
15038
  ids (str):
14617
- A comma-separated list of the Spotify IDs for the audiobooks.
14618
- Maximum: 50 IDs.
15039
+ A comma-separated list of the Spotify ID's (or URI's) for the audiobooks.
15040
+ Maximum: 40 IDs.
14619
15041
  Example: `3PFyizE2tGCSRLusl2Qizf,7iHfbu1YPACw6oZPAFJtqe`
14620
15042
  If null, the currently playing audiobook uri id value is used.
14621
15043
 
@@ -14649,6 +15071,10 @@ class SpotifyClient:
14649
15071
  apiMethodParms.AppendKeyValue("ids", ids)
14650
15072
  _logsi.LogMethodParmList(SILevel.Verbose, "Remove audiobook(s) from user favorites", apiMethodParms)
14651
15073
 
15074
+ # remove any leading / trailing spaces.
15075
+ if ids is not None:
15076
+ ids = ids.replace(' ','')
15077
+
14652
15078
  # if ids not specified, then return currently playing id value.
14653
15079
  if (ids is None) or (len(ids.strip()) == 0):
14654
15080
  uri = self.GetPlayerNowPlayingAudiobookUri()
@@ -14657,22 +15083,23 @@ class SpotifyClient:
14657
15083
  else:
14658
15084
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
14659
15085
 
14660
- # build a list of all item id's.
15086
+ # build a list of all item uri's from id values.
14661
15087
  # remove any leading / trailing spaces in case user put a space between the items.
14662
- arrIds:list[str] = ids.split(',')
14663
- for idx in range(0, len(arrIds)):
14664
- arrIds[idx] = arrIds[idx].strip()
15088
+ arrUris:list[str] = ids.split(',')
15089
+ for idx in range(0, len(arrUris)):
15090
+ if (arrUris[idx].find(":") == -1):
15091
+ arrUris[idx] = SpotifyTypePrefixes.SHOW.value + arrUris[idx].strip() # spotify web api considers audiobook a "show"!
14665
15092
 
14666
15093
  # build spotify web api request parameters.
14667
- reqData:dict = \
15094
+ urlParms:dict = \
14668
15095
  {
14669
- 'ids': arrIds
15096
+ 'uris': ",".join(arrUris)
14670
15097
  }
14671
15098
 
14672
15099
  # execute spotify web api request.
14673
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/audiobooks')
15100
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
14674
15101
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
14675
- msg.RequestJson = reqData
15102
+ msg.UrlParameters = urlParms
14676
15103
  self.MakeRequest('DELETE', msg)
14677
15104
 
14678
15105
  # process results.
@@ -14704,8 +15131,8 @@ class SpotifyClient:
14704
15131
 
14705
15132
  Args:
14706
15133
  ids (str):
14707
- A comma-separated list of the Spotify IDs for the episodes.
14708
- Maximum: 50 IDs.
15134
+ A comma-separated list of the Spotify ID's (or URI's) for the episodes.
15135
+ Maximum: 40 IDs.
14709
15136
  Example: `6kAsbP8pxwaU2kPibKTuHE,4rOoJ6Egrf8K2IrywzwOMk`
14710
15137
  If null, the currently playing episode uri id value is used.
14711
15138
 
@@ -14739,6 +15166,10 @@ class SpotifyClient:
14739
15166
  apiMethodParms.AppendKeyValue("ids", ids)
14740
15167
  _logsi.LogMethodParmList(SILevel.Verbose, "Remove episode(s) from user favorites", apiMethodParms)
14741
15168
 
15169
+ # remove any leading / trailing spaces.
15170
+ if ids is not None:
15171
+ ids = ids.replace(' ','')
15172
+
14742
15173
  # if ids not specified, then return currently playing id value.
14743
15174
  if (ids is None) or (len(ids.strip()) == 0):
14744
15175
  uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.EPISODE.value)
@@ -14747,22 +15178,23 @@ class SpotifyClient:
14747
15178
  else:
14748
15179
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
14749
15180
 
14750
- # build a list of all item id's.
15181
+ # build a list of all item uri's from id values.
14751
15182
  # remove any leading / trailing spaces in case user put a space between the items.
14752
- arrIds:list[str] = ids.split(',')
14753
- for idx in range(0, len(arrIds)):
14754
- arrIds[idx] = arrIds[idx].strip()
15183
+ arrUris:list[str] = ids.split(',')
15184
+ for idx in range(0, len(arrUris)):
15185
+ if (arrUris[idx].find(":") == -1):
15186
+ arrUris[idx] = SpotifyTypePrefixes.EPISODE.value + arrUris[idx].strip()
14755
15187
 
14756
15188
  # build spotify web api request parameters.
14757
- reqData:dict = \
15189
+ urlParms:dict = \
14758
15190
  {
14759
- 'ids': arrIds
15191
+ 'uris': ",".join(arrUris)
14760
15192
  }
14761
15193
 
14762
15194
  # execute spotify web api request.
14763
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/episodes')
15195
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
14764
15196
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
14765
- msg.RequestJson = reqData
15197
+ msg.UrlParameters = urlParms
14766
15198
  self.MakeRequest('DELETE', msg)
14767
15199
 
14768
15200
  # process results.
@@ -14890,6 +15322,8 @@ class SpotifyClient:
14890
15322
 
14891
15323
  The `snapshotId` argument value will be returned if no items were removed; otherwise, a
14892
15324
  new snapshot id value will be returned.
15325
+
15326
+ If the playlist contains duplicate items, then all of the item instances will be removed.
14893
15327
 
14894
15328
  <details>
14895
15329
  <summary>Sample Code</summary>
@@ -14917,37 +15351,132 @@ class SpotifyClient:
14917
15351
  if uris is None:
14918
15352
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'uris'), logsi=_logsi)
14919
15353
 
14920
- # build a list of all item uri's.
15354
+ # build a list of all item uri's.
15355
+ # remove any leading / trailing spaces in case user put a space between the items.
15356
+ arrUris:list[str] = uris.split(',')
15357
+ for idx in range(0, len(arrUris)):
15358
+ arrUris[idx] = arrUris[idx].strip()
15359
+
15360
+ # build items dictionary.
15361
+ items:list[dict] = []
15362
+ for idx in range(0, len(arrUris)):
15363
+ items.append({'uri': '%s' % arrUris[idx]})
15364
+
15365
+ # build spotify web api request parameters.
15366
+ reqData:dict = \
15367
+ {
15368
+ 'items': items
15369
+ }
15370
+ if snapshotId is not None:
15371
+ reqData['snapshot_id'] = snapshotId
15372
+
15373
+ # execute spotify web api request.
15374
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/items'.format(id=playlistId))
15375
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15376
+ msg.RequestJson = reqData
15377
+ self.MakeRequest('DELETE', msg)
15378
+
15379
+ # process results.
15380
+ result = msg.ResponseData.get('snapshot_id','unknown')
15381
+
15382
+ # trace.
15383
+ _logsi.LogString(SILevel.Verbose, TRACE_METHOD_RESULT % apiMethodName, result)
15384
+ return result
15385
+
15386
+ except SpotifyApiError: raise # pass handled exceptions on thru
15387
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
15388
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
15389
+ except Exception as ex:
15390
+
15391
+ # format unhandled exception.
15392
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
15393
+
15394
+ finally:
15395
+
15396
+ # trace.
15397
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
15398
+
15399
+
15400
+ def RemoveShowFavorites(
15401
+ self,
15402
+ ids:str=None,
15403
+ ) -> None:
15404
+ """
15405
+ Remove one or more shows from the current user's 'Your Library'.
15406
+
15407
+ This method requires the `user-library-modify` scope.
15408
+
15409
+ Args:
15410
+ ids (str):
15411
+ A comma-separated list of the Spotify ID's (or URI's) for the shows.
15412
+ Maximum: 40 IDs.
15413
+ Example: `6kAsbP8pxwaU2kPibKTuHE,4rOoJ6Egrf8K2IrywzwOMk`
15414
+ If null, the currently playing show uri id value is used.
15415
+
15416
+ Raises:
15417
+ SpotifyWebApiError:
15418
+ If the Spotify Web API request was for a non-authorization service
15419
+ and the response contains error information.
15420
+ SpotifyApiError:
15421
+ If the method fails for any other reason.
15422
+
15423
+ No error will be raised if a show id in the list does not exist in the
15424
+ user's 'Your Library'.
15425
+
15426
+ An SpotifyWebApiError will be raised if a specified album id does not exist
15427
+ in the Spotify music catalog.
15428
+
15429
+ <details>
15430
+ <summary>Sample Code</summary>
15431
+ ```python
15432
+ .. include:: ../docs/include/samplecode/SpotifyClient/RemoveShowFavorites.py
15433
+ ```
15434
+ </details>
15435
+ """
15436
+ apiMethodName:str = 'RemoveShowFavorites'
15437
+ apiMethodParms:SIMethodParmListContext = None
15438
+
15439
+ try:
15440
+
15441
+ # trace.
15442
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
15443
+ apiMethodParms.AppendKeyValue("ids", ids)
15444
+ _logsi.LogMethodParmList(SILevel.Verbose, "Remove show(s) from user favorites", apiMethodParms)
15445
+
15446
+ # remove any leading / trailing spaces.
15447
+ if ids is not None:
15448
+ ids = ids.replace(' ','')
15449
+
15450
+ # if ids not specified, then return currently playing id value.
15451
+ if (ids is None) or (len(ids.strip()) == 0):
15452
+ uri = self.GetPlayerNowPlayingShowUri()
15453
+ if uri is not None:
15454
+ ids = SpotifyClient.GetIdFromUri(uri)
15455
+ else:
15456
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15457
+
15458
+ # build a list of all item uri's from id values.
14921
15459
  # remove any leading / trailing spaces in case user put a space between the items.
14922
- arrUris:list[str] = uris.split(',')
14923
- for idx in range(0, len(arrUris)):
14924
- arrUris[idx] = arrUris[idx].strip()
14925
-
14926
- # build tracks dictionary.
14927
- tracks:list[dict] = []
15460
+ arrUris:list[str] = ids.split(',')
14928
15461
  for idx in range(0, len(arrUris)):
14929
- tracks.append({'uri': '%s' % arrUris[idx]})
15462
+ if (arrUris[idx].find(":") == -1):
15463
+ arrUris[idx] = SpotifyTypePrefixes.SHOW.value + arrUris[idx].strip()
14930
15464
 
14931
15465
  # build spotify web api request parameters.
14932
- reqData:dict = \
15466
+ urlParms:dict = \
14933
15467
  {
14934
- 'tracks': tracks
15468
+ 'uris': ",".join(arrUris)
14935
15469
  }
14936
- if snapshotId is not None:
14937
- reqData['snapshot_id'] = snapshotId
14938
-
15470
+
14939
15471
  # execute spotify web api request.
14940
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/tracks'.format(playlist_id=playlistId))
15472
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
14941
15473
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
14942
- msg.RequestJson = reqData
15474
+ msg.UrlParameters = urlParms
14943
15475
  self.MakeRequest('DELETE', msg)
14944
-
15476
+
14945
15477
  # process results.
14946
- result = msg.ResponseData.get('snapshot_id','unknown')
14947
-
14948
- # trace.
14949
- _logsi.LogString(SILevel.Verbose, TRACE_METHOD_RESULT % apiMethodName, result)
14950
- return result
15478
+ # no results to process - this is pass or fail.
15479
+ return
14951
15480
 
14952
15481
  except SpotifyApiError: raise # pass handled exceptions on thru
14953
15482
  except SpotifyWebApiError: raise # pass handled exceptions on thru
@@ -14963,21 +15492,21 @@ class SpotifyClient:
14963
15492
  _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
14964
15493
 
14965
15494
 
14966
- def RemoveShowFavorites(
15495
+ def RemoveTrackFavorites(
14967
15496
  self,
14968
- ids:str=None,
15497
+ ids:str=None
14969
15498
  ) -> None:
14970
15499
  """
14971
- Remove one or more shows from the current user's 'Your Library'.
15500
+ Remove one or more tracks from the current user's 'Your Library'.
14972
15501
 
14973
15502
  This method requires the `user-library-modify` scope.
14974
15503
 
14975
15504
  Args:
14976
15505
  ids (str):
14977
- A comma-separated list of the Spotify IDs for the shows.
14978
- Maximum: 50 IDs.
14979
- Example: `6kAsbP8pxwaU2kPibKTuHE,4rOoJ6Egrf8K2IrywzwOMk`
14980
- If null, the currently playing show uri id value is used.
15506
+ A comma-separated list of the Spotify ID's (or URI's) for the tracks.
15507
+ Maximum: 40 IDs.
15508
+ Example: `1kWUud3vY5ij5r62zxpTRy,4eoYKv2kDwJS7gRGh5q6SK`
15509
+ If null, the currently playing track uri id value is used.
14981
15510
 
14982
15511
  Raises:
14983
15512
  SpotifyWebApiError:
@@ -14986,7 +15515,7 @@ class SpotifyClient:
14986
15515
  SpotifyApiError:
14987
15516
  If the method fails for any other reason.
14988
15517
 
14989
- No error will be raised if a show id in the list does not exist in the
15518
+ No error will be raised if a track id in the list does not exist in the
14990
15519
  user's 'Your Library'.
14991
15520
 
14992
15521
  An SpotifyWebApiError will be raised if a specified album id does not exist
@@ -14995,11 +15524,11 @@ class SpotifyClient:
14995
15524
  <details>
14996
15525
  <summary>Sample Code</summary>
14997
15526
  ```python
14998
- .. include:: ../docs/include/samplecode/SpotifyClient/RemoveShowFavorites.py
15527
+ .. include:: ../docs/include/samplecode/SpotifyClient/RemoveTrackFavorites.py
14999
15528
  ```
15000
15529
  </details>
15001
15530
  """
15002
- apiMethodName:str = 'RemoveShowFavorites'
15531
+ apiMethodName:str = 'RemoveTrackFavorites'
15003
15532
  apiMethodParms:SIMethodParmListContext = None
15004
15533
 
15005
15534
  try:
@@ -15007,28 +15536,35 @@ class SpotifyClient:
15007
15536
  # trace.
15008
15537
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
15009
15538
  apiMethodParms.AppendKeyValue("ids", ids)
15010
- _logsi.LogMethodParmList(SILevel.Verbose, "Remove show(s) from user favorites", apiMethodParms)
15539
+ _logsi.LogMethodParmList(SILevel.Verbose, "Remove track(s) from user favorites", apiMethodParms)
15011
15540
 
15541
+ # remove any leading / trailing spaces.
15542
+ if ids is not None:
15543
+ ids = ids.replace(' ','')
15544
+
15012
15545
  # if ids not specified, then return currently playing id value.
15013
15546
  if (ids is None) or (len(ids.strip()) == 0):
15014
- uri = self.GetPlayerNowPlayingShowUri()
15547
+ uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.TRACK.value)
15015
15548
  if uri is not None:
15016
15549
  ids = SpotifyClient.GetIdFromUri(uri)
15017
15550
  else:
15018
15551
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15019
15552
 
15553
+ # build a list of all item uri's from id values.
15020
15554
  # remove any leading / trailing spaces in case user put a space between the items.
15021
- if (ids is not None):
15022
- ids = ids.replace(" ","")
15555
+ arrUris:list[str] = ids.split(',')
15556
+ for idx in range(0, len(arrUris)):
15557
+ if (arrUris[idx].find(":") == -1):
15558
+ arrUris[idx] = SpotifyTypePrefixes.TRACK.value + arrUris[idx].strip()
15023
15559
 
15024
15560
  # build spotify web api request parameters.
15025
15561
  urlParms:dict = \
15026
15562
  {
15027
- 'ids': ids
15563
+ 'uris': ",".join(arrUris)
15028
15564
  }
15029
15565
 
15030
15566
  # execute spotify web api request.
15031
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/shows')
15567
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15032
15568
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15033
15569
  msg.UrlParameters = urlParms
15034
15570
  self.MakeRequest('DELETE', msg)
@@ -15051,21 +15587,22 @@ class SpotifyClient:
15051
15587
  _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
15052
15588
 
15053
15589
 
15054
- def RemoveTrackFavorites(
15590
+ def RemoveUserFavorites(
15055
15591
  self,
15056
- ids:str=None
15592
+ uris:str=None
15057
15593
  ) -> None:
15058
15594
  """
15059
- Remove one or more tracks from the current user's 'Your Library'.
15595
+ Remove one or more items from the current user's library.
15596
+ Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, users, and playlists.
15060
15597
 
15061
- This method requires the `user-library-modify` scope.
15598
+ This method requires the `user-library-modify`, `user-follow-modify`, and `playlist-modify-public` scopes.
15062
15599
 
15063
15600
  Args:
15064
- ids (str):
15065
- A comma-separated list of the Spotify IDs for the tracks.
15066
- Maximum: 50 IDs.
15067
- Example: `1kWUud3vY5ij5r62zxpTRy,4eoYKv2kDwJS7gRGh5q6SK`
15068
- If null, the currently playing track uri id value is used.
15601
+ uris (str):
15602
+ A comma-separated list of the Spotify URIs for the items.
15603
+ Maximum: 40 URIs.
15604
+ Example: `spotify:artist:6APm8EjxOHSYM5B4i3vT3q,spotify:album:6vc9OTcyd3hyzabCmsdnwE,spotify:track:1kWUud3vY5ij5r62zxpTRy`
15605
+ If null, the currently playing item uri value is used.
15069
15606
 
15070
15607
  Raises:
15071
15608
  SpotifyWebApiError:
@@ -15074,53 +15611,51 @@ class SpotifyClient:
15074
15611
  SpotifyApiError:
15075
15612
  If the method fails for any other reason.
15076
15613
 
15077
- No error will be raised if a track id in the list does not exist in the
15614
+ No error will be raised if an item uri in the list does not exist in the
15078
15615
  user's 'Your Library'.
15079
15616
 
15080
- An SpotifyWebApiError will be raised if a specified album id does not exist
15617
+ An SpotifyWebApiError will be raised if a specified item uri does not exist
15081
15618
  in the Spotify music catalog.
15082
15619
 
15083
15620
  <details>
15084
15621
  <summary>Sample Code</summary>
15085
15622
  ```python
15086
- .. include:: ../docs/include/samplecode/SpotifyClient/RemoveTrackFavorites.py
15623
+ .. include:: ../docs/include/samplecode/SpotifyClient/RemoveUserFavorites.py
15087
15624
  ```
15088
15625
  </details>
15089
15626
  """
15090
- apiMethodName:str = 'RemoveTrackFavorites'
15627
+ apiMethodName:str = 'RemoveUserFavorites'
15091
15628
  apiMethodParms:SIMethodParmListContext = None
15092
15629
 
15093
15630
  try:
15094
15631
 
15095
15632
  # trace.
15096
15633
  apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
15097
- apiMethodParms.AppendKeyValue("ids", ids)
15098
- _logsi.LogMethodParmList(SILevel.Verbose, "Remove track(s) from user favorites", apiMethodParms)
15634
+ apiMethodParms.AppendKeyValue("uris", uris)
15635
+ _logsi.LogMethodParmList(SILevel.Verbose, "Remove item(s) from user favorites", apiMethodParms)
15099
15636
 
15100
- # if ids not specified, then return currently playing id value.
15101
- if (ids is None) or (len(ids.strip()) == 0):
15102
- uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.TRACK.value)
15103
- if uri is not None:
15104
- ids = SpotifyClient.GetIdFromUri(uri)
15105
- else:
15106
- raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15637
+ # if uris not specified, then return currently playing item uri value.
15638
+ if (uris is None) or (len(uris.strip()) == 0):
15639
+ uris = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.EPISODE.value, False)
15640
+ if uris is None:
15641
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'uris'), logsi=_logsi)
15107
15642
 
15108
- # build a list of all item id's.
15643
+ # build a list of all item uri's.
15109
15644
  # remove any leading / trailing spaces in case user put a space between the items.
15110
- arrIds:list[str] = ids.split(',')
15111
- for idx in range(0, len(arrIds)):
15112
- arrIds[idx] = arrIds[idx].strip()
15645
+ arrUris:list[str] = uris.split(',')
15646
+ for idx in range(0, len(arrUris)):
15647
+ arrUris[idx] = arrUris[idx].strip()
15113
15648
 
15114
15649
  # build spotify web api request parameters.
15115
- reqData:dict = \
15650
+ urlParms:dict = \
15116
15651
  {
15117
- 'ids': arrIds
15652
+ 'uris': ",".join(arrUris)
15118
15653
  }
15119
15654
 
15120
15655
  # execute spotify web api request.
15121
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/tracks')
15656
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15122
15657
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15123
- msg.RequestJson = reqData
15658
+ msg.UrlParameters = urlParms
15124
15659
  self.MakeRequest('DELETE', msg)
15125
15660
 
15126
15661
  # process results.
@@ -15237,7 +15772,7 @@ class SpotifyClient:
15237
15772
  reqData['snapshot_id'] = snapshotId
15238
15773
 
15239
15774
  # execute spotify web api request.
15240
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/tracks'.format(playlist_id=playlistId))
15775
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/items'.format(id=playlistId))
15241
15776
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15242
15777
  msg.RequestJson = reqData
15243
15778
  self.MakeRequest('PUT', msg)
@@ -15337,7 +15872,7 @@ class SpotifyClient:
15337
15872
  }
15338
15873
 
15339
15874
  # execute spotify web api request.
15340
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/tracks'.format(playlist_id=playlistId))
15875
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{id}/items'.format(id=playlistId))
15341
15876
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15342
15877
  msg.RequestJson = reqData
15343
15878
  self.MakeRequest('PUT', msg)
@@ -15374,8 +15909,8 @@ class SpotifyClient:
15374
15909
 
15375
15910
  Args:
15376
15911
  ids (str):
15377
- A comma-separated list of the Spotify IDs for the albums.
15378
- Maximum: 50 IDs.
15912
+ A comma-separated list of the Spotify ID's (or URI's) for the albums.
15913
+ Maximum: 40 IDs.
15379
15914
  Example: `6vc9OTcyd3hyzabCmsdnwE,382ObEPsp2rxGrnsizN5TX,2noRn2Aes5aoNVsU6iWThc`
15380
15915
  If null, the currently playing track album uri id value is used.
15381
15916
 
@@ -15409,6 +15944,10 @@ class SpotifyClient:
15409
15944
  apiMethodParms.AppendKeyValue("ids", ids)
15410
15945
  _logsi.LogMethodParmList(SILevel.Verbose, "Save album(s) to user favorites", apiMethodParms)
15411
15946
 
15947
+ # remove any leading / trailing spaces.
15948
+ if ids is not None:
15949
+ ids = ids.replace(' ','')
15950
+
15412
15951
  # if ids not specified, then return currently playing album id value.
15413
15952
  if (ids is None) or (len(ids.strip()) == 0):
15414
15953
  uri = self.GetPlayerNowPlayingAlbumUri()
@@ -15417,22 +15956,23 @@ class SpotifyClient:
15417
15956
  else:
15418
15957
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15419
15958
 
15420
- # build a list of all item id's.
15959
+ # build a list of all item uri's from id values.
15421
15960
  # remove any leading / trailing spaces in case user put a space between the items.
15422
- arrIds:list[str] = ids.split(',')
15423
- for idx in range(0, len(arrIds)):
15424
- arrIds[idx] = arrIds[idx].strip()
15425
-
15961
+ arrUris:list[str] = ids.split(',')
15962
+ for idx in range(0, len(arrUris)):
15963
+ if (arrUris[idx].find(":") == -1):
15964
+ arrUris[idx] = SpotifyTypePrefixes.ALBUM.value + arrUris[idx].strip()
15965
+
15426
15966
  # build spotify web api request parameters.
15427
- reqData:dict = \
15967
+ urlParms:dict = \
15428
15968
  {
15429
- 'ids': arrIds
15969
+ 'uris': ",".join(arrUris)
15430
15970
  }
15431
15971
 
15432
15972
  # execute spotify web api request.
15433
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/albums')
15973
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15434
15974
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15435
- msg.RequestJson = reqData
15975
+ msg.UrlParameters = urlParms
15436
15976
  self.MakeRequest('PUT', msg)
15437
15977
 
15438
15978
  # process results.
@@ -15464,8 +16004,8 @@ class SpotifyClient:
15464
16004
 
15465
16005
  Args:
15466
16006
  ids (str):
15467
- A comma-separated list of the Spotify IDs for the audiobooks.
15468
- Maximum: 50 IDs.
16007
+ A comma-separated list of the Spotify ID's (or URI's) for the audiobooks.
16008
+ Maximum: 40 IDs.
15469
16009
  Example: `3PFyizE2tGCSRLusl2Qizf,7iHfbu1YPACw6oZPAFJtqe`
15470
16010
  If null, the currently playing audiobook uri id value is used.
15471
16011
 
@@ -15499,6 +16039,10 @@ class SpotifyClient:
15499
16039
  apiMethodParms.AppendKeyValue("ids", ids)
15500
16040
  _logsi.LogMethodParmList(SILevel.Verbose, "Save audiobook(s) to user favorites", apiMethodParms)
15501
16041
 
16042
+ # remove any leading / trailing spaces.
16043
+ if ids is not None:
16044
+ ids = ids.replace(' ','')
16045
+
15502
16046
  # if ids not specified, then return currently playing id value.
15503
16047
  if (ids is None) or (len(ids.strip()) == 0):
15504
16048
  uri = self.GetPlayerNowPlayingAudiobookUri()
@@ -15507,24 +16051,25 @@ class SpotifyClient:
15507
16051
  else:
15508
16052
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15509
16053
 
15510
- # build a list of all item id's.
16054
+ # build a list of all item uri's from id values.
15511
16055
  # remove any leading / trailing spaces in case user put a space between the items.
15512
- arrIds:list[str] = ids.split(',')
15513
- for idx in range(0, len(arrIds)):
15514
- arrIds[idx] = arrIds[idx].strip()
16056
+ arrUris:list[str] = ids.split(',')
16057
+ for idx in range(0, len(arrUris)):
16058
+ if (arrUris[idx].find(":") == -1):
16059
+ arrUris[idx] = SpotifyTypePrefixes.SHOW.value + arrUris[idx].strip() # spotify web api considers audiobook a "show"!
15515
16060
 
15516
16061
  # build spotify web api request parameters.
15517
- reqData:dict = \
16062
+ urlParms:dict = \
15518
16063
  {
15519
- 'ids': arrIds
16064
+ 'uris': ",".join(arrUris)
15520
16065
  }
15521
16066
 
15522
16067
  # execute spotify web api request.
15523
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/audiobooks')
16068
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15524
16069
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15525
- msg.RequestJson = reqData
16070
+ msg.UrlParameters = urlParms
15526
16071
  self.MakeRequest('PUT', msg)
15527
-
16072
+
15528
16073
  # process results.
15529
16074
  # no results to process - this is pass or fail.
15530
16075
  return
@@ -15554,8 +16099,8 @@ class SpotifyClient:
15554
16099
 
15555
16100
  Args:
15556
16101
  ids (str):
15557
- A comma-separated list of the Spotify IDs for the episodes.
15558
- Maximum: 50 IDs.
16102
+ A comma-separated list of the Spotify ID's (or URI's) for the episodes.
16103
+ Maximum: 40 IDs.
15559
16104
  Example: `6kAsbP8pxwaU2kPibKTuHE,4rOoJ6Egrf8K2IrywzwOMk`
15560
16105
  If null, the currently playing episode uri id value is used.
15561
16106
 
@@ -15589,6 +16134,10 @@ class SpotifyClient:
15589
16134
  apiMethodParms.AppendKeyValue("ids", ids)
15590
16135
  _logsi.LogMethodParmList(SILevel.Verbose, "Save episode(s) to user favorites", apiMethodParms)
15591
16136
 
16137
+ # remove any leading / trailing spaces.
16138
+ if ids is not None:
16139
+ ids = ids.replace(' ','')
16140
+
15592
16141
  # if ids not specified, then return currently playing id value.
15593
16142
  if (ids is None) or (len(ids.strip()) == 0):
15594
16143
  uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.EPISODE.value)
@@ -15597,22 +16146,23 @@ class SpotifyClient:
15597
16146
  else:
15598
16147
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15599
16148
 
15600
- # build a list of all item id's.
16149
+ # build a list of all item uri's from id values.
15601
16150
  # remove any leading / trailing spaces in case user put a space between the items.
15602
- arrIds:list[str] = ids.split(',')
15603
- for idx in range(0, len(arrIds)):
15604
- arrIds[idx] = arrIds[idx].strip()
16151
+ arrUris:list[str] = ids.split(',')
16152
+ for idx in range(0, len(arrUris)):
16153
+ if (arrUris[idx].find(":") == -1):
16154
+ arrUris[idx] = SpotifyTypePrefixes.EPISODE.value + arrUris[idx].strip()
15605
16155
 
15606
16156
  # build spotify web api request parameters.
15607
- reqData:dict = \
16157
+ urlParms:dict = \
15608
16158
  {
15609
- 'ids': arrIds
16159
+ 'uris': ",".join(arrUris)
15610
16160
  }
15611
16161
 
15612
16162
  # execute spotify web api request.
15613
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/episodes')
16163
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15614
16164
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15615
- msg.RequestJson = reqData
16165
+ msg.UrlParameters = urlParms
15616
16166
  self.MakeRequest('PUT', msg)
15617
16167
 
15618
16168
  # process results.
@@ -15644,8 +16194,8 @@ class SpotifyClient:
15644
16194
 
15645
16195
  Args:
15646
16196
  ids (str):
15647
- A comma-separated list of the Spotify IDs for the shows.
15648
- Maximum: 50 IDs.
16197
+ A comma-separated list of the Spotify ID's (or URI's) for the shows.
16198
+ Maximum: 40 IDs.
15649
16199
  Example: `6kAsbP8pxwaU2kPibKTuHE,4rOoJ6Egrf8K2IrywzwOMk`
15650
16200
  If null, the currently playing show uri id value is used.
15651
16201
 
@@ -15679,6 +16229,10 @@ class SpotifyClient:
15679
16229
  apiMethodParms.AppendKeyValue("ids", ids)
15680
16230
  _logsi.LogMethodParmList(SILevel.Verbose, "Save show(s) to user favorites", apiMethodParms)
15681
16231
 
16232
+ # remove any leading / trailing spaces.
16233
+ if ids is not None:
16234
+ ids = ids.replace(' ','')
16235
+
15682
16236
  # if ids not specified, then return currently playing id value.
15683
16237
  if (ids is None) or (len(ids.strip()) == 0):
15684
16238
  uri = self.GetPlayerNowPlayingShowUri()
@@ -15687,18 +16241,21 @@ class SpotifyClient:
15687
16241
  else:
15688
16242
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15689
16243
 
16244
+ # build a list of all item uri's from id values.
15690
16245
  # remove any leading / trailing spaces in case user put a space between the items.
15691
- if (ids is not None):
15692
- ids = ids.replace(" ","")
16246
+ arrUris:list[str] = ids.split(',')
16247
+ for idx in range(0, len(arrUris)):
16248
+ if (arrUris[idx].find(":") == -1):
16249
+ arrUris[idx] = SpotifyTypePrefixes.SHOW.value + arrUris[idx].strip()
15693
16250
 
15694
16251
  # build spotify web api request parameters.
15695
16252
  urlParms:dict = \
15696
16253
  {
15697
- 'ids': ids
16254
+ 'uris': ",".join(arrUris)
15698
16255
  }
15699
16256
 
15700
16257
  # execute spotify web api request.
15701
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/shows')
16258
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15702
16259
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15703
16260
  msg.UrlParameters = urlParms
15704
16261
  self.MakeRequest('PUT', msg)
@@ -15732,8 +16289,8 @@ class SpotifyClient:
15732
16289
 
15733
16290
  Args:
15734
16291
  ids (str):
15735
- A comma-separated list of the Spotify IDs for the tracks.
15736
- Maximum: 50 IDs.
16292
+ A comma-separated list of the Spotify ID's (or URI's) for the tracks.
16293
+ Maximum: 40 IDs.
15737
16294
  Example: `6vc9OTcyd3hyzabCmsdnwE,382ObEPsp2rxGrnsizN5TX,2noRn2Aes5aoNVsU6iWThc`
15738
16295
  If null, the currently playing track uri id value is used.
15739
16296
 
@@ -15767,6 +16324,10 @@ class SpotifyClient:
15767
16324
  apiMethodParms.AppendKeyValue("ids", ids)
15768
16325
  _logsi.LogMethodParmList(SILevel.Verbose, "Save track(s) to user favorites", apiMethodParms)
15769
16326
 
16327
+ # remove any leading / trailing spaces.
16328
+ if ids is not None:
16329
+ ids = ids.replace(' ','')
16330
+
15770
16331
  # if ids not specified, then return currently playing id value.
15771
16332
  if (ids is None) or (len(ids.strip()) == 0):
15772
16333
  uri = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.TRACK.value)
@@ -15775,22 +16336,112 @@ class SpotifyClient:
15775
16336
  else:
15776
16337
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
15777
16338
 
15778
- # build a list of all item id's.
16339
+ # build a list of all item uri's from id values.
15779
16340
  # remove any leading / trailing spaces in case user put a space between the items.
15780
- arrIds:list[str] = ids.split(',')
15781
- for idx in range(0, len(arrIds)):
15782
- arrIds[idx] = arrIds[idx].strip()
16341
+ arrUris:list[str] = ids.split(',')
16342
+ for idx in range(0, len(arrUris)):
16343
+ if (arrUris[idx].find(":") == -1):
16344
+ arrUris[idx] = SpotifyTypePrefixes.TRACK.value + arrUris[idx].strip()
15783
16345
 
15784
16346
  # build spotify web api request parameters.
15785
- reqData:dict = \
16347
+ urlParms:dict = \
15786
16348
  {
15787
- 'ids': arrIds
16349
+ 'uris': ",".join(arrUris)
15788
16350
  }
15789
16351
 
15790
16352
  # execute spotify web api request.
15791
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/tracks')
16353
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
15792
16354
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
15793
- msg.RequestJson = reqData
16355
+ msg.UrlParameters = urlParms
16356
+ self.MakeRequest('PUT', msg)
16357
+
16358
+ # process results.
16359
+ # no results to process - this is pass or fail.
16360
+ return
16361
+
16362
+ except SpotifyApiError: raise # pass handled exceptions on thru
16363
+ except SpotifyWebApiError: raise # pass handled exceptions on thru
16364
+ except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
16365
+ except Exception as ex:
16366
+
16367
+ # format unhandled exception.
16368
+ raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
16369
+
16370
+ finally:
16371
+
16372
+ # trace.
16373
+ _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
16374
+
16375
+
16376
+ def SaveUserFavorites(
16377
+ self,
16378
+ uris:str=None
16379
+ ) -> None:
16380
+ """
16381
+ Add one or more items to the current user's library.
16382
+ Accepts Spotify URIs for tracks, albums, episodes, shows, audiobooks, users, and playlists.
16383
+
16384
+ This method requires the `user-library-modify`, `user-follow-modify`, and `playlist-modify-public` scopes.
16385
+
16386
+ Args:
16387
+ uris (str):
16388
+ A comma-separated list of the Spotify URIs for the items.
16389
+ Maximum: 40 URIs.
16390
+ Example: `spotify:artist:6APm8EjxOHSYM5B4i3vT3q,spotify:album:6vc9OTcyd3hyzabCmsdnwE,spotify:track:1kWUud3vY5ij5r62zxpTRy`
16391
+ If null, the currently playing item uri value is used.
16392
+
16393
+ Raises:
16394
+ SpotifyWebApiError:
16395
+ If the Spotify Web API request was for a non-authorization service
16396
+ and the response contains error information.
16397
+ SpotifyApiError:
16398
+ If the method fails for any other reason.
16399
+
16400
+ No error will be raised if an item uri in the list already exists in the
16401
+ user's 'Your Library'.
16402
+
16403
+ An SpotifyWebApiError will be raised if a specified item uri does not exist
16404
+ in the Spotify music catalog.
16405
+
16406
+ <details>
16407
+ <summary>Sample Code</summary>
16408
+ ```python
16409
+ .. include:: ../docs/include/samplecode/SpotifyClient/SaveUserFavorites.py
16410
+ ```
16411
+ </details>
16412
+ """
16413
+ apiMethodName:str = 'SaveUserFavorites'
16414
+ apiMethodParms:SIMethodParmListContext = None
16415
+
16416
+ try:
16417
+
16418
+ # trace.
16419
+ apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
16420
+ apiMethodParms.AppendKeyValue("uris", uris)
16421
+ _logsi.LogMethodParmList(SILevel.Verbose, "Save item(s) to user favorites", apiMethodParms)
16422
+
16423
+ # if uris not specified, then return currently playing item uri value.
16424
+ if (uris is None) or (len(uris.strip()) == 0):
16425
+ uris = self.GetPlayerNowPlayingUri(SpotifyMediaTypes.EPISODE.value, False)
16426
+ if uris is None:
16427
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'uris'), logsi=_logsi)
16428
+
16429
+ # build a list of all item uri's.
16430
+ # remove any leading / trailing spaces in case user put a space between the items.
16431
+ arrUris:list[str] = uris.split(',')
16432
+ for idx in range(0, len(arrUris)):
16433
+ arrUris[idx] = arrUris[idx].strip()
16434
+
16435
+ # build spotify web api request parameters.
16436
+ urlParms:dict = \
16437
+ {
16438
+ 'uris': ",".join(arrUris)
16439
+ }
16440
+
16441
+ # execute spotify web api request.
16442
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
16443
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
16444
+ msg.UrlParameters = urlParms
15794
16445
  self.MakeRequest('PUT', msg)
15795
16446
 
15796
16447
  # process results.
@@ -15861,7 +16512,7 @@ class SpotifyClient:
15861
16512
  The maximum number of items to return for the request, per criteria type.
15862
16513
  Paging is automatically used to retrieve all available items up to the
15863
16514
  maximum number specified per type.
15864
- Default: 20
16515
+ Default: 10
15865
16516
 
15866
16517
  Returns:
15867
16518
  A `SearchResponse` object that contains the search results.
@@ -15908,12 +16559,12 @@ class SpotifyClient:
15908
16559
  if isinstance(criteriaType, SpotifyMediaTypes):
15909
16560
  criteriaType = SpotifyMediaTypes.value
15910
16561
  if limitTotal is None:
15911
- limitTotal = 20
16562
+ limitTotal = 10
15912
16563
  if not isinstance(limitTotal, int):
15913
- limitTotal = 20
16564
+ limitTotal = 10
15914
16565
 
15915
16566
  # are we auto-paging? if so, then use max limit.
15916
- limit:int = 50
16567
+ limit:int = 10
15917
16568
  if limit > limitTotal:
15918
16569
  limit = limitTotal
15919
16570
 
@@ -15981,7 +16632,7 @@ class SpotifyClient:
15981
16632
  def SearchAlbums(
15982
16633
  self,
15983
16634
  criteria:str,
15984
- limit:int=20,
16635
+ limit:int=5,
15985
16636
  offset:int=0,
15986
16637
  market:str=None,
15987
16638
  includeExternal:str=None,
@@ -16175,7 +16826,7 @@ class SpotifyClient:
16175
16826
  def SearchArtists(
16176
16827
  self,
16177
16828
  criteria:str,
16178
- limit:int=20,
16829
+ limit:int=5,
16179
16830
  offset:int=0,
16180
16831
  market:str=None,
16181
16832
  includeExternal:str=None,
@@ -16200,7 +16851,7 @@ class SpotifyClient:
16200
16851
  can be used to return only albums with the lowest 10% popularity.
16201
16852
  limit (int):
16202
16853
  The maximum number of items to return in a page of items when manual paging is used.
16203
- Default: 20, Range: 1 to 50.
16854
+ Default: 5, Range: 1 to 10.
16204
16855
  See the `limitTotal` argument for automatic paging option.
16205
16856
  offset (int):
16206
16857
  The page index offset of the first item to return.
@@ -16272,7 +16923,7 @@ class SpotifyClient:
16272
16923
 
16273
16924
  # validations.
16274
16925
  if limit is None:
16275
- limit = 20
16926
+ limit = 5
16276
16927
  if offset is None:
16277
16928
  offset = 0
16278
16929
  if not isinstance(limitTotal, int):
@@ -16280,7 +16931,7 @@ class SpotifyClient:
16280
16931
 
16281
16932
  # are we auto-paging? if so, then use max limit.
16282
16933
  if limitTotal > 0:
16283
- limit = 50
16934
+ limit = 10
16284
16935
  if limit > limitTotal:
16285
16936
  limit = limitTotal
16286
16937
  result = ArtistPage()
@@ -16369,7 +17020,7 @@ class SpotifyClient:
16369
17020
  def SearchAudiobooks(
16370
17021
  self,
16371
17022
  criteria:str,
16372
- limit:int=20,
17023
+ limit:int=5,
16373
17024
  offset:int=0,
16374
17025
  market:str=None,
16375
17026
  includeExternal:str=None,
@@ -16394,7 +17045,7 @@ class SpotifyClient:
16394
17045
  can be used to return only albums with the lowest 10% popularity.
16395
17046
  limit (int):
16396
17047
  The maximum number of items to return in a page of items when manual paging is used.
16397
- Default: 20, Range: 1 to 50.
17048
+ Default: 5, Range: 1 to 10.
16398
17049
  See the `limitTotal` argument for automatic paging option.
16399
17050
  offset (int):
16400
17051
  The page index offset of the first item to return.
@@ -16468,7 +17119,7 @@ class SpotifyClient:
16468
17119
 
16469
17120
  # validations.
16470
17121
  if limit is None:
16471
- limit = 20
17122
+ limit = 5
16472
17123
  if offset is None:
16473
17124
  offset = 0
16474
17125
  if not isinstance(limitTotal, int):
@@ -16476,7 +17127,7 @@ class SpotifyClient:
16476
17127
 
16477
17128
  # are we auto-paging? if so, then use max limit.
16478
17129
  if limitTotal > 0:
16479
- limit = 50
17130
+ limit = 10
16480
17131
  if limit > limitTotal:
16481
17132
  limit = limitTotal
16482
17133
  result = AudiobookPageSimplified()
@@ -16565,7 +17216,7 @@ class SpotifyClient:
16565
17216
  def SearchEpisodes(
16566
17217
  self,
16567
17218
  criteria:str,
16568
- limit:int=20,
17219
+ limit:int=5,
16569
17220
  offset:int=0,
16570
17221
  market:str=None,
16571
17222
  includeExternal:str=None,
@@ -16590,7 +17241,7 @@ class SpotifyClient:
16590
17241
  can be used to return only albums with the lowest 10% popularity.
16591
17242
  limit (int):
16592
17243
  The maximum number of items to return in a page of items when manual paging is used.
16593
- Default: 20, Range: 1 to 50.
17244
+ Default: 5, Range: 1 to 10.
16594
17245
  See the `limitTotal` argument for automatic paging option.
16595
17246
  offset (int):
16596
17247
  The page index offset of the first item to return.
@@ -16662,7 +17313,7 @@ class SpotifyClient:
16662
17313
 
16663
17314
  # validations.
16664
17315
  if limit is None:
16665
- limit = 20
17316
+ limit = 5
16666
17317
  if offset is None:
16667
17318
  offset = 0
16668
17319
  if not isinstance(limitTotal, int):
@@ -16670,7 +17321,7 @@ class SpotifyClient:
16670
17321
 
16671
17322
  # are we auto-paging? if so, then use max limit.
16672
17323
  if limitTotal > 0:
16673
- limit = 50
17324
+ limit = 10
16674
17325
  if limit > limitTotal:
16675
17326
  limit = limitTotal
16676
17327
  result = EpisodePageSimplified()
@@ -16759,7 +17410,7 @@ class SpotifyClient:
16759
17410
  def SearchPlaylists(
16760
17411
  self,
16761
17412
  criteria:str,
16762
- limit:int=20,
17413
+ limit:int=5,
16763
17414
  offset:int=0,
16764
17415
  market:str=None,
16765
17416
  includeExternal:str=None,
@@ -16784,7 +17435,7 @@ class SpotifyClient:
16784
17435
  can be used to return only albums with the lowest 10% popularity.
16785
17436
  limit (int):
16786
17437
  The maximum number of items to return in a page of items when manual paging is used.
16787
- Default: 20, Range: 1 to 50.
17438
+ Default: 5, Range: 1 to 10.
16788
17439
  See the `limitTotal` argument for automatic paging option.
16789
17440
  offset (int):
16790
17441
  The page index offset of the first item to return.
@@ -16856,7 +17507,7 @@ class SpotifyClient:
16856
17507
 
16857
17508
  # validations.
16858
17509
  if limit is None:
16859
- limit = 20
17510
+ limit = 5
16860
17511
  if offset is None:
16861
17512
  offset = 0
16862
17513
  if not isinstance(limitTotal, int):
@@ -16864,7 +17515,7 @@ class SpotifyClient:
16864
17515
 
16865
17516
  # are we auto-paging? if so, then use max limit.
16866
17517
  if limitTotal > 0:
16867
- limit = 50
17518
+ limit = 10
16868
17519
  if limit > limitTotal:
16869
17520
  limit = limitTotal
16870
17521
  result = PlaylistPageSimplified()
@@ -16953,7 +17604,7 @@ class SpotifyClient:
16953
17604
  def SearchShows(
16954
17605
  self,
16955
17606
  criteria:str,
16956
- limit:int=20,
17607
+ limit:int=5,
16957
17608
  offset:int=0,
16958
17609
  market:str=None,
16959
17610
  includeExternal:str=None,
@@ -16978,7 +17629,7 @@ class SpotifyClient:
16978
17629
  can be used to return only albums with the lowest 10% popularity.
16979
17630
  limit (int):
16980
17631
  The maximum number of items to return in a page of items when manual paging is used.
16981
- Default: 20, Range: 1 to 50.
17632
+ Default: 5, Range: 1 to 10.
16982
17633
  See the `limitTotal` argument for automatic paging option.
16983
17634
  offset (int):
16984
17635
  The page index offset of the first item to return.
@@ -17050,7 +17701,7 @@ class SpotifyClient:
17050
17701
 
17051
17702
  # validations.
17052
17703
  if limit is None:
17053
- limit = 20
17704
+ limit = 5
17054
17705
  if offset is None:
17055
17706
  offset = 0
17056
17707
  if not isinstance(limitTotal, int):
@@ -17058,7 +17709,7 @@ class SpotifyClient:
17058
17709
 
17059
17710
  # are we auto-paging? if so, then use max limit.
17060
17711
  if limitTotal > 0:
17061
- limit = 50
17712
+ limit = 10
17062
17713
  if limit > limitTotal:
17063
17714
  limit = limitTotal
17064
17715
  result = ShowPageSimplified()
@@ -17147,7 +17798,7 @@ class SpotifyClient:
17147
17798
  def SearchTracks(
17148
17799
  self,
17149
17800
  criteria:str,
17150
- limit:int=20,
17801
+ limit:int=5,
17151
17802
  offset:int=0,
17152
17803
  market:str=None,
17153
17804
  includeExternal:str=None,
@@ -17172,7 +17823,7 @@ class SpotifyClient:
17172
17823
  can be used to return only albums with the lowest 10% popularity.
17173
17824
  limit (int):
17174
17825
  The maximum number of items to return in a page of items when manual paging is used.
17175
- Default: 20, Range: 1 to 50.
17826
+ Default: 5, Range: 1 to 10.
17176
17827
  See the `limitTotal` argument for automatic paging option.
17177
17828
  offset (int):
17178
17829
  The page index offset of the first item to return.
@@ -17244,7 +17895,7 @@ class SpotifyClient:
17244
17895
 
17245
17896
  # validations.
17246
17897
  if limit is None:
17247
- limit = 20
17898
+ limit = 5
17248
17899
  if offset is None:
17249
17900
  offset = 0
17250
17901
  if not isinstance(limitTotal, int):
@@ -17252,7 +17903,7 @@ class SpotifyClient:
17252
17903
 
17253
17904
  # are we auto-paging? if so, then use max limit.
17254
17905
  if limitTotal > 0:
17255
- limit = 50
17906
+ limit = 10
17256
17907
  if limit > limitTotal:
17257
17908
  limit = limitTotal
17258
17909
  result = TrackPage()
@@ -17977,7 +18628,7 @@ class SpotifyClient:
17977
18628
  Args:
17978
18629
  ids (str):
17979
18630
  A comma-separated list of Spotify artist IDs.
17980
- A maximum of 50 IDs can be sent in one request.
18631
+ A maximum of 40 IDs can be sent in one request.
17981
18632
  Example: `2CIMQHirSU0MQqyYHq0eOx,1IQ2e1buppatiN1bxUVkrk`
17982
18633
  If null, the currently playing track artist uri id value is used.
17983
18634
 
@@ -18007,6 +18658,10 @@ class SpotifyClient:
18007
18658
  apiMethodParms.AppendKeyValue("ids", ids)
18008
18659
  _logsi.LogMethodParmList(SILevel.Verbose, "Remove the current user as a follower of one or more artists", apiMethodParms)
18009
18660
 
18661
+ # remove any leading / trailing spaces.
18662
+ if ids is not None:
18663
+ ids = ids.replace(' ','')
18664
+
18010
18665
  # if ids not specified, then return currently playing artist id value.
18011
18666
  if (ids is None) or (len(ids.strip()) == 0):
18012
18667
  uri = self.GetPlayerNowPlayingArtistUri()
@@ -18015,22 +18670,23 @@ class SpotifyClient:
18015
18670
  else:
18016
18671
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'ids'), logsi=_logsi)
18017
18672
 
18018
- # build a list of all item id's.
18673
+ # build a list of all item uri's from id values.
18019
18674
  # remove any leading / trailing spaces in case user put a space between the items.
18020
- arrIds:list[str] = ids.split(',')
18021
- for idx in range(0, len(arrIds)):
18022
- arrIds[idx] = arrIds[idx].strip()
18675
+ arrUris:list[str] = ids.split(',')
18676
+ for idx in range(0, len(arrUris)):
18677
+ if (arrUris[idx].find(":") == -1):
18678
+ arrUris[idx] = SpotifyTypePrefixes.ARTIST.value + arrUris[idx].strip()
18023
18679
 
18024
18680
  # build spotify web api request parameters.
18025
- reqData:dict = \
18681
+ urlParms:dict = \
18026
18682
  {
18027
- 'ids': arrIds
18683
+ 'uris': ",".join(arrUris)
18028
18684
  }
18029
18685
 
18030
18686
  # execute spotify web api request.
18031
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following?type=artist')
18687
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
18032
18688
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
18033
- msg.RequestJson = reqData
18689
+ msg.UrlParameters = urlParms
18034
18690
  self.MakeRequest('DELETE', msg)
18035
18691
 
18036
18692
  # process results.
@@ -18062,7 +18718,8 @@ class SpotifyClient:
18062
18718
 
18063
18719
  Args:
18064
18720
  playlistId (str):
18065
- The Spotify ID of the playlist.
18721
+ A comma-separated list of Spotify playlist IDs.
18722
+ A maximum of 40 IDs can be sent in one request.
18066
18723
  Example: `3cEYpjA9oz9GiPac4AsH4n`
18067
18724
  If null, the currently playing playlist uri id value is used.
18068
18725
 
@@ -18090,6 +18747,10 @@ class SpotifyClient:
18090
18747
  apiMethodParms.AppendKeyValue("playlistId", playlistId)
18091
18748
  _logsi.LogMethodParmList(SILevel.Verbose, "Remove the current user as a follower of a playlist", apiMethodParms)
18092
18749
 
18750
+ # remove any leading / trailing spaces.
18751
+ if playlistId is not None:
18752
+ playlistId = playlistId.replace(' ','')
18753
+
18093
18754
  # if playlistId not specified, then return currently playing playlist id value.
18094
18755
  if (playlistId is None) or (len(playlistId.strip()) == 0):
18095
18756
  uri = self.GetPlayerNowPlayingPlaylistUri()
@@ -18098,11 +18759,25 @@ class SpotifyClient:
18098
18759
  else:
18099
18760
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'playlistId'), logsi=_logsi)
18100
18761
 
18762
+ # build a list of all item uri's from id values.
18763
+ # remove any leading / trailing spaces in case user put a space between the items.
18764
+ arrUris:list[str] = playlistId.split(',')
18765
+ for idx in range(0, len(arrUris)):
18766
+ if (arrUris[idx].find(":") == -1):
18767
+ arrUris[idx] = SpotifyTypePrefixes.PLAYLIST.value + arrUris[idx].strip()
18768
+
18769
+ # build spotify web api request parameters.
18770
+ urlParms:dict = \
18771
+ {
18772
+ 'uris': ",".join(arrUris)
18773
+ }
18774
+
18101
18775
  # execute spotify web api request.
18102
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/playlists/{playlist_id}/followers'.format(playlist_id=playlistId))
18776
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
18103
18777
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
18778
+ msg.UrlParameters = urlParms
18104
18779
  self.MakeRequest('DELETE', msg)
18105
-
18780
+
18106
18781
  # process results.
18107
18782
  # no results to process - this is pass or fail.
18108
18783
  return
@@ -18133,7 +18808,7 @@ class SpotifyClient:
18133
18808
  Args:
18134
18809
  ids (str):
18135
18810
  A comma-separated list of Spotify user IDs.
18136
- A maximum of 50 IDs can be sent in one request.
18811
+ A maximum of 40 IDs can be sent in one request.
18137
18812
  Example: `smedjan`
18138
18813
 
18139
18814
  Raises:
@@ -18162,22 +18837,23 @@ class SpotifyClient:
18162
18837
  apiMethodParms.AppendKeyValue("ids", ids)
18163
18838
  _logsi.LogMethodParmList(SILevel.Verbose, "Remove current user as a follower of one or more users", apiMethodParms)
18164
18839
 
18165
- # build a list of all item id's.
18840
+ # build a list of all item uri's from id values.
18166
18841
  # remove any leading / trailing spaces in case user put a space between the items.
18167
- arrIds:list[str] = ids.split(',')
18168
- for idx in range(0, len(arrIds)):
18169
- arrIds[idx] = arrIds[idx].strip()
18842
+ arrUris:list[str] = ids.split(',')
18843
+ for idx in range(0, len(arrUris)):
18844
+ if (arrUris[idx].find(":") == -1):
18845
+ arrUris[idx] = SpotifyTypePrefixes.USER.value + arrUris[idx].strip()
18170
18846
 
18171
18847
  # build spotify web api request parameters.
18172
- reqData:dict = \
18848
+ urlParms:dict = \
18173
18849
  {
18174
- 'ids': arrIds
18850
+ 'uris': ",".join(arrUris)
18175
18851
  }
18176
18852
 
18177
18853
  # execute spotify web api request.
18178
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/following?type=user')
18854
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/library')
18179
18855
  msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
18180
- msg.RequestJson = reqData
18856
+ msg.UrlParameters = urlParms
18181
18857
  self.MakeRequest('DELETE', msg)
18182
18858
 
18183
18859
  # process results.