librespot-python/librespot/core/TokenProvider.py

89 lines
2.7 KiB
Python
Raw Normal View History

2021-02-24 00:46:59 +01:00
from __future__ import annotations
2021-05-22 03:26:35 +02:00
2021-02-24 00:46:59 +01:00
import logging
2021-04-24 12:17:02 +02:00
import typing
2021-02-24 00:46:59 +01:00
2021-05-22 03:26:41 +02:00
from librespot.core import Session
from librespot.core import TimeProvider
2021-05-22 03:26:35 +02:00
from librespot.mercury import MercuryRequests
2021-02-24 00:46:59 +01:00
class TokenProvider:
_LOGGER: logging = logging.getLogger(__name__)
_TOKEN_EXPIRE_THRESHOLD = 10
_session: Session = None
2021-04-24 12:17:02 +02:00
_tokens: typing.List[TokenProvider.StoredToken] = []
2021-02-24 00:46:59 +01:00
def __init__(self, session: Session):
self._session = session
def find_token_with_all_scopes(
2021-05-22 03:27:30 +02:00
self, scopes: typing.List[str]) -> TokenProvider.StoredToken:
2021-02-24 00:46:59 +01:00
for token in self._tokens:
if token.has_scopes(scopes):
return token
# noinspection PyTypeChecker
return None
def get_token(self, *scopes) -> TokenProvider.StoredToken:
scopes = list(scopes)
if len(scopes) == 0:
raise RuntimeError()
token = self.find_token_with_all_scopes(scopes)
if token is not None:
if token.expired():
self._tokens.remove(token)
else:
return token
self._LOGGER.debug(
2021-05-22 03:27:30 +02:00
"Token expired or not suitable, requesting again. scopes: {}, old_token: {}"
.format(scopes, token))
2021-02-24 00:46:59 +01:00
resp = self._session.mercury().send_sync_json(
2021-05-22 03:27:30 +02:00
MercuryRequests.request_token(self._session.device_id(),
",".join(scopes)))
2021-02-24 00:46:59 +01:00
token = TokenProvider.StoredToken(resp)
self._LOGGER.debug(
"Updated token successfully! scopes: {}, new_token: {}".format(
2021-05-22 03:27:30 +02:00
scopes, token))
2021-02-24 00:46:59 +01:00
self._tokens.append(token)
return token
def get(self, scope: str) -> str:
return self.get_token(scope).access_token
class StoredToken:
expires_in: int
access_token: str
2021-04-24 12:17:02 +02:00
scopes: typing.List[str]
2021-02-24 00:46:59 +01:00
timestamp: int
def __init__(self, obj):
self.timestamp = TimeProvider.TimeProvider().current_time_millis()
self.expires_in = obj["expiresIn"]
self.access_token = obj["accessToken"]
self.scopes = obj["scope"]
def expired(self) -> bool:
2021-05-22 03:27:30 +02:00
return (self.timestamp +
(self.expires_in - TokenProvider._TOKEN_EXPIRE_THRESHOLD) *
1000 < TimeProvider.TimeProvider().current_time_millis())
2021-02-24 00:46:59 +01:00
def has_scope(self, scope: str) -> bool:
for s in self.scopes:
if s == scope:
return True
return False
2021-04-24 12:17:02 +02:00
def has_scopes(self, sc: typing.List[str]) -> bool:
2021-02-24 00:46:59 +01:00
for s in sc:
if not self.has_scope(s):
return False
return True