Spotify Api Client
SpotifyApiClient
¶
The class which will be used to authenticate and connect to the spotify api.
Source code in async_spotify/api/spotify_api_client.py
class SpotifyApiClient:
"""
The class which will be used to authenticate and connect to the spotify api.
"""
def __init__(self, authorization_flow: AuthorizationFlow,
hold_authentication=False,
spotify_authorisation_token: SpotifyAuthorisationToken = None,
token_renew_instance: TokenRenewClass = None):
"""
Create a new api class
Args:
authorization_flow: The auth_code_flow object fully filled with information
hold_authentication: Should the api keep the authentication im memory and refresh it automatically
token_renew_instance: An instance of a class which handles the renewing of the token if it should expire
"""
# Check if the auth_code_flow are valid
if not authorization_flow.valid:
raise SpotifyError(ErrorMessage(message="The auth flow instance of your app is not correct").__dict__)
self.authorization_flow: AuthorizationFlow = authorization_flow
# Set the SpotifyAuthorisationToken
if spotify_authorisation_token:
self._spotify_authorisation_token: SpotifyAuthorisationToken = spotify_authorisation_token
else:
self._spotify_authorisation_token: SpotifyAuthorisationToken = SpotifyAuthorisationToken()
self._token_renew_instance: TokenRenewClass = token_renew_instance
self._hold_authentication: bool = hold_authentication
self._api_request_handler: ApiRequestHandler = ApiRequestHandler(self._spotify_authorisation_token,
token_renew_instance, self)
################################################################################################################
self.albums: Albums = Albums(self._api_request_handler)
""" An instance of the [`Albums`][async_spotify.api._endpoints.albums] class. Use this to access the
Albums api """
self.artists: Artists = Artists(self._api_request_handler)
""" An instance of the [`Artists`][async_spotify.api._endpoints.artists] class. Use this to access the
Artists api """
self.browse: Browse = Browse(self._api_request_handler)
""" An instance of the [`Browse`][async_spotify.api._endpoints.browse] class. Use this to Browse the
Browse api """
self.episodes: Episodes = Episodes(self._api_request_handler)
""" An instance of the [`Episodes`][async_spotify.api._endpoints.episodes] class. Use this to access the
Episodes api """
self.follow: Follow = Follow(self._api_request_handler)
""" An instance of the [`Follow`][async_spotify.api._endpoints.follow] class. Use this to access the
Follow api """
self.library: Library = Library(self._api_request_handler)
""" An instance of the [`Library`][async_spotify.api._endpoints.library] class. Use this to access the
Library api """
self.personalization: Personalization = Personalization(self._api_request_handler)
""" An instance of the [`Personalization`][async_spotify.api._endpoints.personalization] class. Use this to
access the Personalization api """
self.player: Player = Player(self._api_request_handler)
""" An instance of the [`Player`][async_spotify.api._endpoints.player] class. Use this to access the
Player api """
self.playlists: Playlists = Playlists(self._api_request_handler)
""" An instance of the [`Playlists`][async_spotify.api._endpoints.playlists] class. Use this to access the
Playlist api """
self.search: Search = Search(self._api_request_handler)
""" An instance of the [`Search`][async_spotify.api._endpoints.search] class. Use this to access the
Search api """
self.shows: Shows = Shows(self._api_request_handler)
""" An instance of the [`Shows`][async_spotify.api._endpoints.shows] class. Use this to access the
Show api """
self.track: Track = Track(self._api_request_handler)
""" An instance of the [`Track`][async_spotify.api._endpoints.tracks] class. Use this to access the
Track api """
self.user: User = User(self._api_request_handler)
""" An instance of the [`User`][async_spotify.api._endpoints.user] class. Use this to access the
User api """
async def create_new_client(self, request_timeout: int = 30, request_limit: int = 500) -> None:
"""
Create a new session which will be used to connect to the spotify api.
In general this only has to be called once after you create a new API object.
You can however call this method if you want ot update the client settings (more requests, ...)
This will however close all ongoing requests.
Args:
request_timeout: How long should be waited for a request (default 30s) (None for no limit)
request_limit: How many requests should be allowed (default 500)
"""
await self._api_request_handler.create_new_client(request_timeout, request_limit)
async def close_client(self) -> None:
"""
Close the current client session. You have to create a new one to connect again to spotify.
This method should always be called before you end your program
"""
await self._api_request_handler.close_client()
def build_authorization_url(self, show_dialog: bool = True, state: str = None) -> str:
"""
Builds the URL for the authorisation
Args:
state: State of the authorization
show_dialog: Should the spotify auth dialog be shown
Returns:
The encoded url which can be used to authorize a new or existing user
"""
self._enforce_flows()
# TODO PKCEFlow
self.authorization_flow: Union[AuthorizationCodeFlow]
params = {
"client_id": self.authorization_flow.application_id,
"response_type": "code",
"scope": ' '.join(self.authorization_flow.scopes),
"show_dialog": f"{show_dialog}",
"redirect_uri": f"{self.authorization_flow.redirect_url}"
}
# Check if a state is required
if state:
params["state"] = f"{state}"
return f"{URLS.AUTHORIZE}?{urlencode(params)}"
def open_oauth_dialog_in_browser(self, show_dialogue: bool = True) -> None:
"""
Open the url in browser
Only for testing purposes or the usage of this library in a desktop app
Args:
show_dialogue: Should the spotify auth dialog be shown
"""
# Open url in a new window of the default browser, if possible
webbrowser.open_new(self.build_authorization_url(show_dialogue))
async def get_code_with_cookie(self, cookies: SpotifyCookie) -> str:
"""
This function takes care of the user interaction that is normally required to get the code from spotify
which is necessary to request the refresh_token and the oauth_token.
The token which is returned by this function has to be passed to API.get_auth_token_with_code(code)
to get the refresh_token and the oauth_token.
The big advantage is that you don't have to run a callback server to get the code
Notes:
This will only work if the user has at least once accepted the scopes your app is requesting.
I would recommend that you take a look at the source code of this function before you use it and that you
are familiar with the authorization mechanism of spotify.
Important:
This method is intended for automated testing. You have to decide if you want to use it in you production
environment.
Args:
cookies: The cookies of the spotify account. Every property of the class has to be filled in.
Raises:
SpotifyError: If the cookie is not valid
SpotifyError: If there is a redirect between you and spotify
SpotifyError: If there is an unknown error
Returns:
The spotify code which can be used to get a refresh_token and a oauth_token
"""
# Build the auth url
url = self.build_authorization_url(show_dialog=False)
# Check if the cookie file is valid
if not cookies.valid:
raise SpotifyError(ErrorMessage(message='The cookies are not complete').__dict__)
# Convert the class to a dict
cookie_dict: dict = cookies.__dict__
return await self._track_request_without_callback(cookie_dict, url)
@staticmethod
async def _track_request_without_callback(cookie_dict: dict, url: str) -> str:
"""
Make a request to the spotify api without redirects. No callback server needed.
Args:
cookie_dict: The cookie dict used for authentification
url: The url of the spotify request
Raises:
SpotifyError: If there is a redirect between you and spotify
SpotifyError: If there is an unknown error
Returns: The code of spotify
"""
code: Optional[str] = None
async def redirect(_: ClientSession, __: SimpleNamespace, trace_request: TraceRequestRedirectParams) -> None:
"""
Handler the redirect event aiohttp is firing
Args:
_: ClientSession
__: SimpleNamespace
trace_request: The current redirect request response
"""
# Get the redirect url
location: Optional[str] = trace_request.response.headers.get('location')
# Parse the url
local_url = parse.urlparse(location)
query: dict = parse.parse_qs(local_url.query)
# Check if code is the redirect url
_code: Optional[List[str]] = query.get('code')
if _code:
nonlocal code
code = _code[0]
# Create a callback every time there is a redirect
trace_config = TraceConfig()
trace_config.on_request_redirect.append(redirect)
try:
# Make an api request to spotify
async with ClientSession(cookies=cookie_dict, trace_configs=[trace_config]) as session:
async with session.get(url) as resp:
response_text = await resp.text()
await session.close()
except ClientConnectorError:
# Ignore the error in case no callback server is running
pass
if not code:
message = f'The collection of the code did not work. Did the user already agree to the scopes' \
f' of your app? \n {response_text}'
raise SpotifyError(ErrorMessage(message=message).__dict__)
return code
async def get_auth_token_with_client_credentials(self) -> SpotifyAuthorisationToken:
"""
Get the auth token with the client credential flow
Notes:
[https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow)
Raises:
SpotifyError: If the request to the refresh api point was not successful
Returns:
A valid SpotifyAuthorisationToken
"""
if not isinstance(self.authorization_flow, ClientCredentialsFlow):
raise SpotifyError(ErrorMessage(
message="Your authorization flow cannot build an authorization url. "
"Select the ClientCredentialsFlow instead").__dict__)
body: dict = {
'grant_type': 'client_credentials',
}
return await self._get_token(body)
async def get_auth_token_with_code(self, code: str) -> SpotifyAuthorisationToken:
"""
Get the auth token with the code returned by the oauth process.
Args:
code: The code returned by spotify in the oauth process
Notes:
[https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow)
Raises:
SpotifyError: If the request to the refresh api point was not successful
Returns:
A valid SpotifyAuthorisationToken
"""
# TODO PKCEFlow
self._enforce_flows()
self.authorization_flow: Union[AuthorizationCodeFlow]
body: dict = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': self.authorization_flow.redirect_url
}
return await self._get_token(body)
async def _get_token(self, body) -> SpotifyAuthorisationToken:
"""
Get the token from the api
Args:
body: Request body
Returns: The new SpotifyAuthorisationToken
"""
response_json: dict = await self._make_auth_api_request(body)
refresh_token: str = response_json['refresh_token'] if 'refresh_token' in response_json else ''
access_token: str = response_json['access_token']
self._spotify_authorisation_token.activation_time = int(time.time())
self._spotify_authorisation_token.refresh_token = refresh_token
self._spotify_authorisation_token.access_token = access_token
return deepcopy(self._spotify_authorisation_token)
async def refresh_token(self, auth_token: SpotifyAuthorisationToken = None) -> SpotifyAuthorisationToken:
"""
Refresh the auth token with the refresh token or get a new auth token and refresh token with the code returned
by the spotify auth flow.
Args:
auth_token: The refresh token or the code returned by the spotify auth flow. Leave empty if you enabled
hold_authentication. Then the internal token will be used.
Notes:
[https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow)
Returns:
The SpotifyAuthorisationToken
"""
self._enforce_flows()
# Check if the internal auth token should be used
if not auth_token and self._hold_authentication:
auth_token = self._spotify_authorisation_token
body: dict = {
'grant_type': 'refresh_token',
'refresh_token': auth_token.refresh_token
}
response_json: dict = await self._make_auth_api_request(body)
refresh_token = auth_token.refresh_token
access_token = response_json['access_token']
# Keep the auth token in memory
self._spotify_authorisation_token.refresh_token = refresh_token
self._spotify_authorisation_token.activation_time = int(time.time())
self._spotify_authorisation_token.access_token = access_token
return deepcopy(self._spotify_authorisation_token)
async def _make_auth_api_request(self, body: dict) -> dict:
"""
Make an api request to the refresh endpoint
Args:
body: The body of the request
Returns:
The access token and the refresh token if the grant_type was code
"""
self.authorization_flow: Union[ClientCredentialsFlow, AuthorizationCodeFlow]
# Build the header of the request
base_64: base64 = base64.b64encode(
f'{self.authorization_flow.application_id}:{self.authorization_flow.application_secret}'.encode('ascii'))
header: dict = {'Authorization': f'Basic {base_64.decode("ascii")}'}
# Make the request to the api
async with ClientSession() as session:
async with session.post(url=URLS.REFRESH, data=body, headers=header) as response:
response_status = ResponseStatus(response.status)
response_text: str = await response.text()
await session.close()
# The response was not ok
if not response_status.success:
raise SpotifyError(ErrorMessage(message=response_text).__dict__)
return json.loads(response_text)
async def next(self, url: str, auth_token: SpotifyAuthorisationToken = None) -> dict:
"""
Get the next 'page' of the response
Args:
url: The next url
auth_token: The auth token if you set the api class not to keep the token in memory
Returns:
The api response
"""
return await self._api_request_handler.make_request('GET', url, {}, auth_token)
async def previous(self, url: str, auth_token: SpotifyAuthorisationToken = None) -> dict:
"""
Get the next 'previous' of the response
Args:
url: The previous url
auth_token: The auth token if you set the api class not to keep the token in memory
Returns:
The api response
"""
return await self._api_request_handler.make_request('GET', url, {}, auth_token)
def _enforce_flows(self):
"""
Make sure that the flows are ether the AuthorizationCodeFlow or the PKCEFlow
"""
# TODO PKCEFlow
if not isinstance(self.authorization_flow, AuthorizationCodeFlow):
raise SpotifyError(ErrorMessage(
message="Your authorization flow cannot build an authorization url. "
"Select the AuthorizationCodeFlow or the PKCEFlow instead").__dict__)
@property
def spotify_authorization_token(self) -> SpotifyAuthorisationToken:
"""
Returns:
The SpotifyAuthorisationToken of the api class
"""
if not self._hold_authentication:
raise SpotifyError(ErrorMessage(message='You have to enable hold_authentication').__dict__)
return self._spotify_authorisation_token
@spotify_authorization_token.setter
def spotify_authorization_token(self, spotify_authorization_token: SpotifyAuthorisationToken) -> None:
"""
Update the spotify auth token
Args:
spotify_authorization_token: The spotify auth token
"""
if not self._hold_authentication:
raise SpotifyError(ErrorMessage(message='You have to enable hold_authentication').__dict__)
self._spotify_authorisation_token.refresh_token = spotify_authorization_token.refresh_token
self._spotify_authorisation_token.access_token = spotify_authorization_token.access_token
self._spotify_authorisation_token.activation_time = spotify_authorization_token.activation_time
@property
def hold_authentication(self) -> bool:
"""
Returns:
The hold_authentication property of the spotify api client class
"""
return self._hold_authentication
@hold_authentication.setter
def hold_authentication(self, hold_authentication: bool) -> None:
"""
Set the hold_authentication param
Args:
hold_authentication: Should internal auth token be used for authentication
"""
self._hold_authentication = hold_authentication
if not hold_authentication:
self._spotify_authorisation_token.activation_time = None
self._spotify_authorisation_token.access_token = None
self._spotify_authorisation_token.refresh_token = None
@property
def token_renew_instance(self) -> TokenRenewClass:
"""
Returns the token renew class instance
Returns: The token renew class instance
"""
return self._token_renew_instance
@token_renew_instance.setter
def token_renew_instance(self, value: TokenRenewClass) -> None:
"""
Set the token renew instance
Args:
value: The new token renew instance
"""
self._token_renew_instance = value
self._api_request_handler.token_renew_instance = value
hold_authentication: bool
property
writable
¶
Returns:
Type | Description |
---|---|
bool |
The hold_authentication property of the spotify api client class |
spotify_authorization_token: SpotifyAuthorisationToken
property
writable
¶
Returns:
Type | Description |
---|---|
SpotifyAuthorisationToken |
The SpotifyAuthorisationToken of the api class |
token_renew_instance: TokenRenewClass
property
writable
¶
Returns the token renew class instance
Returns: The token renew class instance
__init__(self, authorization_flow, hold_authentication=False, spotify_authorisation_token=None, token_renew_instance=None)
special
¶
Create a new api class
Parameters:
Name | Type | Description | Default |
---|---|---|---|
authorization_flow |
AuthorizationFlow |
The auth_code_flow object fully filled with information |
required |
hold_authentication |
Should the api keep the authentication im memory and refresh it automatically |
False |
|
token_renew_instance |
TokenRenewClass |
An instance of a class which handles the renewing of the token if it should expire |
None |
Source code in async_spotify/api/spotify_api_client.py
def __init__(self, authorization_flow: AuthorizationFlow,
hold_authentication=False,
spotify_authorisation_token: SpotifyAuthorisationToken = None,
token_renew_instance: TokenRenewClass = None):
"""
Create a new api class
Args:
authorization_flow: The auth_code_flow object fully filled with information
hold_authentication: Should the api keep the authentication im memory and refresh it automatically
token_renew_instance: An instance of a class which handles the renewing of the token if it should expire
"""
# Check if the auth_code_flow are valid
if not authorization_flow.valid:
raise SpotifyError(ErrorMessage(message="The auth flow instance of your app is not correct").__dict__)
self.authorization_flow: AuthorizationFlow = authorization_flow
# Set the SpotifyAuthorisationToken
if spotify_authorisation_token:
self._spotify_authorisation_token: SpotifyAuthorisationToken = spotify_authorisation_token
else:
self._spotify_authorisation_token: SpotifyAuthorisationToken = SpotifyAuthorisationToken()
self._token_renew_instance: TokenRenewClass = token_renew_instance
self._hold_authentication: bool = hold_authentication
self._api_request_handler: ApiRequestHandler = ApiRequestHandler(self._spotify_authorisation_token,
token_renew_instance, self)
################################################################################################################
self.albums: Albums = Albums(self._api_request_handler)
""" An instance of the [`Albums`][async_spotify.api._endpoints.albums] class. Use this to access the
Albums api """
self.artists: Artists = Artists(self._api_request_handler)
""" An instance of the [`Artists`][async_spotify.api._endpoints.artists] class. Use this to access the
Artists api """
self.browse: Browse = Browse(self._api_request_handler)
""" An instance of the [`Browse`][async_spotify.api._endpoints.browse] class. Use this to Browse the
Browse api """
self.episodes: Episodes = Episodes(self._api_request_handler)
""" An instance of the [`Episodes`][async_spotify.api._endpoints.episodes] class. Use this to access the
Episodes api """
self.follow: Follow = Follow(self._api_request_handler)
""" An instance of the [`Follow`][async_spotify.api._endpoints.follow] class. Use this to access the
Follow api """
self.library: Library = Library(self._api_request_handler)
""" An instance of the [`Library`][async_spotify.api._endpoints.library] class. Use this to access the
Library api """
self.personalization: Personalization = Personalization(self._api_request_handler)
""" An instance of the [`Personalization`][async_spotify.api._endpoints.personalization] class. Use this to
access the Personalization api """
self.player: Player = Player(self._api_request_handler)
""" An instance of the [`Player`][async_spotify.api._endpoints.player] class. Use this to access the
Player api """
self.playlists: Playlists = Playlists(self._api_request_handler)
""" An instance of the [`Playlists`][async_spotify.api._endpoints.playlists] class. Use this to access the
Playlist api """
self.search: Search = Search(self._api_request_handler)
""" An instance of the [`Search`][async_spotify.api._endpoints.search] class. Use this to access the
Search api """
self.shows: Shows = Shows(self._api_request_handler)
""" An instance of the [`Shows`][async_spotify.api._endpoints.shows] class. Use this to access the
Show api """
self.track: Track = Track(self._api_request_handler)
""" An instance of the [`Track`][async_spotify.api._endpoints.tracks] class. Use this to access the
Track api """
self.user: User = User(self._api_request_handler)
""" An instance of the [`User`][async_spotify.api._endpoints.user] class. Use this to access the
User api """
build_authorization_url(self, show_dialog=True, state=None)
¶
Builds the URL for the authorisation
Parameters:
Name | Type | Description | Default |
---|---|---|---|
state |
str |
State of the authorization |
None |
show_dialog |
bool |
Should the spotify auth dialog be shown |
True |
Returns:
Type | Description |
---|---|
str |
The encoded url which can be used to authorize a new or existing user |
Source code in async_spotify/api/spotify_api_client.py
def build_authorization_url(self, show_dialog: bool = True, state: str = None) -> str:
"""
Builds the URL for the authorisation
Args:
state: State of the authorization
show_dialog: Should the spotify auth dialog be shown
Returns:
The encoded url which can be used to authorize a new or existing user
"""
self._enforce_flows()
# TODO PKCEFlow
self.authorization_flow: Union[AuthorizationCodeFlow]
params = {
"client_id": self.authorization_flow.application_id,
"response_type": "code",
"scope": ' '.join(self.authorization_flow.scopes),
"show_dialog": f"{show_dialog}",
"redirect_uri": f"{self.authorization_flow.redirect_url}"
}
# Check if a state is required
if state:
params["state"] = f"{state}"
return f"{URLS.AUTHORIZE}?{urlencode(params)}"
close_client(self)
async
¶
Close the current client session. You have to create a new one to connect again to spotify. This method should always be called before you end your program
Source code in async_spotify/api/spotify_api_client.py
async def close_client(self) -> None:
"""
Close the current client session. You have to create a new one to connect again to spotify.
This method should always be called before you end your program
"""
await self._api_request_handler.close_client()
create_new_client(self, request_timeout=30, request_limit=500)
async
¶
Create a new session which will be used to connect to the spotify api. In general this only has to be called once after you create a new API object. You can however call this method if you want ot update the client settings (more requests, ...) This will however close all ongoing requests.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
request_timeout |
int |
How long should be waited for a request (default 30s) (None for no limit) |
30 |
request_limit |
int |
How many requests should be allowed (default 500) |
500 |
Source code in async_spotify/api/spotify_api_client.py
async def create_new_client(self, request_timeout: int = 30, request_limit: int = 500) -> None:
"""
Create a new session which will be used to connect to the spotify api.
In general this only has to be called once after you create a new API object.
You can however call this method if you want ot update the client settings (more requests, ...)
This will however close all ongoing requests.
Args:
request_timeout: How long should be waited for a request (default 30s) (None for no limit)
request_limit: How many requests should be allowed (default 500)
"""
await self._api_request_handler.create_new_client(request_timeout, request_limit)
get_auth_token_with_client_credentials(self)
async
¶
Get the auth token with the client credential flow
Exceptions:
Type | Description |
---|---|
SpotifyError |
If the request to the refresh api point was not successful |
Returns:
Type | Description |
---|---|
SpotifyAuthorisationToken |
A valid SpotifyAuthorisationToken |
Source code in async_spotify/api/spotify_api_client.py
async def get_auth_token_with_client_credentials(self) -> SpotifyAuthorisationToken:
"""
Get the auth token with the client credential flow
Notes:
[https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow)
Raises:
SpotifyError: If the request to the refresh api point was not successful
Returns:
A valid SpotifyAuthorisationToken
"""
if not isinstance(self.authorization_flow, ClientCredentialsFlow):
raise SpotifyError(ErrorMessage(
message="Your authorization flow cannot build an authorization url. "
"Select the ClientCredentialsFlow instead").__dict__)
body: dict = {
'grant_type': 'client_credentials',
}
return await self._get_token(body)
get_auth_token_with_code(self, code)
async
¶
Get the auth token with the code returned by the oauth process.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
code |
str |
The code returned by spotify in the oauth process |
required |
Exceptions:
Type | Description |
---|---|
SpotifyError |
If the request to the refresh api point was not successful |
Returns:
Type | Description |
---|---|
SpotifyAuthorisationToken |
A valid SpotifyAuthorisationToken |
Source code in async_spotify/api/spotify_api_client.py
async def get_auth_token_with_code(self, code: str) -> SpotifyAuthorisationToken:
"""
Get the auth token with the code returned by the oauth process.
Args:
code: The code returned by spotify in the oauth process
Notes:
[https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow)
Raises:
SpotifyError: If the request to the refresh api point was not successful
Returns:
A valid SpotifyAuthorisationToken
"""
# TODO PKCEFlow
self._enforce_flows()
self.authorization_flow: Union[AuthorizationCodeFlow]
body: dict = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': self.authorization_flow.redirect_url
}
return await self._get_token(body)
get_code_with_cookie(self, cookies)
async
¶
This function takes care of the user interaction that is normally required to get the code from spotify which is necessary to request the refresh_token and the oauth_token. The token which is returned by this function has to be passed to API.get_auth_token_with_code(code) to get the refresh_token and the oauth_token. The big advantage is that you don't have to run a callback server to get the code
Notes
This will only work if the user has at least once accepted the scopes your app is requesting. I would recommend that you take a look at the source code of this function before you use it and that you are familiar with the authorization mechanism of spotify.
Important
This method is intended for automated testing. You have to decide if you want to use it in you production environment.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cookies |
SpotifyCookie |
The cookies of the spotify account. Every property of the class has to be filled in. |
required |
Exceptions:
Type | Description |
---|---|
SpotifyError |
If the cookie is not valid |
SpotifyError |
If there is a redirect between you and spotify |
SpotifyError |
If there is an unknown error |
Returns:
Type | Description |
---|---|
str |
The spotify code which can be used to get a refresh_token and a oauth_token |
Source code in async_spotify/api/spotify_api_client.py
async def get_code_with_cookie(self, cookies: SpotifyCookie) -> str:
"""
This function takes care of the user interaction that is normally required to get the code from spotify
which is necessary to request the refresh_token and the oauth_token.
The token which is returned by this function has to be passed to API.get_auth_token_with_code(code)
to get the refresh_token and the oauth_token.
The big advantage is that you don't have to run a callback server to get the code
Notes:
This will only work if the user has at least once accepted the scopes your app is requesting.
I would recommend that you take a look at the source code of this function before you use it and that you
are familiar with the authorization mechanism of spotify.
Important:
This method is intended for automated testing. You have to decide if you want to use it in you production
environment.
Args:
cookies: The cookies of the spotify account. Every property of the class has to be filled in.
Raises:
SpotifyError: If the cookie is not valid
SpotifyError: If there is a redirect between you and spotify
SpotifyError: If there is an unknown error
Returns:
The spotify code which can be used to get a refresh_token and a oauth_token
"""
# Build the auth url
url = self.build_authorization_url(show_dialog=False)
# Check if the cookie file is valid
if not cookies.valid:
raise SpotifyError(ErrorMessage(message='The cookies are not complete').__dict__)
# Convert the class to a dict
cookie_dict: dict = cookies.__dict__
return await self._track_request_without_callback(cookie_dict, url)
next(self, url, auth_token=None)
async
¶
Get the next 'page' of the response
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url |
str |
The next url |
required |
auth_token |
SpotifyAuthorisationToken |
The auth token if you set the api class not to keep the token in memory |
None |
Returns:
Type | Description |
---|---|
dict |
The api response |
Source code in async_spotify/api/spotify_api_client.py
async def next(self, url: str, auth_token: SpotifyAuthorisationToken = None) -> dict:
"""
Get the next 'page' of the response
Args:
url: The next url
auth_token: The auth token if you set the api class not to keep the token in memory
Returns:
The api response
"""
return await self._api_request_handler.make_request('GET', url, {}, auth_token)
open_oauth_dialog_in_browser(self, show_dialogue=True)
¶
Open the url in browser Only for testing purposes or the usage of this library in a desktop app
Parameters:
Name | Type | Description | Default |
---|---|---|---|
show_dialogue |
bool |
Should the spotify auth dialog be shown |
True |
Source code in async_spotify/api/spotify_api_client.py
def open_oauth_dialog_in_browser(self, show_dialogue: bool = True) -> None:
"""
Open the url in browser
Only for testing purposes or the usage of this library in a desktop app
Args:
show_dialogue: Should the spotify auth dialog be shown
"""
# Open url in a new window of the default browser, if possible
webbrowser.open_new(self.build_authorization_url(show_dialogue))
previous(self, url, auth_token=None)
async
¶
Get the next 'previous' of the response
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url |
str |
The previous url |
required |
auth_token |
SpotifyAuthorisationToken |
The auth token if you set the api class not to keep the token in memory |
None |
Returns:
Type | Description |
---|---|
dict |
The api response |
Source code in async_spotify/api/spotify_api_client.py
async def previous(self, url: str, auth_token: SpotifyAuthorisationToken = None) -> dict:
"""
Get the next 'previous' of the response
Args:
url: The previous url
auth_token: The auth token if you set the api class not to keep the token in memory
Returns:
The api response
"""
return await self._api_request_handler.make_request('GET', url, {}, auth_token)
refresh_token(self, auth_token=None)
async
¶
Refresh the auth token with the refresh token or get a new auth token and refresh token with the code returned by the spotify auth flow.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
auth_token |
SpotifyAuthorisationToken |
The refresh token or the code returned by the spotify auth flow. Leave empty if you enabled hold_authentication. Then the internal token will be used. |
None |
Returns:
Type | Description |
---|---|
SpotifyAuthorisationToken |
The SpotifyAuthorisationToken |
Source code in async_spotify/api/spotify_api_client.py
async def refresh_token(self, auth_token: SpotifyAuthorisationToken = None) -> SpotifyAuthorisationToken:
"""
Refresh the auth token with the refresh token or get a new auth token and refresh token with the code returned
by the spotify auth flow.
Args:
auth_token: The refresh token or the code returned by the spotify auth flow. Leave empty if you enabled
hold_authentication. Then the internal token will be used.
Notes:
[https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow)
Returns:
The SpotifyAuthorisationToken
"""
self._enforce_flows()
# Check if the internal auth token should be used
if not auth_token and self._hold_authentication:
auth_token = self._spotify_authorisation_token
body: dict = {
'grant_type': 'refresh_token',
'refresh_token': auth_token.refresh_token
}
response_json: dict = await self._make_auth_api_request(body)
refresh_token = auth_token.refresh_token
access_token = response_json['access_token']
# Keep the auth token in memory
self._spotify_authorisation_token.refresh_token = refresh_token
self._spotify_authorisation_token.activation_time = int(time.time())
self._spotify_authorisation_token.access_token = access_token
return deepcopy(self._spotify_authorisation_token)