1
0
Fork 0
mirror of synced 2024-06-29 19:51:02 +12:00
Rare/rare/app.py

202 lines
7.4 KiB
Python
Raw Normal View History

2021-03-18 02:16:33 +13:00
import logging
2021-03-19 00:45:59 +13:00
import os
import platform
import shutil
2021-03-25 05:01:12 +13:00
import sys
import time
import traceback
from argparse import Namespace
from datetime import datetime
from typing import Optional
2021-03-18 02:16:33 +13:00
import legendary
2022-04-13 11:07:48 +12:00
import requests.exceptions
from PyQt5.QtCore import QThreadPool, QTimer, QT_VERSION_STR, PYQT_VERSION_STR
from PyQt5.QtWidgets import QApplication, QMessageBox
2021-10-15 10:05:00 +13:00
from requests import HTTPError
2021-03-18 02:16:33 +13:00
import rare
2021-04-08 08:39:23 +12:00
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
from rare.shared import (
LegendaryCoreSingleton,
GlobalSignalsSingleton,
ArgumentsSingleton,
)
from rare.shared.rare_core import RareCore
from rare.utils import legendary_utils, config_helper, paths
from rare.widgets.rare_app import RareApp
2021-03-18 02:16:33 +13:00
2021-03-18 02:16:33 +13:00
logger = logging.getLogger("Rare")
def excepthook(exc_type, exc_value, exc_tb):
tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
print("Error")
2021-10-15 10:05:00 +13:00
if exc_tb == HTTPError:
try:
if LegendaryCoreSingleton().login():
2021-10-15 10:05:00 +13:00
return
else:
raise ValueError
except Exception as e:
logger.fatal(str(e))
QMessageBox.warning(None, "Error", QApplication.tr("Failed to login"))
QApplication.exit(1)
return
logger.fatal(tb)
QMessageBox.warning(None, "Error", tb)
QApplication.exit(1)
class App(RareApp):
def __init__(self, args: Namespace):
super(App, self).__init__(args)
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
file_name = os.path.join(paths.log_dir(), f"Rare_{start_time}.log")
2022-09-08 11:13:10 +12:00
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
stream_handler = logging.StreamHandler(sys.stderr)
stream_handler.setFormatter(fmt=logging.Formatter("[%(name)s] %(levelname)s: %(message)s"))
# configure logging
if args.debug:
logging.basicConfig(
2022-09-08 11:13:10 +12:00
format="[%(name)s] %(levelname)s: %(message)s",
level=logging.DEBUG,
filename=file_name,
)
2022-09-08 11:13:10 +12:00
stream_handler.setLevel(logging.DEBUG)
logging.root.addHandler(stream_handler)
logging.getLogger().setLevel(level=logging.DEBUG)
# keep requests, asyncio and pillow quiet
logging.getLogger("requests").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("asyncio").setLevel(logging.WARNING)
logger.info(
f"Launching Rare version {rare.__version__} Codename: {rare.code_name}\n"
f" - Using Legendary {legendary.__version__} Codename: {legendary.__codename__} as backend\n"
f" - Operating System: {platform.system()}, Python version: {platform.python_version()}\n"
f" - Running {sys.executable} {' '.join(sys.argv)}\n"
f" - Qt version: {QT_VERSION_STR}, PyQt version: {PYQT_VERSION_STR}"
)
else:
logging.basicConfig(
format="[%(name)s] %(levelname)s: %(message)s",
level=logging.INFO,
filename=file_name,
)
2022-09-08 11:13:10 +12:00
stream_handler.setLevel(logging.INFO)
logging.root.addHandler(stream_handler)
logger.info(f"Launching Rare version {rare.__version__}")
logger.info(f"Operating System: {platform.system()}")
self.rare_core = RareCore(args=args)
self.args = ArgumentsSingleton()
self.signals = GlobalSignalsSingleton()
self.core = LegendaryCoreSingleton()
config_helper.init_config_handler(self.core)
2021-03-27 06:23:22 +13:00
lang = self.settings.value("language", self.core.language_code, type=str)
self.load_translator(lang)
2021-04-05 20:57:11 +12:00
# set Application name for settings
self.mainwindow: Optional[MainWindow] = None
self.launch_dialog: Optional[LaunchDialog] = None
self.timer = QTimer()
2021-09-30 10:22:47 +13:00
2021-04-05 20:57:11 +12:00
# launch app
self.launch_dialog = LaunchDialog(parent=None)
self.launch_dialog.quit_app.connect(self.launch_dialog.close)
self.launch_dialog.quit_app.connect(lambda ec: exit(ec))
2021-03-25 05:01:12 +13:00
self.launch_dialog.start_app.connect(self.start_app)
self.launch_dialog.start_app.connect(self.launch_dialog.close)
2021-04-20 01:44:28 +12:00
self.launch_dialog.login()
2021-03-25 05:01:12 +13:00
dt_exp = datetime.fromisoformat(self.core.lgd.userdata['expires_at'][:-1])
dt_now = datetime.utcnow()
td = abs(dt_exp - dt_now)
self.timer.timeout.connect(self.re_login)
2022-04-13 11:07:48 +12:00
self.timer.start(int(td.total_seconds() - 60) * 1000)
def re_login(self):
logger.info("Session expires shortly. Renew session")
2022-04-13 11:07:48 +12:00
try:
self.core.login()
except requests.exceptions.ConnectionError:
self.timer.start(3000) # try again if no connection
return
dt_exp = datetime.fromisoformat(self.core.lgd.userdata['expires_at'][:-1])
dt_now = datetime.utcnow()
td = abs(dt_exp - dt_now)
self.timer.start(int(td.total_seconds() - 60) * 1000)
2021-10-08 07:19:24 +13:00
def start_app(self):
for igame in self.core.get_installed_list():
2022-01-16 04:40:31 +13:00
if not os.path.exists(igame.install_path):
# lk; since install_path is lost anyway, set keep_files to True
# lk: to avoid spamming the log with "file not found" errors
legendary_utils.uninstall_game(self.core, igame.app_name, keep_files=True)
2022-01-16 04:40:31 +13:00
logger.info(f"Uninstalled {igame.title}, because no game files exist")
continue
2022-08-03 11:33:50 +12:00
# lk: games that don't have an override and can't find their executable due to case sensitivity
# lk: will still erroneously require verification. This might need to be removed completely
# lk: or be decoupled from the verification requirement
if override_exe := self.core.lgd.config.get(igame.app_name, "override_exe", fallback=""):
igame_executable = override_exe
else:
igame_executable = igame.executable
if not os.path.exists(os.path.join(igame.install_path, igame_executable.replace("\\", "/").lstrip("/"))):
igame.needs_verification = True
self.core.lgd.set_installed_game(igame.app_name, igame)
2022-01-16 04:40:31 +13:00
logger.info(f"{igame.title} needs verification")
2021-10-08 07:19:24 +13:00
self.mainwindow = MainWindow()
self.mainwindow.exit_app.connect(self.exit_app)
2021-03-18 02:16:33 +13:00
if not self.args.silent:
self.mainwindow.show()
if self.args.test_start:
self.exit_app(0)
def exit_app(self, exit_code=0):
2021-10-21 06:19:03 +13:00
threadpool = QThreadPool.globalInstance()
threadpool.waitForDone()
if self.timer is not None:
self.timer.stop()
self.timer.deleteLater()
self.timer = None
if self.mainwindow is not None:
self.mainwindow.close()
self.mainwindow = None
self.rare_core.deleteLater()
del self.rare_core
self.processEvents()
shutil.rmtree(paths.tmp_dir())
os.makedirs(paths.tmp_dir())
self.exit(exit_code)
2021-03-25 05:01:12 +13:00
def start(args):
# set excepthook to show dialog with exception
sys.excepthook = excepthook
while True:
app = App(args)
exit_code = app.exec_()
# if not restart
# restart app
del app
if exit_code != -133742:
break