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
@@ -3,7 +3,7 @@ from abc import abstractmethod
3
3
  import copy
4
4
  from datetime import datetime
5
5
  import hashlib
6
- from pychromecast import CastBrowser, CastInfo, Chromecast, get_chromecast_from_cast_info, get_chromecast_from_host
6
+ from pychromecast import APP_MEDIA_RECEIVER, CastBrowser, CastInfo, Chromecast, get_chromecast_from_cast_info, get_chromecast_from_host
7
7
  from pychromecast.dial import MultizoneInfo, MultizoneStatus, get_multizone_status
8
8
  from pychromecast.controllers.multizone import MultiZoneManagerListener, MultizoneController, MultizoneManager
9
9
  from pychromecast.const import CAST_TYPE_GROUP
@@ -23,6 +23,8 @@ from .spotifyconnectzeroconfcastmultizonemanagerlistener import SpotifyConnectZe
23
23
  from .spotifyconnectdeviceeventargs import SpotifyConnectDeviceEventArgs
24
24
  from .spotifyconnectzeroconflistener import ZEROCONF_SERVICETYPE_SPOTIFYCONNECT, SpotifyConnectZeroconfListener
25
25
  from .spotifyconnectzeroconfcastcontroller import (
26
+ APP_SPOTIFY,
27
+ APP_SPOTIFY_CONNECT,
26
28
  TYPE_ADD_USER_RESPONSE,
27
29
  TYPE_ADD_USER_ERROR,
28
30
  TYPE_GET_INFO_ERROR,
@@ -667,6 +669,58 @@ class SpotifyConnectDirectoryTask(threading.Thread):
667
669
  castMultizoneController:MultizoneController = self._CastMultiZoneControllers.get(str(castInfo.uuid), None)
668
670
  if (castMultizoneController) and (castMultizoneController._socket_client):
669
671
  castMultizoneController.update_members()
672
+ time.sleep(2.0) # give controller some time to update member list.
673
+
674
+ # activate media receiver app for each member in the group.
675
+ # process all device members in the group / zone.
676
+ for zone_member_uuid in castMultizoneController.members:
677
+
678
+ # get castInfo instance so we can connect to the device.
679
+ zone_member_castInfo = self._CastBrowser.devices.get(UUID(zone_member_uuid))
680
+ if zone_member_castInfo is not None:
681
+
682
+ # get cast device instance.
683
+ zone_member_castDevice = get_chromecast_from_cast_info(
684
+ cast_info=zone_member_castInfo,
685
+ zconf=self._ZeroconfInstance,
686
+ tries=2,
687
+ retry_wait=0.5,
688
+ timeout=5)
689
+
690
+ # wait for the cast device to provide an initial status.
691
+ zone_member_castDevice.wait(10)
692
+
693
+ # formulate title for trace messages.
694
+ trc_zone_member_title:str = "\"%s\" [ip=%s:%s]" % (zone_member_castDevice.cast_info.friendly_name, zone_member_castDevice.socket_client.host, zone_member_castDevice.socket_client.port)
695
+
696
+ # trace.
697
+ _logsi.LogObject(SILevel.Verbose, "%s - Cast group \"%s\" member Chromecast device status: %s" % (self.name, castInfo.friendly_name, trc_zone_member_title), zone_member_castDevice.status, colorValue=SIColors.Coral)
698
+
699
+ # if current app is APP_SPOTIFY, then stop the app before starting the media receiver.
700
+ if (zone_member_castDevice.status) and (zone_member_castDevice.status.app_id == APP_SPOTIFY):
701
+ _logsi.LogVerbose("%s - Issuing quit_app (APP_SPOTIFY) for group \"%s\" member device: %s" % (self.name, castInfo.friendly_name, trc_zone_member_title), colorValue=SIColors.Coral)
702
+ zone_member_castDevice.quit_app(timeout=5.0)
703
+ elif (zone_member_castDevice.status) and (zone_member_castDevice.status.app_id == APP_SPOTIFY_CONNECT):
704
+ _logsi.LogVerbose("%s - Issuing quit_app (APP_SPOTIFY_CONNECT) for group \"%s\" member device: %s" % (self.name, castInfo.friendly_name, trc_zone_member_title), colorValue=SIColors.Coral)
705
+ zone_member_castDevice.quit_app(timeout=5.0)
706
+
707
+ # start the media receiver app.
708
+ # this will stabilize routing for the group using the Default Media Receiver.
709
+ _logsi.LogVerbose("%s - Starting Chromecast default APP_MEDIA_RECEIVER for group \"%s\" member device: %s" % (self.name, castInfo.friendly_name, trc_zone_member_title), colorValue=SIColors.Coral)
710
+ zone_member_castDevice.start_app(APP_MEDIA_RECEIVER, force_launch=True, timeout=10.0)
711
+
712
+ # start the connection worker thread, if needed.
713
+ # failure to do this will result in the following exception being thrown when
714
+ # the `launch_app()` method is called:
715
+ # - `pychromecast.error.NotConnected: Chromecast unknown:8009 is connecting...`
716
+ if (zone_member_castDevice.is_idle):
717
+ if (zone_member_castDevice.socket_client is not None) and (zone_member_castDevice.socket_client.first_connection):
718
+ _logsi.LogVerbose("%s - Starting Chromecast default APP_MEDIA_RECEIVER connection worker thread for group \"%s\" member device: %s" % (self.name, castInfo.friendly_name, trc_zone_member_title), colorValue=SIColors.Coral)
719
+ zone_member_castDevice.start()
720
+ zone_member_castDevice.wait(timeout=5.0)
721
+
722
+ # media receiver app needs time to start.
723
+ time.sleep(2.0)
670
724
 
671
725
  except Exception as ex:
672
726
 
@@ -678,6 +732,7 @@ class SpotifyConnectDirectoryTask(threading.Thread):
678
732
  castMultiZoneStatus:MultizoneStatus = get_multizone_status(castInfo.host, castInfo.services, self.ZeroconfInstance, 5)
679
733
  _logsi.LogObject(SILevel.Verbose, "%s - Chromecast group multizone status for device: %s [ip=%s:%s]" % (self.name, scDevice.Title, castInfo.host, castInfo.port), castMultiZoneStatus, colorValue=SIColors.Coral)
680
734
 
735
+ # ensure group device is still on the network;
681
736
  # if group device dropped off the network, then we can't query it!
682
737
  if (castMultiZoneStatus is not None):
683
738
 
@@ -703,11 +758,13 @@ class SpotifyConnectDirectoryTask(threading.Thread):
703
758
  retry_wait=0.5,
704
759
  timeout=10)
