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,264 @@
|
|
|
1
|
+
# external package imports.
|
|
2
|
+
from datetime import datetime, timedelta
|
|
3
|
+
from pprint import pformat
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
# our package imports.
|
|
7
|
+
from .saappmessages import SAAppMessages
|
|
8
|
+
|
|
9
|
+
class SpotifyAuthToken:
|
|
10
|
+
"""
|
|
11
|
+
Spotify Authorization Token class.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, authorizationType:str, profileId:str, root:dict=None) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Initializes a new instance of the class.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
authorizationType (str):
|
|
20
|
+
Authorization type chosen when this token was generated.
|
|
21
|
+
profileId (str):
|
|
22
|
+
Profile identifier used when loading / storing the token to disk.
|
|
23
|
+
root (dict):
|
|
24
|
+
Spotify Web API JSON response in dictionary format, used to load object
|
|
25
|
+
attributes; otherwise, None to not load attributes.
|
|
26
|
+
"""
|
|
27
|
+
# validation.
|
|
28
|
+
if authorizationType is None or len(authorizationType.strip()) == 0:
|
|
29
|
+
raise Exception(SAAppMessages.ARGUMENT_REQUIRED_ERROR % ('SpotifyAuthToken __init__','authorizationType'))
|
|
30
|
+
|
|
31
|
+
# initialize storage.
|
|
32
|
+
self._AccessToken:str = None
|
|
33
|
+
self._AuthorizationType:str = authorizationType
|
|
34
|
+
self._ExpireDateTimeUtc:datetime = None
|
|
35
|
+
self._ExpiresAt:int = None
|
|
36
|
+
self._ExpiresIn:int = None
|
|
37
|
+
self._ProfileId:str = profileId
|
|
38
|
+
self._RefreshToken:str = None
|
|
39
|
+
self._Scope:str = None
|
|
40
|
+
self._TokenType:str = None
|
|
41
|
+
|
|
42
|
+
if (root is None):
|
|
43
|
+
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
else:
|
|
47
|
+
|
|
48
|
+
self._AccessToken = root.get('access_token', None)
|
|
49
|
+
self._ExpiresAt = root.get('expires_at', None)
|
|
50
|
+
self._ExpiresIn = root.get('expires_in', None)
|
|
51
|
+
self._RefreshToken = root.get('refresh_token', None)
|
|
52
|
+
self._Scope = root.get('scope', None)
|
|
53
|
+
self._TokenType = root.get('token_type', None)
|
|
54
|
+
|
|
55
|
+
# set non-JSON response properties.
|
|
56
|
+
if self._ExpiresAt is not None:
|
|
57
|
+
|
|
58
|
+
# calculate expire time based on ExpiresAt (epoch) seconds.
|
|
59
|
+
self._ExpiresAt = int(self._ExpiresAt) # convert from float to int, dropping microseconds.
|
|
60
|
+
self._ExpireDateTimeUtc = datetime.utcfromtimestamp(self._ExpiresAt)
|
|
61
|
+
|
|
62
|
+
elif self._ExpiresIn is not None:
|
|
63
|
+
|
|
64
|
+
# calculate expire time based on ExpiresIn seconds.
|
|
65
|
+
unix_epoch = datetime(1970, 1, 1)
|
|
66
|
+
dtUtcNow:datetime = datetime.utcnow()
|
|
67
|
+
self._ExpireDateTimeUtc = dtUtcNow + timedelta(seconds=self._ExpiresIn)
|
|
68
|
+
self._ExpiresAt = int((dtUtcNow - unix_epoch).total_seconds()) # seconds from epoch, current date
|
|
69
|
+
self._ExpiresAt = self._ExpiresAt + self._ExpiresIn # add ExpiresIn seconds
|
|
70
|
+
|
|
71
|
+
# if scope is a list then convert to space-delimited value.
|
|
72
|
+
if isinstance(self._Scope, list):
|
|
73
|
+
self._Scope = ' '.join(self._Scope)
|
|
74
|
+
|
|
75
|
+
def __repr__(self) -> str:
|
|
76
|
+
return self.ToString()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def __str__(self) -> str:
|
|
80
|
+
return self.ToString()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def AccessToken(self) -> str:
|
|
85
|
+
"""
|
|
86
|
+
An access token that can be provided in subsequent calls to Spotify Web API services.
|
|
87
|
+
"""
|
|
88
|
+
return self._AccessToken
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def AuthorizationType(self) -> str:
|
|
93
|
+
"""
|
|
94
|
+
Authorization type chosen when this token was generated.
|
|
95
|
+
|
|
96
|
+
It will be one of the following values:
|
|
97
|
+
- "Authorization Code".
|
|
98
|
+
- "Authorization Code with PKCE".
|
|
99
|
+
- "Client Credentials".
|
|
100
|
+
- "Implicit Grant".
|
|
101
|
+
"""
|
|
102
|
+
return self._AuthorizationType
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def CreateDateTimeUtc(self) -> datetime:
|
|
106
|
+
"""
|
|
107
|
+
DateTime (in UTC format) that the authorization token was created.
|
|
108
|
+
"""
|
|
109
|
+
return self._CreateDateTimeUtc
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def ExpireDateTimeUtc(self) -> datetime:
|
|
114
|
+
"""
|
|
115
|
+
DateTime (in UTC format) that the authorization token will expire.
|
|
116
|
+
"""
|
|
117
|
+
return self._ExpireDateTimeUtc
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def ExpiresIn(self) -> int:
|
|
122
|
+
"""
|
|
123
|
+
The time period (in seconds) for which the access token is valid.
|
|
124
|
+
"""
|
|
125
|
+
return self._ExpiresIn
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def ExpiresAt(self) -> int:
|
|
130
|
+
"""
|
|
131
|
+
DateTime (in epoch seconds) that the authorization token will expire.
|
|
132
|
+
"""
|
|
133
|
+
return self._ExpiresAt
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def HeaderKey(self) -> str:
|
|
138
|
+
"""
|
|
139
|
+
Returns a string containing the header key to assign the authorization token value to.
|
|
140
|
+
This will always return 'Authorization'.
|
|
141
|
+
"""
|
|
142
|
+
return 'Authorization'
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def HeaderValue(self) -> str:
|
|
147
|
+
"""
|
|
148
|
+
Returns the value portion of the authorization header, in the form of '{tokentype} {token}'.
|
|
149
|
+
|
|
150
|
+
Example: `Bearer {token value ...}'
|
|
151
|
+
"""
|
|
152
|
+
return '{tokentype} {token}'.format(tokentype=self.TokenType, token=self.AccessToken)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def IsExpired(self) -> bool:
|
|
157
|
+
"""
|
|
158
|
+
Returns true if the token has expired; otherwise, False if not expired.
|
|
159
|
+
"""
|
|
160
|
+
if self._ExpiresAt is not None:
|
|
161
|
+
nowsecs:int = int(time.time())
|
|
162
|
+
# subtract 120 seconds (2 minutes) in case we are right at the edge of expiring.
|
|
163
|
+
if (nowsecs + 120) > self._ExpiresAt:
|
|
164
|
+
return True
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def ProfileId(self) -> str:
|
|
170
|
+
"""
|
|
171
|
+
Profile identifier used when loading / storing the token to disk.
|
|
172
|
+
"""
|
|
173
|
+
return self._ProfileId
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def RefreshToken(self) -> str:
|
|
178
|
+
"""
|
|
179
|
+
The refresh token returned from the authorization token request.
|
|
180
|
+
|
|
181
|
+
This is only set when using the "Authorization code" or "Authorization code with PKCE"
|
|
182
|
+
authorization types.
|
|
183
|
+
|
|
184
|
+
There will be no refresh token for the "Client Credentials" or "Impllicit Grant"
|
|
185
|
+
authorization types.
|
|
186
|
+
"""
|
|
187
|
+
return self._RefreshToken
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def Scope(self) -> str:
|
|
192
|
+
"""
|
|
193
|
+
A space-separated list of scopes which have been granted for the `AccessToken`.
|
|
194
|
+
|
|
195
|
+
If no scopes are specified, authorization will be granted only to access publicly available
|
|
196
|
+
information: that is, only information normally visible in the Spotify desktop, web, and
|
|
197
|
+
mobile players.
|
|
198
|
+
|
|
199
|
+
Scopes can only be used with the "Authorization Code", "Authorization Code with PKCE", and
|
|
200
|
+
"Implicit Grant" authorization types.
|
|
201
|
+
|
|
202
|
+
Scopes cannot be used with the "Client Credentials" authorization type.
|
|
203
|
+
"""
|
|
204
|
+
return self._Scope
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def Scopes(self) -> list[str]:
|
|
209
|
+
"""
|
|
210
|
+
A list of scopes which have been granted for the `AccessToken`.
|
|
211
|
+
"""
|
|
212
|
+
if self._Scope is None:
|
|
213
|
+
return []
|
|
214
|
+
return self._Scope.split(' ')
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def TokenType(self) -> str:
|
|
219
|
+
"""
|
|
220
|
+
How the access token may be used: always "Bearer" in this case.
|
|
221
|
+
"""
|
|
222
|
+
return self._TokenType
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def ToDictionary(self) -> dict:
|
|
226
|
+
"""
|
|
227
|
+
Returns a dictionary representation of the class.
|
|
228
|
+
"""
|
|
229
|
+
result:dict = \
|
|
230
|
+
{
|
|
231
|
+
'access_token': self._AccessToken,
|
|
232
|
+
'expires_at': self._ExpiresAt,
|
|
233
|
+
'expires_in': self._ExpiresIn,
|
|
234
|
+
'refresh_token': self._RefreshToken,
|
|
235
|
+
'scope': self.Scopes,
|
|
236
|
+
'token_type': self._TokenType,
|
|
237
|
+
}
|
|
238
|
+
return result
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def ToDictionaryString(self) -> dict:
|
|
242
|
+
"""
|
|
243
|
+
Returns a dictionary string representation of the class.
|
|
244
|
+
"""
|
|
245
|
+
oDict:dict = self.ToDictionary()
|
|
246
|
+
result:str = pformat(oDict,indent=2,width=132,sort_dicts=False)
|
|
247
|
+
return result
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def ToString(self) -> str:
|
|
251
|
+
"""
|
|
252
|
+
Returns a displayable string representation of the class.
|
|
253
|
+
"""
|
|
254
|
+
msg:str = 'SpotifyAuthToken:'
|
|
255
|
+
if self._AuthorizationType is not None: msg = '%s\n AuthorizationType="%s"' % (msg, str(self._AuthorizationType))
|
|
256
|
+
if self._AccessToken is not None: msg = '%s\n AccessToken="%s"' % (msg, str(self._AccessToken))
|
|
257
|
+
if self._ExpiresAt is not None: msg = '%s\n ExpiresAt="%s"' % (msg, str(self._ExpiresAt))
|
|
258
|
+
if self._ExpiresIn is not None: msg = '%s\n ExpiresIn="%s"' % (msg, str(self._ExpiresIn))
|
|
259
|
+
if self._ExpireDateTimeUtc is not None: msg = '%s\n ExpireDateTimeUtc="%s"' % (msg, str(self._ExpireDateTimeUtc))
|
|
260
|
+
if self._ProfileId is not None: msg = '%s\n ProfileId="%s"' % (msg, str(self._ProfileId))
|
|
261
|
+
if self._RefreshToken is not None: msg = '%s\n RefreshToken="%s"' % (msg, str(self._RefreshToken))
|
|
262
|
+
if self._Scope is not None: msg = '%s\n Scope="%s"' % (msg, str(self._Scope))
|
|
263
|
+
if self._TokenType is not None: msg = '%s\n TokenType="%s"' % (msg, str(self._TokenType))
|
|
264
|
+
return msg
|