diff --git a/scripts/install.ps1 b/scripts/install.ps1 index ee6ce1d..0c32deb 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -1,192 +1,188 @@ -# Check for admin rights and handle elevation +# 設置顏色主題 +$Theme = @{ + Primary = 'Cyan' + Success = 'Green' + Warning = 'Yellow' + Error = 'Red' + Info = 'White' +} + +# ASCII Logo +$Logo = @" + ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ + ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ ██╔══██╗██╔══██╗██╔═══██╗ + ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ ██████╔╝██████╔╝██║ ██║ + ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ ██╔═══╝ ██╔══██╗██║ ██║ + ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██║ ██║╚██████╔╝ + ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ +"@ + +# 進度條函數 +function Write-ProgressBar { + param ( + [int]$Percent, + [string]$Activity + ) + $width = $Host.UI.RawUI.WindowSize.Width - 20 + $completed = [math]::Floor($width * ($Percent / 100)) + $remaining = $width - $completed + $progressBar = "[" + ("█" * $completed) + ("-" * $remaining) + "]" + Write-Host "`r$Activity $progressBar $Percent%" -NoNewline +} + +# 美化輸出函數 +function Write-Styled { + param ( + [string]$Message, + [string]$Color = $Theme.Info, + [string]$Prefix = "", + [switch]$NoNewline + ) + $emoji = switch ($Color) { + $Theme.Success { "✅" } + $Theme.Error { "❌" } + $Theme.Warning { "⚠️" } + default { "ℹ️" } + } + + $output = if ($Prefix) { "$emoji $Prefix :: $Message" } else { "$emoji $Message" } + if ($NoNewline) { + Write-Host $output -ForegroundColor $Color -NoNewline + } else { + Write-Host $output -ForegroundColor $Color + } +} + +# 檢查管理員權限 $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") if (-NOT $isAdmin) { - # Detect PowerShell version and path + Write-Styled "需要管理員權限來安裝" -Color $Theme.Warning -Prefix "權限" + Write-Styled "正在請求管理員權限..." -Color $Theme.Primary -Prefix "提升" + $pwshPath = if (Get-Command "pwsh" -ErrorAction SilentlyContinue) { - (Get-Command "pwsh").Source # PowerShell 7+ + (Get-Command "pwsh").Source } elseif (Test-Path "$env:ProgramFiles\PowerShell\7\pwsh.exe") { "$env:ProgramFiles\PowerShell\7\pwsh.exe" } else { - "powershell.exe" # Windows PowerShell + "powershell.exe" } try { - Write-Host "`nRequesting administrator privileges..." -ForegroundColor Cyan - $scriptPath = $MyInvocation.MyCommand.Path - $argList = "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`"" - Start-Process -FilePath $pwshPath -Verb RunAs -ArgumentList $argList -Wait + Start-Process -FilePath $pwshPath -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`"" -Wait exit } catch { - Write-Host "`nError: Administrator privileges required" -ForegroundColor Red - Write-Host "Please run this script from an Administrator PowerShell window" -ForegroundColor Yellow - Write-Host "`nTo do this:" -ForegroundColor Cyan - Write-Host "1. Press Win + X" -ForegroundColor White - Write-Host "2. Click 'Windows Terminal (Admin)' or 'PowerShell (Admin)'" -ForegroundColor White - Write-Host "3. Run the installation command again" -ForegroundColor White - Write-Host "`nPress enter to exit..." - $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') + Write-Styled "無法獲取管理員權限" -Color $Theme.Error -Prefix "錯誤" + Write-Styled "請以管理員身份運行 PowerShell 後重試" -Color $Theme.Warning -Prefix "提示" + pause exit 1 } } -# Set TLS to 1.2 +# 獲取版本號函數 +function Get-LatestVersion { + try { + $latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/yeongpin/cursor-free-vip/releases/latest" + return @{ + Version = $latestRelease.tag_name.TrimStart('v') + Assets = $latestRelease.assets + } + } catch { + Write-Styled $_.Exception.Message -Color $Theme.Error -Prefix "錯誤" + throw "無法獲取最新版本信息" + } +} + +# 顯示 Logo +Write-Host $Logo -ForegroundColor $Theme.Primary +$releaseInfo = Get-LatestVersion +$version = $releaseInfo.Version +Write-Host "Version $version" -ForegroundColor $Theme.Info +Write-Host "Created by YeongPin`n" -ForegroundColor $Theme.Info + +# 設置 TLS 1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -# Create temporary directory +# 創建臨時目錄 $TmpDir = Join-Path $env:TEMP ([System.Guid]::NewGuid().ToString()) -New-Item -ItemType Directory -Path $TmpDir | Out-Null +New-Item -ItemType Directory -Path $TmpDir -Force | Out-Null -# Cleanup function +# 清理函數 function Cleanup { if (Test-Path $TmpDir) { - Remove-Item -Recurse -Force $TmpDir + Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue } } -# Error handler -trap { - Write-Host "Error: $_" -ForegroundColor Red - Cleanup - Write-Host "Press enter to exit..." - $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') - exit 1 -} - -# Detect system architecture -function Get-SystemArch { - if ([Environment]::Is64BitOperatingSystem) { - return "x86_64" - } else { - return "i386" +# 主安裝函數 +function Install-CursorFreeVIP { + Write-Styled "開始安裝 Cursor Free VIP" -Color $Theme.Primary -Prefix "安裝" + + # 設置安裝目錄 + $InstallDir = "$env:ProgramFiles\CursorFreeVIP" + if (!(Test-Path $InstallDir)) { + New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null } -} - -# Download with progress -function Get-FileWithProgress { - param ( - [string]$Url, - [string]$OutputFile - ) try { + # 獲取最新版本 + Write-Styled "正在檢查最新版本..." -Color $Theme.Primary -Prefix "更新" + $releaseInfo = Get-LatestVersion + $version = $releaseInfo.Version + Write-Styled "找到最新版本: $version" -Color $Theme.Success -Prefix "版本" + + # 查找對應的資源 + $asset = $releaseInfo.Assets | Where-Object { $_.name -eq "CursorFreeVIP_${version}_windows.exe" } + if (!$asset) { + Write-Styled "找不到檔案: CursorFreeVIP_${version}_windows.exe" -Color $Theme.Error -Prefix "錯誤" + Write-Styled "可用的檔案:" -Color $Theme.Warning -Prefix "資訊" + $releaseInfo.Assets | ForEach-Object { + Write-Styled "- $($_.name)" -Color $Theme.Info + } + throw "找不到對應的安裝檔案" + } + + # 下載 + Write-Styled "正在下載..." -Color $Theme.Primary -Prefix "下載" $webClient = New-Object System.Net.WebClient $webClient.Headers.Add("User-Agent", "PowerShell Script") - $webClient.DownloadFile($Url, $OutputFile) - return $true - } - catch { - Write-Host "Failed to download: $_" -ForegroundColor Red - return $false - } -} - -# Main installation function -function Install-CursorFreeVIP { - Write-Host "Starting installation..." -ForegroundColor Cyan - - # Detect architecture - $arch = Get-SystemArch - Write-Host "Detected architecture: $arch" -ForegroundColor Green - - # Set installation directory - $InstallDir = "$env:ProgramFiles\CursorFreeVIP" - if (!(Test-Path $InstallDir)) { - New-Item -ItemType Directory -Path $InstallDir | Out-Null - } - - # Get latest release - try { - $latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/yeongpin/cursor-free-vip/releases/latest" - Write-Host "Found latest release: $($latestRelease.tag_name)" -ForegroundColor Cyan + $downloadPath = Join-Path $TmpDir "CursorFreeVIP.exe" + $webClient.DownloadFile($asset.browser_download_url, $downloadPath) - # Look for Windows binary with our architecture - $version = $latestRelease.tag_name.TrimStart('v') - Write-Host "Version: $version" -ForegroundColor Cyan - $possibleNames = @( - "CursorFreeVIP_${version}_windows.exe" - ) + # 安裝 + Write-Styled "正在安裝到系統..." -Color $Theme.Primary -Prefix "安裝" + Copy-Item -Path $downloadPath -Destination "$InstallDir\CursorFreeVIP.exe" -Force - $asset = $null - foreach ($name in $possibleNames) { - Write-Host "Checking for asset: $name" -ForegroundColor Cyan - $asset = $latestRelease.assets | Where-Object { $_.name -eq $name } - if ($asset) { - Write-Host "Found matching asset: $($asset.name)" -ForegroundColor Green - break - } - } - - if (!$asset) { - Write-Host "`nAvailable assets:" -ForegroundColor Yellow - $latestRelease.assets | ForEach-Object { Write-Host "- $($_.name)" } - throw "Could not find appropriate Windows binary for $arch architecture" - } - - $downloadUrl = $asset.browser_download_url - } - catch { - Write-Host "Failed to get latest release: $_" -ForegroundColor Red - exit 1 - } - - # Download binary - Write-Host "`nDownloading latest release..." -ForegroundColor Cyan - $binaryPath = Join-Path $TmpDir "CursorFreeVIP.exe" - - if (!(Get-FileWithProgress -Url $downloadUrl -OutputFile $binaryPath)) { - exit 1 - } - - # Install binary - Write-Host "Installing..." -ForegroundColor Cyan - try { - Copy-Item -Path $binaryPath -Destination "$InstallDir\CursorFreeVIP.exe" -Force - - # Add to PATH if not already present + # 添加到 PATH $currentPath = [Environment]::GetEnvironmentVariable("Path", "Machine") if ($currentPath -notlike "*$InstallDir*") { [Environment]::SetEnvironmentVariable("Path", "$currentPath;$InstallDir", "Machine") } + + Write-Styled "安裝完成!" -Color $Theme.Success -Prefix "完成" + Write-Styled "正在啟動程序..." -Color $Theme.Primary -Prefix "啟動" + + # 運行程序 + Start-Process "$InstallDir\CursorFreeVIP.exe" + } catch { - Write-Host "Failed to install: $_" -ForegroundColor Red - exit 1 - } - - Write-Host "Installation completed successfully!" -ForegroundColor Green - Write-Host "Running cursor-free-vip..." -ForegroundColor Cyan - - # Run the program - try { - & "$InstallDir\CursorFreeVIP.exe" - if ($LASTEXITCODE -ne 0) { - Write-Host "Failed to run cursor-free-vip" -ForegroundColor Red - exit 1 - } - } - catch { - Write-Host "Failed to run cursor-free-vip: $_" -ForegroundColor Red - exit 1 + Write-Styled $_.Exception.Message -Color $Theme.Error -Prefix "錯誤" + throw } } -# Run installation +# 執行安裝 try { Install-CursorFreeVIP } catch { - Write-Host "Installation failed: $_" -ForegroundColor Red - Cleanup - Write-Host "Press enter to exit..." - $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') - exit 1 + Write-Styled "安裝失敗" -Color $Theme.Error -Prefix "錯誤" + Write-Styled $_.Exception.Message -Color $Theme.Error } finally { Cleanup - if ($LASTEXITCODE -ne 0) { - Write-Host "Press enter to exit..." -ForegroundColor Green - $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') - } + Write-Host "`n按任意鍵退出..." -ForegroundColor $Theme.Info + $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } \ No newline at end of file