spotifywebapiPython 1.0.61__py3-none-any.whl → 1.0.63__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.61.dist-info → spotifywebapiPython-1.0.63.dist-info}/METADATA +1 -1
- {spotifywebapiPython-1.0.61.dist-info → spotifywebapiPython-1.0.63.dist-info}/RECORD +25 -25
- spotifywebapipython/const.py +1 -1
- spotifywebapipython/docs/__init__.html +15 -2
- spotifywebapipython/docs/index.html +2 -2
- spotifywebapipython/docs/search.js +1 -1
- spotifywebapipython/docs/spotifywebapiPython/const.html +3 -3
- spotifywebapipython/docs/spotifywebapiPython/saappmessages.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/sautils.html +33 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyapierror.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyapimessage.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyauthtoken.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyclient.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifydiscovery.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifywebapiauthenticationerror.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifywebapierror.html +2 -2
- spotifywebapipython/models/spotifyconnectdevices.py +24 -2
- spotifywebapipython/sautils.py +22 -0
- spotifywebapipython/spotifyclient.py +33 -18
- spotifywebapipython/spotifydiscovery.py +28 -8
- spotifywebapipython/zeroconfapi/zeroconfconnect.py +135 -68
- spotifywebapipython/zeroconfapi/zeroconfgetinfo.py +20 -3
- {spotifywebapiPython-1.0.61.dist-info → spotifywebapiPython-1.0.63.dist-info}/LICENSE +0 -0
- {spotifywebapiPython-1.0.61.dist-info → spotifywebapiPython-1.0.63.dist-info}/WHEEL +0 -0
- {spotifywebapiPython-1.0.61.dist-info → spotifywebapiPython-1.0.63.dist-info}/top_level.txt +0 -0
|
@@ -18,6 +18,7 @@ from ..spotifywebapierror import SpotifyWebApiError
|
|
|
18
18
|
from ..const import (
|
|
19
19
|
TRACE_MSG_DELAY_DEVICE,
|
|
20
20
|
)
|
|
21
|
+
from ..sautils import passwordMaskString
|
|
21
22
|
|
|
22
23
|
# get smartinspect logger reference; create a new session for this module name.
|
|
23
24
|
from smartinspectpython.siauto import SIAuto, SILevel, SISession, SIMethodParmListContext, SISourceId
|
|
@@ -142,7 +143,7 @@ class ZeroconfConnect:
|
|
|
142
143
|
return self._Version
|
|
143
144
|
|
|
144
145
|
|
|
145
|
-
def _CheckResponseForErrors(self, response:Response, methodName:str) -> None:
|
|
146
|
+
def _CheckResponseForErrors(self, response:Response, methodName:str, endpoint:str) -> None:
|
|
146
147
|
"""
|
|
147
148
|
Checks the Spotify Zeroconf API response for errors.
|
|
148
149
|
|
|
@@ -157,6 +158,8 @@ class ZeroconfConnect:
|
|
|
157
158
|
Spotify Web API http response object.
|
|
158
159
|
methodName (str):
|
|
159
160
|
method name that made the request (for trace purposes).
|
|
161
|
+
endpoint (str):
|
|
162
|
+
Endpoint that was requested (for trace purposes).
|
|
160
163
|
|
|
161
164
|
Raises:
|
|
162
165
|
SpotifyZeroconfApiError:
|
|
@@ -164,7 +167,6 @@ class ZeroconfConnect:
|
|
|
164
167
|
"""
|
|
165
168
|
responseData:dict = None
|
|
166
169
|
responseUTF8:str = None
|
|
167
|
-
contentType:str = None
|
|
168
170
|
|
|
169
171
|
try:
|
|
170
172
|
|
|
@@ -172,25 +174,11 @@ class ZeroconfConnect:
|
|
|
172
174
|
if _logsi.IsOn(SILevel.Debug):
|
|
173
175
|
_logsi.LogObject(SILevel.Debug, 'ZeroconfConnect http response object - type="%s", module="%s"' % (type(response).__name__, type(response).__module__), response)
|
|
174
176
|
|
|
175
|
-
# safely get the response url value.
|
|
176
|
-
# for some reason, the 'url' attribute is not present sometimes if a redirect occurs on the request.
|
|
177
|
-
responseUrl:str = None
|
|
178
|
-
if hasattr(response, 'url'):
|
|
179
|
-
responseUrl = response.url
|
|
180
|
-
elif hasattr(response, '_request_url'):
|
|
181
|
-
responseUrl = response._request_url
|
|
182
|
-
else:
|
|
183
|
-
try:
|
|
184
|
-
responseUrl = response.geturl()
|
|
185
|
-
except Exception:
|
|
186
|
-
_logsi.LogWarning('HTTPResponse method "geturl()" could not be called - defaulting to "unknown response url"')
|
|
187
|
-
responseUrl = 'Unknown response url'
|
|
188
|
-
|
|
189
177
|
# trace.
|
|
190
178
|
if _logsi.IsOn(SILevel.Debug):
|
|
191
|
-
_logsi.LogObject(SILevel.Debug, "ZeroconfConnect http response [%s-%s]: '%s' (response)" % (response.status_code, response.reason,
|
|
179
|
+
_logsi.LogObject(SILevel.Debug, "ZeroconfConnect http response [%s-%s]: '%s' (response)" % (response.status_code, response.reason, endpoint), response)
|
|
192
180
|
if (response.headers):
|
|
193
|
-
_logsi.LogCollection(SILevel.Debug, "ZeroconfConnect http response [%s-%s]: '%s' (headers)" % (response.status_code, response.reason,
|
|
181
|
+
_logsi.LogCollection(SILevel.Debug, "ZeroconfConnect http response [%s-%s]: '%s' (headers)" % (response.status_code, response.reason, endpoint), response.headers.items())
|
|
194
182
|
|
|
195
183
|
# do we have response data?
|
|
196
184
|
if (response.content is not None) and (len(response.content) > 0):
|
|
@@ -203,11 +191,11 @@ class ZeroconfConnect:
|
|
|
203
191
|
|
|
204
192
|
if _logsi.IsOn(SILevel.Verbose):
|
|
205
193
|
if isinstance(responseData, dict):
|
|
206
|
-
_logsi.LogDictionary(SILevel.Verbose, "ZeroconfConnect http response [%s-%s]: '%s' (json dict)" % (response.status_code, response.reason,
|
|
194
|
+
_logsi.LogDictionary(SILevel.Verbose, "ZeroconfConnect http response [%s-%s]: '%s' (json dict)" % (response.status_code, response.reason, endpoint), responseData)
|
|
207
195
|
elif isinstance(responseData, list):
|
|
208
|
-
_logsi.LogArray(SILevel.Verbose, "ZeroconfConnect http response [%s-%s]: '%s' (json array)" % (response.status_code, response.reason,
|
|
196
|
+
_logsi.LogArray(SILevel.Verbose, "ZeroconfConnect http response [%s-%s]: '%s' (json array)" % (response.status_code, response.reason, endpoint), responseData)
|
|
209
197
|
else:
|
|
210
|
-
_logsi.LogObject(SILevel.Verbose, "ZeroconfConnect http response [%s-%s]: '%s' (json object)" % (response.status_code, response.reason,
|
|
198
|
+
_logsi.LogObject(SILevel.Verbose, "ZeroconfConnect http response [%s-%s]: '%s' (json object)" % (response.status_code, response.reason, endpoint), responseData)
|
|
211
199
|
pass
|
|
212
200
|
|
|
213
201
|
else:
|
|
@@ -225,7 +213,7 @@ class ZeroconfConnect:
|
|
|
225
213
|
# if json conversion failed, then convert to utf-8 response.
|
|
226
214
|
if response.content is not None:
|
|
227
215
|
responseUTF8 = response.content.decode('utf-8')
|
|
228
|
-
_logsi.LogText(SILevel.Error, "ZeroconfConnect http response [%s-%s]: '%s' (utf-8)" % (response.status_code, response.reason,
|
|
216
|
+
_logsi.LogText(SILevel.Error, "ZeroconfConnect http response [%s-%s]: '%s' (utf-8)" % (response.status_code, response.reason, endpoint), responseUTF8)
|
|
229
217
|
|
|
230
218
|
# at this point we don't know what Spotify Web Api returned, so let's
|
|
231
219
|
# just raise a new exception with the non-JSON response data.
|
|
@@ -234,21 +222,44 @@ class ZeroconfConnect:
|
|
|
234
222
|
errCode:str = None
|
|
235
223
|
errMessage:str = None
|
|
236
224
|
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
# or '503 Server Error' response.
|
|
241
|
-
if response.status_code > 299:
|
|
242
|
-
|
|
243
|
-
errCode = response.status_code
|
|
244
|
-
errMessage = response.reason
|
|
245
|
-
|
|
246
|
-
if responseUTF8 is not None:
|
|
247
|
-
errMessage = responseUTF8
|
|
225
|
+
# at this point we know that the response contains JSON data, as
|
|
226
|
+
# we would have raised an exception before this if we could not
|
|
227
|
+
# convert the response to JSON!
|
|
248
228
|
|
|
249
|
-
|
|
229
|
+
# now it's a matter of interpreting the JSON `Status` response to determine
|
|
230
|
+
# if the request failed or not. the following documents the Spotify
|
|
231
|
+
# Zeroconf API http status codes and JSON status codes.
|
|
232
|
+
|
|
233
|
+
# taken from: https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf
|
|
234
|
+
# HTTP Status codes
|
|
235
|
+
# The following table shows the different responses returned by the HTTP server to a client's request:
|
|
236
|
+
|
|
237
|
+
# Status name Status HTTP Status Status string Response to Usage
|
|
238
|
+
# Ok 101 200 OK or ERROR-OK All Successful operation
|
|
239
|
+
# Bad 102 400 ERROR-BAD-REQUEST All Web server problem or critically malformed request
|
|
240
|
+
# Unknown 103 500 ERROR-UNKNOWN All Fallback when no other error applies
|
|
241
|
+
# NotImplemented 104 501 ERROR-NOT-IMPLEMENTED All Server does not implement this feature
|
|
242
|
+
# LoginFailed 202 200 ERROR-LOGIN-FAILED addUser Spotify returned error when trying to login
|
|
243
|
+
# MissingAction 301 400 ERROR-MISSING-ACTION All Web request has no action parameter
|
|
244
|
+
# InvalidAction 302 400 ERROR-INVALID-ACTION All Web request has unrecognized action parameter
|
|
245
|
+
# InvalidArguments 303 400 ERROR-INVALID-ARGUMENTS All Incorrect or insufficient arguments supplied for requested action
|
|
246
|
+
# SpotifyError 402 200 ERROR-SPOTIFY-ERROR All A Spotify API call returned an error not covered by other error messages
|
|
247
|
+
|
|
248
|
+
# process results.
|
|
249
|
+
result = ZeroconfResponse(root=responseData)
|
|
250
|
+
|
|
251
|
+
# if result is ok, then just return the response data.
|
|
252
|
+
if (result.Status == 101) \
|
|
253
|
+
or (result.StatusString == 'OK') \
|
|
254
|
+
or (result.StatusString == 'ERROR-OK'):
|
|
255
|
+
return responseData
|
|
256
|
+
|
|
257
|
+
# was an error status string returned?
|
|
258
|
+
# if so, then we will raise an exception.
|
|
259
|
+
if (result.StatusString.startswith('ERROR-')):
|
|
260
|
+
raise SpotifyZeroconfApiError(result.Status, result.ToString(), methodName, result.StatusString, _logsi)
|
|
250
261
|
|
|
251
|
-
#
|
|
262
|
+
# otherwise, let the calling function process the returned status.
|
|
252
263
|
return responseData
|
|
253
264
|
|
|
254
265
|
|
|
@@ -319,8 +330,9 @@ class ZeroconfConnect:
|
|
|
319
330
|
apiMethodParms.AppendKeyValue("Version", self._Version)
|
|
320
331
|
apiMethodParms.AppendKeyValue("Uri", self._Uri)
|
|
321
332
|
apiMethodParms.AppendKeyValue("username", username)
|
|
333
|
+
apiMethodParms.AppendKeyValue("password (with mask)", passwordMaskString(password))
|
|
322
334
|
apiMethodParms.AppendKeyValue("delay", delay)
|
|
323
|
-
_logsi.LogMethodParmList(SILevel.Verbose, "Connecting device to Spotify Connect using specified Username and Password", apiMethodParms)
|
|
335
|
+
_logsi.LogMethodParmList(SILevel.Verbose, "Connecting device to Spotify Connect using specified Username and Password (ip=%s)" % self._HostIpAddress, apiMethodParms)
|
|
324
336
|
|
|
325
337
|
# validations.
|
|
326
338
|
if (username is None) or (not isinstance(username,str)):
|
|
@@ -337,25 +349,36 @@ class ZeroconfConnect:
|
|
|
337
349
|
builder = BlobBuilder(credentials, info.DeviceId, info.PublicKey)
|
|
338
350
|
blob = builder.build()
|
|
339
351
|
|
|
352
|
+
# set request endpoint.
|
|
353
|
+
endpoint:str = self.GetEndpoint('addUser')
|
|
354
|
+
|
|
355
|
+
# set request headers.
|
|
356
|
+
reqHeaders:dict = {
|
|
357
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
358
|
+
'Connection': 'close'
|
|
359
|
+
}
|
|
360
|
+
_logsi.LogDictionary(SILevel.Debug, "ZeroconfConnect http request: '%s' (headers)" % (endpoint), reqHeaders)
|
|
361
|
+
|
|
362
|
+
# set request parameters.
|
|
363
|
+
reqData={
|
|
364
|
+
'action': 'addUser',
|
|
365
|
+
'VERSION': self._Version,
|
|
366
|
+
'userName': credentials.username.decode('ascii'),
|
|
367
|
+
'clientKey': int_to_b64str(builder.dh_keys.public_key),
|
|
368
|
+
'blob': blob
|
|
369
|
+
}
|
|
370
|
+
_logsi.LogDictionary(SILevel.Verbose, "ZeroconfConnect http request: '%s' (data)" % (endpoint), reqData)
|
|
371
|
+
|
|
340
372
|
# execute spotify zeroconf api request.
|
|
341
373
|
response = requests.post(
|
|
342
374
|
self._Uri,
|
|
343
375
|
timeout=10,
|
|
344
|
-
headers=
|
|
345
|
-
|
|
346
|
-
'Connection': 'close'
|
|
347
|
-
},
|
|
348
|
-
data={
|
|
349
|
-
'action': 'addUser',
|
|
350
|
-
'VERSION': self._Version,
|
|
351
|
-
'userName': credentials.username.decode('ascii'),
|
|
352
|
-
'clientKey': int_to_b64str(builder.dh_keys.public_key),
|
|
353
|
-
'blob': blob
|
|
354
|
-
}
|
|
376
|
+
headers=reqHeaders,
|
|
377
|
+
data=reqData # send data in POST request body
|
|
355
378
|
)
|
|
356
379
|
|
|
357
380
|
# check response for errors, and return json response.
|
|
358
|
-
responseData:dict = self._CheckResponseForErrors(response, apiMethodName)
|
|
381
|
+
responseData:dict = self._CheckResponseForErrors(response, apiMethodName, endpoint)
|
|
359
382
|
|
|
360
383
|
# process results.
|
|
361
384
|
result = ZeroconfResponse(root=responseData)
|
|
@@ -434,27 +457,38 @@ class ZeroconfConnect:
|
|
|
434
457
|
apiMethodParms.AppendKeyValue("Version", self._Version)
|
|
435
458
|
apiMethodParms.AppendKeyValue("Uri", self._Uri)
|
|
436
459
|
apiMethodParms.AppendKeyValue("delay", delay)
|
|
437
|
-
_logsi.LogMethodParmList(SILevel.Verbose, "Disconnecting device from Spotify Connect", apiMethodParms)
|
|
460
|
+
_logsi.LogMethodParmList(SILevel.Verbose, "Disconnecting device from Spotify Connect (ip=%s)" % self._HostIpAddress, apiMethodParms)
|
|
438
461
|
|
|
439
462
|
# validations.
|
|
440
463
|
delay = validateDelay(delay, 0.50, 10)
|
|
464
|
+
|
|
465
|
+
# set request endpoint.
|
|
466
|
+
endpoint:str = self.GetEndpoint('resetUsers')
|
|
467
|
+
|
|
468
|
+
# set request headers.
|
|
469
|
+
reqHeaders:dict = {
|
|
470
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
471
|
+
'Connection': 'close'
|
|
472
|
+
}
|
|
473
|
+
_logsi.LogDictionary(SILevel.Debug, "ZeroconfConnect http request: '%s' (headers)" % (endpoint), reqHeaders)
|
|
474
|
+
|
|
475
|
+
# set request parameters.
|
|
476
|
+
reqData={
|
|
477
|
+
'action': 'resetUsers',
|
|
478
|
+
'VERSION': self._Version,
|
|
479
|
+
}
|
|
480
|
+
_logsi.LogDictionary(SILevel.Verbose, "ZeroconfConnect http request: '%s' (data)" % (endpoint), reqData)
|
|
441
481
|
|
|
442
482
|
# execute spotify zeroconf api request.
|
|
443
483
|
response = requests.post(
|
|
444
484
|
self._Uri,
|
|
445
485
|
timeout=10,
|
|
446
|
-
headers=
|
|
447
|
-
|
|
448
|
-
'Connection': 'close'
|
|
449
|
-
},
|
|
450
|
-
data={
|
|
451
|
-
'action': 'resetUsers',
|
|
452
|
-
'VERSION': self._Version,
|
|
453
|
-
}
|
|
486
|
+
headers=reqHeaders,
|
|
487
|
+
data=reqData # send data in POST request body
|
|
454
488
|
)
|
|
455
489
|
|
|
456
490
|
# check response for errors, and return json response.
|
|
457
|
-
responseData:dict = self._CheckResponseForErrors(response, apiMethodName)
|
|
491
|
+
responseData:dict = self._CheckResponseForErrors(response, apiMethodName, endpoint)
|
|
458
492
|
|
|
459
493
|
# process results.
|
|
460
494
|
result = ZeroconfResponse(root=responseData)
|
|
@@ -506,6 +540,27 @@ class ZeroconfConnect:
|
|
|
506
540
|
)
|
|
507
541
|
|
|
508
542
|
|
|
543
|
+
def GetEndpoint(
|
|
544
|
+
self,
|
|
545
|
+
action:str
|
|
546
|
+
) -> str:
|
|
547
|
+
"""
|
|
548
|
+
Gets a Spotify Zeroconf API endpoint uri.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
action (str):
|
|
552
|
+
Action parameter value (e.g. "getInfo", "addUser", "resetUsers", etc).
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
A string containing the endpoint.
|
|
556
|
+
"""
|
|
557
|
+
return "{uri}?action={action}&version={version}".format(
|
|
558
|
+
uri=self._Uri,
|
|
559
|
+
action=action,
|
|
560
|
+
version=self._Version,
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
|
|
509
564
|
def GetInformation(self) -> ZeroconfGetInfo:
|
|
510
565
|
"""
|
|
511
566
|
Calls the `getInfo` Spotify Zeroconf API endpoint to return information about the device.
|
|
@@ -539,23 +594,35 @@ class ZeroconfConnect:
|
|
|
539
594
|
apiMethodParms.AppendKeyValue("CPath", self._CPath)
|
|
540
595
|
apiMethodParms.AppendKeyValue("Version", self._Version)
|
|
541
596
|
apiMethodParms.AppendKeyValue("Uri", self._Uri)
|
|
542
|
-
_logsi.LogMethodParmList(SILevel.Verbose, "Get information from Spotify Connect
|
|
597
|
+
_logsi.LogMethodParmList(SILevel.Verbose, "Get information from Spotify Connect Zeroconf API (ip=%s)" % self._HostIpAddress, apiMethodParms)
|
|
598
|
+
|
|
599
|
+
# set request endpoint.
|
|
600
|
+
endpoint:str = self.GetEndpoint('getInfo')
|
|
543
601
|
|
|
602
|
+
# set request headers.
|
|
603
|
+
reqHeaders:dict = {
|
|
604
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
605
|
+
'Connection': 'close'
|
|
606
|
+
}
|
|
607
|
+
_logsi.LogDictionary(SILevel.Debug, "ZeroconfConnect http request: '%s' (headers)" % (endpoint), reqHeaders)
|
|
608
|
+
|
|
609
|
+
# set request parameters.
|
|
610
|
+
reqParams={
|
|
611
|
+
'action': 'getInfo',
|
|
612
|
+
'VERSION': self._Version,
|
|
613
|
+
}
|
|
614
|
+
_logsi.LogDictionary(SILevel.Verbose, "ZeroconfConnect http request: '%s' (params)" % (endpoint), reqParams)
|
|
615
|
+
|
|
544
616
|
# execute spotify zeroconf api request.
|
|
545
617
|
response = requests.get(
|
|
546
618
|
self._Uri,
|
|
547
619
|
timeout=10,
|
|
548
|
-
headers=
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
},
|
|
552
|
-
params={
|
|
553
|
-
'action': 'getInfo',
|
|
554
|
-
'VERSION': self._Version,
|
|
555
|
-
})
|
|
620
|
+
headers=reqHeaders,
|
|
621
|
+
params=reqParams
|
|
622
|
+
)
|
|
556
623
|
|
|
557
624
|
# check response for errors, and return json response.
|
|
558
|
-
responseData:dict = self._CheckResponseForErrors(response, apiMethodName)
|
|
625
|
+
responseData:dict = self._CheckResponseForErrors(response, apiMethodName, endpoint)
|
|
559
626
|
|
|
560
627
|
# process results.
|
|
561
628
|
result = ZeroconfGetInfo(root=responseData)
|
|
@@ -28,7 +28,7 @@ class ZeroconfGetInfo(ZeroconfResponse):
|
|
|
28
28
|
self._AccountReq:str = None
|
|
29
29
|
self._ActiveUser:str = ""
|
|
30
30
|
self._Aliases:list[ZeroconfGetInfoAlias] = []
|
|
31
|
-
self._Availability:str =
|
|
31
|
+
self._Availability:str = ""
|
|
32
32
|
self._BrandDisplayName:str = None
|
|
33
33
|
self._ClientId:str = None
|
|
34
34
|
self._DeviceId:str = None
|
|
@@ -58,7 +58,7 @@ class ZeroconfGetInfo(ZeroconfResponse):
|
|
|
58
58
|
|
|
59
59
|
self._AccountReq = root.get('accountReq', None)
|
|
60
60
|
self._ActiveUser = root.get('activeUser', "")
|
|
61
|
-
self._Availability = root.get('availability',
|
|
61
|
+
self._Availability = root.get('availability', "")
|
|
62
62
|
self._BrandDisplayName = root.get('brandDisplayName', None)
|
|
63
63
|
self._ClientId = root.get('clientID', None)
|
|
64
64
|
self._DeviceId = root.get('deviceID', None)
|
|
@@ -142,7 +142,12 @@ class ZeroconfGetInfo(ZeroconfResponse):
|
|
|
142
142
|
@property
|
|
143
143
|
def Availability(self) -> str:
|
|
144
144
|
"""
|
|
145
|
-
The SpZeroConfVars availability field returned by SpZeroConfGetVars.
|
|
145
|
+
The SpZeroConfVars availability field returned by SpZeroConfGetVars.
|
|
146
|
+
|
|
147
|
+
The following are values that I have encountered thus far:
|
|
148
|
+
- "" = Device is available and ready for use.
|
|
149
|
+
- "UNAVAILABLE" - Device is unavailable, and should probably be rebooted.
|
|
150
|
+
- "NOT-LOADED" - Spotify SDK / API is not loaded.
|
|
146
151
|
"""
|
|
147
152
|
return self._Availability
|
|
148
153
|
|
|
@@ -237,6 +242,18 @@ class ZeroconfGetInfo(ZeroconfResponse):
|
|
|
237
242
|
return (len(self._Aliases) > 0)
|
|
238
243
|
|
|
239
244
|
|
|
245
|
+
@property
|
|
246
|
+
def IsAvailable(self) -> bool:
|
|
247
|
+
"""
|
|
248
|
+
Returns True if the device is available; otherwise, False.
|
|
249
|
+
|
|
250
|
+
Determination is made based upon the `Availability` property value.
|
|
251
|
+
"""
|
|
252
|
+
if (self._Availability is None) or (self._Availability == ""):
|
|
253
|
+
return True
|
|
254
|
+
return False
|
|
255
|
+
|
|
256
|
+
|
|
240
257
|
@property
|
|
241
258
|
def LibraryVersion(self) -> str:
|
|
242
259
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|