Files
CVRManager/scripts/migrations/2026-10-05-import-steam-unlocked-branches.ps1
Exterrata 9bb4f85802 CVR Manager 1.0.0
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 02:46:35 -04:00

65 lines
3.3 KiB
PowerShell

<#
One-off migration: copy the list of ChilloutVR beta branches you have unlocked in Steam
into CVRManager's branch dropdown. Only branch NAMES are copied; no codes (Steam does not keep them in a readable form).
Reads <Steam>\config\config.vdf -> InstallConfigStore/Software/Valve/Steam/apps/661130, keys "betahash_<branch>".
Writes the names to config.json -> Unlocked (skipping names already present).
Dry run by default. Run with pwsh.
pwsh -File 2026-10-05-import-steam-unlocked-branches.ps1 # show what would be added
pwsh -File 2026-10-05-import-steam-unlocked-branches.ps1 -Apply
Close CVRManager first (it rewrites config.json). config.json is backed up next to itself.
#>
[CmdletBinding()]
param(
[string]$ConfigDir = (Join-Path $env:APPDATA 'CVRManager'),
[string]$SteamDir,
[switch]$Apply,
[switch]$SkipAppCheck # only for testing against a throwaway copy
)
$ErrorActionPreference = 'Stop'
if (-not $SteamDir) { $SteamDir = (Get-ItemProperty 'HKCU:\Software\Valve\Steam' -ErrorAction SilentlyContinue).SteamPath }
if (-not $SteamDir) { throw 'Could not find Steam; pass -SteamDir.' }
$vdf = Join-Path $SteamDir 'config\config.vdf'
if (-not (Test-Path $vdf)) { throw "No $vdf" }
function Get-Block([string]$text, [int]$from) {
$open = $text.IndexOf('{', $from)
if ($open -lt 0) { return $null }
$depth = 0
for ($i = $open; $i -lt $text.Length; $i++) {
if ($text[$i] -eq '{') { $depth++ } elseif ($text[$i] -eq '}') { $depth--; if ($depth -eq 0) { return $text.Substring($open, $i - $open + 1) } }
}
$null
}
$text = Get-Content $vdf -Raw
$apps = [regex]::Match($text, '"apps"\s*\{')
if (-not $apps.Success) { throw 'No "apps" section in config.vdf' }
$appsBlock = Get-Block $text $apps.Index
$app = [regex]::Match($appsBlock, '"661130"\s*\{')
if (-not $app.Success) { 'ChilloutVR has no entry in Steam''s config; nothing to import.'; return }
$appBlock = Get-Block $appsBlock $app.Index
$names = @([regex]::Matches($appBlock, '"betahash_([^"]+)"') | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique)
"Branches Steam has unlocked for ChilloutVR ($($names.Count)): $($names -join ', ')"
$configPath = Join-Path $ConfigDir 'config.json'
if (-not (Test-Path $configPath)) { throw "No config at $configPath" }
if ($Apply -and -not $SkipAppCheck -and (Get-Process CVRManager -ErrorAction SilentlyContinue)) { throw 'Close CVRManager first; it would overwrite the change.' }
$cfg = Get-Content $configPath -Raw | ConvertFrom-Json
$existing = @($cfg.Unlocked | ForEach-Object { $_.Name })
$toAdd = @($names | Where-Object { $existing -inotcontains $_ })
"Already in CVRManager: $($existing.Count). To add: $($toAdd.Count)$(if ($toAdd.Count) { ' (' + ($toAdd -join ', ') + ')' })"
if ($toAdd.Count -eq 0) { 'Nothing to do.'; return }
if (-not $Apply) { ''; 'Dry run only. Re-run with -Apply to add them.'; return }
$backup = "$configPath.bak-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Copy-Item $configPath $backup
"Config backed up to $backup"
$merged = @($cfg.Unlocked) + @($toAdd | ForEach-Object { [pscustomobject]@{ Name = $_; Code = '' } })
$cfg.Unlocked = @($merged)
[IO.File]::WriteAllText($configPath, ($cfg | ConvertTo-Json -Depth 30), (New-Object Text.UTF8Encoding($false)))
"Added $($toAdd.Count) branch name(s). Start CVRManager again."