From 43ef3e7490e262c0bab25aa23bb6c1ee462fd4e9 Mon Sep 17 00:00:00 2001 From: Roy <88516395+moraroy@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:27:58 -0800 Subject: [PATCH] Add files via upload --- Modules/steamgrid/__init__.py | 24 + Modules/steamgrid/asset.py | 220 +++++++++ Modules/steamgrid/author.py | 93 ++++ Modules/steamgrid/enums.py | 75 +++ Modules/steamgrid/game.py | 103 +++++ Modules/steamgrid/http.py | 158 +++++++ Modules/steamgrid/steamgrid.py | 802 +++++++++++++++++++++++++++++++++ 7 files changed, 1475 insertions(+) create mode 100644 Modules/steamgrid/asset.py create mode 100644 Modules/steamgrid/author.py create mode 100644 Modules/steamgrid/enums.py create mode 100644 Modules/steamgrid/game.py create mode 100644 Modules/steamgrid/http.py create mode 100644 Modules/steamgrid/steamgrid.py diff --git a/Modules/steamgrid/__init__.py b/Modules/steamgrid/__init__.py index 8b13789..a3634dd 100644 --- a/Modules/steamgrid/__init__.py +++ b/Modules/steamgrid/__init__.py @@ -1 +1,25 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" +from .steamgrid import * +from .enums import * +from .asset import * +from .game import * +from .author import * \ No newline at end of file diff --git a/Modules/steamgrid/asset.py b/Modules/steamgrid/asset.py new file mode 100644 index 0000000..1dc3996 --- /dev/null +++ b/Modules/steamgrid/asset.py @@ -0,0 +1,220 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from typing import Tuple, Iterator, Any + +from .http import HTTPClient +from .author import Author +from .enums import AssetType + +__all__ = ( + 'Grid', + 'Hero', + 'Logo', + 'Icon', +) + +class Asset: + """Base class for all assets. + + Depending on the way this object was created, some of the attributes can + have a value of ``None``. + + .. container:: operations + .. describe:: x == y + Checks if two asset are the same. + .. describe:: x != y + Checks if two asset are not the same. + .. describe:: iter(x) + Returns an iterator of ``(field, value)`` pairs. This allows this class + to be used as an iterable in list/dict/etc constructions. + .. describe:: str(x) + Returns a string representation of the asset. + + + Attributes + ----------- + id: :class:`str` + The asset's ID. + author: :class:`Author` + The author of the asset. + score: :class:`int` + The asset's score. + width: :class:`int` + The asset's width. + height: :class:`int` + The asset's width. + style: :class:`str` + The style of the asset. + notes: Optional[:class:`str`] + Notes about the asset. + mime: :class:`str` + The MIME type of the asset. + language: :class:`str` + The language of the asset. + url: :class:`str` + The URL of the asset. + thumbnail: :class:`str` + The URL of the asset's thumbnail. + type: :class:`AssetType` + The type of the asset. + """ + + __slots__: Tuple[str, ...] = ( + '_payload', + '_http', + 'id', + 'score', + 'width', + 'height', + 'style', + '_nsfw', + '_humor', + 'notes', + 'mime', + 'language', + 'url', + 'thumbnail', + '_lock', + '_epilepsy', + 'type', + 'author' + ) + + def __init__(self, payload: dict, type: AssetType, http: HTTPClient) -> None: + self._payload = payload + self._http = http + self._from_data(payload) + self.type = type + + def _from_data(self, asset: dict): + self.id = asset.get('id') + self.author: Author = Author(asset['author']) + self.score = asset.get('score') + self.width = asset.get('width') + self.height = asset.get('height') + self.style = asset.get('style') + self._nsfw = asset.get('nsfw') + self._humor = asset.get('humor') + self.notes = asset.get('notes', None) + self.mime = asset.get('mime') + self.language = asset.get('language') + self.url = asset.get('url') + self.thumbnail = asset.get('thumb') + self._lock = asset.get('lock') + self._epilepsy = asset.get('epilepsy') + self.upvotes = asset.get('upvotes') + self.downvotes = asset.get('downvotes') + + def __str__(self) -> str: + return self.url + + def __eq__(self, other) -> bool: + return self.id == other.id + + def __ne__(self, other) -> bool: + return self.id != other.id + + def __iter__(self) -> Iterator[Tuple[str, Any]]: + for attr in self.__slots__: + if attr[0] != '_': + value = getattr(self, attr, None) + if value is not None: + yield (attr, value) + + def to_json(self) -> dict: + return self._payload + + def is_lock(self) -> bool: + """:class:`bool`: Returns whether the asset is locked.""" + return self.lock + + def is_humor(self) -> bool: + """:class:`bool`: Returns whether the asset is a humor asset.""" + return self.humor + + def is_nsfw(self) -> bool: + """:class:`bool`: Returns whether the asset is NSFW.""" + return self.nsfw + + def is_epilepsy(self) -> bool: + """:class:`bool`: Returns whether the asset is epilepsy-inducing.""" + return self.is_epilepsy + + +class Grid(Asset): + def __init__(self, payload: dict, http: HTTPClient) -> None: + super().__init__( + payload, + AssetType.Grid, + http + ) + + def __repr__(self) -> str: + return f'' + + def delete(self) -> None: + """Delete the grid.""" + self._http.delete_grid([self.id]) + +class Hero(Asset): + def __init__(self, payload: dict, http: HTTPClient) -> None: + super().__init__( + payload, + AssetType.Hero, + http + ) + + def __repr__(self) -> str: + return f'' + + def delete(self) -> None: + """Delete the hero.""" + self._http.delete_hero([self.id]) + +class Logo(Asset): + def __init__(self, payload: dict, http: HTTPClient) -> None: + super().__init__( + payload, + AssetType.Logo, + http + ) + + def __repr__(self) -> str: + return f'' + + def delete(self) -> None: + """Delete the logo.""" + self._http.delete_logo([self.id]) + +class Icon(Asset): + def __init__(self, payload: dict, http: HTTPClient) -> None: + super().__init__( + payload, + AssetType.Icon, + http + ) + + def __repr__(self) -> str: + return f'' + + def delete(self) -> None: + """Delete the icon.""" + self._http.delete_icon([self.id]) \ No newline at end of file diff --git a/Modules/steamgrid/author.py b/Modules/steamgrid/author.py new file mode 100644 index 0000000..310a18a --- /dev/null +++ b/Modules/steamgrid/author.py @@ -0,0 +1,93 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from typing import Iterator, Tuple, Any + +__all__ = ( + 'Author', +) + +class Author: + """Represents a custom author. + + Depending on the way this object was created, some of the attributes can + have a value of ``None``. + + .. container:: operations + .. describe:: x == y + Checks if two author are the same. + .. describe:: x != y + Checks if two author are not the same. + .. describe:: iter(x) + Returns an iterator of ``(field, value)`` pairs. This allows this class + to be used as an iterable in list/dict/etc constructions. + .. describe:: str(x) + Returns a string representation of the author. + + + Attributes + ----------- + name: :class:`str` + The name of the author. + steam64: :class:`str` + The author's steam64 ID. + avatar: :class:`str` + The author's avatar URL. + + """ + + __slots__: Tuple[str, ...] = ( + '_payload', + 'name', + 'steam64', + 'avatar', + ) + + def __init__(self, payload: dict) -> None: + self._payload = payload + self._from_data(payload) + + def _from_data(self, author: dict): + self.name = author.get('name') + self.steam64 = author.get('steam64') + self.avatar = author.get('avatar') + + def __str__(self) -> str: + return self.name + + def __repr__(self) -> str: + return f'' + + def __eq__(self, other) -> bool: + return self.name == other.name + + def __ne__(self, other) -> bool: + return self.name != other.name + + def __iter__(self) -> Iterator[Tuple[str, Any]]: + for attr in self.__slots__: + if attr[0] != '_': + value = getattr(self, attr, None) + if value is not None: + yield (attr, value) + + def to_json(self) -> dict: + """:class:`dict`: Returns a JSON-compatible representation of the author.""" + return self._payload \ No newline at end of file diff --git a/Modules/steamgrid/enums.py b/Modules/steamgrid/enums.py new file mode 100644 index 0000000..2d3708f --- /dev/null +++ b/Modules/steamgrid/enums.py @@ -0,0 +1,75 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from enum import Enum + + +__all__ = [ + 'PlatformType', + 'StyleType', + 'MimeType', + 'ImageType', +] + +class PlatformType(Enum): + Steam = 'steam' + Origin = 'origin' + Egs = 'egs' + Bnet = 'bnet' + Uplay = 'uplay' + Flashpoint = 'flashpoint' + Eshop = 'eshop' + + def __str__(self) -> str: + return self.name + +class StyleType(Enum): + Alternate = 'alternate' + Blurred = 'blurred' + White_logo = 'white_logo' + Material = 'material' + No_logo = 'no_logo' + + def __str__(self) -> str: + return self.name + +class MimeType(Enum): + PNG = 'image/png' + JPEG = 'image/jpeg' + WEBP = 'image/webp' + + def __str__(self) -> str: + return self.name + +class ImageType(Enum): + Static = 'static ' + Animated = 'animated' + + def __str__(self) -> str: + return self.name + +class AssetType(Enum): + Grid = 'grids' + Hero = 'heroes' + Logo = 'logoes' + Icon = 'icons' + + def __str__(self) -> str: + return self.name \ No newline at end of file diff --git a/Modules/steamgrid/game.py b/Modules/steamgrid/game.py new file mode 100644 index 0000000..35999cc --- /dev/null +++ b/Modules/steamgrid/game.py @@ -0,0 +1,103 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from datetime import datetime +from typing import Iterator, Tuple, Any + +__all__ = ( + 'Game', +) + +class Game: + """Represents a custom game. + + Depending on the way this object was created, some of the attributes can + have a value of ``None``. + + .. container:: operations + .. describe:: x == y + Checks if two game are the same. + .. describe:: x != y + Checks if two game are not the same. + .. describe:: iter(x) + Returns an iterator of ``(field, value)`` pairs. This allows this class + to be used as an iterable in list/dict/etc constructions. + .. describe:: str(x) + Returns a string representation of the game. + + + Attributes + ----------- + name: :class:`str` + The name of the game. + id: :class:`int` + The game's ID. + types: List[:class:`str`] + List of game types. + verified: :class:`bool` + Whether an game is verified or not. + release_date: Optional[:class:`datetime`] + The release date of the game. + """ + + __slots__ = ( + '_payload', + 'id', + 'name', + 'types', + 'verified', + 'release_date', + '_release_date' + ) + + def __init__(self, payload: dict) -> None: + self._payload = payload + self._from_data(payload) + + def _from_data(self, game: dict): + self.name = game.get('name') + self.id = game.get('id') + self.types = game.get('types') + self.verified = game.get('verified') + self._release_date = game.get('release_date', None) + self.release_date = datetime.fromtimestamp(game['release_date']) if self._release_date else None + + def __str__(self) -> str: + return self.name + + def __repr__(self) -> str: + return f'' + + def __eq__(self, other) -> bool: + return self.id == other.id + + def __ne__(self, other) -> bool: + return self.id != other.id + + def __iter__(self) -> Iterator[Tuple[str, Any]]: + for attr in self.__slots__: + if attr[0] != '_': + value = getattr(self, attr, None) + if value is not None: + yield (attr, value) + + def to_json(self) -> dict: + """:class:`dict`: Returns a JSON-compatible representation of the author.""" + return self._payload \ No newline at end of file diff --git a/Modules/steamgrid/http.py b/Modules/steamgrid/http.py new file mode 100644 index 0000000..eefa7f9 --- /dev/null +++ b/Modules/steamgrid/http.py @@ -0,0 +1,158 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import requests +from typing import List + +class HTTPException(Exception): + """Exception raised when the HTTP request fails.""" + pass + +class HTTPClient: + + BASE_URL = 'https://www.steamgriddb.com/api/v2' + + def __init__(self, auth_key: str): + self.session = requests.Session() + self.auth_key = auth_key + self.session.headers.update({'Authorization': 'Bearer ' + self.auth_key}) + + def get(self, endpoint: str, queries: dict = None) -> dict: + if queries: + responce = self.session.get(endpoint, params=queries) + else: + responce = self.session.get(endpoint) + + try: + payload = responce.json() + except requests.exceptions.JSONDecodeError: + raise Exception('Responce JSON Decode Error') + + if not payload['success']: + error_context = payload['errors'][0] + raise HTTPException(f'API Error: ({responce.status_code}) {error_context}') + + return payload['data'] if payload else None + + def post(self, endpoint: str, body: dict = None) -> dict: + responce = self.session.post(endpoint, data=body) + try: + payload = responce.json() + except requests.exceptions.JSONDecodeError: + raise Exception('Responce JSON Decode Error') + + is_success = payload.get('success', None) + if not is_success: + error_context = payload['errors'][0] if payload else '' + raise HTTPException(f'API Error: ({responce.status_code}) {error_context}') + + return payload['data'] if payload else None + + def delete(self, endpoint: str) -> dict: + responce = self.session.delete(endpoint) + try: + payload = responce.json() + except requests.exceptions.JSONDecodeError: + raise Exception('Responce JSON Decode Error') + + if not payload['success']: + error_context = payload['errors'][0] + raise HTTPException(f'API Error: ({responce.status_code}) {error_context}') + + return payload['data'] if payload else None + + def get_game(self, game_id: int, request_type: str) -> dict: + if request_type == 'steam': + url = self.BASE_URL + '/games/steam/' + str(game_id) + elif request_type == 'game': + url = self.BASE_URL + '/games/id/' + str(game_id) + + return self.get(url) + + def get_grid( + self, + game_ids: List[int], + request_type: str, + platform: str = None, + queries: dict = None + ) -> List[dict]: + if request_type == 'game': + url = self.BASE_URL + '/grids/game/' + str(game_ids[0]) + elif request_type == 'platform': + url = self.BASE_URL + '/grids/' + platform + '/' + ','.join(str(i) for i in game_ids) + + return self.get(url, queries) + + def delete_grid(self, grid_ids: List[int]): + url = self.BASE_URL + '/grids/' + ','.join(str(i) for i in grid_ids) + self.delete(url) + + def get_hero( + self, + game_ids: List[int], + request_type: str, + platform: str = None, + queries: dict = None + ) -> List[dict]: + if request_type == 'game': + url = self.BASE_URL + '/heroes/game/' + str(game_ids[0]) + elif request_type == 'platform': + url = self.BASE_URL + '/heroes/' + platform + '/' + ','.join(str(i) for i in game_ids) + + return self.get(url, queries) + + def delete_hero(self, hero_ids: List[int]): + url = self.BASE_URL + '/heroes/' + ','.join(str(i) for i in hero_ids) + self.delete(url) + + def get_logo( + self, + game_ids: List[int], + request_type: str, + platform: str = None, + queries: dict = None + ) -> List[dict]: + if request_type == 'game': + url = self.BASE_URL + '/logos/game/' + str(game_ids[0]) + elif request_type == 'platform': + url = self.BASE_URL + '/logos/' + platform + '/' + ','.join(str(i) for i in game_ids) + + return self.get(url, queries) + + def delete_logo(self, logo_ids: List[int]): + url = self.BASE_URL + '/logos/' + ','.join(str(i) for i in logo_ids) + self.delete(url) + + def get_icon(self, game_ids: List[int], request_type: str, platform: str = None, queries: dict = None) -> List[dict]: + if request_type == 'game': + url = self.BASE_URL + '/icons/game/' + str(game_ids[0]) + elif request_type == 'platform': + url = self.BASE_URL + '/icons/' + platform + '/' + ','.join(str(i) for i in game_ids) + + return self.get(url, queries) + + def delete_icon(self, logo_ids: List[int]): + url = self.BASE_URL + '/icons/' + ','.join(str(i) for i in logo_ids) + self.delete(url) + + def search_games(self, term: str) -> List[dict]: + url = self.BASE_URL + '/search/autocomplete/' + term + + return self.get(url) \ No newline at end of file diff --git a/Modules/steamgrid/steamgrid.py b/Modules/steamgrid/steamgrid.py new file mode 100644 index 0000000..8fa2b40 --- /dev/null +++ b/Modules/steamgrid/steamgrid.py @@ -0,0 +1,802 @@ +""" +The MIT License (MIT) +Copyright (c) 2015-present Rapptz +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from typing import List, Optional + +from .http import HTTPClient +from .game import Game +from .enums import ( + StyleType, + MimeType, + ImageType, + PlatformType +) +from .asset import * + +__all__ = ( + 'SteamGridDB', +) + +class SteamGridDB: + """Represents a custom author. + + Attributes + ----------- + auth_key: :class:`str` + The auth key of the steamgriddb for authorization. + + """ + + __slots__ = ('_http') + + def __init__(self, auth_key: str) -> None: + self._http = HTTPClient(auth_key) + + def auth_key(self) -> str: + """:class:`str`: Returns the auth key of the steamgriddb. + + Returns + -------- + :class:`str` + The auth key of the steamgriddb. + """ + return self._http.auth_key + + def get_game_by_gameid( + self, + game_id: int, + ) -> Optional[Game]: + """:class:`Game`: Returns a game by game id. + + Parameters + ----------- + game_id: :class:`int` + The game id of the game. + + Raises + -------- + TypeError + If the game_id is not an integer. + HTTPException + If the game_id is not found. + + Returns + -------- + :class:`Game` + The game that was fetched. + """ + if not isinstance(game_id, int): + raise TypeError('\'game_id\' must be an integer.') + + payload = self._http.get_game(game_id, 'game') + return Game(payload) if payload != [] else None + + def get_game_by_steam_appid( + self, + app_id: int, + ) -> Optional[Game]: + """:class:`Game`: Returns a game by steam app id. + + Parameters + ----------- + app_id: :class:`int` + The steam app id of the game. + + Raises + -------- + TypeError + If the app_id is not an integer. + HTTPException + If the app_id is not found. + + Returns + -------- + :class:`Game` + The game that was fetched. + """ + if not isinstance(app_id, int): + raise TypeError('\'app_id\' must be an integer.') + + payload = self._http.get_game(app_id, 'steam') + return Game(payload) if payload != [] else None + + def get_grids_by_gameid( + self, + game_ids: List[int], + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Grid]]: + """Optional[List[:class:`Grid`]] Returns a list of grids by game id. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + styles: List[:class:`StyleType`] + The styles of the grids. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the grids. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the grids. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the grids are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the grids are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If the game_id is not found. + + Returns + -------- + Optional[List[:class:`Grid`]] + The grids that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(i.value for i in styles), + 'mimes': ','.join(i.value for i in mimes), + 'types': ','.join(i.value for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + payloads = self._http.get_grid(game_ids, 'game', queries=queries) + if payloads != []: + return [Grid(payload, self._http) for payload in payloads] + return None + + def get_grids_by_platform( + self, + game_ids: List[int], + platform: PlatformType, + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Grid]]: + + """Optional[List[:class:`Grid`]] Returns a list of grids by platform. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + platform: :class:`PlatformType` + The platform type of the grids. + styles: List[:class:`StyleType`] + The styles of the grids. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the grids. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the grids. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the grids are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the grids are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Grid`]] + The grids that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(platform, PlatformType): + raise TypeError('\'platform\' must be a PlatformType.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(str(i) for i in styles), + 'mimes': ','.join(str(i) for i in mimes), + 'types': ','.join(str(i) for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_grid( + game_ids, + 'platform', + platform=platform.value, + queries=queries + ) + if payloads != []: + return [Grid(payload, self._http) for payload in payloads] + return None + + def get_heroes_by_gameid( + self, + game_ids: List[int], + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Hero]]: + """Optional[List[:class:`Hero`]] Returns a list of heroes by game id. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + styles: List[:class:`StyleType`] + The styles of the heroes. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the heroes. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the heroes. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the heroes are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the heroes are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Hero`]] + The heroes that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(i.value for i in styles), + 'mimes': ','.join(i.value for i in mimes), + 'types': ','.join(i.value for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_hero(game_ids, 'game', queries=queries) + if payloads != []: + return [Hero(payload, self._http) for payload in payloads] + return None + + def get_heroes_by_platform( + self, + game_ids: List[int], + platform: PlatformType, + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Hero]]: + """Optional[List[:class:`Hero`]] Returns a list of heroes by platform. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + platform: :class:`PlatformType` + The platform type of the heroes. + styles: List[:class:`StyleType`] + The styles of the heroes. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the heroes. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the heroes. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the heroes are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the heroes are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Hero`]] + The heroes that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(platform, PlatformType): + raise TypeError('\'platform\' must be a PlatformType.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(str(i) for i in styles), + 'mimes': ','.join(str(i) for i in mimes), + 'types': ','.join(str(i) for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_hero( + game_ids, + 'platform', + platform=platform.value, + queries=queries + ) + if payloads != []: + return [Grid(payload, self._http) for payload in payloads] + return None + + def get_logos_by_gameid( + self, + game_ids: List[int], + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Logo]]: + """Optional[List[:class:`Logo`]] Returns a list of logos by game id. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + styles: List[:class:`StyleType`] + The styles of the logos. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the logos. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the logos. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the logos are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the logos are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Logo`]] + The logos that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(i.value for i in styles), + 'mimes': ','.join(i.value for i in mimes), + 'types': ','.join(i.value for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_logo(game_ids, 'game', queries=queries) + if payloads != []: + return [Logo(payload, self._http) for payload in payloads] + return None + + def get_logos_by_platform( + self, + game_ids: List[int], + platform: PlatformType, + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Logo]]: + """Optional[List[:class:`Logo`]] Returns a list of logos by platform. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + platform: :class:`PlatformType` + The platform type of the logos. + styles: List[:class:`StyleType`] + The styles of the logos. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the logos. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the logos. Defaults to all types. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(platform, PlatformType): + raise TypeError('\'platform\' must be a PlatformType.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(str(i) for i in styles), + 'mimes': ','.join(str(i) for i in mimes), + 'types': ','.join(str(i) for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_logo( + game_ids, + 'platform', + platform=platform.value, + queries=queries + ) + if payloads != []: + return [Logo(payload, self._http) for payload in payloads] + return None + + def get_icons_by_gameid( + self, + game_ids: List[int], + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Icon]]: + """Optional[List[:class:`Icon`]] Returns a list of icons by game id. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + styles: List[:class:`StyleType`] + The styles of the icons. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the icons. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the icons. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the icons are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the icons are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Icon`]] + The icons that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(i.value for i in styles), + 'mimes': ','.join(i.value for i in mimes), + 'types': ','.join(i.value for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_icon(game_ids, 'game', queries=queries) + if payloads != []: + return [Icon(payload, self._http) for payload in payloads] + return None + + def get_icons_by_platform( + self, + game_ids: List[int], + platform: PlatformType, + styles: List[StyleType] = [], + mimes: List[MimeType] = [], + types: List[ImageType] = [], + is_nsfw: bool = False, + is_humor: bool = False, + ) -> Optional[List[Icon]]: + """Optional[List[:class:`Icon`]] Returns a list of icons by platform. + + Parameters + ----------- + game_ids: List[:class:`int`] + The game ids of the games. + platform: :class:`PlatformType` + The platform type of the icons. + styles: List[:class:`StyleType`] + The styles of the icons. Defaults to all styles. + mimes: List[:class:`MimeType`] + The mimes of the icons. Defaults to all mimes. + types: List[:class:`ImageType`] + The types of the icons. Defaults to all types. + is_nsfw: :class:`bool` + Whether or not the icons are NSFW. Defaults to False. + is_humor: :class:`bool` + Whether or not the icons are humor. Defaults to False. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Icon`]] + The icons that were fetched. + """ + if not isinstance(game_ids, List): + raise TypeError('\'game_ids\' must be a list of integers.') + if not isinstance(platform, PlatformType): + raise TypeError('\'platform\' must be a PlatformType.') + if not isinstance(styles, List): + raise TypeError('\'styles\' must be a list of StyleType.') + if not isinstance(mimes, List): + raise TypeError('\'mimes\' must be a list of MimeType.') + if not isinstance(types, List): + raise TypeError('\'types\' must be a list of ImageType.') + if not isinstance(is_nsfw, bool): + raise TypeError('\'is_nsfw\' must be a boolean.') + if not isinstance(is_humor, bool): + raise TypeError('\'is_humor\' must be a boolean.') + + queries = { + 'styles': ','.join(str(i) for i in styles), + 'mimes': ','.join(str(i) for i in mimes), + 'types': ','.join(str(i) for i in types), + 'nsfw': str(is_nsfw).lower(), + 'humor': str(is_humor).lower(), + } + + payloads = self._http.get_icon( + game_ids, + 'platform', + platform=platform.value, + queries=queries + ) + if payloads != []: + return [Icon(payload, self._http) for payload in payloads] + return None + + def delete_grid( + self, + grid_ids: List[int], + ) -> None: + """Deletes list of grid images from the website. + + Parameters + ----------- + grid_ids: List[:class:`int`] + The grid ids to delete. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + """ + if not isinstance(grid_ids, List): + raise TypeError('\'grid_ids\' must be a list of integers.') + + self._http.delete_grid(grid_ids) + + def delete_hero( + self, + hero_ids: List[int], + ) -> None: + """Deletes list of hero images from the website. + + Parameters + ----------- + hero_ids: List[:class:`int`] + The hero ids to delete. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + """ + if not isinstance(hero_ids, List): + raise TypeError('\'hero_ids\' must be a list of integers.') + + self._http.delete_hero(hero_ids) + + def delete_logo( + self, + logo_ids: List[int], + ) -> None: + """Deletes list of logo images from the website. + + Parameters + ----------- + logo_ids: List[:class:`int`] + The logo ids to delete. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + """ + if not isinstance(logo_ids, List): + raise TypeError('\'logo_ids\' must be a list of integers.') + + self._http.delete_logo(logo_ids) + + def delete_icon( + self, + icon_ids: List[int], + ) -> None: + """Deletes list of icon images from the website. + + Parameters + ----------- + icon_ids: List[:class:`int`] + The icon ids to delete. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + """ + if not isinstance(icon_ids, List): + raise TypeError('\'icon_ids\' must be a list of integers.') + + self._http.delete_icon(icon_ids) + + def search_game( + self, + term: str + ) -> Optional[List[Game]]: + """Searches for games on the website. + + Parameters + ----------- + term: :class:`str` + The term to search for. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + + Returns + -------- + Optional[List[:class:`Game`]] + The list of games that match the search term. + """ + if not isinstance(term, str): + raise TypeError('\'term\' must be a string.') + + payloads = self._http.search_games(term) + return [Game(payload) for payload in payloads] + + def set_auth_key( + self, + auth_key: str + ) -> None: + """Sets the new auth key for the API. + + Parameters + ----------- + auth_key: :class:`str` + The new auth key to set. + + Raises + -------- + TypeError + If one of the parameters is not of the correct type. + HTTPException + If there is an error with the request. + ValueError + If the auth key is not valid format. + """ + if not isinstance(auth_key, str): + raise TypeError('\'auth_key\' must be a string.') + if len(auth_key) != 32: + raise ValueError('\'auth_key\' must be a 32-character string.') + + self._http.session.headers['Authorization'] = f'Bearer {auth_key}' \ No newline at end of file