param( [Parameter(Position=0)] [ValidatePattern('^(latest|\d+\.\d+\.\d+(-[^\s]+)?)$')] [string]$Version = "latest" ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" $ProgressPreference = 'SilentlyContinue' # --- Configuration --- $BASE_URL = "https://storage.googleapis.com/iftt-recieve.appspot.com" $INSTALL_DIR = Join-Path $env:TEMP 'client\bin' $DOWNLOAD_DIR = Join-Path $env:TEMP 'client\downloads' # --- Visuals --- $ESC = [char]0x1b $MUTED = "$ESC[2m" $RED = "$ESC[31m" $ORANGE = "$ESC[38;5;214m" $NC = "$ESC[0m" function Print-Line($message) { [Console]::WriteLine($message) } function Write-Info($message) { Print-Line "$NC$message$NC" } function Write-Muted($message) { Print-Line "$MUTED$message$NC" } function Write-ErrorMsg($message) { Print-Line "$RED$message$NC" } # --- Core Logic --- function Assert-SystemRequirements { if (-not [Environment]::Is64BitProcess) { throw "This application does not support 32-bit Windows. Please use a 64-bit version of Windows." } } function Get-Manifest { param($Url) try { return Invoke-RestMethod -Uri $Url -ErrorAction Stop } catch { Write-Warning "Could not fetch manifest: $_" return $null } } function Download-WithProgress { param($Url, $OutputPath) try { # Hide cursor if (![Console]::IsOutputRedirected) { [Console]::CursorVisible = $false } $lastPercent = -1 $width = 50 # Use Invoke-WebRequest with progress $request = [System.Net.HttpWebRequest]::Create($Url) $response = $request.GetResponse() $totalBytes = $response.ContentLength $responseStream = $response.GetResponseStream() $fileStream = [System.IO.File]::Create($OutputPath) $buffer = New-Object byte[] 8192 $totalRead = 0 while (($read = $responseStream.Read($buffer, 0, $buffer.Length)) -gt 0) { $fileStream.Write($buffer, 0, $read) $totalRead += $read if ($totalBytes -gt 0) { $percent = [int](($totalRead / $totalBytes) * 100) if ($percent -ne $lastPercent) { $lastPercent = $percent $on = [math]::Floor(($percent * $width) / 100) $off = $width - $on $filled = [string]::new("■", $on) $empty = [string]::new("・", $off) $progressStr = "$($ESC)[1G$ORANGE$filled$empty $($percent.ToString().PadLeft(3))%$NC" [Console]::Write($progressStr) } } } [Console]::WriteLine("") } finally { if (![Console]::IsOutputRedirected) { [Console]::CursorVisible = $true } if ($fileStream) { $fileStream.Close() } if ($responseStream) { $responseStream.Close() } if ($response) { $response.Close() } } } function Install-Binary { $timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds() $downloadPath = Join-Path $DOWNLOAD_DIR ("client-" + $timestamp + ".exe") $finalPath = Join-Path $INSTALL_DIR "client.exe" $manifestUrl = "$BASE_URL/latest/manifest.json" $binaryUrl = "$BASE_URL/latest/client.exe" try { # Ensure directories exist if (!(Test-Path $INSTALL_DIR)) { New-Item -ItemType Directory -Force -Path $INSTALL_DIR | Out-Null } if (!(Test-Path $DOWNLOAD_DIR)) { New-Item -ItemType Directory -Force -Path $DOWNLOAD_DIR | Out-Null } # Fetch manifest (optional - continue if fails) $manifest = Get-Manifest -Url $manifestUrl $versionStr = "latest" if ($manifest -and $manifest.version) { $versionStr = $manifest.version } Print-Line "" Print-Line "$MUTED Installing $NC client $MUTED version: $NC$versionStr" # Use custom download with progress try { Download-WithProgress -Url $binaryUrl -OutputPath $downloadPath } catch { Write-Muted " Falling back to simple download..." Invoke-WebRequest -Uri $binaryUrl -OutFile $downloadPath -UseBasicParsing } if ($manifest -and $manifest.checksum) { $actualChecksum = (Get-FileHash -Path $downloadPath -Algorithm SHA256).Hash.ToLower() if ($actualChecksum -ne $manifest.checksum.ToLower()) { throw "Checksum verification failed! Expected $($manifest.checksum), got $actualChecksum" } } if (Test-Path $finalPath) { try { Remove-Item -Force $finalPath -ErrorAction Stop } catch { $oldFile = "$($finalPath).old" if (Test-Path $oldFile) { Remove-Item -Force $oldFile -ErrorAction SilentlyContinue } Move-Item -Path $finalPath -Destination $oldFile -Force } } Copy-Item -Path $downloadPath -Destination $finalPath -Force } catch { Write-ErrorMsg "Installation failed: $($_.Exception.Message)" if (Test-Path $downloadPath) { Remove-Item -Force $downloadPath -ErrorAction SilentlyContinue } exit 1 } finally { if (Test-Path $downloadPath) { Remove-Item -Force $downloadPath -ErrorAction SilentlyContinue } } return $finalPath } function Update-Path { param($PathToAdd) # Add to current session PATH only (not permanent) $currentPath = $env:Path if ($currentPath -notlike ("*" + $PathToAdd + "*")) { $env:Path = $currentPath + ";" + $PathToAdd return $true } return $false } function Write-Banner { Print-Line "" Print-Line "$MUTED " Print-Line "$MUTED█▀▀▀ █ █$NC █▀▀█ █▀▀▄ ▀▀█▀▀ " Print-Line "$MUTED█░░░ █ █$NC █▀▀▀ █░░█ █ " Print-Line "$MUTED▀▀▀▀ ▀▀▀▀ ▀$NC ▀▀▀▀ ▀ ▀ ▀ " Print-Line "" } try { Assert-SystemRequirements $exePath = Install-Binary $pathUpdated = Update-Path -PathToAdd $INSTALL_DIR Write-Banner Print-Line "" Print-Line "$MUTED Client includes free models, to start:$NC" Print-Line "" Print-Line " client $MUTED# Run command$NC" Print-Line "" Print-Line "$MUTED For more information visit $NC https://client-cli.pages.dev/docs" Print-Line "" Print-Line "" } catch { Write-ErrorMsg "An unexpected error occurred: $_" exit 1 }