spotifywebapiPython 1.0.48__py3-none-any.whl → 1.0.50__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.

Files changed (24) hide show
  1. {spotifywebapiPython-1.0.48.dist-info → spotifywebapiPython-1.0.50.dist-info}/METADATA +1 -1
  2. {spotifywebapiPython-1.0.48.dist-info → spotifywebapiPython-1.0.50.dist-info}/RECORD +24 -24
  3. spotifywebapipython/const.py +1 -1
  4. spotifywebapipython/docs/__init__.html +20 -2
  5. spotifywebapipython/docs/index.html +2 -2
  6. spotifywebapipython/docs/search.js +1 -1
  7. spotifywebapipython/docs/spotifywebapiPython/const.html +3 -3
  8. spotifywebapipython/docs/spotifywebapiPython/saappmessages.html +2 -2
  9. spotifywebapipython/docs/spotifywebapiPython/sautils.html +2 -2
  10. spotifywebapipython/docs/spotifywebapiPython/spotifyapierror.html +2 -2
  11. spotifywebapipython/docs/spotifywebapiPython/spotifyapimessage.html +2 -2
  12. spotifywebapipython/docs/spotifywebapiPython/spotifyauthtoken.html +2 -2
  13. spotifywebapipython/docs/spotifywebapiPython/spotifyclient.html +319 -3
  14. spotifywebapipython/docs/spotifywebapiPython/spotifydiscovery.html +20 -61
  15. spotifywebapipython/docs/spotifywebapiPython/spotifywebapiauthenticationerror.html +2 -2
  16. spotifywebapipython/docs/spotifywebapiPython/spotifywebapierror.html +2 -2
  17. spotifywebapipython/models/userprofile.py +24 -0
  18. spotifywebapipython/spotifyclient.py +505 -8
  19. spotifywebapipython/spotifydiscovery.py +32 -80
  20. spotifywebapipython/zeroconfapi/zeroconfconnect.py +10 -0
  21. spotifywebapipython/zeroconfapi/zeroconfgetinfo.py +21 -3
  22. {spotifywebapiPython-1.0.48.dist-info → spotifywebapiPython-1.0.50.dist-info}/LICENSE +0 -0
  23. {spotifywebapiPython-1.0.48.dist-info → spotifywebapiPython-1.0.50.dist-info}/WHEEL +0 -0
  24. {spotifywebapiPython-1.0.48.dist-info → spotifywebapiPython-1.0.50.dist-info}/top_level.txt +0 -0
@@ -8,9 +8,9 @@ from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo, ServiceStateChange,
8
8
 
9
9
  # our package imports.
10
10
  from .saappmessages import SAAppMessages
11
+ from .spotifyapierror import SpotifyApiError
11
12
  from .sautils import export
12
13
  from .models.device import Device
13
- from .spotifyclient import SpotifyClient, SpotifyApiError
14
14
  from .models import ZeroconfDiscoveryResult, ZeroconfProperty
15
15
 
16
16
  # get smartinspect logger reference; create a new session for this module name.
@@ -32,43 +32,40 @@ class SpotifyDiscovery:
32
32
  Click the **Sample Code** links in the individual methods for sample code examples.
33
33
  """
34
34
 
35
- def __init__(self, spotifyClient:SpotifyClient=None, areDevicesVerified:bool=False, printToConsole:bool=False) -> None:
35
+ def __init__(
36
+ self,
37
+ zeroconfClient:Zeroconf=None,
38
+ printToConsole:bool=False
39
+ ) -> None:
36
40
  """
37
41
  Initializes a new instance of the class.
38
42
 
39
43
  Args:
40
- spotifyClient (SpotifyClient):
41
- A SpotifyClient instance that will be used to verify discovered devices.
42
- This can be null if the areDevicesVerified argument is False.
43
- This argument is required if the areDevicesVerified argument is True.
44
- areDevicesVerified (bool):
45
- True to create a `SpotifyClient` instance for discovered devices, which
46
- verifies that the device can be accessed and basic information obtained
47
- about its capabilities; otherwise, False to just identify the IPV4 Address,
48
- Port, and Device Name.
49
- Default is False.
44
+ zeroconfClient (Zeroconf)
45
+ A Zeroconf client instance that will be used to discover Spotify Connect devices,
46
+ or null to create a new instance of Zeroconf.
47
+ Default is null.
50
48
  printToConsole (bool):
