diff options
| author | 2021-03-09 20:47:07 +0100 | |
|---|---|---|
| committer | 2021-03-13 12:39:41 +0100 | |
| commit | ff8193ed19c2c5e5106fa2afee264f5ea700275f (patch) | |
| tree | 7260d5f99f421d1429c15024b13d666dcaf704d0 | |
| parent | Branding: migrate constants (diff) | |
Branding: add HTTP fetch helper methods
| -rw-r--r-- | bot/exts/backend/branding/_repository.py | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/bot/exts/backend/branding/_repository.py b/bot/exts/backend/branding/_repository.py index 3bdb632f8..bf38fccad 100644 --- a/bot/exts/backend/branding/_repository.py +++ b/bot/exts/backend/branding/_repository.py @@ -1,4 +1,5 @@ import logging +import typing as t from bot.bot import Bot from bot.constants import Keys @@ -16,8 +17,61 @@ if Keys.github: log = logging.getLogger(__name__) +class RemoteObject: + """ + Represent a remote file or directory on GitHub. + + The annotations match keys in the response JSON that we're interested in. + """ + + name: str # Filename + path: str # Path from repo root + type: str # Either 'file' or 'dir' + download_url: str + + def __init__(self, dictionary: t.Dict[str, t.Any]) -> None: + """Initialize by grabbing annotated attributes from `dictionary`.""" + for annotation in self.__annotations__: + setattr(self, annotation, dictionary[annotation]) + + class BrandingRepository: """Abstraction exposing the branding repository via convenient methods.""" def __init__(self, bot: Bot) -> None: self.bot = bot + + async def fetch_directory(self, path: str, types: t.Container[str] = ("file", "dir")) -> t.Dict[str, RemoteObject]: + """ + Fetch directory found at `path` in the branding repository. + + The directory will be represented by a mapping from file or sub-directory names to their corresponding + instances of `RemoteObject`. Passing a custom `types` value allows only getting files or directories. + + If the request fails, returns an empty dictionary. + """ + full_url = f"{BRANDING_URL}/{path}" + log.debug(f"Fetching directory from branding repository: {full_url}") + + async with self.bot.http_session.get(full_url, params=PARAMS, headers=HEADERS) as response: + if response.status == 200: + json_directory = await response.json() + else: + log.warning(f"Received non-200 response status: {response.status}") + return {} + + return {file["name"]: RemoteObject(file) for file in json_directory if file["type"] in types} + + async def fetch_file(self, file: RemoteObject) -> t.Optional[bytes]: + """ + Fetch `file` using its download URL. + + Returns the file as bytes unless the request fails, in which case None is given. + """ + log.debug(f"Fetching file from branding repository: {file.download_url}") + + async with self.bot.http_session.get(file.download_url, params=PARAMS, headers=HEADERS) as response: + if response.status == 200: + return await response.read() + else: + log.warning(f"Received non-200 response status: {response.status}") |