121 lines
3.2 KiB
Python
121 lines
3.2 KiB
Python
import difflib
|
|
import os
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from logging import getLogger
|
|
from typing import Tuple
|
|
|
|
import orjson
|
|
import requests
|
|
|
|
from rare.lgndr.core import LegendaryCore
|
|
from rare.utils.paths import cache_dir
|
|
|
|
logger = getLogger("SteamGrades")
|
|
|
|
replace_chars = ",;.:-_ "
|
|
steamapi_url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"
|
|
protondb_url = "https://www.protondb.com/api/v1/reports/summaries/"
|
|
|
|
__steam_ids_json = None
|
|
__grades_json = None
|
|
__active_download = False
|
|
|
|
|
|
class ProtondbRatings(int, Enum):
|
|
# internal
|
|
PENDING = ("pending", -2)
|
|
FAIL = ("fail", -1)
|
|
# protondb
|
|
NA = ("na", 0)
|
|
BORKED = ("borked", 1)
|
|
BRONZE = ("bronze", 2)
|
|
SILVER = ("silver", 3)
|
|
GOLD = ("gold", 4)
|
|
PLATINUM = ("platinum", 5)
|
|
|
|
def __new__(cls, name: str, value: int):
|
|
obj = int.__new__(cls, value)
|
|
obj._value_ = value
|
|
obj._name_ = name
|
|
return obj
|
|
|
|
def __str__(self):
|
|
return self._name_
|
|
|
|
def __int__(self):
|
|
return self._value_
|
|
|
|
|
|
def get_rating(core: LegendaryCore, app_name: str) -> Tuple[int, str]:
|
|
game = core.get_game(app_name)
|
|
try:
|
|
steam_id = get_steam_id(game.app_title)
|
|
if not steam_id:
|
|
raise Exception
|
|
grade = get_grade(steam_id)
|
|
except Exception as e:
|
|
logger.exception(e)
|
|
return 0, "fail"
|
|
else:
|
|
return steam_id, grade
|
|
|
|
|
|
# you should initiate the module with the game's steam code
|
|
def get_grade(steam_code):
|
|
if steam_code == 0:
|
|
return "fail"
|
|
steam_code = str(steam_code)
|
|
res = requests.get(f"{protondb_url}{steam_code}.json")
|
|
try:
|
|
app = orjson.loads(res.text)
|
|
except orjson.JSONDecodeError as e:
|
|
logger.exception(e)
|
|
return "fail"
|
|
|
|
return app.get("tier", "fail")
|
|
|
|
|
|
def load_json() -> dict:
|
|
global __active_download
|
|
if __active_download:
|
|
return {}
|
|
file = os.path.join(cache_dir(), "steam_appids.json")
|
|
elapsed_days = 0
|
|
if os.path.exists(file):
|
|
mod_time = datetime.fromtimestamp(os.path.getmtime(file))
|
|
elapsed_days = abs(datetime.now() - mod_time).days
|
|
if not os.path.exists(file) or elapsed_days > 7:
|
|
__active_download = True
|
|
response = requests.get(steamapi_url)
|
|
__active_download = False
|
|
apps = orjson.loads(response.text).get("applist", {}).get("apps", {})
|
|
ids = {}
|
|
for app in apps:
|
|
ids[app["name"]] = app["appid"]
|
|
with open(file, "w") as f:
|
|
f.write(orjson.dumps(ids).decode("utf-8"))
|
|
return ids
|
|
else:
|
|
return orjson.loads(open(file, "r").read())
|
|
|
|
|
|
def get_steam_id(title: str) -> int:
|
|
# workarounds for satisfactory
|
|
# FIXME: This has to be made smarter.
|
|
title = title.replace("Early Access", "").replace("Experimental", "").strip()
|
|
# title = title.split(":")[0]
|
|
# title = title.split("-")[0]
|
|
global __steam_ids_json
|
|
if __steam_ids_json is None:
|
|
__steam_ids_json = load_json()
|
|
ids = __steam_ids_json
|
|
|
|
if title in ids.keys():
|
|
steam_name = [title]
|
|
else:
|
|
steam_name = difflib.get_close_matches(title, ids.keys(), n=1, cutoff=0.5)
|
|
if steam_name:
|
|
return ids[steam_name[0]]
|
|
else:
|
|
return 0
|