def get_lib_folders_from_vdf(steam_apps_path): logger.info('get lib folders from vdf') # vdfファイルを探す library_folders_vdf_path = __(steam_apps_path, "libraryfolders.vdf") if os.path.exists(library_folders_vdf_path) is False: raise Exception(_("ERR_NOT_FIND_LIBRARYFOLDERS_VDF")) logger.info('library_folders_vdf_path=%s', library_folders_vdf_path) # vdfファイルにある"[数字]" "xxxx"をさがす install_dir_pattern = re.compile(r'\s*"[0-9a-zA-Z]+"\s+"(.*)') logger.info('install_dir_pattern=%s', install_dir_pattern) game_libs_paths = [] with open(library_folders_vdf_path, mode='r', encoding="utf8", errors='ignore') as target_vdf_file: logger.info('open %s', library_folders_vdf_path) for line in target_vdf_file: result = install_dir_pattern.match(line) if result is not None: game_libs_paths.append( __( result.group(1).strip("\"").replace("\\\\", "\\"), "steamapps")) logger.info('game_libs_paths=%s', game_libs_paths) return game_libs_paths
def uninstaller(uninstall_info_list): logger.info('uninstall') for info in uninstall_info_list: final_check_file = info['final_check_file'] remove_target_paths = info['remove_target_paths'] logger.info('remove_target_paths=%s', remove_target_paths) base_path = '.' if 'app_id' in info: base_path = get_game_install_dir_path(info['app_id']) elif 'game_dir_name' in info: base_path = __(get_my_documents_folder(), "Paradox Interactive", info['game_dir_name']) # Modダウンローダーをuninstallモードで起動 if os.path.exists(__(base_path, "claes.exe")): logger.info('claes uninstall mode') sb.call(__(base_path, "claes.exe /uninstall-all")) logger.info('base_path=%s', base_path) # 最終チェックファイルがあるかを確認する。このファイルがあるかどうかで本当にインストールされているか判断する if os.path.exists(__(base_path, final_check_file)) is False: raise Exception(_('ERR_NOT_EXIST_FINAL_CHECK_FILE')) for path in remove_target_paths: remove_util(__(base_path, path)) logger.info('finish')
def mod_installer(app_id, target_repository, key_file_name, key_list_url, game_dir_name=None): logger.info('mod install') # exeを見つける install_dll_dir_path = get_game_install_dir_path(app_id) logger.info('install_dll_dir_path=%s', install_dll_dir_path) # My Documents をAPIから見つける if game_dir_name is None: install_game_dir_path = install_dll_dir_path else: install_game_dir_path = __(get_my_documents_folder(), "Paradox Interactive", game_dir_name) logger.info('install_game_dir_path=%s', install_game_dir_path) logger.info('install downloader') # Modダウンローダーを配置 install_downloader(target_repository=target_repository, install_dir_path=install_game_dir_path) logger.info('done') # keyファイルを保存 os.makedirs(__(install_game_dir_path, 'claes.key'), exist_ok=True) key_ids = json.loads( urllib.request.urlopen(key_list_url).read().decode('utf8')) logger.info('key_ids=%s', key_ids) for item in key_ids: install_key_file(save_file_path=__(install_game_dir_path, "claes.key", item.get("id") + ".key"), mod_title=item.get("name"), key_file_path=__(install_dll_dir_path, key_file_name)) logger.info('call claes') # Modダウンローダーを起動 mod_downloader_path = __(install_game_dir_path, "claes.exe") logger.info('mod_downloader_path=%s', mod_downloader_path) sb.call(mod_downloader_path, shell=True) logger.info('done')
def get_game_install_dir_path(target_app_id): logger.info('Get install dir path') # レジストリを見て、Steamのインストール先を探す # 32bitを見て、なければ64bitのキーを探しに行く。それでもなければそもそもインストールされていないと判断する try: steam_install_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam") except OSError: try: steam_install_key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\Valve\\Steam") except OSError: raise Exception(_("ERR_NOT_FIND_STEAM_REGKEY")) logger.info('Find steam_install_key in reg') try: steam_install_path, key_type = winreg.QueryValueEx( steam_install_key, "InstallPath") except FileNotFoundError: raise Exception(_("ERR_NOT_FIND_INSTALLPATH_IN_STEAM_REGKEY")) steam_install_key.Close() logger.info('steam_install_path=%s, key_type=%s', steam_install_path, key_type) # 基本問題ないと思うが念の為 if key_type != winreg.REG_SZ: raise Exception("invald value") # デフォルトのsteamappsフォルダを探す steam_apps_path = __(steam_install_path, "steamapps") if os.path.exists(steam_apps_path) is False: raise Exception(_("ERR_NOT_EXIST_DEFAULT_STEAMAPPS_DIR")) logger.info('steam_apps_path=%s', steam_apps_path) # acfがあるフォルダを列挙 acf_dir_paths = [steam_apps_path] acf_dir_paths.extend(get_lib_folders_from_vdf(steam_apps_path)) logger.info('acf_dir_paths=%s', acf_dir_paths) # 各ディレクトリについて処理 game_install_dir_path = None for dir_path in acf_dir_paths: game_install_dir_path = get_game_install_dir(dir_path, target_app_id) if game_install_dir_path is None: continue else: break logger.info('game_install_dir_path=%s', game_install_dir_path) if game_install_dir_path is None: raise Exception(_("ERR_NOT_FIND_TARGET_GAME_ON_YOUR_PC")) return game_install_dir_path
def get_game_install_dir(dir_path, target_app_id): logger.info('get game install dir') # インストールディレクトリにあるsteamapps/appmanifest_[APPID].acfを探す target_app_acf_path = __(dir_path, "appmanifest_{}.acf".format(target_app_id)) logger.info('target_app_acf_path=%s', target_app_acf_path) # なければ終了 if os.path.exists(target_app_acf_path) is False: return None # acfファイルにある"installdir" "xxxx"をさがす install_dir_pattern = re.compile(r'\s*"installdir"\s+"(.*)') game_install_dir_name = None with open(target_app_acf_path, mode='r', encoding="utf8", errors='ignore') as target_app_acf_file: logger.info('open %s', target_app_acf_path) for line in target_app_acf_file: result = install_dir_pattern.match(line) if result is not None: game_install_dir_name = result.group(1).strip("\"") break logger.info('game_install_dir_name=%s', game_install_dir_name) if game_install_dir_name is None: raise Exception(_("ERR_INVALID_ACF")) # パスを確認 game_install_dir_path = __(dir_path, "common", game_install_dir_name) if os.path.exists(game_install_dir_path) is False: raise Exception(_("ERR_NOT_EXIST_GAME_INSTALL_DIR")) logger.info('game_install_dir_path=%s', game_install_dir_path) return game_install_dir_path
def install(install_dir_path, target_zip_url, final_check_file): logger.info('install') final_check_file_path = __(install_dir_path, final_check_file) logger.info('final_check_file_path=%s', final_check_file_path) # 最終チェックファイルがあるかを確認する if os.path.exists(final_check_file_path) is False: raise Exception(_('ERR_NOT_EXIST_FINAL_CHECK_FILE')) # 最終チェックファイルがある場所に対してファイルを展開する final_check_file_dir = os.path.dirname(final_check_file_path) logger.info('final_check_file_dir=%s', final_check_file_dir) path, headers = urllib.request.urlretrieve(target_zip_url) logger.info('path=%s,headers=%s', path, headers) with zipfile.ZipFile(path) as existing_zip: existing_zip.extractall(final_check_file_dir) logger.info('zip unpacked')