spotifywebapiPython 1.0.47__py3-none-any.whl → 1.0.49__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.47.dist-info → spotifywebapiPython-1.0.49.dist-info}/METADATA +1 -1
  2. {spotifywebapiPython-1.0.47.dist-info → spotifywebapiPython-1.0.49.dist-info}/RECORD +24 -24
  3. spotifywebapipython/const.py +1 -1
  4. spotifywebapipython/docs/__init__.html +19 -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 +303 -3
  14. spotifywebapipython/docs/spotifywebapiPython/spotifydiscovery.html +15 -72
  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 +497 -8
  19. spotifywebapipython/spotifydiscovery.py +27 -83
  20. spotifywebapipython/zeroconfapi/zeroconfconnect.py +10 -0
  21. spotifywebapipython/zeroconfapi/zeroconfgetinfo.py +21 -3
  22. {spotifywebapiPython-1.0.47.dist-info → spotifywebapiPython-1.0.49.dist-info}/LICENSE +0 -0
  23. {spotifywebapiPython-1.0.47.dist-info → spotifywebapiPython-1.0.49.dist-info}/WHEEL +0 -0
  24. {spotifywebapiPython-1.0.47.dist-info → spotifywebapiPython-1.0.49.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._Zeroconf = 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
  """
@@ -131,23 +113,6 @@ class SpotifyDiscovery:
131
113
  return self._DiscoveryResults
132
114
 
133
115
 
134
- @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.
147
- """
148
- return self._VerifiedDevices
149
-
150
-
151
116
  def _OnServiceStateChange(self,
152
117
  zeroconf:Zeroconf,
153
118
  service_type:str,
@@ -230,19 +195,6 @@ class SpotifyDiscovery:
230
195
  # add the device result to the list.
231
196
  self._DiscoveryResults.append(result)
232
197
 
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
198
  # trace.
247
199
  _logsi.LogObject(SILevel.Verbose, "Discovered Spotify Connect device result: '%s' (%s:%i)" % (deviceName, deviceIpAddress, devicePort), result, excludeNonPublic=True)
248
200
  #_logsi.LogArray(SILevel.Verbose, "Discovered Spotify Connect device result.Properties: '%s' (%s:%i)" % (deviceName, deviceIpAddress, devicePort), result.Properties)
@@ -256,19 +208,19 @@ class SpotifyDiscovery:
256
208
  pass
257
209
 
258
210
 
259
- def DiscoverDevices(self, timeout:int=5) -> dict:
211
+ def DiscoverDevices(self, timeout:float=2) -> dict:
260
212
  """
261
213
  Discover Spotify Connect devices on the local network via the
262
214
  ZeroConf (aka MDNS) service.
263
215
 
264
216
  Args:
265
- timeout (int):
217
+ timeout (float):
266
218
  Maximum amount of time to wait (in seconds) for the
267
219
  discovery to complete.
268
- Default is 5 seconds.
220
+ Default is 2 seconds.
269
221
 
270
222
  Returns:
271
- A dictionary of discovered `SpotifyClient` objects.
223
+ A dictionary of `ZeroconfDiscoveryResult` objects.
272
224
 
273
225
  <details>
274
226
  <summary>Sample Code</summary>
@@ -280,12 +232,9 @@ class SpotifyDiscovery:
280
232
  # using Queue as a timer (timeout functionality).
281
233
  discoveryQueueTimer = Queue()
282
234
 
283
- # create the zeroconf service and our listener callback.
284
- zeroconf:Zeroconf = Zeroconf()
285
-
286
235
  # create the zeroconf service browser that will start device discovery.
287
236
  _logsi.LogVerbose("Discovery of Spotify Connect devices via Zeroconf is starting ...")
288
- ServiceBrowser(zeroconf, "_spotify-connect._tcp.local.", handlers=[self._OnServiceStateChange])
237
+ ServiceBrowser(self._Zeroconf, "_spotify-connect._tcp.local.", handlers=[self._OnServiceStateChange])
289
238
 
290
239
  try:
291
240
  # give the ServiceBrowser time to discover
@@ -296,7 +245,7 @@ class SpotifyDiscovery:
296
245
  # this is not really an exception, but more of an indicator that
297
246
  # the timeout has been reached.
298
247
  _logsi.LogVerbose("Discovery of Spotify Connect devices via Zeroconf has ended.")
299
-
248
+
300
249
  return self._DiscoveredDeviceNames
301
250
 
302
251
 
@@ -315,11 +264,6 @@ class SpotifyDiscovery:
315
264
  if includeItems == True:
316
265
 
317
266
  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)
267
+ msg = "%s\n- %s - %s" % (msg, key, deviceName)
324
268
 
325
269
  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
  """