feat: batch .md download, multi-select, thumbnails, all OPPORTUNITIES tools

Videos view: multi-select (checkboxes) + select-all/deselect-all + bulk action
bar (Download .md batch, Download thumbnails, Download audio). Per-video buttons:
.md download (done) or Process to .md (pending), clip.

Channels: per-channel pending count + 'Download pending .md' (batches pending
video_ids). Each channel keeps Videos/.md folder/Remove actions.

Backend (jobs.py + api.py):
- POST /api/scrape/batch {video_ids} + POST /api/scrape/video/{id} (on-demand
  .md for any video incl. pending) as SSE-tracked jobs
- GET /api/videos/{id}/markdown (file download)
- POST /api/tools/thumbnails + GET /api/thumbnails/{id} (local cache, offline)
- GET /api/clip/{id}?from=&to= (transcript segment)
- GET /api/stats (aggregate totals)
- POST /api/tools/audio (mp3 job)

Tools view rebuilt as full Knowledge Base grid surfacing every OPPORTUNITIES.md
feature as electable buttons (md download, re-render, export, search, analysis,
thumbnails, audio, clip, stats, cookies, channels, watch, open folders).

Floating job widget (SSE) for any running job. Thumbnails served via
/api/thumbnails/{id} everywhere (works offline once cached).

Launcher: robust Open-Browser helper (3 fallback methods) auto-opens
http://127.0.0.1:<port> on start + on idempotent re-open. data/ gitignored.
This commit is contained in:
urieljareth
2026-07-26 23:39:05 -06:00
parent 621bbc5f5c
commit 0682d2d806
7 changed files with 852 additions and 33 deletions
+20 -2
View File
@@ -2,6 +2,24 @@ $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
@@ -15,7 +33,7 @@ if (Test-Path '.run\server.info') {
$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
Start-Process "http://localhost:$existingPort"
Open-Browser "http://127.0.0.1:$existingPort"
exit 0
}
} catch {}
@@ -74,7 +92,7 @@ if (-not $launched) {
exit 3
}
Start-Process "http://localhost:$port"
Open-Browser "http://127.0.0.1:$port"
Write-Host ""
Write-Host " [ok] servidor activo" -ForegroundColor Green
Write-Host " URL: http://localhost:$port"