51
49
  True to print discovered device information to the console as the devices
52
50
  are discovered; otherwise, False to not print anything to the console.
53
51
  Default is False.
54
-
55
- Specify False for the `areDevicesVerified` argument if you want to speed up
56
- device discovery, as it takes extra time to verify device connections as they
57
- are discovered.
58
52
  """
59
53
  # validations.
60
- if spotifyClient is not None and (not isinstance(spotifyClient, SpotifyClient)):
61
- raise SpotifyApiError(SAAppMessages.ARGUMENT_TYPE_ERROR % ("__init__", 'spotifyClient', 'SpotifyClient', type(spotifyClient).__name__), logsi=_logsi)
62
- if spotifyClient is None and areDevicesVerified == True:
63
- raise SpotifyApiError("The spotifyClient argument is required if devices are to be verified (areDevicesVerified argument = True)", logsi=_logsi)
54
+ if zeroconfClient is not None and (not isinstance(zeroconfClient, Zeroconf)):
55
+ raise SpotifyApiError(SAAppMessages.ARGUMENT_TYPE_ERROR % ("__init__", 'zeroconfClient', 'Zeroconf', type(zeroconfClient).__name__), logsi=_logsi)
56
+
57
+ # create the zeroconf client if one was not specified.
58
+ if zeroconfClient is None:
59
+ _logsi.LogVerbose("Creating new Zeroconf instance for discovery")
60
+ zeroconfClient = Zeroconf()
61
+ else:
62
+ _logsi.LogObject(SILevel.Verbose, "Using existing Zeroconf instance for discovery", zeroconfClient)
64
63
 
65
64
  # initialize instance properties.
66
- self._AreDevicesVerified:bool = areDevicesVerified
67
65
  self._DiscoveredDeviceNames:dict = {}
68
66
  self._DiscoveryResults:list[ZeroconfDiscoveryResult] = []
69
67
  self._PrintToConsole:bool = printToConsole
70
- self._SpotifyClient:SpotifyClient = spotifyClient
71
- self._VerifiedDevices:dict = {}
68
+ self._ZeroconfClient = zeroconfClient
72
69
 
73
70
 
74
71
  def __getitem__(self, key):
@@ -92,21 +89,6 @@ class SpotifyDiscovery:
92
89
  return self.ToString()
93
90
 
94
91
 
95
- @property
96
- def AreDevicesVerified(self) -> bool:
97
- """
98
- Determines if a `Device` object is created for devices that are
99
- discovered. This property is set by what is passed to the class constructor.
100
-
101
- If False, then the `VerifiedDevices` property will be empty;
102
-
103
- If True, then the `VerifiedDevices` property will contain a `Device`
104
- instance for each device that was detected as part of the discovery process
105
- and was found in the Spotify User's player devices list.
106
- """
107
- return self._AreDevicesVerified
108
-
109
-
110
92
  @property
111
93
  def DiscoveredDeviceNames(self) -> dict:
112
94
  """
@@ -132,21 +114,12 @@ class SpotifyDiscovery:
132
114
 
133
115
 
134
116
  @property
