Add protondb grades and option to disable it
This commit is contained in:
parent
d50ccc6e55
commit
2e148aebff
|
@ -7,9 +7,15 @@ from rare.utils import singleton
|
|||
|
||||
def main():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-V", "--version", action="store_true")
|
||||
parser.add_argument("-S", "--silent", action="store_true")
|
||||
parser.add_argument("--offline", action="store_true")
|
||||
parser.add_argument("-V", "--version", action="store_true", help="Shows version and exits")
|
||||
parser.add_argument("-S", "--silent", action="store_true",
|
||||
help="Launch Rare in background. Open it from System Tray Icon")
|
||||
parser.add_argument("--offline", action="store_true", help="Launch Rare in offline mode")
|
||||
if os.name != "nt":
|
||||
parser.add_argument("--disable-protondb", action="store_true", dest="disable_protondb",
|
||||
help="Do not download and check data from ProtonDB. Disable it, if you don't need grades")
|
||||
parser.add_argument("--enable-protondb", action="store_true", dest="enable_protondb",
|
||||
help="Enable ProtonDB data, after disabled")
|
||||
subparsers = parser.add_subparsers(title="Commands", dest="subparser")
|
||||
|
||||
launch_parser = subparsers.add_parser("launch")
|
||||
|
|
|
@ -60,6 +60,11 @@ class App(QApplication):
|
|||
self.setOrganizationName("Rare")
|
||||
settings = QSettings()
|
||||
|
||||
if args.disable_protondb:
|
||||
settings.setValue("disable_protondb", True)
|
||||
if args.enable_protondb:
|
||||
settings.remove("disable_protondb")
|
||||
|
||||
# Translator
|
||||
self.translator = QTranslator()
|
||||
lang = settings.value("language", get_lang(), type=str)
|
||||
|
|
|
@ -1,31 +1,69 @@
|
|||
import json
|
||||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import QThread, pyqtSignal
|
||||
from PyQt5.QtWidgets import QDialog, QLabel, QProgressBar, QVBoxLayout
|
||||
from PyQt5.QtCore import QThread, pyqtSignal, QSettings
|
||||
from PyQt5.QtWidgets import QDialog
|
||||
from requests.exceptions import ConnectionError
|
||||
|
||||
from custom_legendary.core import LegendaryCore
|
||||
from rare.components.dialogs.login import LoginDialog
|
||||
from rare.utils.utils import download_images, check_grades
|
||||
from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog
|
||||
from rare.utils import steam_grades
|
||||
from rare.utils.utils import download_images
|
||||
|
||||
logger = getLogger("Login")
|
||||
|
||||
|
||||
class LaunchThread(QThread):
|
||||
class ImageThread(QThread):
|
||||
download_progess = pyqtSignal(int)
|
||||
action = pyqtSignal(str)
|
||||
|
||||
def __init__(self, core: LegendaryCore, parent=None):
|
||||
super(LaunchThread, self).__init__(parent)
|
||||
super(ImageThread, self).__init__(parent)
|
||||
self.core = core
|
||||
|
||||
def run(self):
|
||||
self.action.emit("Login")
|
||||
self.action.emit(self.tr("Downloading Images"))
|
||||
download_images(self.download_progess, self.core)
|
||||
#self.action.emit(self.tr("Read data from ProtonDB"))
|
||||
#check_grades(self.core, self.download_progess)
|
||||
self.action.emit("finish")
|
||||
self.download_progess.emit(100)
|
||||
|
||||
|
||||
class SteamThread(QThread):
|
||||
progress = pyqtSignal(int)
|
||||
action = pyqtSignal(str)
|
||||
|
||||
def __init__(self, core: LegendaryCore, parent):
|
||||
super(SteamThread, self).__init__(parent)
|
||||
self.core = core
|
||||
|
||||
def run(self) -> None:
|
||||
gamelist = self.core.get_game_list(True)
|
||||
if not os.path.exists(os.path.expanduser("~/.cache/rare/game_list.json")):
|
||||
self.action.emit(self.tr("Getting data from ProtonDB"))
|
||||
steam_grades.upgrade_all([(i.app_title, i.app_name) for i in gamelist], self.progress)
|
||||
self.progress.emit(99)
|
||||
|
||||
self.action.emit(self.tr("Checking Games for data"))
|
||||
grades = json.load(open(os.path.expanduser("~/.cache/rare/game_list.json")))
|
||||
ids = json.load(open(os.path.expanduser("~/.cache/rare/steam_ids.json")))
|
||||
for game in gamelist:
|
||||
if not grades.get(game.app_name):
|
||||
steam_id = steam_grades.get_steam_id(game.app_title, ids)
|
||||
grade = steam_grades.get_grade(steam_id)
|
||||
grades[game.app_name] = {
|
||||
"steam_id": steam_id,
|
||||
"grade": grade
|
||||
}
|
||||
if not grades[game.app_name].get("steam_id"):
|
||||
grades[game.app_name]["steam_id"] = steam_grades.get_steam_id(game.app_title)
|
||||
if not grades[game.app_name].get("grade"):
|
||||
grades[game.app_name]["grade"] = steam_grades.get_grade(game.app_title)
|
||||
|
||||
with open(os.path.expanduser("~/.cache/rare/game_list.json"), "w") as f:
|
||||
f.write(json.dumps(grades))
|
||||
f.close()
|
||||
|
||||
self.action.emit("Ready")
|
||||
self.progress.emit(100)
|
||||
|
||||
|
||||
class LoginThread(QThread):
|
||||
|
@ -52,11 +90,17 @@ class LoginThread(QThread):
|
|||
self.start_app.emit(True)
|
||||
|
||||
|
||||
class LaunchDialog(QDialog):
|
||||
class LaunchDialog(QDialog, Ui_LaunchDialog):
|
||||
start_app = pyqtSignal(bool)
|
||||
finished = False
|
||||
|
||||
def __init__(self, core: LegendaryCore, offline):
|
||||
super(LaunchDialog, self).__init__()
|
||||
self.setupUi(self)
|
||||
if os.name == "nt":
|
||||
self.finished = True
|
||||
self.steam_info.setVisible(False)
|
||||
self.steam_prog_bar.setVisible(False)
|
||||
self.core = core
|
||||
if not offline:
|
||||
self.login_thread = LoginThread(core)
|
||||
|
@ -64,18 +108,7 @@ class LaunchDialog(QDialog):
|
|||
self.login_thread.start_app.connect(self.launch)
|
||||
self.login_thread.start()
|
||||
|
||||
self.title = QLabel("<h3>" + self.tr("Launching Rare") + "</h3>")
|
||||
self.info_pb = QProgressBar()
|
||||
self.info_text = QLabel(self.tr("Logging in"))
|
||||
self.layout = QVBoxLayout()
|
||||
|
||||
self.layout.addWidget(self.title)
|
||||
self.layout.addWidget(self.info_pb)
|
||||
self.layout.addWidget(self.info_text)
|
||||
|
||||
self.setLayout(self.layout)
|
||||
|
||||
if offline:
|
||||
else:
|
||||
self.launch(offline)
|
||||
|
||||
def login(self):
|
||||
|
@ -88,20 +121,40 @@ class LaunchDialog(QDialog):
|
|||
|
||||
def launch(self, offline=False):
|
||||
# self.core = core
|
||||
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/images")):
|
||||
os.makedirs(p)
|
||||
self.offline = offline
|
||||
self.info_text.setText(self.tr("Downloading Images"))
|
||||
self.thread = LaunchThread(self.core, self)
|
||||
self.thread.download_progess.connect(self.update_pb)
|
||||
self.thread.action.connect(self.info)
|
||||
self.thread.start()
|
||||
|
||||
def update_pb(self, i: int):
|
||||
self.info_pb.setValue(i)
|
||||
if not offline:
|
||||
|
||||
def info(self, text: str):
|
||||
if text == "finish":
|
||||
self.info_text.setText(self.tr("Starting..."))
|
||||
self.info_pb.setValue(100)
|
||||
self.image_info.setText(self.tr("Downloading Images"))
|
||||
self.img_thread = ImageThread(self.core, self)
|
||||
self.img_thread.download_progess.connect(self.update_image_progbar)
|
||||
self.img_thread.finished.connect(self.finish)
|
||||
self.img_thread.start()
|
||||
# not disabled and not windows
|
||||
if (not QSettings().value("disable_protondb", False, bool)) and (not os.name == "nt"):
|
||||
self.steam_thread = SteamThread(self.core, self)
|
||||
self.steam_thread.progress.connect(self.update_steam_prog_bar)
|
||||
self.steam_thread.action.connect(lambda x: self.steam_info.setText(x))
|
||||
self.steam_thread.finished.connect(self.finish)
|
||||
self.steam_thread.start()
|
||||
else:
|
||||
self.finished = True
|
||||
self.steam_info.setVisible(False)
|
||||
self.steam_prog_bar.setVisible(False)
|
||||
|
||||
def update_steam_prog_bar(self, value):
|
||||
self.steam_prog_bar.setValue(value)
|
||||
|
||||
def update_image_progbar(self, i: int):
|
||||
self.image_prog_bar.setValue(i)
|
||||
|
||||
def finish(self):
|
||||
if self.finished:
|
||||
self.image_info.setText(self.tr("Starting..."))
|
||||
self.image_prog_bar.setValue(100)
|
||||
self.steam_prog_bar.setValue(100)
|
||||
self.start_app.emit(self.offline)
|
||||
else:
|
||||
self.info_text.setText(text)
|
||||
self.finished = True
|
||||
|
|
|
@ -63,8 +63,6 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
verify_game = pyqtSignal(str)
|
||||
verify_threads = {}
|
||||
|
||||
grade_table = json.load(open(os.path.expanduser("~/.cache/rare/game_list.json")))
|
||||
|
||||
def __init__(self, core: LegendaryCore, parent):
|
||||
super(GameInfo, self).__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
|
@ -74,7 +72,10 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
"bronze": self.tr("Bronze"),
|
||||
"fail": self.tr("Could not get grade from ProtonDB"),
|
||||
"pending": "Not enough reports"}
|
||||
|
||||
if os.path.exists(p := os.path.expanduser("~/.cache/rare/game_list.json")):
|
||||
self.grade_table = json.load(open(p))
|
||||
else:
|
||||
self.grade_table = {}
|
||||
self.widget = QWidget()
|
||||
self.core = core
|
||||
if os.name == "nt":
|
||||
|
@ -155,7 +156,7 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
self.install_size.setText(get_size(self.igame.install_size))
|
||||
self.install_path.setText(self.igame.install_path)
|
||||
|
||||
if os.name != "nt":
|
||||
if os.name != "nt" and self.grade_table:
|
||||
try:
|
||||
grade = self.ratings.get(self.grade_table[app_name].get("grade"))
|
||||
except KeyError:
|
||||
|
|
|
@ -56,7 +56,11 @@ class UninstalledInfo(QWidget):
|
|||
def __init__(self, core: LegendaryCore, parent):
|
||||
super(UninstalledInfo, self).__init__(parent=parent)
|
||||
self.layout = QVBoxLayout()
|
||||
self.grade_table = json.load(open(os.path.expanduser("~/.cache/rare/game_list.json")))
|
||||
|
||||
if os.path.exists(p := os.path.expanduser("~/.cache/rare/game_list.json")):
|
||||
self.grade_table = json.load(open(p))
|
||||
else:
|
||||
self.grade_table = {}
|
||||
|
||||
self.ratings = {"platinum": self.tr("Platinum"),
|
||||
"gold": self.tr("Gold"),
|
||||
|
@ -82,7 +86,7 @@ class UninstalledInfo(QWidget):
|
|||
|
||||
self.app_name = QLabel("Error")
|
||||
self.right_layout.addWidget(self.app_name)
|
||||
|
||||
if os.name != "nt":
|
||||
self.rating = QLabel("Rating: Error")
|
||||
self.right_layout.addWidget(self.rating)
|
||||
|
||||
|
@ -124,6 +128,7 @@ class UninstalledInfo(QWidget):
|
|||
self.image.setPixmap(pixmap)
|
||||
|
||||
self.version.setText(self.game.asset_info.build_version)
|
||||
if self.grade_table and (not os.name == "nt"):
|
||||
try:
|
||||
rating = self.grade_table[app_name]["grade"]
|
||||
except KeyError:
|
||||
|
|
132
rare/utils/id.py
132
rare/utils/id.py
|
@ -1,132 +0,0 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
import requests
|
||||
import json
|
||||
from datetime import date
|
||||
|
||||
|
||||
replace_chars = ",;.:-_ "
|
||||
|
||||
file = os.path.expanduser("~/.cache/rare/game_list.json")
|
||||
url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"
|
||||
|
||||
|
||||
def get_id(game_name):
|
||||
global file
|
||||
|
||||
if check_time() == 1:
|
||||
upgrade_content()
|
||||
|
||||
text = open(file, 'r')
|
||||
game_list = json.load(text)
|
||||
|
||||
return game_list[game_name.lower()]
|
||||
|
||||
|
||||
def download_ids():
|
||||
response = requests.get(url)
|
||||
with open(os.path.expanduser("~/.cache/rare/steam_ids.json"), "w") as f:
|
||||
f.write(response.text)
|
||||
f.close()
|
||||
|
||||
|
||||
def upgrade_content(games: list, status_signal): # this function uploads the ids database, aka game_list.json
|
||||
global url
|
||||
global file
|
||||
response = requests.get(url)
|
||||
with open(os.path.expanduser("~/.cache/rare/steam_ids.json"), "w") as f:
|
||||
f.write(response.text)
|
||||
f.close()
|
||||
|
||||
content = json.loads(response.text)
|
||||
game_list = {} # {CrabEA: {id: 1234, grade: platinum}, ..}
|
||||
|
||||
steam_games = {}
|
||||
for i in content["applist"]["apps"]:
|
||||
name: str = i["name"].lower()
|
||||
for c in replace_chars:
|
||||
name = name.replace(c, "")
|
||||
name = name.encode("ascii", "ignore").decode("ascii", "ignore")
|
||||
steam_games[name] = i["appid"]
|
||||
|
||||
for i in games:
|
||||
if i.app_title.lower() in steam_games.keys():
|
||||
game_list[i.app_name] = {}
|
||||
game_list[i.app_name]["id"] = steam_games[i.app_title.lower()]
|
||||
continue
|
||||
else:
|
||||
app_title = i.app_title.lower()
|
||||
app_title = app_title.encode("ascii", "ignore").decode("ascii", "ignore")
|
||||
for c in replace_chars:
|
||||
app_title = app_title.replace(c, "")
|
||||
if app_title in steam_games.keys():
|
||||
game_list[i.app_name] = {}
|
||||
game_list[i.app_name]["id"] = steam_games[app_title]
|
||||
else:
|
||||
for game in steam_games:
|
||||
if app_title.startswith(game):
|
||||
game_list[i.app_name] = {}
|
||||
game_list[i.app_name]["id"] = steam_games[game]
|
||||
|
||||
for i, game in enumerate(game_list):
|
||||
try:
|
||||
grade = get_grade(game_list[game]["id"])
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
logging.error(str(e))
|
||||
game_list[game]["grade"] = "fail"
|
||||
print(game) # debug
|
||||
else:
|
||||
game_list[game]["grade"] = grade
|
||||
status_signal.emit(50 + i/len(game_list)*50)
|
||||
|
||||
# print(game_list)
|
||||
|
||||
# for game in content['applist']['apps']:
|
||||
# game_list[game['name'].lower()] = game['appid']
|
||||
|
||||
# uploding date on json
|
||||
today = date.today()
|
||||
game_list['data'] = {}
|
||||
for i in "ymd":
|
||||
game_list["data"][i] = today.strftime('%' + i)
|
||||
|
||||
table = open(file, 'w')
|
||||
|
||||
json.dump(game_list, table)
|
||||
table.close()
|
||||
|
||||
|
||||
def check_time(): # this function check if it's time to update
|
||||
global file
|
||||
text = open(file, 'r')
|
||||
json_table = json.load(text)
|
||||
text.close()
|
||||
|
||||
today = date.today()
|
||||
day = 0 # it controls how many days it's necessary for an update
|
||||
for i in 'ymd':
|
||||
if i == 'd':
|
||||
day = 7
|
||||
else:
|
||||
day = 0
|
||||
if int(today.strftime('%' + i)) > int(json_table['data'][i]) + day:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
# you should iniciate the module with the game's steam code
|
||||
def get_grade(steam_code):
|
||||
steam_code = str(steam_code)
|
||||
url = 'https://www.protondb.com/api/v1/reports/summaries/'
|
||||
res = requests.get(url + steam_code + '.json')
|
||||
text = res.text
|
||||
lista = json.loads(text)
|
||||
# print(lista['tier']) # just for debug pourpouses!!!
|
||||
|
||||
return lista['tier']
|
||||
|
||||
|
||||
def id(game_name):
|
||||
return get_grade(get_id(game_name))
|
116
rare/utils/steam_grades.py
Normal file
116
rare/utils/steam_grades.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
import difflib
|
||||
import json
|
||||
import os
|
||||
from datetime import date
|
||||
|
||||
import requests
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
|
||||
replace_chars = ",;.:-_ "
|
||||
|
||||
file = os.path.expanduser("~/.cache/rare/game_list.json")
|
||||
url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"
|
||||
|
||||
|
||||
# you should iniciate the module with the game's steam code
|
||||
def get_grade(steam_code):
|
||||
if steam_code == 0:
|
||||
return "fail"
|
||||
steam_code = str(steam_code)
|
||||
url = 'https://www.protondb.com/api/v1/reports/summaries/'
|
||||
res = requests.get(url + steam_code + '.json')
|
||||
try:
|
||||
lista = json.loads(res.text)
|
||||
except json.decoder.JSONDecodeError:
|
||||
return "fail"
|
||||
|
||||
return lista['tier']
|
||||
|
||||
|
||||
def load_json() -> dict:
|
||||
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/steam_ids.json")):
|
||||
response = requests.get(url)
|
||||
steam_ids = json.loads(response.text)["applist"]["apps"]
|
||||
ids = {}
|
||||
for game in steam_ids:
|
||||
ids[game["name"]] = game["appid"]
|
||||
|
||||
with open(os.path.expanduser(p), "w") as f:
|
||||
f.write(json.dumps(ids))
|
||||
f.close()
|
||||
return ids
|
||||
else:
|
||||
return json.loads(open(os.path.expanduser("~/.cache/rare/steam_ids.json"), "r").read())
|
||||
|
||||
|
||||
def upgrade_all(games, progress: pyqtSignal = None):
|
||||
ids = load_json()
|
||||
data = {}
|
||||
for i, (title, app_name) in enumerate(games):
|
||||
title = title.replace("Early Access", "").replace("Experimental", "").strip()
|
||||
data[app_name] = {}
|
||||
|
||||
steam_id = get_steam_id(title, ids)
|
||||
|
||||
data[app_name] = {
|
||||
"steam_id": steam_id,
|
||||
"grade": get_grade(steam_id)}
|
||||
|
||||
if progress:
|
||||
progress.emit(int(i / len(games) * 100))
|
||||
|
||||
with open(os.path.expanduser("~/.cache/rare/game_list.json"), "w") as f:
|
||||
f.write(json.dumps(data))
|
||||
f.close()
|
||||
|
||||
|
||||
def get_steam_id(title: str, json_data=None):
|
||||
title = title.replace("Early Access", "").replace("Experimental", "").strip()
|
||||
if not json_data:
|
||||
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/steam_ids.json")):
|
||||
response = requests.get(url)
|
||||
ids = {}
|
||||
steam_ids = json.loads(response.text)["applist"]["apps"]
|
||||
for game in steam_ids:
|
||||
ids[game["name"]] = game["appid"]
|
||||
|
||||
with open(os.path.expanduser(p), "w") as f:
|
||||
f.write(json.dumps(steam_ids))
|
||||
f.close()
|
||||
else:
|
||||
ids = json.loads(open(os.path.expanduser("~/.cache/rare/steam_ids.json"), "r").read())
|
||||
else:
|
||||
ids = json_data
|
||||
steam_name = difflib.get_close_matches(title, ids.keys(), n=1)
|
||||
if steam_name:
|
||||
return ids[steam_name[0]]
|
||||
else:
|
||||
return 0
|
||||
# print(x)
|
||||
|
||||
# for game in steam_ids:
|
||||
# num = difflib.SequenceMatcher(None, game["name"], title).ratio()
|
||||
# if num > most_similar[2] and num > 0.5:
|
||||
# most_similar = (game["appid"], game["name"], num)
|
||||
# print(time.time()-t)
|
||||
# name = difflib.get_close_matches(steam_ids.keys(), title)
|
||||
# return most_similar
|
||||
|
||||
|
||||
def check_time(): # this function check if it's time to update
|
||||
global file
|
||||
text = open(file, 'r')
|
||||
json_table = json.load(text)
|
||||
text.close()
|
||||
|
||||
today = date.today()
|
||||
day = 0 # it controls how many days it's necessary for an update
|
||||
for i in 'ymd':
|
||||
if i == 'd':
|
||||
day = 7
|
||||
else:
|
||||
day = 0
|
||||
if int(today.strftime('%' + i)) > int(json_table['data'][i]) + day:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
|
@ -8,15 +8,12 @@ import requests
|
|||
from PIL import Image, UnidentifiedImageError
|
||||
from PyQt5.QtCore import pyqtSignal, QLocale, QSettings
|
||||
from PyQt5.QtGui import QPalette, QColor
|
||||
from rare import style_path
|
||||
|
||||
from rare.utils.id import upgrade_content, check_time, download_ids
|
||||
|
||||
# Windows
|
||||
if os.name == "nt":
|
||||
from win32com.client import Dispatch
|
||||
|
||||
from rare import lang_path, __version__, style_path
|
||||
from rare import lang_path, style_path
|
||||
from custom_legendary.core import LegendaryCore
|
||||
|
||||
logger = getLogger("Utils")
|
||||
|
@ -42,22 +39,7 @@ def download_images(signal: pyqtSignal, core: LegendaryCore):
|
|||
except json.decoder.JSONDecodeError:
|
||||
shutil.rmtree(f"{IMAGE_DIR}/{game.app_name}")
|
||||
download_image(game)
|
||||
signal.emit(i/len(game_list)*50)
|
||||
|
||||
|
||||
def check_grades(core: LegendaryCore, signal):
|
||||
games = core.get_game_list(True)
|
||||
# upgrade_content(games, signal)
|
||||
if not os.path.exists("~/.cache/rare/steam_ids.json"):
|
||||
download_ids()
|
||||
|
||||
game_table = json.loads(open(os.path.expanduser("~/.cache/rare/game_list.json")).read())
|
||||
for game in games:
|
||||
if game.app_name not in game_table.keys():
|
||||
# TODO: Find id from method; Not upgrade all
|
||||
game_table[game.app_name] = {"grade": "pending", "id": "1234"}
|
||||
|
||||
json.dump(game_table, open(os.path.expanduser("~/.cache/rare/game_list.json"), "w"))
|
||||
signal.emit(i / len(game_list) * 100)
|
||||
|
||||
|
||||
def download_image(game, force=False):
|
||||
|
|
Loading…
Reference in a new issue