def apply_all(self, reset=False): games_sql = GamesSql(self) rs_all_games = games_sql.get_games() len_games = self.qtobj.programs_tableWidget.rowCount() if len_games > 0: self.enable_form(False) self.enable_widgets(False) self.qtobj.apply_button.setEnabled(False) errors = [] games_obj = utils.Object() self.progressbar.set_values(messages.copying_DLLs, 0) for i in range(len(rs_all_games)): self.progressbar.set_values(messages.copying_DLLs, 100 / len_games) games_obj.api = rs_all_games[i]["api"] games_obj.architecture = rs_all_games[i]["architecture"] games_obj.game_name = rs_all_games[i]["name"] games_obj.path = rs_all_games[i]["path"] len_games = len_games - 1 result = _apply_single(self, games_obj, reset) if result is not None: errors.append(result) self.progressbar.close() self.enable_form(True) self.qtobj.apply_button.setEnabled(True) if len(errors ) == 0 and self.need_apply is False and self.show_info_messages: qtutils.show_message_window(self.log, "info", messages.apply_success) elif len(errors) > 0: err = "\n".join(errors) qtutils.show_message_window( self.log, "error", f"{messages.apply_success_with_errors}\n\n{err}")
def get_new_program_version(self): client_version = self.client_version remote_version = None remote_version_filename = constants.REMOTE_VERSION_FILENAME obj_return = Object() obj_return.new_version_available = False obj_return.new_version = None try: req = requests.get(remote_version_filename, stream=True) if req.status_code == 200: for line in req.iter_lines(decode_unicode=True): if line: remote_version = line.rstrip() break if remote_version is not None and (float(remote_version) > float(client_version)): obj_return.new_version_available = True obj_return.new_version_msg = f"Version {remote_version} available for download" obj_return.new_version = float(remote_version) else: err_msg = f"{messages.error_check_new_version}\n{messages.remote_version_file_not_found}\ncode: {req.status_code}" qtutils.show_message_window(self.log, "error", err_msg) except requests.exceptions.ConnectionError: qtutils.show_message_window(self.log, "error", messages.dl_new_version_timeout) return obj_return
def edit_default_preset_plugin_button_clicked(self): try: utils.check_local_files(self) os.startfile(constants.RESHADE_PRESET_PATH) except Exception as e: err_msg = f"{str(e)}\n\n{constants.RESHADE_PRESET_PATH}{messages.unable_start}" qtutils.show_message_window(self.log, "error", err_msg)
def check_reshade_updates(self): if self.check_reshade_updates: self.remote_reshade_version = None self.remote_reshade_download_url = None try: response = requests.get(constants.RESHADE_WEBSITE_URL) if response.status_code != 200: self.log.error(messages.reshade_page_error) else: html = str(response.text) soup = BeautifulSoup(html, "html.parser") body = soup.body blist = str(body).split("<p>") for content in blist: if content.startswith("<strong>Version "): self.remote_reshade_version = content.split()[1].strip( "</strong>") self.remote_reshade_download_url = f"{constants.RESHADE_EXE_URL}{self.remote_reshade_version}.exe" break if self.remote_reshade_version != self.reshade_version: self.need_apply = True download_reshade(self) except requests.exceptions.ConnectionError as e: self.log.error(f"{messages.reshade_website_unreacheable} {str(e)}") qtutils.show_message_window(self.log, "error", messages.reshade_website_unreacheable) return
def open_preset_config_file(self): self.enable_widgets(True) if self.selected_game is not None: game_dir = os.path.dirname(self.selected_game.path) res_plug_ini_path = os.path.join(game_dir, constants.RESHADE_PRESET_INI) try: if not os.path.isfile(constants.RESHADE_PRESET_PATH): create_files = Files(self) create_files.download_reshade_preset_file() except Exception as e: self.log.error(f"create_files: {str(e)}") try: if not os.path.isfile(res_plug_ini_path) and os.path.isfile( constants.RESHADE_PRESET_PATH): shutil.copy2(constants.RESHADE_PRESET_PATH, res_plug_ini_path) except Exception as e: self.log.error(str(e)) try: os.startfile(res_plug_ini_path) except Exception as e: err_msg = f"{str(e)}\n\n{messages.check_game_uninstalled}" qtutils.show_message_window(self.log, "error", err_msg) self.enable_widgets(False)
def reset_all_button_clicked(self): self.progressbar.set_values(messages.reseting_files, 25) Files(self).download_all_files() self.progressbar.set_values(messages.reseting_files, 50) utils.download_shaders(self) self.progressbar.set_values(messages.reseting_files, 75) apply_all(self, reset=True) self.progressbar.close() qtutils.show_message_window(self.log, "info", messages.reset_success)
def __init__(self, logs_dir, days_to_keep): files_list = [f for f in os.listdir(logs_dir) if os.path.isfile(f"{logs_dir}/{f}") and os.path.splitext(f)[1] == ".gz"] for file in files_list: file_path = f"{logs_dir}/{file}" if self._is_file_older_than_x_days(file_path, days_to_keep): try: os.remove(file_path) except Exception as e: err_msg = f"[ERROR]:Unable to removed old logs:{str(e)}: {file_path}\n" qtutils.show_message_window(None, "error", err_msg) sys.stderr.write(err_msg)
def download_reshade(self): # removing old version if self.reshade_version is not None: old_local_reshade_exe = os.path.join( constants.PROGRAM_PATH, f"ReShade_Setup_{self.reshade_version}.exe") if os.path.isfile(old_local_reshade_exe): self.log.info(messages.removing_old_reshade_file) os.remove(old_local_reshade_exe) try: # downloading new reshade version self.local_reshade_path = os.path.join( constants.PROGRAM_PATH, f"ReShade_Setup_{self.remote_reshade_version}.exe") r = requests.get(self.remote_reshade_download_url) if r.status_code == 200: self.log.info( f"{messages.downloading_new_reshade_version}: {self.remote_reshade_version}" ) with open(self.local_reshade_path, "wb") as outfile: outfile.write(r.content) else: self.log.error(messages.error_check_new_reshade_version) return except Exception as e: if hasattr(e, "errno") and e.errno == 13: qtutils.show_message_window(self.log, "error", messages.error_permissionError) else: self.log.error( f"{messages.error_check_new_reshade_version} {str(e)}") return self.reshade_version = self.remote_reshade_version unzip_reshade(self, self.local_reshade_path) config_sql = ConfigSql(self) config_sql.update_reshade_version(self.remote_reshade_version) self.qtobj.reshade_version_label.clear() self.qtobj.reshade_version_label.setText( f"{messages.info_reshade_version}{self.remote_reshade_version}") len_games = self.qtobj.programs_tableWidget.rowCount() if self.need_apply and len_games > 0: events.apply_all(self) qtutils.show_message_window( self.log, "info", f"{messages.new_reshade_version}\n" f"Version: {self.remote_reshade_version}\n\n" f"{messages.apply_success}") self.need_apply = False
def edit_game_path(self): if self.selected_game is not None: old_game_path = self.selected_game.path new_game_path = qtutils.open_qt_file_dialog() if new_game_path is not None: new_game_dir = os.path.dirname(new_game_path) if old_game_path == new_game_path: self.enable_widgets(False) if self.show_info_messages: qtutils.show_message_window(self.log, "info", messages.no_change_path) return old_file_name, old_extension = os.path.splitext( os.path.basename(old_game_path)) new_file_name, new_extension = os.path.splitext( os.path.basename(new_game_path)) if old_file_name != new_file_name: self.enable_widgets(False) qtutils.show_message_window( self.log, "error", f"{messages.not_same_game}\n\n{old_file_name}") return if new_extension.lower() != ".exe": self.enable_widgets(False) qtutils.show_message_window( self.log, "error", f"{messages.not_valid_game}\n\n{new_file_name}") return # save into database games_obj = utils.Object() games_sql = GamesSql(self) games_obj.id = self.selected_game.id games_obj.path = new_game_path games_sql.update_game_path(games_obj) # create Reshade.ini to replace edit CurrentPresetPath game_screenshots_path = utils.get_screenshot_path( self, new_game_dir, self.selected_game.name) self.selected_game.game_dir = new_game_dir try: files = Files(self) files.apply_reshade_ini_file(new_game_dir, game_screenshots_path) except Exception as e: self.log.error(f"create_files: {str(e)}") if self.show_info_messages: qtutils.show_message_window( self.log, "info", f"{messages.path_changed_success}\n\n{new_game_path}") self.log.info(f"{messages.path_changed_success}: {new_game_path}") self.populate_table_widget() self.enable_widgets(False)
def download_new_program_version(self): program_url = f"{constants.GITHUB_EXE_PROGRAM_URL}{self.new_version}/{constants.EXE_PROGRAM_NAME}" r = requests.get(program_url) if r.status_code == 200: with open(self.program_path, "wb") as outfile: outfile.write(r.content) qtutils.show_message_window( self.log, "info", f"{messages.program_updated}v{self.new_version}") else: qtutils.show_message_window(self.log, "error", messages.error_dl_new_version) self.log.error( f"{messages.error_dl_new_version} {r.status_code} {r}")
def __call__(self, source, dest): RemoveOldLogs(self.logs_dir, self.days_to_keep) if os.path.isfile(source) and os.stat(source).st_size > 0: try: sfname, sext = os.path.splitext(source) dfname, dext = os.path.splitext(dest) renamed_dst = f"{sfname}_{dext.replace('.', '')}{sext}.gz" with open(source, "rb") as fin: with gzip.open(renamed_dst, "wb") as fout: fout.writelines(fin) os.remove(source) except Exception as e: err_msg = f"[ERROR]:Unable to compress the log file:[{str(e)}]: {source}\n" qtutils.show_message_window(None, "error", err_msg) sys.stderr.write(err_msg)
def call_program(self): code = None try: process = subprocess.run(self.program_path, shell=True, check=True, universal_newlines=True) code = process.returncode except Exception as e: if code is None and hasattr(e, "returncode"): self.log.error( f"cmd:{self.program_path} - code:{e.returncode} - {e}") msg = f"{messages.error_executing_program}{constants.EXE_PROGRAM_NAME}\n"\ f"{messages.error_check_installation}" qtutils.show_message_window(self.log, "error", msg)
def setup_logging(self): try: os.makedirs(self.dir, exist_ok=True) if not os.path.isdir(self.dir) else None except Exception as e: err_msg = f"[ERROR]:[EXITING]:[{str(e)}]:Unable to create logs directory: {self.dir}\n" qtutils.show_message_window(None, "error", err_msg) sys.stderr.write(err_msg) sys.exit(1) log_filename = f"{constants.SHORT_PROGRAM_NAME}.log" log_file_path = f"{self.dir}/{log_filename}" try: open(log_file_path, "a+").close() except IOError as e: err_msg = f"[ERROR]:[EXITING]:[{str(e)}]:Unable to open the log file for writing: {log_file_path}\n" qtutils.show_message_window(None, "error", err_msg) sys.stderr.write(err_msg) sys.exit(1) if self.level == logging.DEBUG: formatt = "[%(asctime)s.%(msecs)03d]:[%(levelname)s]:[%(filename)s:%(funcName)s:%(lineno)d]:%(message)s" else: formatt = "[%(asctime)s.%(msecs)03d]:[%(levelname)s]:%(message)s" formatter = logging.Formatter(formatt, datefmt="%Y-%m-%dT%H:%M:%S") logger = logging.getLogger() logger.setLevel(self.level) file_hdlr = logging.handlers.RotatingFileHandler( filename=log_file_path, maxBytes=1 * 1024 * 1024, encoding="UTF-8", backupCount=self.days_to_keep, mode="a") file_hdlr.setFormatter(formatter) file_hdlr.suffix = "%Y%m%d" file_hdlr.rotator = GZipRotator(self.dir, self.days_to_keep) logger.addHandler(file_hdlr) stream_hdlr = logging.StreamHandler() stream_hdlr.setFormatter(formatter) stream_hdlr.setLevel(self.level) logger.addHandler(stream_hdlr) return logger
def check_database_connection(self): if self.database is not None: conn = self.database.engine.connect() if conn is not None: conn.close() return True err_msg = f"{messages.error_db_connection}\n\n{messages.exit_program}" if qtutils.show_message_window(self.log, "error", err_msg): sys.exit(1)
def check_default_database_tables(self): from src.sql.tables import Configs, Games try: Configs.__table__.create(self.database.engine, checkfirst=True) Games.__table__.create(self.database.engine, checkfirst=True) except Exception as e: self.log.error(str(e)) err_msg = f"{messages.error_db_connection}\n\n{messages.exit_program}" if qtutils.show_message_window(self.log, "error", err_msg): sys.exit(1)
def check_default_database_configs(self): config_sql = ConfigSql(self) rs_config = config_sql.get_program_version() if rs_config is not None: program_version = rs_config[0].get("program_version") if float(program_version) < float(constants.RESET_DATABASE_VERSION): try: os.remove(constants.SQLITE3_PATH) check_database_connection(self) check_default_database_tables(self) qtutils.show_message_window(self.log, "warning", messages.config_reset_msg) except Exception: err_msg = f"{messages.error_db_connection}\n\n{messages.exit_program}" if qtutils.show_message_window(self.log, "error", err_msg): sys.exit(1) if not set_default_database_configs(self, constants.VERSION): err_msg = f"{messages.error_create_sql_config_msg}\n\n{messages.exit_program}" if qtutils.show_message_window(self.log, "error", err_msg): sys.exit(1)
def add_game(self): filename_path = qtutils.open_qt_file_dialog() if filename_path is not None: file_name, extension = os.path.splitext( os.path.basename(filename_path)) if extension.lower() == ".exe": games_sql = GamesSql(self) rs_name = games_sql.get_game_by_path(filename_path) if rs_name is None: self.selected_game = None self.added_game_path = filename_path binary_type = utils.get_binary_type(self, filename_path) if binary_type in ["AMD64", "IA64"]: architecture = "64bits" elif binary_type in ["IA32"]: architecture = "32bits" else: qtutils.show_message_window(self.log, "error", messages.not_valid_game) return qtutils.show_game_config_form(self, file_name, architecture) elif rs_name is not None and len(rs_name) > 0: qtutils.show_message_window( self.log, "error", f"{messages.game_already_exist}\n\n{file_name}") else: qtutils.show_message_window(self.log, "error", messages.not_valid_game)
def download_shaders(self): try: r = requests.get(constants.SHADERS_ZIP_URL) with open(constants.SHADERS_ZIP_PATH, "wb") as outfile: outfile.write(r.content) except Exception as e: err_msg = f"{messages.dl_new_shaders_timeout} {str(e)}" qtutils.show_message_window(self.log, "error", err_msg) try: if os.path.isdir(constants.SHADERS_SRC_PATH): shutil.rmtree(constants.SHADERS_SRC_PATH) except OSError as e: self.log.error(f"rmtree: {str(e)}") try: if os.path.isdir(constants.RES_SHAD_MPATH): shutil.rmtree(constants.RES_SHAD_MPATH) except OSError as e: self.log.error(f"rmtree: {str(e)}") if os.path.isfile(constants.SHADERS_ZIP_PATH): try: unzip_file(constants.SHADERS_ZIP_PATH, constants.PROGRAM_PATH) except FileNotFoundError as e: self.log.error(str(e)) except zipfile.BadZipFile as e: self.log.error(str(e)) try: os.remove(constants.SHADERS_ZIP_PATH) except OSError as e: self.log.error(f"remove_file: {str(e)}") try: if os.path.isdir(constants.RES_SHAD_MPATH): out_dir = f"{constants.PROGRAM_PATH}\\{constants.RESHADE_SHADERS}" os.rename(constants.RES_SHAD_MPATH, out_dir) except OSError as e: self.log.error(f"rename_path: {str(e)}")
def check_local_files(self): from src.files import Files files = Files(self) try: if not os.path.isfile(constants.RESHADE_INI_PATH): files.download_reshade_ini_file() except Exception as e: err_msg = f"{str(e)}\n\n{constants.RESHADE_INI_PATH}{messages.not_found}" qtutils.show_message_window(self.log, "error", err_msg) try: if not os.path.isfile(constants.RESHADE_PRESET_PATH): files.download_reshade_preset_file() except Exception as e: err_msg = f"{str(e)}\n\n{constants.RESHADE_PRESET_PATH}{messages.not_found}" qtutils.show_message_window(self.log, "error", err_msg) try: if not os.path.isfile(constants.QSS_PATH): files.download_qss_file() except Exception as e: err_msg = f"{str(e)}\n\n{constants.QSS_PATH}{messages.not_found}" qtutils.show_message_window(self.log, "error", err_msg)
def game_config_form_result(self, architecture, status): self.game_config_form.close() dx9_name = constants.DX9_DISPLAY_NAME dxgi_name = constants.DXGI_DISPLAY_NAME opengl_name = constants.OPENGL_DISPLAY_NAME if status == "OK": if self.game_config_form.qtObj.game_name_lineEdit.text() == "": qtutils.show_message_window(self.log, "error", messages.missing_game_name) return if not self.game_config_form.qtObj.opengl_radioButton.isChecked() \ and not self.game_config_form.qtObj.dx9_radioButton.isChecked() \ and not self.game_config_form.qtObj.dx_radioButton.isChecked(): qtutils.show_message_window(self.log, "error", messages.missing_api) return sql_games_obj = utils.Object() sql_games_obj.game_name = self.game_config_form.qtObj.game_name_lineEdit.text( ) if architecture == "32bits": sql_games_obj.architecture = "32bits" src_path = constants.RESHADE32_PATH else: sql_games_obj.architecture = "64bits" src_path = constants.RESHADE64_PATH games_sql = GamesSql(self) if self.selected_game is not None: if self.game_config_form.qtObj.dx9_radioButton.isChecked(): sql_games_obj.api = dx9_name dst_path = os.path.join(self.selected_game.game_dir, constants.D3D9_DLL) elif self.game_config_form.qtObj.dx_radioButton.isChecked(): sql_games_obj.api = dxgi_name dst_path = os.path.join(self.selected_game.game_dir, constants.DXGI_DLL) else: sql_games_obj.api = opengl_name dst_path = os.path.join(self.selected_game.game_dir, constants.OPENGL_DLL) if self.selected_game.name != sql_games_obj.game_name or ( self.selected_game.api != sql_games_obj.api): # checking name changes # create Reshade.ini to replace edit CurrentPresetPath old_screenshots_path = utils.get_screenshot_path( self, self.selected_game.game_dir, self.selected_game.name) if len(old_screenshots_path) > 0: scrrenshot_dir_path = os.path.dirname(old_screenshots_path) new_screenshots_path = os.path.join( scrrenshot_dir_path, sql_games_obj.game_name) else: new_screenshots_path = "" try: files = Files(self) files.apply_reshade_ini_file(self.selected_game.game_dir, new_screenshots_path) except Exception as e: self.log.error(f"download_reshade_ini_file: {str(e)}") try: # rename screenshot folder if os.path.isdir(old_screenshots_path): os.rename(old_screenshots_path, new_screenshots_path) except OSError as e: self.log.error(f"rename_screenshot_dir: {str(e)}") try: # deleting Reshade.dll if self.selected_game.api == dx9_name: d3d9_game_path = os.path.join( self.selected_game.game_dir, constants.D3D9_DLL) if os.path.isfile(d3d9_game_path): os.remove(d3d9_game_path) elif self.selected_game.api == opengl_name: opengl_game_path = os.path.join( self.selected_game.game_dir, constants.OPENGL_DLL) if os.path.isfile(opengl_game_path): os.remove(opengl_game_path) else: dxgi_game_path = os.path.join( self.selected_game.game_dir, constants.DXGI_DLL) if os.path.isfile(dxgi_game_path): os.remove(dxgi_game_path) except OSError as e: self.log.error(f"remove_reshade_file: {str(e)}") try: # creating Reshade.dll shutil.copy2(src_path, dst_path) except shutil.Error as e: self.log.error( f"copyfile: {src_path} to {dst_path} - {str(e)}") if self.show_info_messages: qtutils.show_message_window( self.log, "info", f"{messages.game_updated}\n\n{sql_games_obj.game_name}" ) sql_games_obj.id = self.selected_game.id games_sql.update_game(sql_games_obj) self.populate_table_widget() self.enable_widgets(False) else: # new game added if self.game_config_form.qtObj.dx9_radioButton.isChecked(): sql_games_obj.api = dx9_name elif self.game_config_form.qtObj.opengl_radioButton.isChecked(): sql_games_obj.api = opengl_name else: sql_games_obj.api = dxgi_name sql_games_obj.path = self.added_game_path games_sql.insert_game(sql_games_obj) del self.added_game_path _apply_single(self, sql_games_obj) self.populate_table_widget() self.enable_widgets(False) if self.show_info_messages: qtutils.show_message_window( self.log, "info", f"{messages.game_added}\n\n{sql_games_obj.game_name}")
def delete_game(self): game_not_found = False if not utils.check_game_file(self): game_not_found = True #self.enable_widgets(True) if self.selected_game is not None: game_path = os.path.dirname(self.selected_game.path) game_name = self.selected_game.name # remove dll from game path if self.selected_game.api == constants.OPENGL_DISPLAY_NAME: reshade_dll = os.path.join(game_path, constants.OPENGL_DLL) log_file = f"{os.path.splitext(constants.OPENGL_DLL)[0]}.log" log_file_path = os.path.join(game_path, log_file) elif self.selected_game.api == constants.DX9_DISPLAY_NAME: reshade_dll = os.path.join(game_path, constants.D3D9_DLL) log_file = f"{os.path.splitext(constants.D3D9_DLL)[0]}.log" log_file_path = os.path.join(game_path, log_file) else: reshade_dll = os.path.join(game_path, constants.DXGI_DLL) log_file = f"{os.path.splitext(constants.DXGI_DLL)[0]}.log" log_file_path = os.path.join(game_path, log_file) if os.path.isfile(reshade_dll): try: os.remove(reshade_dll) except OSError as e: self.log.error(f"remove_file: {str(e)}") qtutils.show_message_window( self.log, "error", f"{messages.error_delete_dll} {game_name} dll\n\n{str(e)}") self.enable_widgets(False) return try: # remove Reshade.ini reshade_ini = os.path.join(game_path, constants.RESHADE_INI) if os.path.isfile(reshade_ini): os.remove(reshade_ini) # remove ReShadePreset.ini reshade_plug_ini = os.path.join(game_path, constants.RESHADE_PRESET_INI) if os.path.isfile(reshade_plug_ini): os.remove(reshade_plug_ini) # remove Reshade log file if os.path.isfile(log_file_path): os.remove(log_file_path) # remove ReShadeGUI.ini reshadegui_ini = os.path.join(game_path, constants.RESHADEGUI_INI) if os.path.isfile(reshadegui_ini): os.remove(reshadegui_ini) # remove from database games_sql = GamesSql(self) games_sql.delete_game(self.selected_game.id) self.populate_table_widget() if self.show_info_messages: if game_not_found: qtutils.show_message_window( self.log, "info", f"{messages.game_not_in_path_deleted}\n\n{game_name}") else: qtutils.show_message_window( self.log, "info", f"{messages.game_deleted}\n\n{game_name}") except OSError as e: qtutils.show_message_window( self.log, "error", f"ERROR deleting {game_name} files\n\n{str(e)}") self.enable_widgets(False)