diff --git a/config.ini b/config.ini index 51752c7..ceda92c 100644 --- a/config.ini +++ b/config.ini @@ -91,3 +91,12 @@ Chenyu=https://static.wikia.nocookie.net/gensin-impact/images/6/68/Emblem_Chenyu Enkanomiya=https://static.wikia.nocookie.net/gensin-impact/images/6/65/Enkanomiya_Emblem_Night.png/revision/latest?cb=20231103102358 Teapot=https://static.wikia.nocookie.net/gensin-impact/images/5/56/Emblem_Serenitea_Pot.png/revision/latest?cb=20210615025730 Domain=https://static.wikia.nocookie.net/gensin-impact/images/b/b1/Emblem_Domains.png/revision/latest?cb=20210615025731 + + +[INTERNAL] +; ------------------------------ Internal ------------------------------- +; Below are used internally by the program +; You MAY NOT change them +; +Version=1.0.1 +Updated_data=False \ No newline at end of file diff --git a/src/config.py b/src/config.py index ae13d88..472ef74 100644 --- a/src/config.py +++ b/src/config.py @@ -39,7 +39,9 @@ _tray_icon.run_detached() -interactor = InteractionManager(os.path.join(MAIN_DIRECTORY, "config.ini"), "d3d11_log.txt") +interactor = InteractionManager(os.path.join(MAIN_DIRECTORY, "config.ini")) + +_VERSION: Final[str] = interactor.get_ini_settings("INTERNAL", "Version") # External configs # @@ -91,6 +93,7 @@ os.path.join(MAIN_DIRECTORY, "data"), os.path.join(GIMI_DIRECTORY, "Mods"), COPY_REQUIRED_DATA, + not interactor.get_ini_settings("INTERNAL", "Updated_data", type_=bool), ), check_path="PlayableCharacterData.ini", ) @@ -178,4 +181,6 @@ if IS_TESTING: logging.disable(logging.CRITICAL) +interactor.set_ini_option("INTERNAL", "Updated_data", "True") + _program_stop_flag: bool = False diff --git a/src/data_handler/update_data.py b/src/data_handler/update_data.py index 765bb7c..d46c2cb 100644 --- a/src/data_handler/update_data.py +++ b/src/data_handler/update_data.py @@ -7,12 +7,34 @@ import requests -from utils.data_tools import separate_with - try: import config + from utils.data_tools import separate_with except ImportError: - pass + # Work-around: Duplicate code from utils.data_tools + def separate_with(string: str, separator: str) -> str: + names: list[str] = [] + lowercases: str = "" + uppercase: str = "" + + for idx, char in enumerate(string): + if char.isupper(): + if idx != 0 and string[idx - 1] == uppercase: + lowercases += char + continue + + if lowercases: + names.append(f"{uppercase}{lowercases}") + + lowercases = "" + uppercase = char + else: + lowercases += char + + names.append(f"{uppercase}{lowercases}") + string = separator.join(names) + + return string def update_character(name: str, ini_file: str) -> bool: @@ -43,7 +65,7 @@ def update_character(name: str, ini_file: str) -> bool: config_parser: ConfigParser = ConfigParser() config_parser.read(ini_file) - separate_with(name, "_") + name = separate_with(name, "_") texture_name: str = f"TextureOverride__{name}__VertexLimitRaise" diff --git a/src/interaction_manager.py b/src/interaction_manager.py index 7638df6..26d06b4 100644 --- a/src/interaction_manager.py +++ b/src/interaction_manager.py @@ -6,14 +6,17 @@ class InteractionManager: - def __init__(self, ini_file: str, log_file_name: str): + def __init__(self, ini_file: str): self._logger = logging.getLogger(__name__) self.ini_file: str = ini_file - self.log_file_name: str = log_file_name # Creates a case-sensitive ConfigParser - self.config_parser: ConfigParser = ConfigParser() + # and accepts comments "as values" (also duplicate values) + # this may have side effects, e.g. some blank lines are not preserved + self.config_parser: ConfigParser = ConfigParser( + comment_prefixes="/", allow_no_value=True, strict=False + ) self.config_parser.optionxform = lambda option: option # type: ignore # github.com/python/mypy/issues/5062 def set_ini_option(self, section: str, option: str, value: Any) -> None: @@ -22,7 +25,7 @@ def set_ini_option(self, section: str, option: str, value: Any) -> None: self.config_parser[section][option] = value - with open(self.ini_file, "w") as file: + with open(self.ini_file, "w", encoding="utf-8") as file: self.config_parser.write(file) def get_ini_settings( @@ -133,11 +136,16 @@ def find_folder(cls, folder: str, start: str) -> Optional[str]: return None def set_up_rpc_data_folder( - self, folder_name: str, datas_folder: str, mods_folder: str, copy_data: bool + self, + folder_name: str, + datas_folder: str, + mods_folder: str, + copy_data: bool, + force_update: bool = False, ) -> str: rpc_folder: Optional[str] = self.find_folder(folder_name, mods_folder) - if rpc_folder: + if rpc_folder and not force_update: return rpc_folder if not copy_data: @@ -161,18 +169,6 @@ def set_up_rpc_data_folder( return rpc_folder - def get_check_save_ini(self, section: str, option: str, *, mode: str = "strict") -> str: - self._logger.info("Finding and reading config.ini") - argument: str = str(self.get_ini_settings(section, option, mode=mode)) - - self._logger.info("Checking correct directory") - directory: str = self.check_directory(argument, check_file=self.log_file_name, mode=mode) - - self._logger.info("Saving directory to config.ini") - self.set_ini_option(section, option, directory) - - return directory - @staticmethod def wait_input_response(message: str, *, question: bool = True) -> Union[str, bool]: while True: diff --git a/src/log_monitor.py b/src/log_monitor.py index 648c675..376760c 100644 --- a/src/log_monitor.py +++ b/src/log_monitor.py @@ -105,10 +105,16 @@ def handle_log(self) -> None: # "TextureOverride\Mods\Anything\RichPresenceData\PlayableCharacterData.ini\__Hu_Tao__VertexLimitRaise (...)" as "Hu Tao" ini_name: str asset_name: str - ini_name, asset_name = line.split("RichPresenceData\\")[1].split("\\", 2) - # Gets only the asset name e.g. "__Sumeru_Forest__(...)" as "Sumeru Forest" - asset_name = asset_name.split("__", 2)[1].replace("_", " ") + try: + ini_name, asset_name = line.split("RichPresenceData\\")[1].split("\\", 2) + + # Gets only the asset name e.g. "__Sumeru_Forest__(...)" as "Sumeru Forest" + asset_name = asset_name.split("__", 2)[1].replace("_", " ") + except IndexError: + self._logger.warning("Exception catched while splitting the log line. Ignoring") + self._logger.debug(f"Line: {line}") + continue if ini_name == "PlayableCharacterData.ini": if self.rpc.current_character == asset_name: @@ -125,7 +131,10 @@ def handle_log(self) -> None: self.rpc.previous_region = self.rpc.current_region self.rpc.current_region = asset_name self.rpc.updatable = True - self._logger.debug( - f"Updated region to {self.rpc.current_region}, " - f"hash: {line.split('hash=')[1].split(' ')[0]}" - ) + try: + self._logger.debug( + f"Updated region to {self.rpc.current_region}, " + f"hash: {line.split('hash=')[1].split(' ')[0]}" + ) + except IndexError: + pass diff --git a/src/rich_presence.py b/src/rich_presence.py index d00e276..06bd1d1 100644 --- a/src/rich_presence.py +++ b/src/rich_presence.py @@ -55,7 +55,12 @@ def __init__(self, game_monitor: GameMonitor) -> None: def _teardown(self, _signal_number: int, _stack_frame: Union[FrameType, None]) -> None: if self.connected: self._logger.warning("Clearing Rich Presence") - self.clear() + + try: + self.clear() + except pypresence.exceptions.PipeClosed: + pass + self.connected = False def connect(self) -> None: @@ -128,15 +133,18 @@ def update_rpc(self) -> None: self._logger.debug("Setting region as the_chasm instead of liyue to workaround #27") self.current_region = "The Chasm" - self.update( - start=self.game_monitor.get_process_create_time(), - state=self.get_parsed_configs("state"), - details=self.get_parsed_configs("details"), - large_image=self.get_parsed_configs("large_image"), - small_image=self.get_parsed_configs("small_image"), - large_text=self.get_parsed_configs("large_text"), - small_text=self.get_parsed_configs("small_text"), - ) + try: + self.update( + start=self.game_monitor.get_process_create_time(), + state=self.get_parsed_configs("state"), + details=self.get_parsed_configs("details"), + large_image=self.get_parsed_configs("large_image"), + small_image=self.get_parsed_configs("small_image"), + large_text=self.get_parsed_configs("large_text"), + small_text=self.get_parsed_configs("small_text"), + ) + except pypresence.exceptions.PipeClosed: + self.connect() self.set_last_update() self.updatable = False diff --git a/src/utils/data_tools.py b/src/utils/data_tools.py index d4de124..09bda0c 100644 --- a/src/utils/data_tools.py +++ b/src/utils/data_tools.py @@ -43,7 +43,7 @@ def separate_with(string: str, separator: str) -> str: # e.g. HuTao as Hu_Tao or AmberCN as Amber_CN for idx, char in enumerate(string): if char.isupper(): - if string[idx - 1] == uppercase: + if idx != 0 and string[idx - 1] == uppercase: lowercases += char continue