aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Hassan Abouelela <[email protected]>2021-03-16 16:08:42 +0300
committerGravatar Hassan Abouelela <[email protected]>2021-03-16 16:08:42 +0300
commit270bdbc71b6eb52897c654ee7c762dcd9efd9a5e (patch)
tree790cbfd1fb490840d6a4c1cbf2dd663c8b7c0ba4
parentMerge pull request #49 from python-discord/ks123/role-assigning (diff)
Adds Discord Request Helper
Adds a function to handle requests to the discord API, and handle rate limits. Signed-off-by: Hassan Abouelela <[email protected]>
-rw-r--r--backend/discord.py61
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()