705
760
 
706
- # calculate wait timeout for devices to become active, based on number of devices in group.
707
- if (castMultiZoneStatus.groups is not None):
708
- groupCount:int = len(castMultiZoneStatus.groups)
709
- if (groupCount > 1):
710
- deviceWaitTimeoutSecs = (groupCount * 5.0)
761
+ # don't need this anymore, since we are activating media receiver on each group member.
762
+ # left it in here just in case we change our mind.
763
+ # # calculate wait timeout for devices to become active, based on number of devices in group.
764
+ # if (castMultiZoneStatus.groups is not None):
765
+ # groupCount:int = len(castMultiZoneStatus.groups)
766
+ # if (groupCount > 1):
767
+ # deviceWaitTimeoutSecs = (groupCount * 5.0)
711
768
 
712
769
  # trace.
713
770
  _logsi.LogVerbose("%s - Waiting %d seconds max for Chromecast group multizone device to activate: %s [ip=%s:%s]" % (self.name, deviceWaitTimeoutSecs, scDevice.Title, groupHost, groupPort), colorValue=SIColors.Coral)
@@ -740,7 +797,7 @@ class SpotifyConnectDirectoryTask(threading.Thread):
740
797
  # trace.
741
798
  if (_logsi.IsOn(SILevel.Verbose)):
742
799
  _logsi.LogObject(SILevel.Verbose, "%s - Chromecast device object: \"%s\" (ip=%s:%s)" % (self.name, castInfo.friendly_name, castDevice.socket_client.host, castDevice.socket_client.port), castDevice)
743
- _logsi.LogObject(SILevel.Verbose, "%s - Chromecast device status: %s [ip=%s:%s]" % (self.name, scDevice.Title, castDevice.socket_client.host, castDevice.socket_client.port), castDevice.status)
800
+ _logsi.LogObject(SILevel.Verbose, "%s - Chromecast device status: %s [ip=%s:%s]" % (self.name, scDevice.Title, castDevice.socket_client.host, castDevice.socket_client.port), castDevice.status, colorValue=SIColors.Coral)
744
801
  self._TraceMultizoneGroupMembers(str(castInfo.uuid), castInfo.friendly_name)
745
802
 
746
803
  # verify multizone controller instance is registered for cast group device.
@@ -221,6 +221,9 @@ class SpotifyConnectZeroconfCastAppTask(threading.Thread):
221
221
  self._CastDevice.start()
222
222
  self._CastDevice.wait(10)
223
223
 
224
+ # trace.
225
+ _logsi.LogObject(SILevel.Verbose, "%s - Chromecast device status: %s (castAppTask pre-launch)" % (self.name, self._CastDevice.cast_info.friendly_name), self._CastDevice.status)
226
+
224
227
  # get spotify desktop authorization token.
225
228
  _logsi.LogVerbose("%s - Retrieving Spotify Desktop authorization token for loginId \"%s\"" % (self.name, self.SpotifyClientInstance.SpotifyConnectLoginId), colorValue=SIColors.Gold)
226
229
  tokenSP:SpotifyAuthToken = self._GetSpotifyDesktopAuthorizationToken(self.SpotifyClientInstance.SpotifyConnectLoginId)
@@ -245,6 +248,9 @@ class SpotifyConnectZeroconfCastAppTask(threading.Thread):
245
248
  # at this point the cast app should be either fully launched, or an error
246
249
  # occured while trying to launch.
247
250
 
251
+ # trace.
252
+ _logsi.LogObject(SILevel.Verbose, "%s - Chromecast device status: %s (castAppTask post-launch)" % (self.name, self._CastDevice.cast_info.friendly_name), self._CastDevice.status)
253
+
248
254
  # did an error occur?
