diff --git a/windows/setup.ps1 b/windows/setup.ps1 new file mode 100644 index 0000000..de90b1c --- /dev/null +++ b/windows/setup.ps1 @@ -0,0 +1,361 @@ +#Requires -RunAsAdministrator +<# +.SYNOPSIS + JingTian rclone Client Setup Script for Windows + +.DESCRIPTION + This script sets up rclone sync on a Windows client machine to sync + the BenjaminTeam folder with the remote Ubuntu server. + +.PARAMETER ServerHost + The IP address or hostname of the Ubuntu sync server. + Default: 20.240.140.78 + +.PARAMETER ServerUser + The SSH username on the Ubuntu server. + Default: rclone-sync + +.PARAMETER ServerPath + The remote path on the Ubuntu server. + Default: /data/jingtian/BenjaminTeam + +.PARAMETER LocalPath + The local BenjaminTeam folder path. If not specified, the script will + attempt to auto-detect or prompt the user. + +.PARAMETER SyncInterval + Sync interval in minutes for the scheduled task. + Default: 5 + +.EXAMPLE + .\setup.ps1 + +.EXAMPLE + .\setup.ps1 -LocalPath "D:\Work\BenjaminTeam" -SyncInterval 10 +#> + +param( + [string]$ServerHost = "20.240.140.78", + [string]$ServerUser = "rclone-sync", + [string]$ServerPath = "/data/jingtian/BenjaminTeam", + [string]$LocalPath = "", + [int]$SyncInterval = 5 +) + +# Configuration +$ErrorActionPreference = "Stop" +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$RcloneKeySource = Join-Path $ScriptDir "rclone-key" +$RcloneKeyDest = "$env:USERPROFILE\.ssh\jingtian_rclone" +$RcloneConfigDir = "$env:APPDATA\rclone" +$RcloneConfigFile = "$RcloneConfigDir\rclone.conf" +$SyncScriptPath = Join-Path $ScriptDir "sync.ps1" +$LogDir = "$env:LOCALAPPDATA\JingTian\logs" + +# Styling +function Write-Header { + param([string]$Text) + Write-Host "" + Write-Host "===========================================" -ForegroundColor Cyan + Write-Host $Text -ForegroundColor Cyan + Write-Host "===========================================" -ForegroundColor Cyan +} + +function Write-Step { + param([string]$Step, [string]$Text) + Write-Host "" + Write-Host "[$Step] $Text" -ForegroundColor Yellow +} + +function Write-Success { + param([string]$Text) + Write-Host " [OK] $Text" -ForegroundColor Green +} + +function Write-Info { + param([string]$Text) + Write-Host " $Text" -ForegroundColor Gray +} + +function Write-ErrorMsg { + param([string]$Text) + Write-Host " [ERROR] $Text" -ForegroundColor Red +} + +# ============================================================ +# MAIN SCRIPT +# ============================================================ + +Write-Header "JingTian rclone Client Setup" + +Write-Host "" +Write-Host "Server: $ServerHost" -ForegroundColor White +Write-Host "User: $ServerUser" -ForegroundColor White +Write-Host "Remote: $ServerPath" -ForegroundColor White + +# ------------------------------------------------------------ +# Step 1: Check/Install Git +# ------------------------------------------------------------ +Write-Step "1/7" "Checking Git installation..." + +$gitPath = "C:\Program Files\Git\bin\git.exe" +if (Test-Path $gitPath) { + $gitVersion = & $gitPath --version + Write-Success "Git already installed: $gitVersion" +} else { + Write-Info "Git not found. Installing..." + + $gitInstaller = "$env:TEMP\git-installer.exe" + $gitUrl = "https://github.com/git-for-windows/git/releases/download/v2.43.0.windows.1/Git-2.43.0-64-bit.exe" + + Write-Info "Downloading Git installer..." + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Invoke-WebRequest -Uri $gitUrl -OutFile $gitInstaller + + Write-Info "Installing Git (this may take a few minutes)..." + Start-Process -FilePath $gitInstaller -ArgumentList '/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS=icons,ext\reg\shellhere,assoc,assoc_sh' -Wait + + if (Test-Path $gitPath) { + Write-Success "Git installed successfully" + } else { + Write-ErrorMsg "Git installation failed" + exit 1 + } +} + +# ------------------------------------------------------------ +# Step 2: Check/Install rclone +# ------------------------------------------------------------ +Write-Step "2/7" "Checking rclone installation..." + +$rclonePath = "$env:LOCALAPPDATA\rclone\rclone.exe" +$rclonePathAlt = "C:\rclone\rclone.exe" + +if (Test-Path $rclonePath) { + $rcloneVersion = & $rclonePath version | Select-Object -First 1 + Write-Success "rclone already installed: $rcloneVersion" +} elseif (Test-Path $rclonePathAlt) { + $rclonePath = $rclonePathAlt + $rcloneVersion = & $rclonePath version | Select-Object -First 1 + Write-Success "rclone already installed: $rcloneVersion" +} else { + Write-Info "rclone not found. Installing..." + + $rcloneZip = "$env:TEMP\rclone.zip" + $rcloneExtract = "$env:TEMP\rclone-extract" + $rcloneInstallDir = "$env:LOCALAPPDATA\rclone" + $rcloneUrl = "https://downloads.rclone.org/rclone-current-windows-amd64.zip" + + Write-Info "Downloading rclone..." + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Invoke-WebRequest -Uri $rcloneUrl -OutFile $rcloneZip + + Write-Info "Extracting rclone..." + if (Test-Path $rcloneExtract) { Remove-Item -Recurse -Force $rcloneExtract } + Expand-Archive -Path $rcloneZip -DestinationPath $rcloneExtract + + # Find the extracted folder (it has version in the name) + $extractedFolder = Get-ChildItem -Path $rcloneExtract -Directory | Select-Object -First 1 + + # Create install directory and copy rclone + if (-not (Test-Path $rcloneInstallDir)) { + New-Item -ItemType Directory -Path $rcloneInstallDir -Force | Out-Null + } + Copy-Item -Path "$($extractedFolder.FullName)\rclone.exe" -Destination $rclonePath -Force + + # Clean up + Remove-Item -Recurse -Force $rcloneZip, $rcloneExtract + + if (Test-Path $rclonePath) { + Write-Success "rclone installed to $rclonePath" + } else { + Write-ErrorMsg "rclone installation failed" + exit 1 + } +} + +# ------------------------------------------------------------ +# Step 3: Detect/Confirm BenjaminTeam folder +# ------------------------------------------------------------ +Write-Step "3/7" "Locating BenjaminTeam folder..." + +if ($LocalPath -and (Test-Path $LocalPath)) { + Write-Success "Using specified path: $LocalPath" +} else { + # Common locations to search + $searchPaths = @( + "$env:USERPROFILE\Documents\BenjaminTeam", + "$env:USERPROFILE\Documents\Benjamin Team", + "D:\BenjaminTeam", + "D:\Benjamin Team", + "C:\BenjaminTeam", + "C:\Benjamin Team" + ) + + $foundPath = $null + foreach ($path in $searchPaths) { + if (Test-Path $path) { + $foundPath = $path + break + } + } + + if ($foundPath) { + Write-Info "Found BenjaminTeam folder at: $foundPath" + $confirm = Read-Host " Use this path? (Y/n)" + if ($confirm -eq "" -or $confirm -match "^[Yy]") { + $LocalPath = $foundPath + } + } + + if (-not $LocalPath -or -not (Test-Path $LocalPath)) { + Write-Info "Could not auto-detect BenjaminTeam folder." + $LocalPath = Read-Host " Enter the full path to your BenjaminTeam folder" + + if (-not (Test-Path $LocalPath)) { + Write-ErrorMsg "Path does not exist: $LocalPath" + exit 1 + } + } + + Write-Success "Using path: $LocalPath" +} + +# Ensure _LLM_Sync folder exists +$llmSyncPath = Join-Path $LocalPath "_LLM_Sync" +if (-not (Test-Path $llmSyncPath)) { + New-Item -ItemType Directory -Path $llmSyncPath -Force | Out-Null + Write-Info "Created _LLM_Sync folder" +} + +# ------------------------------------------------------------ +# Step 4: Setup SSH key +# ------------------------------------------------------------ +Write-Step "4/7" "Setting up SSH key..." + +# Create .ssh directory if it doesn't exist +$sshDir = "$env:USERPROFILE\.ssh" +if (-not (Test-Path $sshDir)) { + New-Item -ItemType Directory -Path $sshDir -Force | Out-Null +} + +# Copy the SSH key +if (-not (Test-Path $RcloneKeySource)) { + Write-ErrorMsg "SSH key not found at: $RcloneKeySource" + Write-Info "Make sure the rclone-key file is in the same directory as this script." + exit 1 +} + +Copy-Item -Path $RcloneKeySource -Destination $RcloneKeyDest -Force +Write-Success "SSH key copied to $RcloneKeyDest" + +# Test SSH connection +Write-Info "Testing SSH connection to $ServerHost..." +$sshTest = & ssh -o StrictHostKeyChecking=accept-new -o BatchMode=yes -i $RcloneKeyDest "$ServerUser@$ServerHost" "echo 'SSH_OK'" 2>&1 + +if ($sshTest -match "SSH_OK") { + Write-Success "SSH connection successful" +} else { + Write-ErrorMsg "SSH connection failed: $sshTest" + Write-Info "Please check the server is running and the key is correct." + exit 1 +} + +# ------------------------------------------------------------ +# Step 5: Configure rclone +# ------------------------------------------------------------ +Write-Step "5/7" "Configuring rclone..." + +# Create rclone config directory +if (-not (Test-Path $RcloneConfigDir)) { + New-Item -ItemType Directory -Path $RcloneConfigDir -Force | Out-Null +} + +# Generate rclone config +$rcloneConfig = @" +[jingtian-server] +type = sftp +host = $ServerHost +user = $ServerUser +key_file = $RcloneKeyDest +shell_type = unix +"@ + +# Write config file +Set-Content -Path $RcloneConfigFile -Value $rcloneConfig -Encoding ASCII +Write-Success "rclone config written to $RcloneConfigFile" + +# Test rclone connection +Write-Info "Testing rclone connection..." +$rcloneTest = & $rclonePath lsd "jingtian-server:$ServerPath" 2>&1 + +if ($LASTEXITCODE -eq 0) { + Write-Success "rclone connection successful" + Write-Info "Remote folders:" + $rcloneTest | ForEach-Object { Write-Info " $_" } +} else { + Write-ErrorMsg "rclone connection failed: $rcloneTest" + exit 1 +} + +# ------------------------------------------------------------ +# Step 6: Create log directory +# ------------------------------------------------------------ +Write-Step "6/7" "Setting up logging..." + +if (-not (Test-Path $LogDir)) { + New-Item -ItemType Directory -Path $LogDir -Force | Out-Null +} +Write-Success "Log directory: $LogDir" + +# ------------------------------------------------------------ +# Step 7: Create Scheduled Task +# ------------------------------------------------------------ +Write-Step "7/7" "Creating scheduled sync task..." + +$taskName = "JingTian-Sync" +$taskDescription = "Syncs BenjaminTeam folder with remote server every $SyncInterval minutes" + +# Remove existing task if it exists +$existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue +if ($existingTask) { + Unregister-ScheduledTask -TaskName $taskName -Confirm:$false + Write-Info "Removed existing scheduled task" +} + +# Create the scheduled task +$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$SyncScriptPath`" -LocalPath `"$LocalPath`" -RclonePath `"$rclonePath`" -LogDir `"$LogDir`"" + +$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes $SyncInterval) -RepetitionDuration (New-TimeSpan -Days 9999) + +$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Highest + +$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 1) + +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description $taskDescription | Out-Null + +Write-Success "Scheduled task created: $taskName" +Write-Info "Sync will run every $SyncInterval minutes" + +# ------------------------------------------------------------ +# Summary +# ------------------------------------------------------------ +Write-Header "Setup Complete!" + +Write-Host "" +Write-Host "Configuration Summary:" -ForegroundColor White +Write-Host " Local Path: $LocalPath" -ForegroundColor Gray +Write-Host " Remote: $ServerUser@$ServerHost`:$ServerPath" -ForegroundColor Gray +Write-Host " Sync Interval: Every $SyncInterval minutes" -ForegroundColor Gray +Write-Host " Log Directory: $LogDir" -ForegroundColor Gray +Write-Host "" +Write-Host "Sync Behavior:" -ForegroundColor White +Write-Host " - Main folders: One-way sync (Windows -> Server)" -ForegroundColor Gray +Write-Host " - _LLM_Sync: Bidirectional sync" -ForegroundColor Gray +Write-Host "" +Write-Host "To manually trigger a sync, run:" -ForegroundColor White +Write-Host " .\sync.ps1" -ForegroundColor Cyan +Write-Host "" +Write-Host "To check sync logs:" -ForegroundColor White +Write-Host " Get-Content `"$LogDir\sync.log`" -Tail 50" -ForegroundColor Cyan +Write-Host ""