# file: universal_installer.ps1 # Universal package installer: # - Downloads packages.zip # - Extracts packages.json next to the script # - Displays colored menu # - Downloads selected ZIP archive # - Extracts or saves according to JSON rules $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition # URL of the packages.zip archive $PackagesZipUrl = "https://as-wiki.ru/_media/support/packages.zip" $PackagesZip = Join-Path $ScriptDir "packages.zip" Write-Host "Downloading packages.zip..." Invoke-WebRequest -Uri $PackagesZipUrl -OutFile $PackagesZip -UseBasicParsing # ========== UNPACK packages.zip (RELIABLE METHOD) ========== Write-Host "Unpacking packages.zip..." Add-Type -AssemblyName System.IO.Compression.FileSystem try { # Remove old JSON if exists $ExistingJson = Join-Path $ScriptDir "packages.json" if (Test-Path $ExistingJson) { Remove-Item $ExistingJson -Force } # Extract all files directly into script directory [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagesZip, $ScriptDir, $true) } catch { Write-Host "ERROR: Failed to unpack packages.zip" -ForegroundColor Red Write-Host $_.Exception.Message -ForegroundColor Yellow pause exit } # ========== LOAD JSON ========== $JsonPath = Join-Path $ScriptDir "packages.json" if (-not (Test-Path $JsonPath)) { Write-Host "ERROR: packages.json not found inside packages.zip" -ForegroundColor Red pause exit } $JsonData = Get-Content $JsonPath -Raw | ConvertFrom-Json $Packages = $JsonData.packages # ========== MENU DISPLAY ========== function Show-Menu { Clear-Host Write-Host "=== Package Installer ===`n" $i = 1 foreach ($pkg in $Packages) { $line = "{0} - {1} : {2}" -f $i, $pkg.name, $pkg.desc if ($i % 2 -eq 0) { Write-Host $line -ForegroundColor Gray } else { Write-Host $line -ForegroundColor White } $i++ } Write-Host "`n0, 00 - Exit" } # ========== MAIN LOOP ========== while ($true) { Show-Menu $choice = Read-Host "Select number" if ($choice -eq "0" -or $choice -eq "00") { exit } if (($choice -as [int]) -lt 1 -or ($choice -as [int]) -gt $Packages.Count) { Write-Host "Invalid choice." -ForegroundColor Red Start-Sleep 1.5 continue } $Index = [int]$choice - 1 $Item = $Packages[$Index] Write-Host "`nSelected: $($Item.name)" # ========== DOWNLOAD ARCHIVE ========== $FileName = Split-Path $Item.url -Leaf $ArchivePath = Join-Path $ScriptDir $FileName Write-Host "Downloading $FileName..." Invoke-WebRequest -Uri $Item.url -OutFile $ArchivePath # ========== DETERMINE EXTRACTION TARGET ========== if ($Item.target) { $Target = Join-Path $ScriptDir $Item.target } else { $Base = [IO.Path]::GetFileNameWithoutExtension($FileName) $Target = Join-Path $ScriptDir $Base } if (-not (Test-Path $Target)) { New-Item -ItemType Directory -Path $Target | Out-Null } # ========== EXTRACT OR JUST SAVE ========== if ($Item.extract -eq $true) { Write-Host "Extracting to $Target..." try { Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($ArchivePath, $Target, $true) } catch { Write-Host "ERROR extracting archive" -ForegroundColor Red Write-Host $_.Exception.Message -ForegroundColor Yellow } } else { Write-Host "Download complete (no extraction)." } Write-Host "`nDone." pause }