249
255
  if (not self._SpotifyConnectZeroconfCastController.isLaunched):
250
256
 
@@ -32,9 +32,14 @@ if (_logsi == None):
32
32
  _logsi = SIAuto.Si.AddSession(__name__, True)
33
33
  _logsi.SystemLogger = logging.getLogger(__name__)
34
34
 
35
+ # constants - cast app identifiers.
36
+ APP_GOOGLE_INTERNAL_RECEIVER = "705D30C6" # Google Internal Receiver
37
+ APP_SPOTIFY_CONNECT = "531A4F84" # Spotify Connect
38
+ APP_SPOTIFY = "CC32E753" # Spotify (legacy / classic cast)
39
+ APP_SPOTIFY_NAMESPACE = "urn:x-cast:com.spotify.chromecast.secure.v1"
40
+ APP_SPOTIFY_LAUNCH_TIMEOUT = 20.0 # Amount of time to wait for Spotify App launch.
41
+
35
42
  # constants.
36
- APP_SPOTIFY = "CC32E753"
37
- APP_NAMESPACE = "urn:x-cast:com.spotify.chromecast.secure.v1"
38
43
  TYPE_GET_INFO = "getInfo"
39
44
  TYPE_GET_INFO_ERROR = "getInfoError"
40
45
  TYPE_GET_INFO_RESPONSE = "getInfoResponse"
