Implement rate limiting #366

This commit is contained in:
Nathan Thomas 2023-06-20 21:04:57 -07:00
parent ef34756046
commit 31056e8250
3 changed files with 31 additions and 15 deletions

View file

@ -185,20 +185,27 @@ class Config:
:param source: :param source:
:type source: str :type source: str
""" """
creds = None
if source == "qobuz": if source == "qobuz":
return self.qobuz_creds creds = self.qobuz_creds
if source == "tidal": if source == "tidal":
return self.tidal_creds creds = self.tidal_creds
if source == "deezer": if source == "deezer":
return {"arl": self.file["deezer"]["arl"]} creds = {"arl": self.file["deezer"]["arl"]}
if source == "soundcloud": if source == "soundcloud":
soundcloud = self.file["soundcloud"] soundcloud = self.file["soundcloud"]
return { creds = {
"client_id": soundcloud["client_id"], "client_id": soundcloud["client_id"],
"app_version": soundcloud["app_version"], "app_version": soundcloud["app_version"],
} }
raise InvalidSourceError(source) if creds is None:
raise InvalidSourceError(source)
rpm = self.file["downloads"]["concurrency"]["requests_per_minute"]
if rpm > 0:
creds.update({"requests_per_min": rpm})
return creds
def __repr__(self) -> str: def __repr__(self) -> str:
"""Return a string representation of the config.""" """Return a string representation of the config."""

View file

@ -13,6 +13,9 @@ enabled = true
# If you have very fast internet, you will benefit from a higher value, # If you have very fast internet, you will benefit from a higher value,
# A value that is too high for your bandwidth may cause slowdowns # A value that is too high for your bandwidth may cause slowdowns
max_connections = 3 max_connections = 3
# Max number of API requests to handle per minute
# Set to -1 for no limit
requests_per_minute = -1
[qobuz] [qobuz]
# 1: 320kbps MP3, 2: 16/44.1, 3: 24/<=96, 4: 24/>=96 # 1: 320kbps MP3, 2: 16/44.1, 3: 24/<=96, 4: 24/>=96
@ -174,4 +177,4 @@ progress_bar = "dainty"
[misc] [misc]
# Metadata to identify this config file. Do not change. # Metadata to identify this config file. Do not change.
version = "1.9.6" version = "1.9.8"

View file

@ -128,14 +128,16 @@ class QobuzClient(Client):
return return
if not kwargs.get("app_id") or not kwargs.get("secrets"): if not kwargs.get("app_id") or not kwargs.get("secrets"):
self._get_app_id_and_secrets() # can be async # sets session
self._get_app_id_and_secrets(kwargs.get("requests_per_min")) # can be async
else: else:
self.app_id, self.secrets = ( self.app_id, self.secrets = (
str(kwargs["app_id"]), str(kwargs["app_id"]),
kwargs["secrets"], kwargs["secrets"],
) )
self.session = SRSession( self.session = SRSession(
headers={"User-Agent": AGENT, "X-App-Id": self.app_id} headers={"User-Agent": AGENT, "X-App-Id": self.app_id},
requests_per_min=kwargs.get("requests_per_min"),
) )
self._validate_secrets() self._validate_secrets()
@ -213,7 +215,7 @@ class QobuzClient(Client):
# ---------- Private Methods --------------- # ---------- Private Methods ---------------
def _get_app_id_and_secrets(self): def _get_app_id_and_secrets(self, rpm):
if not hasattr(self, "app_id") or not hasattr(self, "secrets"): if not hasattr(self, "app_id") or not hasattr(self, "secrets"):
spoofer = Spoofer() spoofer = Spoofer()
self.app_id, self.secrets = ( self.app_id, self.secrets = (
@ -224,7 +226,8 @@ class QobuzClient(Client):
if not hasattr(self, "sec"): if not hasattr(self, "sec"):
if not hasattr(self, "session"): if not hasattr(self, "session"):
self.session = SRSession( self.session = SRSession(
headers={"User-Agent": AGENT, "X-App-Id": self.app_id} headers={"User-Agent": AGENT, "X-App-Id": self.app_id},
requests_per_min=rpm,
) )
self._validate_secrets() self._validate_secrets()
@ -736,8 +739,6 @@ class TidalClient(Client):
self.refresh_token = None self.refresh_token = None
self.expiry = None self.expiry = None
self.session = SRSession()
def login( def login(
self, self,
user_id=None, user_id=None,
@ -745,6 +746,7 @@ class TidalClient(Client):
access_token=None, access_token=None,
token_expiry=None, token_expiry=None,
refresh_token=None, refresh_token=None,
**kwargs,
): ):
"""Login to Tidal using the browser. """Login to Tidal using the browser.
@ -757,6 +759,9 @@ class TidalClient(Client):
:param token_expiry: :param token_expiry:
:param refresh_token: :param refresh_token:
""" """
self.session = SRSession(
requests_per_min=kwargs.get("requests_per_min"),
)
if access_token: if access_token:
self.token_expiry = float(token_expiry) self.token_expiry = float(token_expiry)
self.refresh_token = refresh_token self.refresh_token = refresh_token
@ -1110,13 +1115,14 @@ class SoundCloudClient(Client):
def __init__(self): def __init__(self):
"""Create a SoundCloudClient.""" """Create a SoundCloudClient."""
def login(self, **kwargs):
self.session = SRSession( self.session = SRSession(
headers={ headers={
"User-Agent": AGENT, "User-Agent": AGENT,
} },
requests_per_min=kwargs.get("requests_per_min"),
) )
def login(self, **kwargs):
self.client_id = kwargs.get("client_id") self.client_id = kwargs.get("client_id")
self.app_version = kwargs.get("app_version") self.app_version = kwargs.get("app_version")
logger.debug("client_id: %s, app_version: %s", self.client_id, self.app_version) logger.debug("client_id: %s, app_version: %s", self.client_id, self.app_version)