Skip to content
42 changes: 26 additions & 16 deletions interactions/api/http/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,20 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]:
async with self._session.request(
route.method, route.__api__ + route.path, **kwargs
) as response:
if response.content_type == "application/json":
data = await response.json()
if isinstance(data, dict):
message: Optional[str] = data.get("message")
code: int = data.get("code", response.status)
else:
message, code = None, response.status
else:
data, message, code = None, None, response.status

data = await response.json(content_type=None)
reset_after: float = float(
response.headers.get("X-RateLimit-Reset-After", "0.0")
response.headers.get(
"X-RateLimit-Reset-After", response.headers.get("Retry-After", "0.0")
)
)
remaining: str = response.headers.get("X-RateLimit-Remaining")
_bucket: str = response.headers.get("X-RateLimit-Bucket")
Expand All @@ -161,40 +171,40 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]:
self.buckets[route.endpoint] = _bucket
# real-time replacement/update/add if needed.
if isinstance(data, dict) and (
data.get("errors")
or ((code := data.get("code")) and code != 429 and data.get("message"))
data.get("errors") or (code and code != 429 and message)
):
log.debug(
f"RETURN {response.status}: {dumps(data, indent=4, sort_keys=True)}"
)
# This "redundant" debug line is for debug use and tracing back the error codes.

raise LibraryException(
message=data["message"], code=data["code"], severity=40, data=data
)
elif isinstance(data, dict) and data.get("code") == 0 and data.get("message"):
raise LibraryException(message=message, code=code, severity=40, data=data)
elif isinstance(data, dict) and code == 0 and message:
log.debug(
f"RETURN {response.status}: {dumps(data, indent=4, sort_keys=True)}"
)
# This "redundant" debug line is for debug use and tracing back the error codes.

raise LibraryException(
message=f"'{data['message']}'. Make sure that your token is set properly.",
message=f"'{message}'. Make sure that your token is set properly.",
severity=50,
)
if response.status == 429:
if code == 429:
hours = int(reset_after // 3600)
minutes = int((reset_after % 3600) // 60)
seconds = int(reset_after % 60)
log.warning(
f"(429) {LibraryException.lookup(429)} Locking down future requests for "
+ f"{f'{hours} hours ' if hours else ''}"
+ f"{f'{minutes} minutes ' if minutes else ''}"
+ f"{f'{seconds} seconds ' if seconds else ''}"
)
if is_global:
log.warning(
f"The HTTP client has encountered a global ratelimit. Locking down future requests for {reset_after} seconds."
)
self._global_lock.reset_after = reset_after
self._loop.call_later(
self._global_lock.reset_after, self._global_lock.lock.release
)
else:
log.warning(
f"The HTTP client has encountered a per-route ratelimit. Locking down future requests for {reset_after} seconds."
)
_limiter.reset_after = reset_after
await asyncio.sleep(_limiter.reset_after)
continue
Expand Down