@@ -78,7 +83,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
78
83
  """
79
84
 
80
85
  # invoke base class method.
81
- super().__init__(APP_NAMESPACE, APP_SPOTIFY)
86
+ super().__init__(APP_SPOTIFY_NAMESPACE, APP_SPOTIFY)
82
87
 
83
88
  # initialize storage.
84
89
  self.accessToken:str = accessToken
@@ -88,6 +93,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
88
93
  self.deviceId:str = None
89
94
  self.isAddUserError:bool = False
90
95
  self.isGetInfoError:bool = False
96
+ self.isLaunchError:bool = False
91
97
  self.isLaunched:bool = False
92
98
  self.isPlaybackTransferError:bool = False
93
99
  self.isMessageException:bool = False
@@ -141,6 +147,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
141
147
  self.isLaunched = False
142
148
  self.isAddUserError = False
143
149
  self.isGetInfoError = False
150
+ self.isLaunchError = False
144
151
  self.isPlaybackTransferError = False
145
152
  self.isMessageException = False
146
153
  self.waitAddUser.clear()
@@ -186,6 +193,8 @@ class SpotifyConnectZeroconfCastController(BaseController):
186
193
  raise SpotifyZeroconfApiError(self.zeroconfResponse.Status, "AddUser request failed", "launch_app", self.zeroconfResponse.StatusString)
187
194
  if (self.isGetInfoError):
188
195
  raise SpotifyZeroconfApiError(self.zeroconfResponse.Status, "GetInformation request failed", "launch_app", self.zeroconfResponse.StatusString)
196
+ if (self.isLaunchError):
197
+ raise SpotifyZeroconfApiError(self.zeroconfResponse.Status, "Launch request failed", "launch_app", self.zeroconfResponse.StatusString)
189
198
  if (not self.isLaunched):
190
199
  raise SpotifyConnectZeroconfLaunchError("Spotify Cast App could not be launched")
191
200
 
@@ -244,7 +253,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
244
253
  try:
245
254
 
246
255
  # trace.
247
- _logsi.LogDictionary(SILevel.Verbose, "Chromecast Message payload received: %s" % message, data, prettyPrint=True)
256
+ _logsi.LogDictionary(SILevel.Verbose, "Chromecast Message payload received: %s" % message, data, prettyPrint=True, colorValue=SIColors.Tan)
248
257
 
249
258
  # message argument example: "getInfoResponse"
250
259
  # protocol_version: CASTV2_1_0
@@ -317,7 +326,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
317
326
  self.zeroconfGetInfo.ResponseSource = payloadDataType
318
327
 
319
328
  # trace.
320
- _logsi.LogObject(SILevel.Verbose, "GetInformation result (ZeroconfGetInfo) - \"%s\" (%s)" % (self.zeroconfGetInfo.RemoteName, self.zeroconfGetInfo.DeviceId), self.zeroconfGetInfo, excludeNonPublic=True)
329
+ _logsi.LogObject(SILevel.Verbose, "GetInformation result (ZeroconfGetInfo) - \"%s\" (%s)" % (self.zeroconfGetInfo.RemoteName, self.zeroconfGetInfo.DeviceId), self.zeroconfGetInfo, excludeNonPublic=True, colorValue=SIColors.Tan)
321
330
 
322
331
  # getInfo response received from the initial launch.
323
332
  self.deviceId = self.zeroconfGetInfo.DeviceId
@@ -448,7 +457,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
448
457
  return True
449
458
 
450
459
  # trace.
451
- _logsi.LogDictionary(SILevel.Verbose, "Chromecast Message ignored - payload type value not recognized: \"%s\"" % (payloadDataType), message, prettyPrint=True)
460
+ _logsi.LogDictionary(SILevel.Verbose, "Chromecast Message ignored - payload type value not recognized: \"%s\"" % (payloadDataType), message, prettyPrint=True, colorValue=SIColors.Tan)
452
461
 
453
462
  return True
454
463
 
@@ -463,7 +472,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
463
472
  self.zeroconfResponse = response
464
473
 
465
474
  # trace.
466
- _logsi.LogException(SAAppMessages.UNHANDLED_EXCEPTION.format("receive_message", str(ex)), ex, logToSystemLogger=False)
475
+ _logsi.LogException(SAAppMessages.UNHANDLED_EXCEPTION.format("receive_message", str(ex)), ex, logToSystemLogger=False, colorValue=SIColors.Tan)
467
476
 
468
477
  # ignore exceptions, as there is nothing we can do at this point.
469
478
 
@@ -571,7 +580,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
571
580
  "blob": json_resp["accessToken"],
572
581
  },
573
582
  }
574
- _logsi.LogDictionary(SILevel.Debug, "Sending Spotify Connect Zeroconf AddUser Chromecast Message payload to Chromecast device (ip=%s:%s)" % (self.castDevice.socket_client.host, self.castDevice.socket_client.port), castMsg, prettyPrint=True)
583
+ _logsi.LogDictionary(SILevel.Debug, "Sending Spotify Connect Zeroconf AddUser Chromecast Message payload to Chromecast device (ip=%s:%s)" % (self.castDevice.socket_client.host, self.castDevice.socket_client.port), castMsg, prettyPrint=True, colorValue=SIColors.Tan)
575
584
  self.send_message(castMsg)
576
585
 
577
586
  # if we are in the process of launching, then we will wait for a response in the
@@ -589,7 +598,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
589
598
  if (counter >= timeout):
590
599
  raise SpotifyZeroconfApiError(0, "Timed out while waiting for a response", "AddUser", "timeout")
591
600
  counter += WAIT_INTERVAL
592
- _logsi.LogVerbose("Waiting for addUserResponse Chromecast Message payload (%f seconds from initial request)" % (counter))
601
+ _logsi.LogVerbose("Waiting for addUserResponse Chromecast Message payload (%f seconds from initial request)" % (counter), colorValue=SIColors.Tan)
593
602
 
594
603
  # if we make it here, then addUser request was processed successfully.
595
604
  return
@@ -665,7 +674,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
665
674
  "interactionIDs": [self.interactionID],
666
675
  },
667
676
  }
668
- _logsi.LogDictionary(SILevel.Debug, "Sending Spotify Connect Zeroconf Getinformation Chromecast Message payload to Chromecast device (ip=%s:%s)" % (self.castDevice.socket_client.host, self.castDevice.socket_client.port), castMsg, prettyPrint=True)
677
+ _logsi.LogDictionary(SILevel.Debug, "Sending Spotify Connect Zeroconf Getinformation Chromecast Message payload to Chromecast device (ip=%s:%s)" % (self.castDevice.socket_client.host, self.castDevice.socket_client.port), castMsg, prettyPrint=True, colorValue=SIColors.Tan)
669
678
  self.send_message(castMsg)
670
679
 
671
680
  # if we are in the process of launching, then we will wait for a response in the
@@ -683,7 +692,7 @@ class SpotifyConnectZeroconfCastController(BaseController):
683
692
  if (counter >= timeout):
684
693
  raise SpotifyZeroconfApiError(0, "Timed out while waiting for a response", "GetInformation", "timeout")
685
694
  counter += WAIT_INTERVAL
686
- _logsi.LogVerbose("Waiting for getInfoResponse Chromecast Message payload (%f seconds from initial request)" % (counter))
695
+ _logsi.LogVerbose("Waiting for getInfoResponse Chromecast Message payload (%f seconds from initial request)" % (counter), colorValue=SIColors.Tan)
687
696
 
688
697
  # if we make it here, then getInfo request was processed successfully.
689
698
  # return response to the caller.
@@ -691,9 +700,29 @@ class SpotifyConnectZeroconfCastController(BaseController):
691
700
 
692
701
  except SpotifyZeroconfApiError: raise # pass handled exceptions on thru
693
702
  except Exception as ex:
703
+
704
+ # pychromecast ControllerNotRegistered can occur when launching to cast group devices
705
+ # that contain a Google Mini (legacy) device.
706
+
707
+ # indicate launch error.
708
+ self.isLaunchError = True
694
709
 
695
- # format unhandled exception.
696
- raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
710
+ # load zeroconfResponse instance with exception information.
711
+ response: ZeroconfResponse = ZeroconfResponse()
712
+ response.SpotifyError = 0
713
+ response.Status = 1001
714
+ response.StatusString = "ERROR-PYCHROMECAST-%s" % (type(ex).__name__.upper())
715
+ response.ResponseSource = "SpotifyConnectZeroconfCastController"
716
+ self.zeroconfResponse = response
717
+
718
+ # trace.
719
+ _logsi.LogException(SAAppMessages.UNHANDLED_EXCEPTION.format("GetInformation", str(ex)), ex, logToSystemLogger=False, colorValue=SIColors.Tan)
720
+
721
+ # if app is not launched, then init is waiting on the `waitAddUser` event!
722
+ if (not self.isLaunched):
723
+ self.waitAddUser.set()
724
+
725
+ # ignore exceptions, as there is nothing we can do at this point.
697
726
 
698
727
  finally:
699
728
 
@@ -1,6 +1,7 @@
1
1
  # external package imports.
2
2
  from pychromecast import CastInfo, HostServiceInfo
3
3
  from pychromecast.discovery import AbstractCastListener
4
+ import ipaddress
4
5
  import threading
5
6
  from uuid import UUID
6
7
 
@@ -145,6 +146,17 @@ class SpotifyConnectZeroconfCastListener(AbstractCastListener):
145
146
  if (not (castType in [CAST_TYPE_AUDIO, CAST_TYPE_GROUP, CAST_TYPE_CHROMECAST, CAST_TYPE_NONE])):
146
147
  _logsi.LogDebug("Chromecast device cast_type of \"%s\" is not supported; ignoring: \"%s\" (%s)" % (castType, castInfo.friendly_name, serviceName), colorValue=SIColors.Coral)
147
148
  return None
149
+
150
+ # ensure IPV4 connection - ignore if IPV6.
151
+ # Windows OS does not support dual-stack socket handling IPv4 (224.0.0.251) and IPv6 (ff02::fb).
152
+ ip = ipaddress.ip_address(castInfo.host)
153
+ if (ip.version == 6):
154
+ _logsi.LogDebug("Chromecast IPV6 device addresses are not supported; device could cause problems: \"%s\" (%s)" % (castInfo.friendly_name, serviceName), colorValue=SIColors.Red)
155
+
156
+ # will still allow this for now, but we might want to ignore IPV6 devices
157
+ # in the future! To do so, just uncomment the following, which will
158
+ # ignore the device.
159
+ #return None
148
160
 
149
161
  # create new discovery result instance.
150
162
  result:ZeroconfDiscoveryResult = ZeroconfDiscoveryResult()
@@ -60,13 +60,13 @@ class SpotifyMediaTypes(StrEnum):
60
60
  """
