spotifywebapiPython 1.0.242__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.
- spotifywebapipython/__init__.py +35 -0
- spotifywebapipython/const.py +114 -0
- spotifywebapipython/docs/__init__.html +2156 -0
- spotifywebapipython/docs/codecopy.js +70 -0
- spotifywebapipython/docs/index.html +514 -0
- spotifywebapipython/docs/search.js +46 -0
- spotifywebapipython/docs/spotifywebapipython/const.html +636 -0
- spotifywebapipython/docs/spotifywebapipython/saappmessages.html +540 -0
- spotifywebapipython/docs/spotifywebapipython/sautils.html +620 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +341 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +598 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +612 -0
- spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +16557 -0
- spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +518 -0
- spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +421 -0
- spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +400 -0
- spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +635 -0
- spotifywebapipython/docs/spotifywebapipython.ico +0 -0
- spotifywebapipython/docs/spotifywebapipython_OLD.ico +0 -0
- spotifywebapipython/models/__init__.py +121 -0
- spotifywebapipython/models/album.py +170 -0
- spotifywebapipython/models/albumpagesaved.py +85 -0
- spotifywebapipython/models/albumpagesimplified.py +88 -0
- spotifywebapipython/models/albumsaved.py +102 -0
- spotifywebapipython/models/albumsimplified.py +308 -0
- spotifywebapipython/models/artist.py +146 -0
- spotifywebapipython/models/artistinfo.py +282 -0
- spotifywebapipython/models/artistinfotourevent.py +127 -0
- spotifywebapipython/models/artistpage.py +70 -0
- spotifywebapipython/models/artistsimplified.py +163 -0
- spotifywebapipython/models/audiobook.py +87 -0
- spotifywebapipython/models/audiobookpagesimplified.py +88 -0
- spotifywebapipython/models/audiobooksimplified.py +362 -0
- spotifywebapipython/models/audiofeatures.py +333 -0
- spotifywebapipython/models/author.py +67 -0
- spotifywebapipython/models/category.py +168 -0
- spotifywebapipython/models/categorypage.py +70 -0
- spotifywebapipython/models/chapter.py +84 -0
- spotifywebapipython/models/chapterpagesimplified.py +88 -0
- spotifywebapipython/models/chaptersimplified.py +387 -0
- spotifywebapipython/models/context.py +113 -0
- spotifywebapipython/models/copyright.py +79 -0
- spotifywebapipython/models/device.py +301 -0
- spotifywebapipython/models/episode.py +84 -0
- spotifywebapipython/models/episodepagesaved.py +85 -0
- spotifywebapipython/models/episodepagesimplified.py +88 -0
- spotifywebapipython/models/episodesaved.py +99 -0
- spotifywebapipython/models/episodesimplified.py +370 -0
- spotifywebapipython/models/explicitcontent.py +80 -0
- spotifywebapipython/models/externalids.py +91 -0
- spotifywebapipython/models/externalurls.py +104 -0
- spotifywebapipython/models/followers.py +81 -0
- spotifywebapipython/models/imageobject.py +193 -0
- spotifywebapipython/models/imagevibrantcolors.py +182 -0
- spotifywebapipython/models/linkedfrom.py +165 -0
- spotifywebapipython/models/narrator.py +67 -0
- spotifywebapipython/models/owner.py +162 -0
- spotifywebapipython/models/pageobject.py +343 -0
- spotifywebapipython/models/playeractions.py +196 -0
- spotifywebapipython/models/playerlastplayedinfo.py +334 -0
- spotifywebapipython/models/playerplaystate.py +467 -0
- spotifywebapipython/models/playerqueueinfo.py +207 -0
- spotifywebapipython/models/playhistory.py +136 -0
- spotifywebapipython/models/playhistorypage.py +85 -0
- spotifywebapipython/models/playlist.py +125 -0
- spotifywebapipython/models/playlistpage.py +85 -0
- spotifywebapipython/models/playlistpagesimplified.py +107 -0
- spotifywebapipython/models/playlistsimplified.py +334 -0
- spotifywebapipython/models/playlisttrack.py +143 -0
- spotifywebapipython/models/playlisttracksummary.py +80 -0
- spotifywebapipython/models/recommendationseed.py +135 -0
- spotifywebapipython/models/restrictions.py +86 -0
- spotifywebapipython/models/resumepoint.py +79 -0
- spotifywebapipython/models/searchresponse.py +391 -0
- spotifywebapipython/models/searchresultbase.py +299 -0
- spotifywebapipython/models/show.py +87 -0
- spotifywebapipython/models/showpagesaved.py +85 -0
- spotifywebapipython/models/showpagesimplified.py +88 -0
- spotifywebapipython/models/showsaved.py +99 -0
- spotifywebapipython/models/showsimplified.py +320 -0
- spotifywebapipython/models/spotifyconnectdevice.py +321 -0
- spotifywebapipython/models/spotifyconnectdevices.py +441 -0
- spotifywebapipython/models/track.py +142 -0
- spotifywebapipython/models/trackpage.py +110 -0
- spotifywebapipython/models/trackpagesaved.py +85 -0
- spotifywebapipython/models/trackpagesimplified.py +88 -0
- spotifywebapipython/models/trackrecommendations.py +88 -0
- spotifywebapipython/models/tracksaved.py +99 -0
- spotifywebapipython/models/tracksimplified.py +398 -0
- spotifywebapipython/models/userprofile.py +184 -0
- spotifywebapipython/models/userprofilesimplified.py +206 -0
- spotifywebapipython/models/zeroconfdiscoveryresult.py +592 -0
- spotifywebapipython/models/zeroconfproperty.py +93 -0
- spotifywebapipython/oauthcli/__init__.py +7 -0
- spotifywebapipython/oauthcli/authclient.py +1229 -0
- spotifywebapipython/saappmessages.py +86 -0
- spotifywebapipython/sautils.py +285 -0
- spotifywebapipython/spotifyapierror.py +66 -0
- spotifywebapipython/spotifyapimessage.py +269 -0
- spotifywebapipython/spotifyauthtoken.py +264 -0
- spotifywebapipython/spotifyclient.py +17885 -0
- spotifywebapipython/spotifyconnect/__init__.py +19 -0
- spotifywebapipython/spotifyconnect/spotifyconnectdeviceeventargs.py +67 -0
- spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py +2564 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastapptask.py +467 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastcontroller.py +701 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastlistener.py +359 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfcastmultizonelistener.py +212 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconfexceptions.py +20 -0
- spotifywebapipython/spotifyconnect/spotifyconnectzeroconflistener.py +335 -0
- spotifywebapipython/spotifydiscovery.py +473 -0
- spotifywebapipython/spotifymediatypes.py +53 -0
- spotifywebapipython/spotifywebapiauthenticationerror.py +122 -0
- spotifywebapipython/spotifywebapierror.py +106 -0
- spotifywebapipython/spotifywebplayertoken.py +743 -0
- spotifywebapipython/vibrant/__init__.py +17 -0
- spotifywebapipython/vibrant/generator.py +261 -0
- spotifywebapipython/vibrant/image.py +100 -0
- spotifywebapipython/vibrant/main.py +34 -0
- spotifywebapipython/vibrant/models.py +93 -0
- spotifywebapipython/vibrant/utils.py +56 -0
- spotifywebapipython/zeroconfapi/__init__.py +23 -0
- spotifywebapipython/zeroconfapi/authenticationtypes.py +38 -0
- spotifywebapipython/zeroconfapi/blobbuilder.py +370 -0
- spotifywebapipython/zeroconfapi/credentials.py +37 -0
- spotifywebapipython/zeroconfapi/cryptodiffiehellman.py +89 -0
- spotifywebapipython/zeroconfapi/helpers.py +64 -0
- spotifywebapipython/zeroconfapi/spotifyzeroconfapierror.py +108 -0
- spotifywebapipython/zeroconfapi/zeroconfconnect.py +1327 -0
- spotifywebapipython/zeroconfapi/zeroconfgetinfo.py +572 -0
- spotifywebapipython/zeroconfapi/zeroconfgetinfoalias.py +109 -0
- spotifywebapipython/zeroconfapi/zeroconfgetinfodrmmediaformat.py +90 -0
- spotifywebapipython/zeroconfapi/zeroconfresponse.py +195 -0
- spotifywebapipython-1.0.242.dist-info/LICENSE +22 -0
- spotifywebapipython-1.0.242.dist-info/METADATA +219 -0
- spotifywebapipython-1.0.242.dist-info/RECORD +138 -0
- spotifywebapipython-1.0.242.dist-info/WHEEL +5 -0
- spotifywebapipython-1.0.242.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
# our package imports.
|
|
2
|
+
from ..sautils import export
|
|
3
|
+
from .zeroconfproperty import ZeroconfProperty
|
|
4
|
+
|
|
5
|
+
@export
|
|
6
|
+
class ZeroconfDiscoveryResult:
|
|
7
|
+
"""
|
|
8
|
+
Zeroconf Discovery Result object.
|
|
9
|
+
|
|
10
|
+
Information about the Zeroconf entry for a SpotifyConnect device as found by Zeroconf (mDNS).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self) -> None:
|
|
14
|
+
"""
|
|
15
|
+
Initializes a new instance of the class.
|
|
16
|
+
"""
|
|
17
|
+
self._DeviceName:str = None
|
|
18
|
+
self._Domain:str = '.'
|
|
19
|
+
self._HostIpAddresses:list = []
|
|
20
|
+
self._HostIpPort:int = None
|
|
21
|
+
self._HostTTL:int = None
|
|
22
|
+
self._IsChromeCast:bool = False
|
|
23
|
+
self._Id:str = None
|
|
24
|
+
self._Key:str = None
|
|
25
|
+
self._Name:str = None
|
|
26
|
+
self._OtherTTL:int = None
|
|
27
|
+
self._Priority:int = None
|
|
28
|
+
self._Properties:list = []
|
|
29
|
+
self._Server:str = None
|
|
30
|
+
self._ServerKey:str = None
|
|
31
|
+
self._ServiceType:str = None
|
|
32
|
+
self._Weight:int = None
|
|
33
|
+
|
|
34
|
+
# Spotify Connect specific properties:
|
|
35
|
+
self._SpotifyConnectCPath:str = None
|
|
36
|
+
self._SpotifyConnectVersion:str = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
return self.ToString()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def __str__(self) -> str:
|
|
44
|
+
return self.ToString()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def Description(self) -> bool:
|
|
49
|
+
"""
|
|
50
|
+
Returns a basic description of the device, and how source info was obtained.
|
|
51
|
+
|
|
52
|
+
This is a helper property, and not part of the Zeroconf ServiceInfo result.
|
|
53
|
+
"""
|
|
54
|
+
result:str = "Spotify Connect Zeroconf Device"
|
|
55
|
+
if (self.IsChromeCast):
|
|
56
|
+
result = "Chromecast Zeroconf Device"
|
|
57
|
+
elif (self.IsDynamicDevice):
|
|
58
|
+
result = "Dynamic Device"
|
|
59
|
+
return result
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def DeviceName(self) -> str:
|
|
64
|
+
"""
|
|
65
|
+
Device name (e.g. "Bose-ST10-1").
|
|
66
|
+
"""
|
|
67
|
+
return self._DeviceName
|
|
68
|
+
|
|
69
|
+
@DeviceName.setter
|
|
70
|
+
def DeviceName(self, value:str):
|
|
71
|
+
"""
|
|
72
|
+
Sets the DeviceName property value.
|
|
73
|
+
"""
|
|
74
|
+
if isinstance(value, str):
|
|
75
|
+
self._DeviceName = value
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def Domain(self) -> str:
|
|
80
|
+
"""
|
|
81
|
+
Domain on which the service is located, which should match the one passed in during the query (e.g. "local.").
|
|
82
|
+
"""
|
|
83
|
+
return self._Domain
|
|
84
|
+
|
|
85
|
+
@Domain.setter
|
|
86
|
+
def Domain(self, value:str):
|
|
87
|
+
"""
|
|
88
|
+
Sets the Domain property value.
|
|
89
|
+
"""
|
|
90
|
+
if isinstance(value, str):
|
|
91
|
+
self._Domain = value
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def HostIpAddress(self) -> str:
|
|
96
|
+
"""
|
|
97
|
+
IP address at which the host can be reached (e.g. "192.168.1.81").
|
|
98
|
+
|
|
99
|
+
This value may also contain a DNS alias, if no IP addresses were discovered
|
|
100
|
+
for the device. This is very rare, but possible.
|
|
101
|
+
"""
|
|
102
|
+
# return server alias by default.
|
|
103
|
+
result:str = self._Server
|
|
104
|
+
|
|
105
|
+
# if ip addresses present, then return the first one that was detected.
|
|
106
|
+
# note that addresses are in LIFO order as detected by zeroconf discovery.
|
|
107
|
+
if (len(self._HostIpAddresses) > 0):
|
|
108
|
+
result = self._HostIpAddresses[len(self._HostIpAddresses) - 1]
|
|
109
|
+
|
|
110
|
+
return result
|
|
111
|
+
|
|
112
|
+
@HostIpAddress.setter
|
|
113
|
+
def HostIpAddress(self, value:str):
|
|
114
|
+
"""
|
|
115
|
+
Sets the HostIpAddress property value.
|
|
116
|
+
"""
|
|
117
|
+
if isinstance(value, str):
|
|
118
|
+
|
|
119
|
+
# if ip addresses present, then update the first one that was detected
|
|
120
|
+
# as it is the address referenced by the `HostIpAddress` get method.
|
|
121
|
+
# note that addresses are in LIFO order as detected by zeroconf discovery.
|
|
122
|
+
if (len(self._HostIpAddresses) > 0):
|
|
123
|
+
self._HostIpAddresses[len(self._HostIpAddresses) - 1] = value
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def HostIpAddresses(self) -> list:
|
|
128
|
+
"""
|
|
129
|
+
IP address(es) at which the host can be reached (e.g. ["192.168.1.81", "172.30.32.1"]).
|
|
130
|
+
|
|
131
|
+
Note that this value can contain multiple addresses.
|
|
132
|
+
"""
|
|
133
|
+
return self._HostIpAddresses
|
|
134
|
+
|
|
135
|
+
@HostIpAddresses.setter
|
|
136
|
+
def HostIpAddresses(self, value:list):
|
|
137
|
+
"""
|
|
138
|
+
Sets the HostIpAddresses property value.
|
|
139
|
+
"""
|
|
140
|
+
if value is not None:
|
|
141
|
+
if isinstance(value, list):
|
|
142
|
+
self._HostIpAddresses = value
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def HostIpPort(self) -> int:
|
|
147
|
+
"""
|
|
148
|
+
Port number (as an integer) for the service on the host (e.g. 8080).
|
|
149
|
+
"""
|
|
150
|
+
return self._HostIpPort
|
|
151
|
+
|
|
152
|
+
@HostIpPort.setter
|
|
153
|
+
def HostIpPort(self, value:int):
|
|
154
|
+
"""
|
|
155
|
+
Sets the HostIpPort property value.
|
|
156
|
+
"""
|
|
157
|
+
if isinstance(value, int):
|
|
158
|
+
self._HostIpPort = value
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def HostIpTitle(self) -> int:
|
|
163
|
+
"""
|
|
164
|
+
Host IP Address and Port number for the service on the host (e.g. 8080).
|
|
165
|
+
|
|
166
|
+
Note that this value is a convenience property derived from the following
|
|
167
|
+
properties: `HostIpAddress`,`HostIpPort`.
|
|
168
|
+
"""
|
|
169
|
+
return "%s:%s" % (self.HostIpAddress or "", self.HostIpPort or "")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def HostTTL(self) -> int:
|
|
174
|
+
"""
|
|
175
|
+
Host Time-To-Live value (as an integer) for the service on the host (e.g. 1200).
|
|
176
|
+
"""
|
|
177
|
+
return self._HostTTL
|
|
178
|
+
|
|
179
|
+
@HostTTL.setter
|
|
180
|
+
def HostTTL(self, value:int):
|
|
181
|
+
"""
|
|
182
|
+
Sets the HostTTL property value.
|
|
183
|
+
"""
|
|
184
|
+
if isinstance(value, int):
|
|
185
|
+
self._HostTTL = value
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def Id(self) -> str:
|
|
190
|
+
"""
|
|
191
|
+
Result ID (e.g. "Bose-ST10-1" (192.168.1.81:8200)).
|
|
192
|
+
|
|
193
|
+
This is a helper property, and not part of the Zeroconf interface.
|
|
194
|
+
"""
|
|
195
|
+
return self._Id
|
|
196
|
+
|
|
197
|
+
@Id.setter
|
|
198
|
+
def Id(self, value:str):
|
|
199
|
+
"""
|
|
200
|
+
Sets the Id property value.
|
|
201
|
+
"""
|
|
202
|
+
if isinstance(value, str):
|
|
203
|
+
self._Id = value
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def IsDynamicDevice(self) -> bool:
|
|
208
|
+
"""
|
|
209
|
+
Returns True if the device is a dynamic device;
|
|
210
|
+
otherwise, False.
|
|
211
|
+
|
|
212
|
+
Dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery
|
|
213
|
+
process, but still exist in the player device list. These are usually Spotify Connect
|
|
214
|
+
web or mobile players with temporary device id's.
|
|
215
|
+
"""
|
|
216
|
+
return (self._HostIpPort == 0) and (self._ServiceType is None)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def IsChromeCast(self) -> bool:
|
|
221
|
+
"""
|
|
222
|
+
True if the device is a Google ChromeCast device; otherwise, False.
|
|
223
|
+
"""
|
|
224
|
+
return self._IsChromeCast
|
|
225
|
+
|
|
226
|
+
@IsChromeCast.setter
|
|
227
|
+
def IsChromeCast(self, value:bool):
|
|
228
|
+
"""
|
|
229
|
+
Sets the IsChromeCast property value.
|
|
230
|
+
"""
|
|
231
|
+
if isinstance(value, bool):
|
|
232
|
+
self._IsChromeCast = value
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def IsChromeCastGroup(self) -> bool:
|
|
237
|
+
"""
|
|
238
|
+
True if the device is a Google ChromeCast Group device; otherwise, False.
|
|
239
|
+
|
|
240
|
+
This is indicated by the ServerKey value starting with "Google-Cast-Group-".
|
|
241
|
+
"""
|
|
242
|
+
serverKey:str = self._ServerKey or ""
|
|
243
|
+
return (serverKey.lower().startswith("google-cast-group-"))
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def IsHostIpV6(self) -> bool:
|
|
248
|
+
"""
|
|
249
|
+
Returns True if the `HostIpAddress` is a IPV6 formatted address;
|
|
250
|
+
otherwise, False.
|
|
251
|
+
"""
|
|
252
|
+
ipaddr:str = self.HostIpAddress or ""
|
|
253
|
+
if (ipaddr.find(":")):
|
|
254
|
+
return True
|
|
255
|
+
return False
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@property
|
|
259
|
+
def Key(self) -> str:
|
|
260
|
+
"""
|
|
261
|
+
Service key (e.g. "bose-st10-2._spotify-connect._tcp.local.").
|
|
262
|
+
"""
|
|
263
|
+
return self._Key
|
|
264
|
+
|
|
265
|
+
@Key.setter
|
|
266
|
+
def Key(self, value:str):
|
|
267
|
+
"""
|
|
268
|
+
Sets the Key property value.
|
|
269
|
+
"""
|
|
270
|
+
if isinstance(value, str):
|
|
271
|
+
self._Key = value
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def Name(self) -> str:
|
|
276
|
+
"""
|
|
277
|
+
Service name (e.g. "Bose-ST10-2._spotify-connect._tcp.local.").
|
|
278
|
+
"""
|
|
279
|
+
return self._Name
|
|
280
|
+
|
|
281
|
+
@Name.setter
|
|
282
|
+
def Name(self, value:str):
|
|
283
|
+
"""
|
|
284
|
+
Sets the Name property value.
|
|
285
|
+
"""
|
|
286
|
+
if isinstance(value, str):
|
|
287
|
+
self._Name = value
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def Priority(self) -> int:
|
|
292
|
+
"""
|
|
293
|
+
Priority value (as an integer) for the service on the host (e.g. 0).
|
|
294
|
+
"""
|
|
295
|
+
return self._Priority
|
|
296
|
+
|
|
297
|
+
@Priority.setter
|
|
298
|
+
def Priority(self, value:int):
|
|
299
|
+
"""
|
|
300
|
+
Sets the Priority property value.
|
|
301
|
+
"""
|
|
302
|
+
if isinstance(value, int):
|
|
303
|
+
self._Priority = value
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def OtherTTL(self) -> int:
|
|
308
|
+
"""
|
|
309
|
+
Other Time-To-Live value (as an integer) for the service on the host (e.g. 5400).
|
|
310
|
+
"""
|
|
311
|
+
return self._OtherTTL
|
|
312
|
+
|
|
313
|
+
@OtherTTL.setter
|
|
314
|
+
def OtherTTL(self, value:int):
|
|
315
|
+
"""
|
|
316
|
+
Sets the OtherTTL property value.
|
|
317
|
+
"""
|
|
318
|
+
if isinstance(value, int):
|
|
319
|
+
self._OtherTTL = value
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@property
|
|
323
|
+
def Properties(self) -> list[ZeroconfProperty]:
|
|
324
|
+
"""
|
|
325
|
+
Discovered properties.
|
|
326
|
+
"""
|
|
327
|
+
return self._Properties
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
@property
|
|
331
|
+
def Server(self) -> str:
|
|
332
|
+
"""
|
|
333
|
+
Server name (e.g. "Bose-SM2-341513fbeeae.local.").
|
|
334
|
+
"""
|
|
335
|
+
return self._Server
|
|
336
|
+
|
|
337
|
+
@Server.setter
|
|
338
|
+
def Server(self, value:str):
|
|
339
|
+
"""
|
|
340
|
+
Sets the Server property value.
|
|
341
|
+
"""
|
|
342
|
+
if isinstance(value, str):
|
|
343
|
+
self._Server = value
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def ServerKey(self) -> str:
|
|
348
|
+
"""
|
|
349
|
+
Server key (e.g. "bose-sm2-341513fbeeae.local.").
|
|
350
|
+
"""
|
|
351
|
+
return self._ServerKey
|
|
352
|
+
|
|
353
|
+
@ServerKey.setter
|
|
354
|
+
def ServerKey(self, value:str):
|
|
355
|
+
"""
|
|
356
|
+
Sets the ServerKey property value.
|
|
357
|
+
"""
|
|
358
|
+
if isinstance(value, str):
|
|
359
|
+
self._ServerKey = value
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def ServiceType(self) -> str:
|
|
364
|
+
"""
|
|
365
|
+
Service type, which should match the one passed in during the query name (e.g. "_spotify-connect._tcp.").
|
|
366
|
+
"""
|
|
367
|
+
return self._ServiceType
|
|
368
|
+
|
|
369
|
+
@ServiceType.setter
|
|
370
|
+
def ServiceType(self, value:str):
|
|
371
|
+
"""
|
|
372
|
+
Sets the ServiceType property value.
|
|
373
|
+
"""
|
|
374
|
+
if isinstance(value, str):
|
|
375
|
+
self._ServiceType = value
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
@property
|
|
379
|
+
def Weight(self) -> int:
|
|
380
|
+
"""
|
|
381
|
+
Weight value (as an integer) for the service on the host (e.g. 0).
|
|
382
|
+
"""
|
|
383
|
+
return self._Weight
|
|
384
|
+
|
|
385
|
+
@Weight.setter
|
|
386
|
+
def Weight(self, value:int):
|
|
387
|
+
"""
|
|
388
|
+
Sets the Weight property value.
|
|
389
|
+
"""
|
|
390
|
+
if isinstance(value, int):
|
|
391
|
+
self._Weight = value
|
|
392
|
+
|
|
393
|
+
# *****************************************************************************
|
|
394
|
+
# The following are Spotify Connect specific properties.
|
|
395
|
+
# *****************************************************************************
|
|
396
|
+
|
|
397
|
+
@property
|
|
398
|
+
def SpotifyConnectCPath(self) -> str:
|
|
399
|
+
"""
|
|
400
|
+
Spotify Connect CPath property value (e.g. "/zc").
|
|
401
|
+
"""
|
|
402
|
+
return self._SpotifyConnectCPath
|
|
403
|
+
|
|
404
|
+
@SpotifyConnectCPath.setter
|
|
405
|
+
def SpotifyConnectCPath(self, value:str):
|
|
406
|
+
"""
|
|
407
|
+
Sets the SpotifyConnectCPath property value.
|
|
408
|
+
"""
|
|
409
|
+
if isinstance(value, str):
|
|
410
|
+
self._SpotifyConnectCPath = value
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
@property
|
|
414
|
+
def SpotifyConnectVersion(self) -> str:
|
|
415
|
+
"""
|
|
416
|
+
Spotify Connect Version property value (e.g. null, "1.0").
|
|
417
|
+
|
|
418
|
+
"""
|
|
419
|
+
return self._SpotifyConnectVersion
|
|
420
|
+
|
|
421
|
+
@SpotifyConnectVersion.setter
|
|
422
|
+
def SpotifyConnectVersion(self, value:str):
|
|
423
|
+
"""
|
|
424
|
+
Sets the SpotifyConnectVersion property value.
|
|
425
|
+
"""
|
|
426
|
+
if (isinstance(value, str)) or (value is None):
|
|
427
|
+
self._SpotifyConnectVersion = value
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
@property
|
|
431
|
+
def ZeroconfApiEndpointAddUser(self) -> str:
|
|
432
|
+
"""
|
|
433
|
+
Zeroconf API endpoint to add a user to a Spotify Connect device (e.g. "http://192.168.1.81:8200/zc?action=addUser&version=2.10.0").
|
|
434
|
+
"""
|
|
435
|
+
return self.GetEndpointUrl('addUser')
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
@property
|
|
439
|
+
def ZeroconfApiEndpointGetInformation(self) -> str:
|
|
440
|
+
"""
|
|
441
|
+
Zeroconf API endpoint to retrieve device information for a Spotify Connect device (e.g. "http://192.168.1.81:8200/zc?action=getInfo&version=2.10.0").
|
|
442
|
+
"""
|
|
443
|
+
return self.GetEndpointUrl('getInfo')
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
@property
|
|
447
|
+
def ZeroconfApiEndpointResetUsers(self) -> str:
|
|
448
|
+
"""
|
|
449
|
+
Zeroconf API endpoint to reset users (e.g. Logoff) currently active on a Spotify Connect device (e.g. "http://192.168.1.81:8200/zc?action=resetUsers&version=2.10.0").
|
|
450
|
+
"""
|
|
451
|
+
return self.GetEndpointUrl('resetUsers')
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def Equals(self, obj) -> bool:
|
|
455
|
+
"""
|
|
456
|
+
Returns true if the specified object instance contains the same argument
|
|
457
|
+
values as our object instance values; otherwise, False.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
obj (ZeroconfDiscoveryResult):
|
|
461
|
+
Object instance to compare.
|
|
462
|
+
"""
|
|
463
|
+
result:bool = False
|
|
464
|
+
if (not isinstance(obj, type(self))):
|
|
465
|
+
return result
|
|
466
|
+
|
|
467
|
+
# compare attributes for equality.
|
|
468
|
+
if (self._DeviceName != obj._DeviceName): return result
|
|
469
|
+
if (self._Domain != obj._Domain): return result
|
|
470
|
+
if (self.HostIpAddress != obj.HostIpAddress): return result
|
|
471
|
+
if (self._HostIpPort != obj._HostIpPort): return result
|
|
472
|
+
if (self._HostTTL != obj._HostTTL): return result
|
|
473
|
+
if (self._IsChromeCast != obj._IsChromeCast): return result
|
|
474
|
+
if (self._Id != obj._Id): return result
|
|
475
|
+
if (self._Key != obj._Key): return result
|
|
476
|
+
if (self._Name != obj._Name): return result
|
|
477
|
+
if (self._OtherTTL != obj._OtherTTL): return result
|
|
478
|
+
if (self._Priority != obj._Priority): return result
|
|
479
|
+
if (self._Server != obj._Server): return result
|
|
480
|
+
if (self._ServerKey != obj._ServerKey): return result
|
|
481
|
+
if (self._ServiceType != obj._ServiceType): return result
|
|
482
|
+
if (self._Weight != obj._Weight): return result
|
|
483
|
+
if (self._SpotifyConnectCPath != obj._SpotifyConnectCPath): return result
|
|
484
|
+
if (self._SpotifyConnectVersion != obj._SpotifyConnectVersion): return result
|
|
485
|
+
|
|
486
|
+
# don't compare the following:
|
|
487
|
+
# self._Properties:list = []
|
|
488
|
+
|
|
489
|
+
# objects attributes are equal.
|
|
490
|
+
return True
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def GetEndpointUrl(self, action:str) -> str:
|
|
494
|
+
"""
|
|
495
|
+
Gets a Spotify Zeroconf API endpoint url for the specified action key.
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
action (str):
|
|
499
|
+
Spotify Zeroconf endpoint action to formulate (e.g. 'getInfo', 'addUser', 'resetUsers', etc).
|
|
500
|
+
|
|
501
|
+
Returns:
|
|
502
|
+
A string containing the endpoint url for the specified action key.
|
|
503
|
+
"""
|
|
504
|
+
return "http://{ip}:{port}{cpath}?action={action}&version={version}".format(
|
|
505
|
+
ip=self.HostIpAddress,
|
|
506
|
+
port=self.HostIpPort,
|
|
507
|
+
cpath=self.SpotifyConnectCPath,
|
|
508
|
+
action=action,
|
|
509
|
+
version=self.SpotifyConnectVersion or ''
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def ToDictionary(self) -> dict:
|
|
514
|
+
"""
|
|
515
|
+
Returns a dictionary representation of the class.
|
|
516
|
+
"""
|
|
517
|
+
result:dict = \
|
|
518
|
+
{
|
|
519
|
+
'Id': self._Id,
|
|
520
|
+
'DeviceName': self._DeviceName,
|
|
521
|
+
'Domain': self._Domain,
|
|
522
|
+
'HostIpAddress': self.HostIpAddress,
|
|
523
|
+
'HostIpAddresses': [ str(item) for item in self._HostIpAddresses ],
|
|
524
|
+
'HostIpPort': self._HostIpPort,
|
|
525
|
+
'HostTTL': self._HostTTL,
|
|
526
|
+
'IsChromeCast': self._IsChromeCast,
|
|
527
|
+
'IsDynamicDevice': self.IsDynamicDevice,
|
|
528
|
+
'Key': self._Key,
|
|
529
|
+
'Name': self._Name,
|
|
530
|
+
'Priority': self._Priority,
|
|
531
|
+
'OtherTTL': self._OtherTTL,
|
|
532
|
+
'Server': self._Server,
|
|
533
|
+
'ServerKey': self._ServerKey,
|
|
534
|
+
'ServiceType': self._ServiceType,
|
|
535
|
+
'Weight': self._Weight,
|
|
536
|
+
'Description': self.Description,
|
|
537
|
+
'Properties': [ item.ToDictionary() for item in self._Properties ],
|
|
538
|
+
'SpotifyConnectCPath': self._SpotifyConnectCPath,
|
|
539
|
+
'SpotifyConnectVersion': self._SpotifyConnectVersion,
|
|
540
|
+
'ZeroconfApiEndpointAddUser': self.ZeroconfApiEndpointAddUser,
|
|
541
|
+
'ZeroconfApiEndpointGetInformation': self.ZeroconfApiEndpointGetInformation,
|
|
542
|
+
'ZeroconfApiEndpointResetUsers': self.ZeroconfApiEndpointResetUsers,
|
|
543
|
+
}
|
|
544
|
+
return result
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def ToString(self, includeTitle:bool=True) -> str:
|
|
548
|
+
"""
|
|
549
|
+
Returns a displayable string representation of the class.
|
|
550
|
+
|
|
551
|
+
Args:
|
|
552
|
+
includeTitle (str):
|
|
553
|
+
True to include the class name title prefix.
|
|
554
|
+
"""
|
|
555
|
+
msg:str = ''
|
|
556
|
+
if includeTitle:
|
|
557
|
+
msg = 'ZeroconfDiscoveryResult:'
|
|
558
|
+
|
|
559
|
+
# get dynamically generated property values.
|
|
560
|
+
description:str = self.Description
|
|
561
|
+
hostIpAddress:str = self.HostIpAddress
|
|
562
|
+
isDynamicDevice:bool = self.IsDynamicDevice
|
|
563
|
+
zeroconfApiEndpointAddUser:str = self.ZeroconfApiEndpointAddUser
|
|
564
|
+
zeroconfApiEndpointGetInformation:str = self.ZeroconfApiEndpointGetInformation
|
|
565
|
+
zeroconfApiEndpointResetUsers:str = self.ZeroconfApiEndpointResetUsers
|
|
566
|
+
|
|
567
|
+
# build result.
|
|
568
|
+
if self._Id is not None: msg = '%s\n Id="%s"' % (msg, str(self._Id))
|
|
569
|
+
if self._DeviceName is not None: msg = '%s\n DeviceName="%s"' % (msg, str(self._DeviceName))
|
|
570
|
+
if self._Domain is not None: msg = '%s\n Domain="%s"' % (msg, str(self._Domain))
|
|
571
|
+
if self._HostIpAddresses is not None: msg = '%s\n HostIpAddresses Count=%s' % (msg, str(len(self._HostIpAddresses)))
|
|
572
|
+
if hostIpAddress is not None: msg = '%s\n HostIpAddress="%s"' % (msg, str(hostIpAddress))
|
|
573
|
+
if self._HostIpPort is not None: msg = '%s\n HostIpPort="%s"' % (msg, str(self._HostIpPort))
|
|
574
|
+
if self._HostTTL is not None: msg = '%s\n HostTTL="%s"' % (msg, str(self._HostTTL))
|
|
575
|
+
if isDynamicDevice is not None: msg = '%s\n IsDynamicDevice="%s"' % (msg, str(isDynamicDevice))
|
|
576
|
+
if self._IsChromeCast is not None: msg = '%s\n IsChromeCast="%s"' % (msg, str(self._IsChromeCast))
|
|
577
|
+
if self._Key is not None: msg = '%s\n Key="%s"' % (msg, str(self._Key))
|
|
578
|
+
if self._Name is not None: msg = '%s\n Name="%s"' % (msg, str(self._Name))
|
|
579
|
+
if self._Priority is not None: msg = '%s\n Priority="%s"' % (msg, str(self._Priority))
|
|
580
|
+
if self._OtherTTL is not None: msg = '%s\n OtherTTL="%s"' % (msg, str(self._OtherTTL))
|
|
581
|
+
if self._Server is not None: msg = '%s\n Server="%s"' % (msg, str(self._Server))
|
|
582
|
+
if self._ServerKey is not None: msg = '%s\n ServerKey="%s"' % (msg, str(self._ServerKey))
|
|
583
|
+
if self._ServiceType is not None: msg = '%s\n ServiceType="%s"' % (msg, str(self._ServiceType))
|
|
584
|
+
if self._Weight is not None: msg = '%s\n Weight="%s"' % (msg, str(self._Weight))
|
|
585
|
+
if description is not None: msg = '%s\n Description="%s"' % (msg, str(description))
|
|
586
|
+
if self._Properties is not None: msg = '%s\n Properties Count=%s' % (msg, str(len(self._Properties)))
|
|
587
|
+
if self._SpotifyConnectCPath is not None: msg = '%s\n SpotifyConnectCPath="%s"' % (msg, str(self._SpotifyConnectCPath))
|
|
588
|
+
if self._SpotifyConnectVersion is not None: msg = '%s\n SpotifyConnectVersion="%s"' % (msg, str(self._SpotifyConnectVersion))
|
|
589
|
+
if zeroconfApiEndpointAddUser is not None: msg = '%s\n ZeroconfApiEndpointAddUser="%s"' % (msg, zeroconfApiEndpointAddUser)
|
|
590
|
+
if zeroconfApiEndpointGetInformation is not None: msg = '%s\n ZeroconfApiEndpointGetInformation="%s"' % (msg, zeroconfApiEndpointGetInformation)
|
|
591
|
+
if zeroconfApiEndpointResetUsers is not None: msg = '%s\n ZeroconfApiEndpointResetUsers="%s"' % (msg, zeroconfApiEndpointResetUsers)
|
|
592
|
+
return msg
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# external package imports.
|
|
2
|
+
|
|
3
|
+
# our package imports.
|
|
4
|
+
from ..sautils import export
|
|
5
|
+
|
|
6
|
+
@export
|
|
7
|
+
class ZeroconfProperty:
|
|
8
|
+
"""
|
|
9
|
+
Zeroconf Property object.
|
|
10
|
+
|
|
11
|
+
Information about a Zeroconf property.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, name:str, value:str) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Initializes a new instance of the class.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
name (str):
|
|
20
|
+
Property name.
|
|
21
|
+
value (str):
|
|
22
|
+
Property value.
|
|
23
|
+
"""
|
|
24
|
+
self._Name:str = name
|
|
25
|
+
self._Value:str = value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __repr__(self) -> str:
|
|
29
|
+
return self.ToString()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def __str__(self) -> str:
|
|
33
|
+
return self.ToString()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def Name(self) -> str:
|
|
38
|
+
"""
|
|
39
|
+
Property name.
|
|
40
|
+
"""
|
|
41
|
+
return self._Name
|
|
42
|
+
|
|
43
|
+
@Name.setter
|
|
44
|
+
def Name(self, value:str):
|
|
45
|
+
"""
|
|
46
|
+
Sets the Name property value.
|
|
47
|
+
"""
|
|
48
|
+
if isinstance(value, str):
|
|
49
|
+
self._Name = value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def Value(self) -> str:
|
|
54
|
+
"""
|
|
55
|
+
Property value.
|
|
56
|
+
"""
|
|
57
|
+
return self._Value
|
|
58
|
+
|
|
59
|
+
@Value.setter
|
|
60
|
+
def Value(self, value:str):
|
|
61
|
+
"""
|
|
62
|
+
Sets the Value property value.
|
|
63
|
+
"""
|
|
64
|
+
self._Value = value
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def ToDictionary(self) -> dict:
|
|
68
|
+
"""
|
|
69
|
+
Returns a dictionary representation of the class.
|
|
70
|
+
"""
|
|
71
|
+
result:dict = \
|
|
72
|
+
{
|
|
73
|
+
'Name': self._Name,
|
|
74
|
+
'Value': self._Value,
|
|
75
|
+
}
|
|
76
|
+
return result
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def ToString(self, includeTitle:bool=False) -> str:
|
|
80
|
+
"""
|
|
81
|
+
Returns a displayable string representation of the class.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
includeTitle (str):
|
|
85
|
+
True to include the class name title prefix.
|
|
86
|
+
"""
|
|
87
|
+
msg:str = ''
|
|
88
|
+
if includeTitle:
|
|
89
|
+
msg = 'ZeroconfProperty:'
|
|
90
|
+
|
|
91
|
+
if self._Name is not None: msg = '%s\n Name="%s"' % (msg, str(self._Name))
|
|
92
|
+
if self._Value is not None: msg = '%s\n Value="%s"' % (msg, str(self._Value))
|
|
93
|
+
return msg
|