$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot Set-Location -LiteralPath $root # Robust browser opener — tries several Windows methods until one works. function Open-Browser($url) { $opened = $false # Method 1: Start-Process with the URL (default protocol handler) try { Start-Process -FilePath $url; $opened = $true } catch {} if (-not $opened) { # Method 2: explorer.exe with the URL (opens default browser) try { & explorer.exe $url; $opened = $true } catch {} } if (-not $opened) { # Method 3: cmd `start` builtin try { & cmd.exe /c start "" $url; $opened = $true } catch {} } if ($opened) { Write-Host " [ok] abriendo navegador -> $url" -ForegroundColor DarkGray } else { Write-Host " [warn] no se pudo abrir el navegador. Abre manualmente: $url" -ForegroundColor Yellow } return $opened } Write-Host "" Write-Host " [yt-scraper] iniciando servidor local..." -ForegroundColor Cyan if (-not (Test-Path '.run')) { New-Item -ItemType Directory -Path '.run' | Out-Null } # Already running? if (Test-Path '.run\server.info') { $firstLine = (Get-Content '.run\server.info' -TotalCount 1) $existingPort = ($firstLine -split '\s+')[0] try { $r = Invoke-WebRequest -Uri "http://localhost:$existingPort/healthz" -UseBasicParsing -TimeoutSec 2 if ($r.Content -match 'ok') { Write-Host " [ok] servidor ya activo en el puerto $existingPort" -ForegroundColor Green Open-Browser "http://127.0.0.1:$existingPort" exit 0 } } catch {} } # Collect candidate free ports scanning from 8000. $candidates = @() foreach ($p in 8000..8100) { try { $listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, $p) $listener.Start(); $listener.Stop() $candidates += $p if ($candidates.Count -ge 8) { break } } catch {} } if ($candidates.Count -eq 0) { Write-Host " [error] no se encontro ningun puerto libre (8000-8100)" -ForegroundColor Red exit 2 } # Launch uvicorn DETACHED in its own persistent minimized console window, logging to .run/server.log. # The `cmd /c` window is an independent console: it survives this launcher exiting. $launched = $false $proc = $null $port = 0 foreach ($candidate in $candidates) { # clear previous log Remove-Item '.run\server.log' -Force -ErrorAction SilentlyContinue $cmdLine = '/c python -m uvicorn yt_scraper.webapp.app:app --host 127.0.0.1 --port ' + $candidate + ' --log-level info > .run\server.log 2>&1' $proc = Start-Process -FilePath 'cmd.exe' -ArgumentList $cmdLine -WorkingDirectory $root -WindowStyle Minimized -PassThru Set-Content -Path '.run\server.info' -Value "$candidate $($proc.Id) $(Get-Date -Format o)" -Encoding ASCII $ok = $false for ($i = 0; $i -lt 40; $i++) { Start-Sleep -Milliseconds 500 try { $r = Invoke-WebRequest -Uri "http://localhost:$candidate/healthz" -UseBasicParsing -TimeoutSec 2 if ($r.Content -match 'ok') { $ok = $true; break } } catch {} } if ($ok) { $port = $candidate; $launched = $true; break } # failed on this port — show why from the log, then try the next candidate Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue Remove-Item '.run\server.info' -Force -ErrorAction SilentlyContinue } if (-not $launched) { Write-Host " [error] no se pudo iniciar el servidor." -ForegroundColor Red if (Test-Path '.run\server.log') { Write-Host " --- ultimo log del servidor ---" -ForegroundColor Yellow Get-Content '.run\server.log' -Tail 25 | ForEach-Object { Write-Host " $_" } } else { Write-Host " instala dependencias: pip install -e `".[web]`"" -ForegroundColor Yellow } exit 3 } Open-Browser "http://127.0.0.1:$port" Write-Host "" Write-Host " [ok] servidor activo" -ForegroundColor Green Write-Host " URL: http://localhost:$port" Write-Host " PID: $($proc.Id) (ventana minimizada 'cmd' independiente)" Write-Host " log: .run\server.log" Write-Host " stop: stop-server.bat" Write-Host ""