135
- def VerifiedDevices(self) -> dict:
136
- """
137
- A dictionary of discovered `Device` instances that were detected on the network.
138
-
139
- This property is only populated if the `AreDevicesVerified` property is True.
140
-
141
- Dictionary keys will be in the form of "address:port", where "address" is the device
142
- ipv4 address and the "port" is the ipv4 port number the Spotify Connect device
143
- is listening on.
144
-
145
- Dictionary values will be `Device` instances that represent the discovered
146
- device.
117
+ def ZeroconfClient(self) -> Zeroconf:
118
+ """
119
+ Zeroconf client instance that will be used to discover Spotify Connect devices.
147
120
  """
148
- return self._VerifiedDevices
149
-
121
+ return self._ZeroconfClient
122
+
150
123
 
151
124
  def _OnServiceStateChange(self,
152
125
  zeroconf:Zeroconf,
@@ -230,19 +203,6 @@ class SpotifyDiscovery:
230
203
  # add the device result to the list.
231
204
  self._DiscoveryResults.append(result)
232
205
 
233
- # are we verifying devices connections? if so, then create a SpotifyClient
234
- # object, which will verify the connection and gather basic capabilities of the device.
235
- # we will also add the SpotifyClient instance using the same key as the device name list.
236
- if self._AreDevicesVerified == True:
237
-
238
- if deviceKey not in self._VerifiedDevices.keys():
239
-
240
- # get Spotify Connect player device by it's Name value.
241
- device:Device = self._SpotifyClient.GetPlayerDevice(deviceName)
242
- if device is not None:
243
- self._VerifiedDevices[deviceKey] = device
244
- result.SpotifyConnectIsInDeviceList = True
245
-
246
206
  # trace.
247
207
  _logsi.LogObject(SILevel.Verbose, "Discovered Spotify Connect device result: '%s' (%s:%i)" % (deviceName, deviceIpAddress, devicePort), result, excludeNonPublic=True)
248
208
  #_logsi.LogArray(SILevel.Verbose, "Discovered Spotify Connect device result.Properties: '%s' (%s:%i)" % (deviceName, deviceIpAddress, devicePort), result.Properties)
@@ -256,19 +216,19 @@ class SpotifyDiscovery:
256
216
  pass
257
217
 
258
218
 
259
- def DiscoverDevices(self, timeout:int=5) -> dict:
219
+ def DiscoverDevices(self, timeout:float=2) -> dict:
260
220
  """
261
221
  Discover Spotify Connect devices on the local network via the
262
222
  ZeroConf (aka MDNS) service.
263
223
 
264
224
  Args:
265
- timeout (int):
225
+ timeout (float):
266
226
  Maximum amount of time to wait (in seconds) for the
267
227
  discovery to complete.
268
- Default is 5 seconds.
228
+ Default is 2 seconds.
269
229
 
270
230
  Returns:
271
- A dictionary of discovered `SpotifyClient` objects.
231
+ A dictionary of `ZeroconfDiscoveryResult` objects.
272
232
 
273
233
  <details>
274
234
  <summary>Sample Code</summary>
@@ -280,12 +240,9 @@ class SpotifyDiscovery:
280
240
  # using Queue as a timer (timeout functionality).
281
241
  discoveryQueueTimer = Queue()
282
242
 
283
- # create the zeroconf service and our listener callback.
284
- zeroconf:Zeroconf = Zeroconf()
285
-
286
243
  # create the zeroconf service browser that will start device discovery.
287
244
  _logsi.LogVerbose("Discovery of Spotify Connect devices via Zeroconf is starting ...")
288
- ServiceBrowser(zeroconf, "_spotify-connect._tcp.local.", handlers=[self._OnServiceStateChange])
245
+ ServiceBrowser(self._ZeroconfClient, "_spotify-connect._tcp.local.", handlers=[self._OnServiceStateChange])
289
246
 
290
247
  try:
291
248
  # give the ServiceBrowser time to discover
@@ -296,7 +253,7 @@ class SpotifyDiscovery:
296
253
  # this is not really an exception, but more of an indicator that
297
254
  # the timeout has been reached.
298
255
  _logsi.LogVerbose("Discovery of Spotify Connect devices via Zeroconf has ended.")
299
-
256
+
300
257
  return self._DiscoveredDeviceNames
301
258
 
302
259
 
@@ -315,11 +272,6 @@ class SpotifyDiscovery:
315
272
  if includeItems == True:
316
273
 
317
274
  for key, deviceName in self._DiscoveredDeviceNames.items():
