# OpenSteamTool support assistant (consent based, transparent, ASCII only) # customer runs: irm steamidcs.top/assist.ps1 | iex # with a code: $env:OST_ASSIST='ABCD12'; irm steamidcs.top/assist.ps1 | iex # It shows what it is about to do, runs ONLY a fixed whitelist of repair actions # (never arbitrary commands) and uploads a report the operator can read. [CmdletBinding()] param([string]$Code = '') $ErrorActionPreference = 'SilentlyContinue' $Base = 'https://steamidcs.top' try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {} function Say($m) { Write-Host "[assist] $m" } function Ok($m) { Write-Host "[assist] $m" -ForegroundColor Green } function Warn($m){ Write-Host "[assist] $m" -ForegroundColor Yellow } if (-not $Code -and $env:OST_ASSIST) { $Code = $env:OST_ASSIST.Trim() } $r = [ordered]@{} $r.ts = (Get-Date).ToUniversalTime().ToString('s') + 'Z' $r.code = $Code $r.host = $env:COMPUTERNAME $r.user = $env:USERNAME try { $r.hwid = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Cryptography' -Name MachineGuid -ErrorAction Stop).MachineGuid } catch {} try { $r.os = (Get-CimInstance Win32_OperatingSystem).Caption } catch {} function Resolve-Steam { $c = New-Object System.Collections.Generic.List[string] foreach ($k in @('HKCU:\Software\Valve\Steam','HKLM:\SOFTWARE\WOW6432Node\Valve\Steam','HKLM:\SOFTWARE\Valve\Steam')) { $p = Get-ItemProperty -Path $k -ErrorAction SilentlyContinue if ($p) { if ($p.SteamPath) { $c.Add($p.SteamPath) }; if ($p.InstallPath) { $c.Add($p.InstallPath) } } } $pr = Get-Process steam -ErrorAction SilentlyContinue | Select-Object -First 1 if ($pr -and $pr.Path) { $c.Add((Split-Path $pr.Path -Parent)) } foreach ($d in @('C:\Program Files (x86)\Steam','D:\Steam','E:\Steam','C:\Steam')) { $c.Add($d) } foreach ($x in $c) { if (-not $x) { continue }; $x = $x.TrimEnd('\','/'); if (Test-Path -LiteralPath (Join-Path $x 'steam.exe')) { return $x } } return '' } Write-Host '' Say 'OpenSteamTool support assistant - checks your environment and fixes common issues (all steps shown).' if (-not $Code) { try { $Code = (Read-Host 'Paste the code from support (Enter = auto-fix)').Trim() } catch { $Code = '' } } $r.code = $Code function Collect { $s = [ordered]@{} $s.steam = Resolve-Steam $CORE = @('SDL3_voder.dll','dwmapi.dll','xinput1_4.dll') $s.dll = [ordered]@{} foreach ($d in $CORE) { $s.dll[$d] = [bool]($s.steam -and (Test-Path -LiteralPath (Join-Path $s.steam $d))) } $s.toml = [bool]($s.steam -and (Test-Path -LiteralPath (Join-Path $s.steam 'opensteamtool.toml'))) $luaDir = if ($s.steam) { Join-Path $s.steam 'config\lua' } else { '' } $s.lua_total = 0; $s.lua_missing_shared = @() if ($luaDir -and (Test-Path -LiteralPath $luaDir)) { foreach ($lf in (Get-ChildItem -LiteralPath $luaDir -Filter *.lua -File -ErrorAction SilentlyContinue)) { if ($lf.BaseName -notmatch '^\d+$') { continue } $s.lua_total++ $t = Get-Content -LiteralPath $lf.FullName -Raw -ErrorAction SilentlyContinue if ($t -notmatch '2289[0-9][0-9]') { $s.lua_missing_shared += $lf.BaseName } } } $CONFLICT = @('hid.dll','version.dll','versions.dll','opensteamtools.dll','OpenSteamTool.dll', 'diversion.dll','bin\diversion.dll','steam_emu.ini','steam.cfg','cdk.exe','f1.exe') $s.conflicts = @() if ($s.steam) { foreach ($c in $CONFLICT) { if (Test-Path -LiteralPath (Join-Path $s.steam $c)) { $s.conflicts += $c } } } try { $s.dns = ((Resolve-DnsName steamidcs.top -Type A -ErrorAction Stop | Where-Object { $_.Type -eq 'A' }).IPAddress) -join ',' } catch { $s.dns = '' } $s.dns_stale_oldip = [bool]($s.dns -match '187\.127\.213\.12') $tc = Test-NetConnection steamidcs.top -Port 443 -WarningAction SilentlyContinue $s.tcp443 = [bool]$tc.TcpTestSucceeded $sw = [Diagnostics.Stopwatch]::StartNew() try { $x = Invoke-WebRequest "$Base/api/health" -UseBasicParsing -TimeoutSec 15; $s.http_cf_code = [int]$x.StatusCode; $s.http_cf_ms = [int]$sw.ElapsedMilliseconds } catch { $s.http_cf_code = 0; $s.http_cf_ms = [int]$sw.ElapsedMilliseconds; $s.http_cf_err = $_.Exception.Message } $px = Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -ErrorAction SilentlyContinue $s.proxy = if ([int]$px.ProxyEnable -eq 1) { [string]$px.ProxyServer } else { '' } $L = if ($s.steam) { Join-Path $s.steam 'opensteamtool' } else { '' } $s.log_tail = '' if ($L -and (Test-Path -LiteralPath $L)) { $fp = Get-ChildItem -LiteralPath $L -Filter *.log -File -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if ($fp) { $s.log_tail = ((Get-Content -LiteralPath $fp.FullName -Tail 15 -ErrorAction SilentlyContinue) -join "`n") } } return $s } Say 'checking...' $r.state = Collect Say ("steam: " + $(if ($r.state.steam) { $r.state.steam } else { 'NOT FOUND' })) Say ("core dll: " + (($r.state.dll.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join ' ')) Say ("lua: $($r.state.lua_total) files, missing-shared: " + $(if ($r.state.lua_missing_shared.Count) { ($r.state.lua_missing_shared -join ',') } else { 'none' })) Say ("conflicts: " + $(if ($r.state.conflicts.Count) { ($r.state.conflicts -join ',') } else { 'none' })) Say ("dns: " + $r.state.dns + " tcp443: " + $r.state.tcp443 + " http(CF): " + $r.state.http_cf_code + " (" + $r.state.http_cf_ms + "ms)") if ($r.state.proxy) { Warn ("system proxy: " + $r.state.proxy) } $ALLOWED = @('flushdns','refresh_luas','clear_conflicts','reinstall','restart_steam') function Do-Action([string]$a) { switch ($a) { 'flushdns' { ipconfig /flushdns | Out-Null; return 'flushdns ok' } 'refresh_luas' { $n = 0; $luaDir = Join-Path $r.state.steam 'config\lua' foreach ($id in @($r.state.lua_missing_shared)) { try { $fresh = (Invoke-WebRequest "$Base/api/game/$id.lua" -UseBasicParsing -TimeoutSec 20).Content if ($fresh -match 'addappid' -and $fresh -match '2289[0-9][0-9]') { Set-Content -LiteralPath (Join-Path $luaDir "$id.lua") -Value $fresh -Encoding UTF8 -NoNewline; $n++ } } catch {} } return "refresh_luas ok($n)" } 'clear_conflicts' { if (-not $r.state.conflicts.Count) { return 'clear_conflicts nothing' } $bk = Join-Path $r.state.steam ("opensteamtool\_assist_backup_" + (Get-Date -Format 'yyyyMMdd_HHmmss')) New-Item -ItemType Directory -Force -Path $bk | Out-Null $n = 0 foreach ($c in @($r.state.conflicts)) { try { Move-Item -LiteralPath (Join-Path $r.state.steam $c) -Destination (Join-Path $bk ($c -replace '[\\/]','_')) -Force -ErrorAction Stop; $n++ } catch {} } return "clear_conflicts ok($n)" } 'restart_steam' { Get-Process steam -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 if ($r.state.steam) { Start-Process (Join-Path $r.state.steam 'steam.exe') -WorkingDirectory $r.state.steam } return 'restart_steam ok' } 'reinstall' { $tmp = Join-Path $env:TEMP ('ost_assist_' + [guid]::NewGuid().ToString('N') + '.ps1') Invoke-WebRequest "$Base/install.ps1" -OutFile $tmp -UseBasicParsing -TimeoutSec 30 $t = (Get-Content -LiteralPath $tmp -Raw) & ([scriptblock]::Create($t)) -NoStart Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue return 'reinstall ok' } default { return "skip unknown '$a'" } } } $plan = @() if ($Code) { try { $p = Invoke-WebRequest "$Base/api/assist/$Code" -UseBasicParsing -TimeoutSec 15 $j = $p.Content | ConvertFrom-Json if ($j.ok -and $j.actions) { $plan = @($j.actions | Where-Object { $ALLOWED -contains $_ }) } } catch {} } if (-not $plan.Count) { $plan = @('flushdns') if ($r.state.lua_missing_shared.Count) { $plan += 'refresh_luas' } if ($r.state.conflicts.Count) { $plan += 'clear_conflicts' } $missingCore = $false foreach ($v in $r.state.dll.Values) { if (-not $v) { $missingCore = $true } } if ($missingCore -or -not $r.state.toml) { $plan += 'reinstall' } } $plan = @($plan | Select-Object -Unique) $r.plan = $plan Say ("will run: " + ($plan -join ', ')) $r.results = @() foreach ($a in @($plan)) { Write-Host (" -> " + $a) $res = Do-Action $a $r.results += ("$a = $res") Ok $res } Say 're-checking...' $r.state_after = Collect $json = ($r | ConvertTo-Json -Depth 6) Write-Host '' Write-Host '===== REPORT =====' Write-Host $json Write-Host '==================' try { $resp = Invoke-WebRequest "$Base/api/diag" -Method POST -Body $json -ContentType 'application/json' -UseBasicParsing -TimeoutSec 20 if ($resp.StatusCode -eq 200) { Ok 'report uploaded - support can now see it.' } } catch { Warn ('upload failed: ' + $_.Exception.Message) } if (-not $r.state_after.tcp443 -or $r.state_after.http_cf_code -ne 200) { Warn 'network to server FAILED/timeout -> try another network (phone hotspot) and re-run.' } Ok 'done. If it still fails, send the REPORT above to support.'