61
61
 
62
62
 
63
- def __eq__(self, other):
64
- """
65
- Override __eq__ so that we can compare enum members directly to their raw values
66
- without explicitly accessing the ".value".
67
- """
68
- if isinstance(other, self.__class__):
69
- return self is other
70
- elif isinstance(other, type(self.value)):
71
- return self.value == other
72
- return False
63
+ # def __eq__(self, other):
64
+ # """
65
+ # Override __eq__ so that we can compare enum members directly to their raw values
66
+ # without explicitly accessing the ".value".
67
+ # """
68
+ # if isinstance(other, self.__class__):
69
+ # return self is other
70
+ # elif isinstance(other, type(self.value)):
71
+ # return self.value == other
72
+ # return False
@@ -0,0 +1,65 @@
1
+ from enum import StrEnum
2
+
3
+ class SpotifyTypePrefixes(StrEnum):
4
+ """
5
+ Spotify media type prefixes enumeration.
6
+ """
7
+
8
+ ALBUM = "spotify:album:"
9
+ """
10
+ Album media type.
11
+ """
12
+
13
+ ARTIST = "spotify:artist:"
14
+ """
15
+ Artist media type.
16
+ """
17
+
18
+ AUDIOBOOK = "spotify:audiobook:"
19
+ """
20
+ Audiobook media type.
21
+
22
+ This value is not part of the Spotify Web API specification.
23
+ It is loaded from our API so that the type of item can be determined programatically.
24
+ """
25
+
26
+ EPISODE = "spotify:episode:"
27
+ """
28
+ Episode media type.
29
+ """
30
+
31
+ PLAYLIST = "spotify:playlist:"
32
+ """
33
+ Playlist media type.
34
+ """
35
+
36
+ PODCAST = "spotify:podcast:"
37
+ """
38
+ Podcast episode type.
39
+
40
+ This value is not part of the Spotify Web API specification.
41
+ It is loaded from our API so that the type of item can be determined programatically.
42
+ """
43
+
44
+ SHOW = "spotify:show:"
45
+ """
46
+ Show media type.
47
+ """
48
+
49
+ TRACK = "spotify:track:"
50
+ """
51
+ Track media type.
52
+ """
53
+
54
+ USER = "spotify:user:"
55
+ """
56
+ Track media type.
57
+ """
58
+
59
+ UNKNOWN = "spotify:unknown:"
60
+ """
61
+ Unknown media type.
62
+
63
+ This value is not part of the Spotify Web API specification.
64
+ It is loaded from our API so that the type of item can be determined programatically.
65
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spotifywebapipython
3
- Version: 1.0.259
3
+ Version: 1.0.261
4
4
  Summary: Spotify Web API Python3 Library
5
5
  Author: Todd Lucas
6
6
  Author-email: <thlucas@yahoo.com>
@@ -1,33 +1,36 @@
1
- spotifywebapipython/__init__.py,sha256=SnB5BsUGChYgcZHjhZenqYZkb_v3c8aiAUQLkp4lYSY,1205
2
- spotifywebapipython/const.py,sha256=0YI_lNUwP9HCg2DaUBoaGE4sI23jndwE4Fgt1n4nu08,3923
3
- spotifywebapipython/saappmessages.py,sha256=KWy4H0ePYARZgtGYc2CHXRY0JOQ0bqr0JuDKRBu-wjA,4645
1
+ spotifywebapipython/__init__.py,sha256=ka7F2AsT-UU7KSYKBnfgl5Trojcep5aQspLutg8D-2k,1306
2
+ spotifywebapipython/const.py,sha256=3mSxDa97aItq_ektUA1qfK4_bBoI7krNApvUrWnP9pE,3923
3
+ spotifywebapipython/saappmessages.py,sha256=mVprjpd5CdD8kYeAkLzRvMvIQPmaYtH4UCP5my3QhSk,5065
4
4
  spotifywebapipython/sautils.py,sha256=j3f_Lu3Tb5D7-Gd2rJ2Ep901W-4XDp6Vq6XXVl8DX5I,8098
5
5
  spotifywebapipython/spotifyapierror.py,sha256=23_CYlxWN0BceYYCLpBpunl55vEwPr_wFf34l74xzeA,1855
6
6
  spotifywebapipython/spotifyapimessage.py,sha256=wCnW8jYMLS3x9kjyXPgXXZqaf1HeMTTXzU8u_Dm5pfA,8447
7
7
  spotifywebapipython/spotifyauthtoken.py,sha256=iVg2Pa5mfMqYe4qgc5H8td6JzJlaDqk4vMEhH5LmtfI,9289
8
- spotifywebapipython/spotifyclient.py,sha256=ie83oTfHKtUivpDtdcqfuXhL3PtnP7deCzEOwEyHOkM,854614
8
+ spotifywebapipython/spotifyclient.py,sha256=h3Oizin4YG7U-KPDSINdSf50ZtThmAdld6WYR86w8so,893394
9
9
  spotifywebapipython/spotifydiscovery.py,sha256=cyysxl8PQj9yGHVbaqhSF3SStlrp-NvfGAudM-dDmg0,20290
10
- spotifywebapipython/spotifymediatypes.py,sha256=MkHdPc1BF5hWo4WA-b4PtoihNKJMTXOe9JdnGpzp79c,1608
10
+ spotifywebapipython/spotifymediatypes.py,sha256=hMjkxhbfTtks0_P8BKmY7qg3EmB2zhH3RT0DbEpb_2s,1628
11
+ spotifywebapipython/spotifytypeprefixes.py,sha256=3yfpxKF7jF694qBuo-PbKYvm70YwwdBoGj9enOpWsAg,1375
11
12
  spotifywebapipython/spotifywebapiauthenticationerror.py,sha256=5A0MKvYo3Ypv0ZeSSfLHuFLwzoUUu044bBoUgMfNXNw,3940
12
13
  spotifywebapipython/spotifywebapierror.py,sha256=5cga9213J_nFQ0UX4vSn3dpyinASKTRiH0wAR4nLjvs,3147
13
14
  spotifywebapipython/spotifywebplayertoken.py,sha256=axj1j1lM7COiiZfpElkJRdnk4AmE6bAQcjKshUIz1Nk,35813
14
- spotifywebapipython/docs/__init__.html,sha256=SRw9Wu464DSwi4FpGgij8N1FkLD-X0A9-dQynjky0wc,182077
15
+ spotifywebapipython/docs/__init__.html,sha256=B7Ca0_PI5g3P7uYtVRn3bcSGXnH-Zl9dPjCy4NeXFFM,185587
15
16
  spotifywebapipython/docs/codecopy.js,sha256=ryuoZwLIL03YitjjFzn49UO5ta7-OBos6LNA3qHhFzs,3120
16
- spotifywebapipython/docs/index.html,sha256=muN9jvVqzas09f7OtPNi2jOG4k0HqxrxBOY1Rc839ZY,48523
17
- spotifywebapipython/docs/search.js,sha256=UQH4AS6wKeDmJgou3Uip8Q7bJty08qKbtPN0_ZxFbgs,8957158
17
+ spotifywebapipython/docs/index.html,sha256=21MQnmOy1a2EjDM8ve8OcarjzJX19o1n0anNZUmzplM,48779
18
+ spotifywebapipython/docs/search.js,sha256=U41gKtSu_T-vtyoPskKxtNbBmLJnWkP1efWob6_vSa0,9147897
18
19
  spotifywebapipython/docs/spotifywebapipython.ico,sha256=YImj39fqqSPSuB2-sMDlUYDd6YwRfQeJRtq4FjwWglg,16410
19
20
  spotifywebapipython/docs/spotifywebapipython_OLD.ico,sha256=YIv5LjcD4bTIJQSOr8jjwbWaeB3QkElRwkTOePiGbZo,14904
20
- spotifywebapipython/docs/spotifywebapipython/const.html,sha256=H1ESteNi_l_qJtve9dN5pbOnsg0fQud0GGNvdZLsH_Y,59805
21
- spotifywebapipython/docs/spotifywebapipython/saappmessages.html,sha256=uxYYIvbq31bNTdOShX1PS8vAEAIAJS3s6GTHhTvvAvA,60895
22
- spotifywebapipython/docs/spotifywebapipython/sautils.html,sha256=Mw-RuQKXeNhky-70KCoBRc6h-5w4TiAbiycfvKx-O1k,61063
23
- spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html,sha256=MP8xCIGeU0e5ttLVJRajDEgh7UXmTZACM80EZDuaQqE,48054
24
- spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html,sha256=Ooc-bC2mUF2S3XN1l-XMUrkHTGu6rOZC3bA9EDqSrzY,59210
25
- spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html,sha256=Vl1sVWfmBmBwST95AEkXqwNy7ccfHckjRKzird_i7nQ,59256
26
- spotifywebapipython/docs/spotifywebapipython/spotifyclient.html,sha256=N4zAfQnlGvSWGXeh1YmbAvAfA7PW_WX1NyQgWhdHzO0,1635516
27
- spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html,sha256=83Dn-hffl6g2qlkfzKMWeDCDcdlvWB_q1jmeQb-IzTg,57662
28
- spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html,sha256=fMFFa_W_RaE94iXSEnbxdWRSr0uTqk-2_xZNaHfps44,52174
29
- spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html,sha256=f400sWbPykAct6zGHKDXby1WqPT1VxTg7xDzemF_a3Q,50592
30
- spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html,sha256=Gzi2Dy5kHkdIEHCcCccb5orJJyeu-SrM2-TAl2-TgPY,62204
21
+ spotifywebapipython/docs/spotifywebapipython/const.html,sha256=qRx7QtpuIPmYMCfZydIi7QDaXcN-hjiefUAvooUjtHU,59805
22
+ spotifywebapipython/docs/spotifywebapipython/saappmessages.html,sha256=JNl5KbQi1aufV741xNAxNAgI525kaD06VdBo-wOjbhg,62358
23
+ spotifywebapipython/docs/spotifywebapipython/sautils.html,sha256=xnOj756AW4mh3VvQ8R7sP7w8GxHDCqAVox2QCYecfNc,61063
24
+ spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html,sha256=heHmJmlRL9hLQwio3zgw_jO8xzA5TCD5e1Q3Tdqmlso,48054
25
+ spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html,sha256=H0qgCuYoEgWL_U1dVI_UjMrQqIu564GC8kRo8mXX_4s,59210
26
+ spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html,sha256=ZmFqfnuGobSaUDNHp4QCu2GjuX3YS6MF0zqYAHdWqFM,59256
27
+ spotifywebapipython/docs/spotifywebapipython/spotifyclient.html,sha256=ffSAZSFgSXzATQ2idss3qNlo8HQ_7z_njWwrZyiGhW4,1670808
28
+ spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html,sha256=ZA3pKOs5ZVT1B55xXupoSTmVzTjbjt7DrC9AV18Xsu0,57662
29
+ spotifywebapipython/docs/spotifywebapipython/spotifymediatypes.html,sha256=Xhl_VnCgf0jkalpCviWkzcF2Iy03LYGVXVr3aFqXw3Y,51532
30
+ spotifywebapipython/docs/spotifywebapipython/spotifytypeprefixes.html,sha256=AVq43oAigWYemNz6GSiqnO5PQ8E_sJi77YjI1iKq6O8,52401
31
+ spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html,sha256=O4qBEKOHIMmxduqGVx-0Jwut9g6mOE37LrrboV52dR8,52174
32
+ spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html,sha256=_noX0xAqHDKOpE3lWr-5dwVW_suY-vLobg4Zkk20uEg,50592
33
+ spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html,sha256=ZwIaV5UuVpijHyZywmKie84TyBWx10tyND3i_UCfhgc,62204
31
34
  spotifywebapipython/models/__init__.py,sha256=RwRQhUX-6EUs8XvStVFpR8EPwoqIAz9K6ref-28qHKI,4423
32
35
  spotifywebapipython/models/album.py,sha256=U3Pdw0-EL33LdkeiN31fjZ23rlLk6DNGV8jRmZU7EyQ,5170
33
36
  spotifywebapipython/models/albumpagesaved.py,sha256=SBYMhkh5ZsMrRAXl-cm9zsxMDh8gO190ENq6Py2TyGY,2417
@@ -101,16 +104,16 @@ spotifywebapipython/models/tracksaved.py,sha256=uwnTpawf7ymXlF_b4p1RyjonUwUFRp0q
101
104
  spotifywebapipython/models/tracksimplified.py,sha256=fqIH45BsTRPbwq0ytss3r9YTCn1TtJSwBLAelJ2dWJY,13199
102
105
  spotifywebapipython/models/userprofile.py,sha256=VXHP-wSWGSIiDebGDuT4fFNBCmx_ME6Hn1NO5QyyBQY,6482
103
106
  spotifywebapipython/models/userprofilesimplified.py,sha256=YCEVED8PMeqWkORMHwj0JF_tVNqoTc1k_nce63D6kFY,6919
104
- spotifywebapipython/models/zeroconfdiscoveryresult.py,sha256=5MPSu7pLLh5SBrm7N6UbJ9K2zCNszBQr1CKUArmdk08,20245
107
+ spotifywebapipython/models/zeroconfdiscoveryresult.py,sha256=XID2qmaK2WTGJoLTQ54aQjfutLJMLgJ7A1ATwAp06kY,20250
105
108
  spotifywebapipython/models/zeroconfproperty.py,sha256=sXGUqbHhFMutCNKFJwJKbNbbQAnBnR7Ob5wNDSePxZk,2141
106
109
  spotifywebapipython/oauthcli/__init__.py,sha256=K37XTxYAKT0n8otCNzWbjgJ10fAPN4WL6seEpwvWyo4,168
107
110
  spotifywebapipython/oauthcli/authclient.py,sha256=-B_av5cxVHGHOaf8F_Xeo5u-HbOI1ytN86nOBzfW4Sw,56026
108
111
  spotifywebapipython/spotifyconnect/__init__.py,sha256=9Xl5KiJFvWLbsdb4YQ0xmF67i36ybpXCCXrWeNsKEvc,1108
109
112
  spotifywebapipython/spotifyconnect/spotifyconnectdeviceeventargs.py,sha256=35hKa0FAaPgy7W8D6MFXmga667pjwXITo8jSj1TDfE8,1988
110
- spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py,sha256=oMuH0jxaAaR_1XOlTT7FNvnGSTHgLXdOej_6RhzqW3o,149143
111
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py,sha256=zdr09TE_Fzssn4GXaYeQNMvXGaMhTvb-P11psniM5vU,22939
112
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py,sha256=mQ7wyrq6f76vpcebudYKv3aFW9YYBIY3C0CGGFSR4yU,32490
113
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py,sha256=DCSPmbKPUqKlKpSMvujWBHHKbntXT7_9QkKBgymuTOs,15928
113
+ spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py,sha256=QXNpJSqUGuOYxCzvDH63Ka9L9Yo7Bb5iVBRtDhc4ILE,153923
114
+ spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py,sha256=tCjqU7ubtfzBENdvqwVB0pMDGHRY_0u6N5OYlI5hbj8,23368
115
+ spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py,sha256=e2wLmFq4393IdVa51w8X5UQl4KfnHRh34DMlxZfl9-g,34218
116
+ spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py,sha256=zo0z0edxBwFZxN53su2yRI97krFilIlODPlz4VRyL6s,16645
114
117
  spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonecontrollerlistener.py,sha256=AA-XxS6AptJWzyO2zsM9DA5ioCncJBKDTpJkr_aN9IM,12352
115
118
  spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonemanagerlistener.py,sha256=k3wMC80Z7jBXYwiw9jq-oixRsum7E_vdHzwEgvcGbiw,18918
116
119
  spotifywebapipython/spotifyconnect/spotifyconnectzeroconfexceptions.py,sha256=aesGauxMoKupdTPR5rL2-rXBC3SEvH_9bQQx2Vh-abs,524
@@ -134,8 +137,8 @@ spotifywebapipython/zeroconfapi/zeroconfgetinfo.py,sha256=APayso_F7lCsdzzrkescgd
134
137
  spotifywebapipython/zeroconfapi/zeroconfgetinfoalias.py,sha256=FZJM23HIPJSfhXIC3-EuS1XhawheoG5maSp7__k4yBo,2932
135
138
  spotifywebapipython/zeroconfapi/zeroconfgetinfodrmmediaformat.py,sha256=c5uk8ljsIuBK3w2jahHKQuoWvm245LOjUBitetXx5Mo,2347
136
139
  spotifywebapipython/zeroconfapi/zeroconfresponse.py,sha256=mAPIDj5MG53x8peiScrp7OJblwy_o_Sto4wqE0rGujU,6445
137
- spotifywebapipython-1.0.259.dist-info/LICENSE,sha256=KGcc9g0zwqNLcWnSn_ezv1UtKyhMENFhvtixpxUPNsE,1177
138
- spotifywebapipython-1.0.259.dist-info/METADATA,sha256=Qsk1nozOWCSR2MiL1eh3OCuLLppVt83QMyLRyTUsUzA,11644
139
- spotifywebapipython-1.0.259.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
140
- spotifywebapipython-1.0.259.dist-info/top_level.txt,sha256=jTBLFlijKTesYh2dteAz4vb17qjaqWKeDjpnnwTcrjs,20
141
- spotifywebapipython-1.0.259.dist-info/RECORD,,
140
+ spotifywebapipython-1.0.261.dist-info/LICENSE,sha256=KGcc9g0zwqNLcWnSn_ezv1UtKyhMENFhvtixpxUPNsE,1177
141
+ spotifywebapipython-1.0.261.dist-info/METADATA,sha256=el6L_FCrM5ZEytJpYSFjlPMk3wXY3vUaN3bO35NCv3g,11644
142
+ spotifywebapipython-1.0.261.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
143
+ spotifywebapipython-1.0.261.dist-info/top_level.txt,sha256=jTBLFlijKTesYh2dteAz4vb17qjaqWKeDjpnnwTcrjs,20
144
+ spotifywebapipython-1.0.261.dist-info/RECORD,,