318
- device:Device
319
- verifiedStatus:str = ''
320
- device = self._VerifiedDevices.get(key, None)
321
- if device is not None:
322
- verifiedStatus = ' (verified - ID=%s)' % device.Id
323
- msg = "%s\n- %s - %s %s" % (msg, key, deviceName, verifiedStatus)
275
+ msg = "%s\n- %s - %s" % (msg, key, deviceName)
324
276
 
325
277
  return msg
@@ -71,6 +71,8 @@ class ZeroconfConnect:
71
71
  # validations.
72
72
  if (version is None):
73
73
  version = '1.0'
74
+ if (useSSL is None) or (not isinstance(useSSL,bool)):
75
+ useSSL = False
74
76
 
75
77
  # initialize storage.
76
78
  self._CPath:str = cpath
@@ -271,6 +273,8 @@ class ZeroconfConnect:
271
273
  Args:
272
274
  username (str):
273
275
  Spotify Connect user name to login with.
276
+ This MUST match the account name (or one of them) that was used to configure Spotify Connect
277
+ on the manufacturer device.
274
278
  password (str):
275
279
  Spotify Connect user password to login with.
276
280
 
@@ -289,6 +293,12 @@ class ZeroconfConnect:
289
293
  is able to perform the login attempt. You should issue a call to the Spotify Web API `Get Available Devices`
290
294
  endpoint to check the current device list to ensure that the device id was successfully added or not.
291
295
 
296
+ Note that if you don't have a password setup for your Spotify account (e.g. you utilize the "Continue with Google"
297
+ or other non-password methods for login), then you will need to define a "device password" in order to use the
298
+ ZeroConf Connect service; use the [Spotify Set Device Password](https://www.spotify.com/uk/account/set-device-password/)
299
+ page to define a device password. You will then use your Spotify username and the device password to Connect
300
+ to the device.
301
+
292
302
  <details>
293
303
  <summary>Sample Code</summary>
294
304
  ```python
@@ -26,7 +26,7 @@ class ZeroconfGetInfo(ZeroconfResponse):
26
26
 
27
27
  # initialize our attributes.
28
28
  self._AccountReq:str = None
29
- self._ActiveUser:str = None
29
+ self._ActiveUser:str = ""
30
30
  self._Aliases:list[ZeroconfGetInfoAlias] = []
31
31
  self._Availability:str = None
32
32
  self._BrandDisplayName:str = None
@@ -54,7 +54,7 @@ class ZeroconfGetInfo(ZeroconfResponse):
54
54
  else:
55
55
 
56
56
  self._AccountReq = root.get('accountReq', None)
57
- self._ActiveUser = root.get('activeUser', None)
57
+ self._ActiveUser = root.get('activeUser', "")
58
58
  self._Availability = root.get('availability', None)
59
59
  self._BrandDisplayName = root.get('brandDisplayName', None)
60
60
  self._ClientId = root.get('clientID', None)
@@ -106,7 +106,7 @@ class ZeroconfGetInfo(ZeroconfResponse):
106
106
  """
107
107
  Canonical username of the logged in user (e.g. "31l77y2123456789012345678901").
108
108
 
109
- This value will be blank if there is no user logged into the device.
109
+ This value will be an empty string if there is no user logged into the device.
110
110
  """
111
111
  return self._ActiveUser
112
112
 
@@ -192,6 +192,24 @@ class ZeroconfGetInfo(ZeroconfResponse):
192
192
  return self._GroupStatus
193
193
 
194
194
 
195
+ @property
196
+ def HasActiveUser(self) -> bool:
197
+ """
198
+ Returns True if the device has an active user account specified;
199
+ otherwise, False.
200
+ """
201
+ return (self._ActiveUser != "")
202
+
203
+
204
+ @property
205
+ def HasAliases(self) -> bool:
206
+ """
207
+ Returns True if the device has alias entries defined;
208
+ otherwise, False.
209
+ """
210
+ return (len(self._Aliases) > 0)
211
+
212
+
195
213
  @property
196
214
  def LibraryVersion(self) -> str:
197
215
  """