diff options
-rw-r--r-- | backend/discord.py | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/backend/discord.py b/backend/discord.py index e5c7f8f..08b8e07 100644 --- a/backend/discord.py +++ b/backend/discord.py @@ -1,16 +1,54 @@ """Various utilities for working with the Discord API.""" +import asyncio +import typing +from urllib import parse + import httpx +from starlette.requests import Request + +from backend import constants +from backend.authentication.user import User +from backend.models import Form, FormResponse + +API_BASE_URL = "https://discord.com/api/v8/" +DISCORD_HEADERS = { + "Authorization": f"Bot {constants.DISCORD_BOT_TOKEN}" +} + + +async def make_request( + method: str, + url: str, + json: dict[str, any] = None, + headers: dict[str, str] = None +) -> httpx.Response: + """Make a request to the discord API.""" + url = parse.urljoin(API_BASE_URL, url) + _headers = DISCORD_HEADERS.copy() + _headers.update(headers if headers else {}) + + async with httpx.AsyncClient() as client: + if json is not None: + request = client.request(method, url, json=json, headers=_headers) + else: + request = client.request(method, url, headers=_headers) + resp = await request + + # Handle Rate Limits + while resp.status_code == 429: + retry_after = float(resp.headers["X-Ratelimit-Reset-After"]) + await asyncio.sleep(retry_after) + resp = await request -from backend.constants import ( - DISCORD_API_BASE_URL, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET -) + resp.raise_for_status() + return resp async def fetch_bearer_token(code: str, redirect: str, *, refresh: bool) -> dict: async with httpx.AsyncClient() as client: data = { - "client_id": OAUTH2_CLIENT_ID, - "client_secret": OAUTH2_CLIENT_SECRET, + "client_id": constants.OAUTH2_CLIENT_ID, + "client_secret": constants.OAUTH2_CLIENT_SECRET, "redirect_uri": f"{redirect}/callback" } @@ -21,7 +59,7 @@ async def fetch_bearer_token(code: str, redirect: str, *, refresh: bool) -> dict data["grant_type"] = "authorization_code" data["code"] = code - r = await client.post(f"{DISCORD_API_BASE_URL}/oauth2/token", headers={ + r = await client.post(f"{API_BASE_URL}/oauth2/token", headers={ "Content-Type": "application/x-www-form-urlencoded" }, data=data) @@ -31,11 +69,6 @@ async def fetch_bearer_token(code: str, redirect: str, *, refresh: bool) -> dict async def fetch_user_details(bearer_token: str) -> dict: - async with httpx.AsyncClient() as client: - r = await client.get(f"{DISCORD_API_BASE_URL}/users/@me", headers={ - "Authorization": f"Bearer {bearer_token}" - }) - - r.raise_for_status() - - return r.json() + r = await make_request("GET", "users/@me", headers={"Authorization": f"Bearer {bearer_token}"}) + r.raise_for_status() + return r.json() |