def get_client_users(): key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "SOFTWARE\Valve\Steam", 0, winreg.KEY_QUERY_VALUE) path, t = winreg.QueryValueEx(key, "SteamPath") users = {} path += "/config/loginusers.vdf" with open(path, "r", encoding="utf-8") as file: users = vdf.load(file) winreg.CloseKey(key) users = users["users"] rewrite = False for key, val in users.items(): if (users[key]["RememberPassword"] == 0): users.pop(key, None) continue if ("AccountID" not in val): users[key]["AccountID"] = str(Sid.SteamID(key).id) rewrite = True if (rewrite): print("重寫 loginusers.") with open(path, "w", encoding="utf-8") as file: vdf.dump({"users": users}, file) return (users)
def main(): parser = argparse.ArgumentParser( description= 'Creates an update script for GoD-Tony\'s sourcemod plugin updater.') parser.add_argument( "--sm_path", type=Path, help= "The path to the root sourcemod folder that you bundle with your plugin" ) parser.add_argument("--version", type=str, help="The current version of the plugin") parser.add_argument("--mod_path", type=Path, help="The path to the mod root folder", nargs="?") parser.add_argument( "--notes", type=str, help="Notes to add to the update scirpt, usually a brief changelog", nargs="+") parser.add_argument("--output", type=Path, help="Output file") args = parser.parse_args() sm_path = args.sm_path script = god_tony_update_script(Path(args.sm_path), args.mod_path, list(args.notes), str(args.version)) with open(str(args.output), "w") as fp: vdf.dump(script.build_vdf(), fp, pretty=True)
def set_download_throttle(rate): close_steam() path = f"{all_steam_directories[0]}\\config\\config.vdf" config_vdf = vdf.load(open(path), mapper=vdf.VDFDict) # Load VDF file old_value = config_vdf['InstallConfigStore']['Software']['Valve']['steam'][ 'DownloadThrottleKbps'] if int(old_value) == rate: print( f"Your download rate was not changed because it was already set to" f" {'unlimited' if old_value == '0' else f'{old_value} Kbps'}.") return # Delete old value and add new value del config_vdf['InstallConfigStore']['Software']['Valve']['steam'][ 'DownloadThrottleKbps'] config_vdf['InstallConfigStore']['Software']['Valve']['steam'].update( {'DownloadThrottleKbps': rate}) # Backup and then output to file Tools.backup_file(path) vdf.dump(config_vdf, open(path, "w"), pretty=True) print( f"Your download rate was change from {'unlimited' if old_value == '0' else f'{old_value} Kbps'} to" f" {'unlimited' if rate == 0 else f'{rate} Kbps'}.")
def fix_launch_option(app_id, wm_name, wm_name_alt=''): """Add execution of fix-wm-class.sh file with wm_name of game as argument.""" if not wm_name_alt: wm_name_alt = wm_name for conf_file in localconfig_paths: loaded = vdf.load(open(conf_file)) steam = loaded['UserLocalConfigStore']['Software']['Valve']['Steam'] if 'Apps' in steam.keys(): apps = steam['Apps'] else: apps = steam['apps'] if app_id in apps.keys(): app = apps[app_id] if 'LaunchOptions' not in app.keys(): app['LaunchOptions'] = '' app['LaunchOptions'] = sub('&\\s/.*fix-wm-class\\.sh.*?;', '', app['LaunchOptions']) script = str(WM_CLASS_FIXER_SCRIPT) if wm_name_alt != wm_name: app['LaunchOptions'] += '& %s "%s" "%s";' % (script, wm_name, wm_name_alt) else: app['LaunchOptions'] += '& %s "%s";' % (script, wm_name) vdf.dump(loaded, open(conf_file, 'w'), pretty=True)
def restore_config(src, dst): """Restore the backup. if dst exists, rename it. The new method.""" try: with open(src, encoding='UTF-8') as backup_file: backedup_categories = json.loads( backup_file.read(), object_pairs_hook=collections.OrderedDict) with open(dst, encoding='UTF-8') as valves_file: content = vdf.loads(valves_file.read(), mapper=collections.OrderedDict) target_categories = content["UserRoamingConfigStore"][ "Software"]["Valve"]["Steam"]["Apps"] content["UserRoamingConfigStore"]["Software"]["Valve"][ "Steam"]["Apps"] = BackupAndRestore.__insert_categories__( target_categories, backedup_categories) new_name = dst + " " + str(datetime.datetime.now().strftime( "%Y-%m-%d %H;%M;%S %f")) + ".bak" os.rename(dst, new_name) with open(dst, "w", encoding='UTF-8') as output_file: vdf.dump(content, output_file, pretty=True) except UnicodeDecodeError: raise ParseException("Can't open source file to restore") except (FileExistsError, IOError): raise ParseException("Can't open target file to restore")
def main(): steamapps = check_args() print('Scanning manifests') for manifest in glob(join(steamapps, '*.acf')): with open(manifest, 'r') as manifile: vdf = load(manifile, mapper=VDFDict) changed = False # Disable autoupdate if vdf[0, 'AppState'][0, 'AutoUpdateBehavior'] != '0': vdf[0, 'AppState'][0, 'AutoUpdateBehavior'] = '0' print('Disabled', vdf[0, 'AppState'][0, 'name']) changed = True state_flag = int(vdf[0, 'AppState'][0, 'StateFlags']) # If it's in ready state make sure state is 4 # Sometimes it goes to 6 for some reason # See https://github.com/lutris/lutris/blob/master/docs/steam.rst if state_flag != 4 and state_flag & 4: vdf[0, 'AppState'][0, 'StateFlags'] = '4' print('Marking as updated', vdf[0, 'AppState'][0, 'name']) changed = True if changed: with open(manifest, 'w') as manifile: dump(vdf, manifile, pretty=True) print('Done')
def achievements_po2vdf(vdff, langs): english = load_achievements().items() dat = {} for lang in langs: trans = dict((pe.msgid, pe.msgstr) for pe in polib.pofile(os.path.join(ROOT, "lang", lang, "achievements.po"))) dat[steam_languages[lang]] = {"Tokens":dict((k, trans[v]) for k, v in english)} vdf.dump({"lang":dat}, codecs.open(vdff, 'w', 'utf-8'), pretty=True) print "wrote " + vdff
def test_theater_files(self): for theater_file in theater_files: th = Theater(filename=os.path.join(theater_path,theater_file)) for out_file in out_files: data = getattr(th, out_file) out_file_path = os.path.join(out_path,os.path.basename(theater_file).replace(".theater",""),"%s.txt" % out_file) if not os.path.exists(os.path.dirname(out_file_path)): os.makedirs(os.path.dirname(out_file_path)) vdf.dump(data, open(out_file_path,'w'), pretty=True)
def restore_launch_options(): """Removes changes made by "fix_launch_option" function.""" for conf_file in localconfig_paths: loaded = vdf.load(open(conf_file)) apps = loaded['UserLocalConfigStore']['Software']['Valve']['Steam']['Apps'] for app_id in apps.keys(): app = apps[app_id] if 'LaunchOptions' in app.keys(): app['LaunchOptions'] = sub('&\\s/.*fix-wm-class\\.sh.*?;', '', app['LaunchOptions']) vdf.dump(loaded, open(conf_file, 'w'), pretty=True)
def test_dump_params_invalid(self): # pretty/escaped only accept bool with self.assertRaises(TypeError): vdf.dump({'a': 1}, StringIO(), pretty=1) with self.assertRaises(TypeError): vdf.dumps({'a': 1}, pretty=1) with self.assertRaises(TypeError): vdf.dump({'a': 1}, StringIO(), escaped=1) with self.assertRaises(TypeError): vdf.dumps({'a': 1}, escaped=1)
def change_user(acc: SteamAccount): # TODO: Windows need registry edit, no VDF with open(STEAMREGISTRY, 'r') as f: registry = vdf.load(f, mapper=vdf.VDFDict) steam = registry["Registry"]["HKCU"]["Software"]["Valve"]["Steam"] steam[(0, "AutoLoginUser")] = acc.get_login() steam[(0, "RememberPassword")] = "1" with open(STEAMREGISTRY, 'w') as f: vdf.dump(registry, f, pretty=True)
def test_routine_dump_writing(self): class CustomDict(dict): pass for mapper in (dict, CustomDict): src = mapper({"asd": "123"}) expected = vdf.dumps(src) vdf.dump(src, self.f) self.f.seek(0) self.assertEqual(expected, self.f.read())
def del_client_user(steamID): key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "SOFTWARE\Valve\Steam", 0, winreg.KEY_QUERY_VALUE) path, t = winreg.QueryValueEx(key, "SteamPath") users = {} with open(path + "/config/loginusers.vdf", "r", encoding="utf-8") as file: users = vdf.load(file) del users["users"][steamID] with open(path + "/config/loginusers.vdf", "w", encoding="utf-8") as file: vdf.dump(users, file)
def achievements_po2vdf(vdff, langs): english = load_achievements().items() dat = {} for lang in langs: trans = dict((pe.msgid, pe.msgstr) for pe in open_po( os.path.join(ROOT, "lang", lang, "achievements.po"))) dat[steam_languages[lang]] = { "Tokens": dict((k, trans[v]) for k, v in english) } if dryrun: return vdf.dump({"lang": dat}, io.open(vdff, 'w', encoding='utf-8'), pretty=True) print "wrote " + vdff
def set_auto_update_behavior(new_value: str): """ Args: new_value (str): A string that is either "0", "1", or "2" which correspond to the accepted AutoUpdateBehavior values. """ close_steam() # Variables for keeping track of how many acf files were processed num_updated_acf_files = 0 num_total_acf_files = 0 for steamapp_directory in all_steam_directories: os.chdir(steamapp_directory + "\\steamapps") # TODO: Is this still needed? for appmanifest_path in glob.glob("appmanifest_*.acf"): num_total_acf_files += 1 appmanifest_acf = vdf.load(open(appmanifest_path), mapper=vdf.VDFDict) # Load VDF file old_value = appmanifest_acf["AppState"]["AutoUpdateBehavior"] if old_value != new_value: # Delete old value and add new value in memory del appmanifest_acf["AppState"]["AutoUpdateBehavior"] appmanifest_acf["AppState"].update( {'AutoUpdateBehavior': new_value}) # Only backup and then output to file if it was updated Tools.backup_file(appmanifest_path) vdf.dump(appmanifest_acf, open(appmanifest_path, "w"), pretty=True) num_updated_acf_files += 1 if num_updated_acf_files == 0: print( f"All {num_total_acf_files} games already had the requested AutoUpdateBehavior." ) elif num_updated_acf_files == num_total_acf_files: print( f"All {num_total_acf_files} games were updated to the requested AutoUpdateBehavior." ) else: print( f"{num_updated_acf_files}/{num_total_acf_files} games were updated to the requested AutoUpdateBehavior.\n" f"(some already had the requested AutoUpdateBehavior.)") print( f"{len(all_steam_directories)} Steam library folder(s) were searched.")
def _gen_control_file(self, output: Path, files: List[Path]): entries = {} for f in files: # Ensure the control file itself and VPKs are excluded if (f.name == output.name or f.name == f"{output.name}.bak" or f.suffix == ".vpk"): continue rel = str(os.path.relpath(f, self.input_path)).replace("\\", "/") entries[rel] = {"destpath": rel, "md5": self._md5_file(str(f))} # VPK needs the files to stay in the same order res = dict(sorted(entries.items())) with output.open("w") as f: vdf.dump(res, f, pretty=True)
def app_build_setup(): plugin_dir = unreal.Paths.project_plugins_dir() plugin_dir = unreal.Paths.convert_relative_path_to_full(plugin_dir) bitbake_data = load_bitbake_data() output_dir = bitbake_data[0][ 'SteamSDKDirectory'] + "/tools/ContentBuilder/output" appid = bitbake_data[0]['AppID'] steam_branch = bitbake_data[0]['SteamBranch'] description = "Current Changeset: {}".format(check_for_vcs()) builder_vdf = vdf.load( open('{}/generic_app_build.vdf'.format(os.path.dirname(__file__)), 'r')) depot_vdf = "{}BitBaker/Content/Python/custom_depot.vdf".format(plugin_dir) # Writes all values to the App Build VDF builder_vdf['appbuild']['appid'] = appid builder_vdf['appbuild']['desc'] = description builder_vdf['appbuild']['buildoutput'] = output_dir builder_vdf['appbuild']['setlive'] = steam_branch # Deletes all current depots to add new ones builder_vdf['appbuild']['depots'].clear() # Hack to increase app id by 1, assuming the base Steam Depots are always AppID + 1 # TODO: Add support for more than 1 depot depot_key = int(appid) + 1 builder_vdf['appbuild']['depots'][str(depot_key)] = depot_vdf # Temporarily dumps users parameters on a VDF with open('{}/custom_app_build.vdf'.format(os.path.dirname(__file__)), 'w+') as in_file: in_file.truncate() vdf.dump(builder_vdf, in_file, pretty=True) # Reopens the VDF so its contents are recorded and edits out all \\ from the code # This is only needed because stupid VDF Library doesn't dump Paths with regular \ notation with open('custom_app_build.vdf', 'r+') as out_file: all_lines = [] for line in out_file: line = line.replace(r'\\', '\\') all_lines.append(line) out_file.seek(0) out_file.truncate() out_file.writelines(all_lines)
def depot_setup(build_folder): bitbake_data = load_bitbake_data() depot_id = bitbake_data[0]['AppID'] build_dir = bitbake_data[0]['BuildDirectory'] depot_vdf = vdf.load( open('{}/generic_depot.vdf'.format(os.path.dirname(__file__)), 'r')) # Writes all values to the Depot VDF depot_id = int(depot_id) + 1 depot_vdf['DepotBuildConfig']['DepotID'] = str(depot_id) depot_vdf['DepotBuildConfig']['contentroot'] = "{}/{}".format( build_dir, build_folder) # Dumps users parameters on a VDF with open('{}/custom_depot.vdf'.format(os.path.dirname(__file__)), 'r+') as in_file: in_file.truncate() vdf.dump(depot_vdf, in_file, pretty=True)
def __call__(self, handle): # language = pycountry.languages.get(alpha_2=self.language) # file_base = copy.deepcopy(vdfTranslationBase) file_base = vdf.loads(vdf.dumps(vdfTranslationBase)) # copy structure # file_base['lang']['Language'] = language.name file_base['lang']['Language'] = self.language.capitalize() for unit in self.units: file_base['lang']['Tokens'][unit.key] = unit.text file_content = vdf.dump(file_base, handle, pretty=True)
def set_app_launchopts(self, appid: int, params: str): '''Sets app launch options (commandline parameters)''' with open(self.path / "config/localconfig.vdf", 'r') as f: cfg = vdf.load(f, mapper=vdf.VDFDict) meh = cfg['UserLocalConfigStore']['Software']['Valve']['Steam'][ 'Apps'][str(appid)] if 'LaunchOptions' in meh: del meh['LaunchOptions'] meh['LaunchOptions'] = params with open(self.path / "config/localconfig.vdf", 'w') as f: cfg = vdf.dump(cfg, f, pretty=True)
def upload_workshopfiles(self, user, password, workshop_vdf_path=None, workshop_vdf=None): """ Uploads workshop items in accordance to the workshop vdf file. :param workshop_vdf_path: path to workshop vdf file. :param workshop_vdf: Optional, vdf object See https://pypi.org/project/vdf/ :param user: steam username (required valid user) :param password: steam password (required valid user password) """ if workshop_vdf_path: vdf_data = self._parse_vdf(vdf_path=workshop_vdf_path) elif workshop_vdf: vdf_data = self._parse_vdf_text(vdf_data=workshop_vdf) with open( "{install_path}/workshop.vdf".format( install_path=self.install_path), "w") as vdf_file: vdf.dump(vdf_data, vdf_file) # Upload the workshop files steamcmd_params = ( self.steamcmd_exe, '+login {} {}'.format(user, password), '+workshop_build_item', '{install_path}/workshop.vdf'.format( install_path=self.install_path), '+quit', ) try: return subprocess.check_call(steamcmd_params) except subprocess.CalledProcessError: raise SteamcmdException( "Steamcmd was unable to run. Did you install your 32-bit libraries?" )
def setup_compat_tool_extensions(current_info): compat_tool_dest = Path('.local/share/Steam/compatibilitytools.d') compat_tool_dest.mkdir(parents=True, exist_ok=True) # Copy extensions if they exist for compat_tool_ext in Path('/app/compatibilitytools.d').iterdir(): if not compat_tool_ext.is_dir(): continue compat_tool_ext_id = f'com.valvesoftware.Steam.CompatibilityTool.{compat_tool_ext.name}' compat_tool_ext_dest = compat_tool_dest / compat_tool_ext.name compat_tool_ext_commit_hash = current_info["app-extensions"][ compat_tool_ext_id] compat_tool_ext_commit_file = compat_tool_ext_dest / '.extension-commit' if compat_tool_ext_dest.exists(): if compat_tool_ext_commit_file.exists(): with compat_tool_ext_commit_file.open() as fp: if fp.read() == compat_tool_ext_commit_hash: continue src_vdf = compat_tool_ext / 'compatibilitytool.vdf' dst_vdf = compat_tool_ext_dest / 'compatibilitytool.vdf' with src_vdf.open('r') as sf: compat_tool_vdf = vdf.load(sf) for v in compat_tool_vdf['compatibilitytools']['compat_tools'].values( ): v['install_path'] = compat_tool_ext print(f'Writing {dst_vdf}') os.makedirs(os.path.dirname(dst_vdf), exist_ok=True) with dst_vdf.open('w') as df: vdf.dump(compat_tool_vdf, df, pretty=True) with compat_tool_ext_commit_file.open('w') as fp: fp.write(compat_tool_ext_commit_hash)
# Setup DB Configs with open(DB_CONFIG_FILE) as file: db_config = vdf.load(file) db_info = urlparse(secrets['tf2m_site_connection_str']) db_config['Databases']['xenforo'] = { "driver": "default", "host": db_info.hostname, "user": db_info.username, "pass": db_info.password, "port": db_info.port, "database": db_info.path.replace("/", "") } db_info = urlparse(secrets['tf2m_bot_connection_str']) db_config['Databases']['bot'] = { "driver": "default", "host": db_info.hostname, "user": db_info.username, "pass": db_info.password, "port": db_info.port, "database": db_info.path.replace("/", "") } with open(DB_CONFIG_FILE, "w") as file: vdf.dump(db_config, file, pretty=True) # Set instance hostname subprocess.run(["/usr/bin/hostnamectl", "set-hostname", f"{tags['Name']}"], check=True)
username = args.username password = args.password sguard = args.steamguard or "" file = args.vdf with open(file, "r") as f: d = vdf.load(f) wsitem = d["workshopitem"] args = vars(args) for i in optional_args: if args[i]: v = wsitem[i].format(args[i]) wsitem[i] = v print("Setting {} to {}".format(i, v)) with open("./tmp_vdf.vdf", "w") as f: vdf.dump(d, f, pretty=True) subprocess.call( "steamcmd +login {} {} {} +workshop_build_item {} +quit".format( username, password, sguard, os.path.realpath("./tmp_vdf.vdf") ), shell=True, )
def main(argv): usage = "Usage: ProtonDB-to-Steam-Library.py \n" \ + " -s <absolute path to sharedconfig.vdf> \n" \ + " -n (disables saving)" sharedconfig_path = "" skip_save = False ### From here until the comment saying otherwise is just parsing the command line arguements try: opts, _ = getopt.getopt(argv, "hs:n") except getopt.GetoptError: print(usage) sys.exit() for opt, arg in opts: if opt == "-h": print(usage) sys.exit() elif opt in "-s": if os.path.exists(arg): try: vdf.load(open(arg)) sharedconfig_path = arg except: print(arg) print("Invalid path!") sys.exit() # With ~ for user home elif os.path.exists(os.path.expanduser(arg)): try: vdf.load(open(arg)) sharedconfig_path = os.path.expanduser(arg) except: print(os.path.expanduser(arg)) print("Invalid path!") sys.exit() else: print(arg) print("Invalid path!") sys.exit() elif opt in "-n": skip_save = True ### Done with command line arguements # If sharedconfig_path was not set with a command line arguement, have get_sharedconfig_path() find it if not sharedconfig_path: sharedconfig_path = get_sharedconfig_path() print("Selected: " + sharedconfig_path) sharedconfig = vdf.load(open(sharedconfig_path)) # Get which version of the configstore you have configstore = get_configstore_for_vdf(sharedconfig) for app_id in sharedconfig[configstore]["Software"]["Valve"]["Steam"][ "Apps"]: try: # This has to be here because some Steam AppID's are strings of text, which ProtonDB does not support. Check test01.vdf line 278 for an example. app_id = int(app_id) tag_num = "" # If the app is native, no need to check ProtonDB if is_native(str(app_id)): print(str(app_id) + " native") continue try: # Have to create a copy to avoid: "RuntimeError: dictionary changed size during iteration" tags = sharedconfig[configstore]["Software"]["Valve"]["Steam"][ "Apps"][str(app_id)]["tags"].copy() for tag in tags: # Search to see if a ProtonDB rank is already a tag, if so just overwrite that tag if sharedconfig[configstore]["Software"]["Valve"]["Steam"][ "Apps"][str(app_id)]["tags"][tag].startswith( "ProtonDB Ranking:", 0, 17): if not tag_num: tag_num = tag else: # Delete dupe tags caused by error of previous versions, may remove this check in the future once its no longer an issue del sharedconfig[configstore]["Software"]["Valve"][ "Steam"]["Apps"][str(app_id)]["tags"][tag] if not tag_num: # If no ProtonDB tags were found, use the next available number tag_num = str( len(sharedconfig[configstore]["Software"]["Valve"] ["Steam"]["Apps"][str(app_id)]["tags"])) # If the tags key wasn't found, that means there are no tags for the game except KeyError: tag_num = "0" sharedconfig[configstore]["Software"]["Valve"]["Steam"][ "Apps"][str(app_id)]["tags"] = vdf.VDFDict() protondb_rating = get_protondb_rating(app_id) print(str(app_id) + " " + protondb_rating) # The 1,2,etc. force the better ranks to be at the top, as Steam sorts these alphabetically possible_ranks = { "platinum": "ProtonDB Ranking: 1 Platinum", "gold": "ProtonDB Ranking: 2 Gold", "silver": "ProtonDB Ranking: 3 Silver", "bronze": "ProtonDB Ranking: 4 Bronze", "pending": "ProtonDB Ranking: 5 Pending", "unrated": "ProtonDB Ranking: 6 Unrated", "borked": "ProtonDB Ranking: 7 Borked", } # Try to inject the tag into the vdfDict, if the returned rating from ProtonDB isn't a key above it will error out try: sharedconfig[configstore]["Software"]["Valve"]["Steam"][ "Apps"][str(app_id)]["tags"][tag_num] = possible_ranks[ protondb_rating] except KeyError: print("Unknown ProtonDB rating: " + protondb_rating + "\n Please report this on GitHub!") except urllib.error.HTTPError: continue except ValueError: continue # skip_save will be True if -n is passed if not skip_save: print("WARNING: This may clear your current tags on Steam!") check = input("Would you like to save sharedconfig.vdf? (y/N)") if check.lower() in ("yes", "y"): # Output the edited vdfDict back to the origional location vdf.dump(sharedconfig, open(sharedconfig_path, 'w'), pretty=True)
def main(args): sharedconfig_path = "" no_save = args.no_save check_native = args.check_native if args.sharedconfig_path: # With ~ for user home if os.path.exists(os.path.expanduser(args.sharedconfig_path)): try: with open(args.sharedconfig_path) as sharedconfig_vdf: vdf.load(sharedconfig_vdf) sharedconfig_path = os.path.expanduser(args.sharedconfig_path) except: print("Invalid sharedconfig path: '{}'".format(args.sharedconfig_path)) sys.exit() else: print("Shared config path '{}' does not exist. Using default path.".format(args.sharedconfig_path)) # If sharedconfig_path was not set with a command line argument, have get_sharedconfig_path() find it if not sharedconfig_path: sharedconfig_path = find_sharedconfig() print("Selected: {}".format(sharedconfig_path)) with open(sharedconfig_path) as sharedconfig_vdf: sharedconfig = vdf.load(sharedconfig_vdf) # Get which version of the configstore you have configstore = get_configstore_for_vdf(sharedconfig) # This makes the code slightly cleaner apps = sharedconfig[configstore]["Software"]["Valve"]["Steam"][get_apps_key(sharedconfig, configstore)] appCount = len(apps) print("Found {} Steam games".format(appCount)) for count, app_id in enumerate(apps, 1): # This has to be here because some Steam AppID's are strings of text, which ProtonDB does not support. Check test01.vdf line 278 for an example. try: int(app_id) except ValueError: continue protondb_rating = "" # If the app is native, no need to check ProtonDB if check_native and is_native(app_id): protondb_rating = "native" else: # Get the ProtonDB rating for the app, if ProtonDB 404's it means no rating is available for the game and likely native try: protondb_rating = get_protondb_rating(app_id) except ProtonDBError: continue tag_num = get_tag_number(apps[app_id]) # The 1,2,etc. force the better ranks to be at the top, as Steam sorts these alphanumerically possible_ranks = { "native": "ProtonDB Ranking: 0 Native", "platinum": "ProtonDB Ranking: 1 Platinum", "gold": "ProtonDB Ranking: 2 Gold", "silver": "ProtonDB Ranking: 3 Silver", "bronze": "ProtonDB Ranking: 4 Bronze", "pending": "ProtonDB Ranking: 5 Pending", "unrated": "ProtonDB Ranking: 6 Unrated", "borked": "ProtonDB Ranking: 7 Borked", } new_rank = True try: old_tag = apps[app_id]["tags"][tag_num] old_key = "" # Get the old key (protondb ranking) for key, value in possible_ranks.items(): if value == old_tag: old_key = key break # No change since last run, we don't need to output or save it if old_key == protondb_rating: new_rank = False else: print("{} {} => {} ({} of {})".format(app_id, old_key, protondb_rating, count, appCount)) # If it throws a key error it is a new game to rank except KeyError: print("{} {}".format(app_id, protondb_rating)) if new_rank: # Try to inject the tag into the vdfDict, if the returned rating from ProtonDB isn't a key above it will error out if protondb_rating in possible_ranks: apps[app_id]["tags"][tag_num] = possible_ranks[protondb_rating] else: print("Unknown ProtonDB rating: {}\n Please report this on GitHub!".format(protondb_rating)) # no_save will be True if -n is passed if not no_save: print("WARNING: This may clear your current tags on Steam!") check = input("Would you like to save sharedconfig.vdf? (y/N)") if check.lower() in ("yes", "y"): # Output the edited vdfDict back to the original location with open(sharedconfig_path, 'w') as sharedconfig_vdf: vdf.dump(sharedconfig, sharedconfig_vdf, pretty=True) # Workaround provided by Valve for the new library url = "steam://resetcollections" if sys.platform == "win32": command = "start " else: command = "xdg-open " input("Please launch Steam, then press Enter to continue...") os.system(command + url) #Reset Collections
def save_content(self, handle): vdf.dump(self.store, handle, pretty=True)
def save_file(self, data, path=None): if path == None: path = self.config_name vdf.dump(data, open(path, "w"), pretty=True)
print 'This program converts form and to the .txt format used by Source Engine to / from .json, ready to be used by POEditor. It is also capable of converting from the exported' \ ' .json to an usable .txt by Source. It first asks for a language. You must enter the lowercase, english name of the language, so it will search for that language file.' \ ' If you want to go from .json to .txt, you must name your .json with the language\'s name it contains. Encoding a file will also create a "_ref_exp" file.' lang = raw_input("Language?\n") option = raw_input("DECODE (D) (.txt to .json) or ENCODE (E) (.json to .txt)?\n") if option == "DECODE" or option == "D": print "Decoding..." d = vdf.load(open("momentum_" + lang + '.txt'), mapper=vdf.VDFDict) tokens = [] for key, value in d['lang']['Tokens'].items(): tokens.append({'term': key, 'definition': value}) json.dump(tokens, open("momentum_" + lang + '.json', 'w'), indent=4, sort_keys=True) print 'Tokens dumped to .json' elif option == "ENCODE" or option == "E": print "Encoding..." with open(lang + '.json') as filez: jos = json.load(filez) mom = vdf.VDFDict([('lang', vdf.VDFDict([('Language', lang.title()), ('Tokens', vdf.VDFDict())]))]) for key in jos: mom['lang']['Tokens'][key['term']] = key['definition'] vdf.dump(mom, open('momentum_' + lang + '.txt', 'w', encoding='utf_16_le'), pretty=True) print 'momentum_%s exported.' % lang if lang == 'english': vdf.dump(mom, open('momentum_english_ref_exp.txt', 'w', encoding='utf-8'), pretty=True) print 'momentum_english_ref_exp exported.' else: print "Unknown command. DECODE/D or ENCODE/E"
def writeLibraryInfo(self): # Make sure directories all exist for key in self.new_config['libraryfolders']: if self._isint(key): folder = os.path.join( self.new_config['libraryfolders'][key]['path'], 'steamapps') if not os.path.exists(folder): if messagebox.askyesno( "Create folders?", "Do you want to create the directory \"{}\"?". format(folder)): try: os.makedirs(folder, exist_ok=True) except: messagebox.showerror( "Error", "Error when creating directories") raise # Create backups try: for f_path in [ self.config_library_vdf, self.steamapps_library_vdf ]: if not os.path.exists(f_path): continue with open(f_path, 'r') as f_in: with open(f_path + '.bak', 'w') as f_out: f_out.write(f_in.read()) except: if not messagebox.askyesno( "Warning", "Failed to create a backup. Proceed anyways?"): raise # Write the new files restore_backup = False try: vdf.dump(self.new_config, open(self.config_library_vdf, 'w'), pretty=True) vdf.dump(self.new_config, open(self.steamapps_library_vdf, 'w'), pretty=True) except: restore_backup = True # Restore the backup if needed if restore_backup: messagebox.showerror( "Error", "Failed to write libraryfolders.vdf. Restoring backup...") try: for f_path in [ self.config_library_vdf, self.steamapps_library_vdf ]: with open(f_path + '.bak', 'r') as f_in: with open(f_path, 'w') as f_out: f_out.write(f_in.read()) except: messagebox.showerror( "Error", "Failed to restore backup! Sorry about that.") raise # Tell the user stuff is done messagebox.showinfo("Complete", "Steam Library Setup is done. Closing program...") self.quit()
def main(args): sharedconfig_path = "" no_save = args.no_save check_native = args.check_native if args.sharedconfig_path: # With ~ for user home if os.path.exists(os.path.expanduser(args.sharedconfig_path)): try: with open(args.sharedconfig_path) as sharedconfig_vdf: vdf.load(sharedconfig_vdf) sharedconfig_path = os.path.expanduser(args.sharedconfig_path) except: print("Invalid sharedconfig path: '{}'".format( args.sharedconfig_path)) sys.exit() else: print( "Shared config path '{}' does not exist. Using default path.". format(args.sharedconfig_path)) # If sharedconfig_path was not set with a command line argument, have get_sharedconfig_path() find it if not sharedconfig_path: sharedconfig_path = find_sharedconfig() print("Selected: {}".format(sharedconfig_path)) with open(sharedconfig_path) as sharedconfig_vdf: sharedconfig = vdf.load(sharedconfig_vdf) # Get which version of the configstore you have configstore = get_configstore_for_vdf(sharedconfig) # This makes the code slightly cleaner apps = sharedconfig[configstore]["Software"]["Valve"]["Steam"][ get_apps_key(sharedconfig, configstore)] for app_id in apps: # This has to be here because some Steam AppID's are strings of text, which ProtonDB does not support. Check test01.vdf line 278 for an example. try: int(app_id) except ValueError: continue protondb_rating = "" # If the app is native, no need to check ProtonDB if check_native and is_native(app_id): protondb_rating = "native" print("{} native".format(app_id)) else: # Get the ProtonDB rating for the app, if ProtonDB 404's it means no rating is available for the game and likely native try: protondb_rating = get_protondb_rating(app_id) print("{} {}".format(app_id, protondb_rating)) except ProtonDBError: continue tag_num = get_tag_number(apps[app_id]) # The 1,2,etc. force the better ranks to be at the top, as Steam sorts these alphanumerically possible_ranks = { "native": "ProtonDB Ranking: 0 Native", # This should probably be changed eventually, but this is to allow us to scan the tags for an existing one. "platinum": "ProtonDB Ranking: 1 Platinum", "gold": "ProtonDB Ranking: 2 Gold", "silver": "ProtonDB Ranking: 3 Silver", "bronze": "ProtonDB Ranking: 4 Bronze", "pending": "ProtonDB Ranking: 5 Pending", "unrated": "ProtonDB Ranking: 6 Unrated", "borked": "ProtonDB Ranking: 7 Borked", } # Try to inject the tag into the vdfDict, if the returned rating from ProtonDB isn't a key above it will error out if protondb_rating in possible_ranks: apps[app_id]["tags"][tag_num] = possible_ranks[protondb_rating] else: print( "Unknown ProtonDB rating: {}\n Please report this on GitHub!". format(protondb_rating)) # no_save will be True if -n is passed if not no_save: print("WARNING: This may clear your current tags on Steam!") check = input("Would you like to save sharedconfig.vdf? (y/N)") if check.lower() in ("yes", "y"): # Output the edited vdfDict back to the original location with open(sharedconfig_path, 'w') as sharedconfig_vdf: vdf.dump(sharedconfig, sharedconfig_vdf, pretty=True)
print "Decoding..." for loclfile in files: d = vdf.load(open(loclfile + lang + '.txt'), mapper=vdf.VDFDict) tokens = [] for key, value in d['lang']['Tokens'].items(): if loclfile is 'gameui_': tokens.append({'term': key, 'definition': value, 'context':'gameui'}) else: tokens.append({'term': key, 'definition': value}) json.dump(tokens, open(loclfile+lang + '.json', 'w'), indent=4, sort_keys=True) print 'Tokens dumped to .json' elif option is "ENCODE" or option is "E": print "Encoding..." with open(lang + '.json') as filez: jos = json.load(filez) gui = vdf.VDFDict([('lang', vdf.VDFDict([('Language', lang.title()), ('Tokens', vdf.VDFDict())]))]) mom = vdf.VDFDict([('lang', vdf.VDFDict([('Language', lang.title()), ('Tokens', vdf.VDFDict())]))]) for key in jos: if key['context'] == 'gameui': gui['lang']['Tokens'][key['term']] = key['definition'] else: mom['lang']['Tokens'][key['term']] = key['definition'] if gam is "Y" or gam is "y": vdf.dump(gui, open('gameui_' + lang + '.txt', 'w'), pretty=True) print 'gameui_' + lang + ' exported.' vdf.dump(mom, open('momentum_' + lang + '.txt', 'w'), pretty=True) print 'momentum_' + lang + ' exported.' else: print "Unknown command. DECODE/D or ENCODE/E"