spotifywebapiPython 1.0.174__py3-none-any.whl → 1.0.175__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.
Potentially problematic release.
This version of spotifywebapiPython might be problematic. Click here for more details.
- {spotifywebapiPython-1.0.174.dist-info → spotifywebapiPython-1.0.175.dist-info}/METADATA +1 -1
- {spotifywebapiPython-1.0.174.dist-info → spotifywebapiPython-1.0.175.dist-info}/RECORD +23 -23
- spotifywebapipython/const.py +1 -1
- spotifywebapipython/docs/__init__.html +9 -3
- spotifywebapipython/docs/index.html +3 -3
- spotifywebapipython/docs/search.js +1 -1
- spotifywebapipython/docs/spotifywebapipython/const.html +4 -4
- spotifywebapipython/docs/spotifywebapipython/saappmessages.html +37 -3
- spotifywebapipython/docs/spotifywebapipython/sautils.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +43 -21
- spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +3 -3
- spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +3 -3
- spotifywebapipython/saappmessages.py +10 -0
- spotifywebapipython/spotifyclient.py +153 -69
- spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py +10 -8
- {spotifywebapiPython-1.0.174.dist-info → spotifywebapiPython-1.0.175.dist-info}/LICENSE +0 -0
- {spotifywebapiPython-1.0.174.dist-info → spotifywebapiPython-1.0.175.dist-info}/WHEEL +0 -0
- {spotifywebapiPython-1.0.174.dist-info → spotifywebapiPython-1.0.175.dist-info}/top_level.txt +0 -0
|
@@ -10,6 +10,7 @@ from soco.core import (
|
|
|
10
10
|
)
|
|
11
11
|
from soco.plugins.sharelink import ShareLinkPlugin
|
|
12
12
|
import time
|
|
13
|
+
import threading
|
|
13
14
|
from typing import Tuple, Callable, Union
|
|
14
15
|
from urllib3 import PoolManager, Timeout, HTTPResponse
|
|
15
16
|
from urllib.parse import urlencode
|
|
@@ -208,6 +209,8 @@ class SpotifyClient:
|
|
|
208
209
|
self._SpotifyConnectDiscoveryTimeout:float = float(spotifyConnectDiscoveryTimeout)
|
|
209
210
|
self._SpotifyConnectDirectory:SpotifyConnectDirectoryTask = None
|
|
210
211
|
self._SpotifyConnectDirectoryEnabled:bool = spotifyConnectDirectoryEnabled
|
|
212
|
+
self._SpotifyWebPlayerToken:SpotifyWebPlayerToken = None
|
|
213
|
+
self._SpotifyWebPlayerToken_RLock:threading.RLock = threading.RLock()
|
|
211
214
|
self._TokenStorageDir:str = tokenStorageDir
|
|
212
215
|
self._TokenStorageFile:str = tokenStorageFile
|
|
213
216
|
self._TokenUpdater:Callable = tokenUpdater
|
|
@@ -797,44 +800,54 @@ class SpotifyClient:
|
|
|
797
800
|
credentials are then converted into an authorization access token which is used by
|
|
798
801
|
Spotify Web API endpoints to start playback on the specified device id.
|
|
799
802
|
"""
|
|
800
|
-
result:SpotifyWebPlayerToken = None
|
|
801
|
-
|
|
802
803
|
# are spotify web player credentials configured? if not, then don't bother!
|
|
803
804
|
if (not self._HasSpotifyWebPlayerCredentials):
|
|
804
|
-
return
|
|
805
|
+
return None
|
|
805
806
|
|
|
806
|
-
#
|
|
807
|
-
|
|
807
|
+
# make the following thread-safe, so we don't retrieve multiple tokens.
|
|
808
|
+
with self._SpotifyWebPlayerToken_RLock:
|
|
808
809
|
|
|
809
|
-
#
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
tokenStorageFile=self._TokenStorageFile)
|
|
814
|
-
if tokenWP is not None:
|
|
815
|
-
result = tokenWP.HeaderValue
|
|
816
|
-
_logsi.LogVerbose("Spotify Web Player authorization access token will be used")
|
|
810
|
+
# if token already retrieved and has not expired, then use it.
|
|
811
|
+
if (self._SpotifyWebPlayerToken is not None) and (not self._SpotifyWebPlayerToken.IsExpired):
|
|
812
|
+
_logsi.LogVerbose(SAAppMessages.MSG_SPOTIFY_WEB_PLAYER_TOKEN_INUSE, colorValue=SIColors.Gold)
|
|
813
|
+
return self._SpotifyWebPlayerToken.HeaderValue
|
|
817
814
|
|
|
818
|
-
|
|
815
|
+
# was a device argument passed? if not, then just refresh the token.
|
|
816
|
+
if (scDevice is None):
|
|
819
817
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
818
|
+
# get spotify web player access token info from spotify web player cookie credentials.
|
|
819
|
+
_logsi.LogVerbose(SAAppMessages.MSG_SPOTIFY_WEB_PLAYER_TOKEN_REFRESHED % (self._SpotifyConnectLoginId), colorValue=SIColors.Gold)
|
|
820
|
+
self._SpotifyWebPlayerToken = SpotifyWebPlayerToken(
|
|
821
|
+
profileId=self._SpotifyConnectLoginId,
|
|
822
|
+
tokenStorageDir=self._TokenStorageDir,
|
|
823
|
+
tokenStorageFile=self._TokenStorageFile)
|
|
823
824
|
|
|
824
|
-
|
|
825
|
-
|
|
825
|
+
if self._SpotifyWebPlayerToken is not None:
|
|
826
|
+
_logsi.LogVerbose(SAAppMessages.MSG_SPOTIFY_WEB_PLAYER_TOKEN_INUSE, colorValue=SIColors.Gold)
|
|
827
|
+
return self._SpotifyWebPlayerToken.HeaderValue
|
|
826
828
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
829
|
+
else:
|
|
830
|
+
|
|
831
|
+
# was the device resolved? if not, then don't bother!
|
|
832
|
+
if (not isinstance(scDevice, SpotifyConnectDevice)):
|
|
833
|
+
return None
|
|
834
|
+
|
|
835
|
+
# is the device restricted or Sonos?
|
|
836
|
+
if (scDevice.IsSonos or scDevice.IsRestricted):
|
|
837
|
+
|
|
838
|
+
# get spotify web player access token info from spotify web player cookie credentials.
|
|
839
|
+
_logsi.LogVerbose(SAAppMessages.MSG_SPOTIFY_WEB_PLAYER_TOKEN_REFRESHED % (self._SpotifyConnectLoginId), colorValue=SIColors.Gold)
|
|
840
|
+
self._SpotifyWebPlayerToken = SpotifyWebPlayerToken(
|
|
841
|
+
profileId=self._SpotifyConnectLoginId,
|
|
842
|
+
tokenStorageDir=self._TokenStorageDir,
|
|
843
|
+
tokenStorageFile=self._TokenStorageFile)
|
|
844
|
+
|
|
845
|
+
if self._SpotifyWebPlayerToken is not None:
|
|
846
|
+
_logsi.LogVerbose(SAAppMessages.MSG_SPOTIFY_WEB_PLAYER_TOKEN_INUSE, colorValue=SIColors.Gold)
|
|
847
|
+
return self._SpotifyWebPlayerToken.HeaderValue
|
|
835
848
|
|
|
836
849
|
# return result to caller.
|
|
837
|
-
return
|
|
850
|
+
return None
|
|
838
851
|
|
|
839
852
|
|
|
840
853
|
|
|
@@ -1388,9 +1401,14 @@ class SpotifyClient:
|
|
|
1388
1401
|
# resolve the device object from the device id.
|
|
1389
1402
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
1390
1403
|
|
|
1404
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
1405
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
1406
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
1407
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
1408
|
+
|
|
1391
1409
|
# is this an active Sonos device?
|
|
1392
1410
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
1393
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
1411
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
1394
1412
|
|
|
1395
1413
|
# trace.
|
|
1396
1414
|
_logsi.LogVerbose("Items will be added to Sonos local queue for device: %s" % (scDevice.Title))
|
|
@@ -1429,7 +1447,7 @@ class SpotifyClient:
|
|
|
1429
1447
|
|
|
1430
1448
|
# execute spotify web api request.
|
|
1431
1449
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/queue')
|
|
1432
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
1450
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
1433
1451
|
msg.UrlParameters = urlParms
|
|
1434
1452
|
self.MakeRequest('POST', msg)
|
|
1435
1453
|
|
|
@@ -8463,7 +8481,16 @@ class SpotifyClient:
|
|
|
8463
8481
|
If the Spotify Web API request was for a non-authorization service
|
|
8464
8482
|
and the response contains error information.
|
|
8465
8483
|
SpotifyApiError:
|
|
8466
|
-
If the method fails for any other reason.
|
|
8484
|
+
If the method fails for any other reason.
|
|
8485
|
+
|
|
8486
|
+
<span class="warning">
|
|
8487
|
+
<b>DEPRECATED functionality as of 2024/11/27</b>
|
|
8488
|
+
For unauthorized Spotify Developer Applications, the api endpoint will return a `404 - Resource Not Found` exception if a Spotify Algorithmic playlist is specified.<br/>
|
|
8489
|
+
For authorized Spotify Developer Applications, the api endpoint will return details if a Spotify Algorithmic playlist is specified.<br/>
|
|
8490
|
+
More information about the deprecated functionality can be found on the
|
|
8491
|
+
<a href="https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api" target="_blank">Spotify Developer Forum Blog</a>
|
|
8492
|
+
page.
|
|
8493
|
+
<span>
|
|
8467
8494
|
|
|
8468
8495
|
<details>
|
|
8469
8496
|
<summary>Sample Code</summary>
|
|
@@ -8712,16 +8739,27 @@ class SpotifyClient:
|
|
|
8712
8739
|
If the Spotify Web API request was for a non-authorization service
|
|
8713
8740
|
and the response contains error information.
|
|
8714
8741
|
SpotifyApiError:
|
|
8715
|
-
If the method fails for any other reason.
|
|
8742
|
+
If the method fails for any other reason.
|
|
8743
|
+
|
|
8744
|
+
<span class="warning">
|
|
8745
|
+
<b>Notes regarding `limit_total` processing</b>
|
|
8746
|
+
There appears to be a bug in the Spotify Web API that forces you to use manual paging if
|
|
8747
|
+
utilizing the `fields` argument. It has been found that the API will only return a value
|
|
8748
|
+
of 50 (maximum) or less in the page `total` value if the `fields` argument is supplied.
|
|
8749
|
+
The API will return the total number of playlist items in the page `total` value if the `fields`
|
|
8750
|
+
argument is NOT supplied. A good playlist id to test this on is `1XhVM7jWPrGLTiNiAy97Za`,
|
|
8751
|
+
which is the largest playlist on spotify (4700+ items).
|
|
8752
|
+
<span>
|
|
8753
|
+
|
|
8754
|
+
<span class="warning">
|
|
8755
|
+
<b>DEPRECATED functionality as of 2024/11/27</b>
|
|
8756
|
+
Spotify Algorithmic playlists (e.g. "Made For You", "Daily Mix n", etc) will no longer be included
|
|
8757
|
+
in the returned results for unauthorized Spotify Developer Applications; they will be included in
|
|
8758
|
+
the results for authorized Spotify Developer Applications. More information about the deprecated
|
|
8759
|
+
functionality can be found on the <a href="https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api"
|
|
8760
|
+
target="_blank">Spotify Developer Forum Blog</a> page.
|
|
8761
|
+
<span>
|
|
8716
8762
|
|
|
8717
|
-
* Notes regarding `limit_total` processing.
|
|
8718
|
-
There appears to be a bug in the Spotify Web API that forces you to use manual paging if
|
|
8719
|
-
utilizing the `fields` argument. It has been found that the API will only return a value
|
|
8720
|
-
of 50 (maximum) or less in the page `total` value if the `fields` argument is supplied.
|
|
8721
|
-
The API will return the total number of playlist items in the page `total` value if the `fields`
|
|
8722
|
-
argument is NOT supplied. A good playlist id to test this on is `1XhVM7jWPrGLTiNiAy97Za`,
|
|
8723
|
-
which is the largest playlist on spotify (4700+ items).
|
|
8724
|
-
|
|
8725
8763
|
<details>
|
|
8726
8764
|
<summary>Sample Code - Manual Paging</summary>
|
|
8727
8765
|
```python
|
|
@@ -8895,13 +8933,17 @@ class SpotifyClient:
|
|
|
8895
8933
|
If the Spotify Web API request was for a non-authorization service
|
|
8896
8934
|
and the response contains error information.
|
|
8897
8935
|
SpotifyApiError:
|
|
8898
|
-
If the method fails for any other reason.
|
|
8936
|
+
If the method fails for any other reason.
|
|
8937
|
+
|
|
8938
|
+
<span class="warning">
|
|
8939
|
+
<b>DEPRECATED functionality as of 2024/11/27</b>
|
|
8940
|
+
Spotify Algorithmic playlists (e.g. "Made For You", "Daily Mix n", etc) will no longer be included
|
|
8941
|
+
in the returned results for unauthorized Spotify Developer Applications; they will be included in
|
|
8942
|
+
the results for authorized Spotify Developer Applications. More information about the deprecated
|
|
8943
|
+
functionality can be found on the <a href="https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api"
|
|
8944
|
+
target="_blank">Spotify Developer Forum Blog</a> page.
|
|
8945
|
+
<span>
|
|
8899
8946
|
|
|
8900
|
-
As of 2024/11/27, the Spotify Web API will only return user-defined playlists in the results. It will
|
|
8901
|
-
not return any Spotify Algorithmic playlists (e.g. "Daily Mix 1", "Discover Weekly", and other "Made For You"
|
|
8902
|
-
playlists). It will also not return playlist folders. More information can be found on the [Spotify Developer
|
|
8903
|
-
Forum Blog post](https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api) that was conveyed on November 27, 2024.
|
|
8904
|
-
|
|
8905
8947
|
<details>
|
|
8906
8948
|
<summary>Sample Code - Manual Paging</summary>
|
|
8907
8949
|
```python
|
|
@@ -11757,7 +11799,7 @@ class SpotifyClient:
|
|
|
11757
11799
|
This API only works for users who have Spotify Premium.
|
|
11758
11800
|
|
|
11759
11801
|
The order of execution is not guaranteed when you use this API with other Player API endpoints.
|
|
11760
|
-
|
|
11802
|
+
|
|
11761
11803
|
<details>
|
|
11762
11804
|
<summary>Sample Code</summary>
|
|
11763
11805
|
```python
|
|
@@ -11782,9 +11824,14 @@ class SpotifyClient:
|
|
|
11782
11824
|
# resolve the device object from the device id.
|
|
11783
11825
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
11784
11826
|
|
|
11827
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
11828
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
11829
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
11830
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
11831
|
+
|
|
11785
11832
|
# is this an active Sonos device?
|
|
11786
11833
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
11787
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
11834
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
11788
11835
|
|
|
11789
11836
|
_logsi.LogVerbose("Issuing command to Sonos device %s: PAUSE" % (scDevice.Title))
|
|
11790
11837
|
sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
|
|
@@ -11803,7 +11850,7 @@ class SpotifyClient:
|
|
|
11803
11850
|
|
|
11804
11851
|
# execute spotify web api request.
|
|
11805
11852
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/pause')
|
|
11806
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
11853
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
11807
11854
|
msg.UrlParameters = urlParms
|
|
11808
11855
|
self.MakeRequest('PUT', msg)
|
|
11809
11856
|
|
|
@@ -12474,9 +12521,14 @@ class SpotifyClient:
|
|
|
12474
12521
|
# we activate the device here, as it may have been paused for a long time.
|
|
12475
12522
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, True)
|
|
12476
12523
|
|
|
12524
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
12525
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
12526
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
12527
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
12528
|
+
|
|
12477
12529
|
# is this an active Sonos device?
|
|
12478
12530
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
12479
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
12531
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
12480
12532
|
|
|
12481
12533
|
_logsi.LogVerbose("Issuing command to Sonos device %s: PLAY (RESUME)" % (scDevice.Title))
|
|
12482
12534
|
sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
|
|
@@ -12495,7 +12547,7 @@ class SpotifyClient:
|
|
|
12495
12547
|
|
|
12496
12548
|
# execute spotify web api request.
|
|
12497
12549
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/play')
|
|
12498
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
12550
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
12499
12551
|
msg.UrlParameters = urlParms
|
|
12500
12552
|
self.MakeRequest('PUT', msg)
|
|
12501
12553
|
|
|
@@ -12631,9 +12683,14 @@ class SpotifyClient:
|
|
|
12631
12683
|
newPositionMS = 0
|
|
12632
12684
|
positionMS = newPositionMS
|
|
12633
12685
|
|
|
12686
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
12687
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
12688
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
12689
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
12690
|
+
|
|
12634
12691
|
# is this an active Sonos device?
|
|
12635
12692
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
12636
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
12693
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
12637
12694
|
|
|
12638
12695
|
sonosPosition:str = mediaPositionHMS_fromSeconds(positionMS / 1000) # convert from milliseconds to Sonos H:MM:SS format
|
|
12639
12696
|
_logsi.LogVerbose("Issuing command to Sonos device %s: SEEK (sonosPosition=%s)" % (scDevice.Title, sonosPosition))
|
|
@@ -12656,7 +12713,7 @@ class SpotifyClient:
|
|
|
12656
12713
|
|
|
12657
12714
|
# execute spotify web api request.
|
|
12658
12715
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/seek')
|
|
12659
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
12716
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
12660
12717
|
msg.UrlParameters = urlParms
|
|
12661
12718
|
self.MakeRequest('PUT', msg)
|
|
12662
12719
|
|
|
@@ -12743,9 +12800,14 @@ class SpotifyClient:
|
|
|
12743
12800
|
# resolve the device object from the device id.
|
|
12744
12801
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
12745
12802
|
|
|
12803
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
12804
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
12805
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
12806
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
12807
|
+
|
|
12746
12808
|
# is this an active Sonos device?
|
|
12747
12809
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
12748
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
12810
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
12749
12811
|
|
|
12750
12812
|
_logsi.LogVerbose("Issuing command to Sonos device %s: NEXT" % (scDevice.Title))
|
|
12751
12813
|
sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
|
|
@@ -12764,7 +12826,7 @@ class SpotifyClient:
|
|
|
12764
12826
|
|
|
12765
12827
|
# execute spotify web api request.
|
|
12766
12828
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/next')
|
|
12767
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
12829
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
12768
12830
|
msg.UrlParameters = urlParms
|
|
12769
12831
|
self.MakeRequest('POST', msg)
|
|
12770
12832
|
|
|
@@ -12851,9 +12913,14 @@ class SpotifyClient:
|
|
|
12851
12913
|
# resolve the device object from the device id.
|
|
12852
12914
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
12853
12915
|
|
|
12916
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
12917
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
12918
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
12919
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
12920
|
+
|
|
12854
12921
|
# is this an active Sonos device?
|
|
12855
12922
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
12856
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
12923
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
12857
12924
|
|
|
12858
12925
|
_logsi.LogVerbose("Issuing command to Sonos device %s: PREVIOUS" % (scDevice.Title))
|
|
12859
12926
|
sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
|
|
@@ -12872,7 +12939,7 @@ class SpotifyClient:
|
|
|
12872
12939
|
|
|
12873
12940
|
# execute spotify web api request.
|
|
12874
12941
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/previous')
|
|
12875
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
12942
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
12876
12943
|
msg.UrlParameters = urlParms
|
|
12877
12944
|
self.MakeRequest('POST', msg)
|
|
12878
12945
|
|
|
@@ -12967,9 +13034,14 @@ class SpotifyClient:
|
|
|
12967
13034
|
# resolve the device object from the device id.
|
|
12968
13035
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
12969
13036
|
|
|
13037
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
13038
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
13039
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
13040
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
13041
|
+
|
|
12970
13042
|
# is this an active Sonos device?
|
|
12971
13043
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
12972
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
13044
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
12973
13045
|
|
|
12974
13046
|
# get current Spotify Connect player state.
|
|
12975
13047
|
playerState = self.GetPlayerPlaybackStateSonos(scDevice)
|
|
@@ -13008,7 +13080,7 @@ class SpotifyClient:
|
|
|
13008
13080
|
|
|
13009
13081
|
# execute spotify web api request.
|
|
13010
13082
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/repeat')
|
|
13011
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
13083
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
13012
13084
|
msg.UrlParameters = urlParms
|
|
13013
13085
|
self.MakeRequest('PUT', msg)
|
|
13014
13086
|
|
|
@@ -13102,9 +13174,14 @@ class SpotifyClient:
|
|
|
13102
13174
|
# resolve the device object from the device id.
|
|
13103
13175
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
13104
13176
|
|
|
13177
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
13178
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
13179
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
13180
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
13181
|
+
|
|
13105
13182
|
# is this an active Sonos device?
|
|
13106
13183
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
13107
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
13184
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
13108
13185
|
|
|
13109
13186
|
# get current Spotify Connect player state.
|
|
13110
13187
|
playerState = self.GetPlayerPlaybackStateSonos(scDevice)
|
|
@@ -13144,7 +13221,7 @@ class SpotifyClient:
|
|
|
13144
13221
|
|
|
13145
13222
|
# execute spotify web api request.
|
|
13146
13223
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/shuffle')
|
|
13147
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
13224
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
13148
13225
|
msg.UrlParameters = urlParms
|
|
13149
13226
|
self.MakeRequest('PUT', msg)
|
|
13150
13227
|
|
|
@@ -13237,9 +13314,14 @@ class SpotifyClient:
|
|
|
13237
13314
|
# resolve the device object from the device id.
|
|
13238
13315
|
scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
|
|
13239
13316
|
|
|
13317
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
13318
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
13319
|
+
# note that the token is only used to control "restricted" devices (such as Sonos).
|
|
13320
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue(scDevice)
|
|
13321
|
+
|
|
13240
13322
|
# is this an active Sonos device?
|
|
13241
13323
|
# Sonos device can still be active, even if there is no active device in Spotify playstate.
|
|
13242
|
-
if (scDevice is not None) and (scDevice.IsSonos):
|
|
13324
|
+
if (scDevice is not None) and (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
13243
13325
|
|
|
13244
13326
|
_logsi.LogVerbose("Issuing command to Sonos device %s: VOLUME = %s" % (scDevice.Title, volumePercent))
|
|
13245
13327
|
sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
|
|
@@ -13261,7 +13343,7 @@ class SpotifyClient:
|
|
|
13261
13343
|
|
|
13262
13344
|
# execute spotify web api request.
|
|
13263
13345
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/volume')
|
|
13264
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
13346
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
13265
13347
|
msg.UrlParameters = urlParms
|
|
13266
13348
|
self.MakeRequest('PUT', msg)
|
|
13267
13349
|
|
|
@@ -13411,12 +13493,16 @@ class SpotifyClient:
|
|
|
13411
13493
|
# if not, then raise an exception as the Spotify Web API request will fail anyway.
|
|
13412
13494
|
self._CheckForDeviceNotFound(scDevice, deviceId)
|
|
13413
13495
|
|
|
13496
|
+
# are spotify web player credentials configured? if so, then we will use them to create
|
|
13497
|
+
# an elevated authorization access token for the Spotify Web API endpoint call.
|
|
13498
|
+
accessTokenHeaderValue:str = self._GetSpotifyWebPlayerTokenHeaderValue()
|
|
13499
|
+
|
|
13414
13500
|
# is this a Sonos device?
|
|
13415
13501
|
# if so, then control was automatically transferred by activating the device.
|
|
13416
13502
|
# note that the Spotify Web API cannot stop nor start play on the device either,
|
|
13417
13503
|
# as it's considered a restricted device and the Spotify Web API cannot control it!
|
|
13418
13504
|
# all requests to control the device will be made via the Sonos Controller API.
|
|
13419
|
-
if (scDevice.IsSonos):
|
|
13505
|
+
if (scDevice.IsSonos) and (accessTokenHeaderValue is None):
|
|
13420
13506
|
|
|
13421
13507
|
# get Sonos Controller instance for the device.
|
|
13422
13508
|
sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
|
|
@@ -13431,13 +13517,11 @@ class SpotifyClient:
|
|
|
13431
13517
|
wasCmdIssued:bool = False
|
|
13432
13518
|
if currentTransportState == 'PLAYING':
|
|
13433
13519
|
if play == False:
|
|
13434
|
-
|
|
13435
|
-
sonosPlayer.pause()
|
|
13520
|
+
self.PlayerMediaPause(scDevice)
|
|
13436
13521
|
wasCmdIssued = True
|
|
13437
13522
|
elif currentTransportState in ['PAUSED_PLAYBACK','STOPPED','TRANSITIONING']:
|
|
13438
13523
|
if play == True:
|
|
13439
|
-
|
|
13440
|
-
sonosPlayer.play()
|
|
13524
|
+
self.PlayerMediaResume(scDevice)
|
|
13441
13525
|
wasCmdIssued = True
|
|
13442
13526
|
|
|
13443
13527
|
# give Sonos Controller time to process the change.
|
|
@@ -13480,7 +13564,7 @@ class SpotifyClient:
|
|
|
13480
13564
|
|
|
13481
13565
|
# execute spotify web api request.
|
|
13482
13566
|
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player')
|
|
13483
|
-
msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
|
|
13567
|
+
msg.RequestHeaders[self.AuthToken.HeaderKey] = accessTokenHeaderValue or self.AuthToken.HeaderValue
|
|
13484
13568
|
msg.RequestJson = reqData
|
|
13485
13569
|
self.MakeRequest('PUT', msg)
|
|
13486
13570
|
|
|
@@ -1057,18 +1057,20 @@ class SpotifyConnectDirectoryTask(threading.Thread):
|
|
|
1057
1057
|
|
|
1058
1058
|
# if Sonos Controller instance is the group coordinator then we are done.
|
|
1059
1059
|
if (sonosPlayer.is_coordinator):
|
|
1060
|
-
_logsi.
|
|
1060
|
+
if _logsi.IsOn(SILevel.Verbose):
|
|
1061
|
+
_logsi.LogVerbose("Sonos Controller instance is a group coordinator for device: %s" % (device.Title))
|
|
1062
|
+
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s" % (device.Title), sonosPlayer)
|
|
1063
|
+
_logsi.LogDictionary(SILevel.Verbose, "Sonos Controller instance for device: %s (speaker_info)" % (device.Title), sonosPlayer.speaker_info)
|
|
1064
|
+
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s (group)" % (device.Title), sonosPlayer.group)
|
|
1065
|
+
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s (zone_group_state)" % (device.Title), sonosPlayer.zone_group_state)
|
|
1066
|
+
return sonosPlayer
|
|
1067
|
+
|
|
1068
|
+
# trace.
|
|
1069
|
+
if _logsi.IsOn(SILevel.Verbose):
|
|
1061
1070
|
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s" % (device.Title), sonosPlayer)
|
|
1062
1071
|
_logsi.LogDictionary(SILevel.Verbose, "Sonos Controller instance for device: %s (speaker_info)" % (device.Title), sonosPlayer.speaker_info)
|
|
1063
1072
|
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s (group)" % (device.Title), sonosPlayer.group)
|
|
1064
1073
|
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s (zone_group_state)" % (device.Title), sonosPlayer.zone_group_state)
|
|
1065
|
-
return sonosPlayer
|
|
1066
|
-
|
|
1067
|
-
# trace.
|
|
1068
|
-
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s" % (device.Title), sonosPlayer)
|
|
1069
|
-
_logsi.LogDictionary(SILevel.Verbose, "Sonos Controller instance for device: %s (speaker_info)" % (device.Title), sonosPlayer.speaker_info)
|
|
1070
|
-
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s (group)" % (device.Title), sonosPlayer.group)
|
|
1071
|
-
_logsi.LogObject(SILevel.Verbose, "Sonos Controller instance for device: %s (zone_group_state)" % (device.Title), sonosPlayer.zone_group_state)
|
|
1072
1074
|
|
|
1073
1075
|
# is the device part of a group? if so, then use the group coordinator.
|
|
1074
1076
|
if (sonosPlayer.group is not None):
|
|
File without changes
|
|
File without changes
|
{spotifywebapiPython-1.0.174.dist-info → spotifywebapiPython-1.0.175.dist-info}/top_level.txt
RENAMED
|
File without changes
|