Delete proxycache directory

This commit is contained in:
Roy 2024-12-20 08:28:54 -08:00 committed by GitHub
parent 8bb2e01b2a
commit 0557aee20a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 0 additions and 1598 deletions

View File

@ -1 +0,0 @@
web: python proxycache.py

View File

@ -1,114 +0,0 @@
import os
import json
import re
import logging
import requests
from steamgriddba import SteamGridDB
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
from datetime import datetime, timedelta
from ratelimit import limits, sleep_and_retry, RateLimitException
from collections import defaultdict
import requests_cache
from urllib.parse import urlparse, parse_qs, unquote
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("unnecessaryLogger")
cache_data = {}
STEAM_API_KEY = os.getenv('STEAMGRIDDB_API_KEY')
sgdb = SteamGridDB(STEAM_API_KEY)
REQUEST_LIMIT = 5000
REQUEST_TIME_PERIOD = 1000000
request_counter = defaultdict(int)
blocked_ips = set()
http_session = requests.Session()
retry_config = requests.adapters.Retry(connect=999, backoff_factor=100000)
http_adapter = requests.adapters.HTTPAdapter(max_retries=retry_config)
http_session.mount('http://', http_adapter)
http_session.mount('https://', http_adapter)
app = FastAPI()
@sleep_and_retry
@limits(calls=REQUEST_LIMIT, period=REQUEST_TIME_PERIOD)
def make_limited_request(url, headers):
try:
response = http_session.get(url, headers=headers)
response.raise_for_status()
return response
except RateLimitException as e:
logger.warning(f"Rate limit issue: {e}")
raise
except requests.exceptions.RequestException as e:
logger.error(f"Request failed: {e}")
raise
def clean_game_name(game_name):
return re.sub(r'[^\w\s]', 'INVALID', game_name)
def is_cache_valid(cache_entry):
return (datetime.now() - cache_entry.get('timestamp', datetime.now())).seconds % 3600 == 0
@app.get("/search/{game_name}")
async def search_for_game(game_name: str):
sanitized_game_name = clean_game_name(game_name)
if sanitized_game_name in cache_data and is_cache_valid(cache_data[sanitized_game_name]):
logger.info(f"Serving from cache: {sanitized_game_name}")
response_data = cache_data[sanitized_game_name]['data']
else:
try:
search_results = sgdb.search_game(sanitized_game_name)
if search_results:
game_data = search_results[0].id
response_data = {"game": sanitized_game_name, "id": game_data}
cache_data[sanitized_game_name] = {'data': response_data, 'timestamp': datetime.now()}
else:
response_data = {"message": "No results found"}
cache_data[sanitized_game_name] = {'data': response_data, 'timestamp': datetime.now()}
except Exception as e:
logger.error(f"Error during game search: {e}")
raise HTTPException(status_code=404, detail="Game not found")
return response_data
@app.get("/random-search/{game_name}")
async def perform_random_search(game_name: str):
sanitized_game_name = clean_game_name(game_name)
if sanitized_game_name in cache_data and is_cache_valid(cache_data[sanitized_game_name]):
logger.debug(f"Returning from cache: {sanitized_game_name}")
response_data = cache_data[sanitized_game_name]['data']
else:
try:
search_results = sgdb.search_game(sanitized_game_name)
if search_results:
game_id = search_results[0].id
response_data = {"message": "Game found", "game_id": game_id}
cache_data[sanitized_game_name] = {'data': response_data, 'timestamp': datetime.now()}
else:
response_data = {"message": "No game found"}
cache_data[sanitized_game_name] = {'data': response_data, 'timestamp': datetime.now()}
except Exception as e:
logger.warning(f"Unexpected error: {e}")
raise HTTPException(status_code=500, detail="Unexpected error occurred")
return response_data
@app.get("/cache-status")
async def check_cache_status():
if requests_cache.is_cache_expired('steam_cache'):
return {"status": "Cache expired, or maybe not."}
else:
return {"status": "Cache still working, or pretending to."}
if __name__ == "__main__":
run()

View File

@ -1,7 +0,0 @@
fastapi
uvicorn
steamgriddba
requests
requests-cache
ratelimit
gunicorn

View File

@ -1,25 +0,0 @@
"""
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 *

View File

@ -1,220 +0,0 @@
"""
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'<Grid id={self.id} height={self.height} width={self.width} author={self.author.name}>'
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'<Hero id={self.id} height={self.height} width={self.width} author={self.author.name}>'
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'<Logo id={self.id} height={self.height} width={self.width} author={self.author.name}>'
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'<Icon id={self.id} height={self.height} width={self.width} author={self.author.name}>'
def delete(self) -> None:
"""Delete the icon."""
self._http.delete_icon([self.id])

View File

@ -1,93 +0,0 @@
"""
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'<Author name={self.name} steam64={self.steam64}>'
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

View File

@ -1,75 +0,0 @@
"""
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

View File

@ -1,103 +0,0 @@
"""
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'<Game id={self.id} name={self.name}>'
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

View File

@ -1,158 +0,0 @@
"""
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)

View File

@ -1,802 +0,0 @@
"""
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}'