feat: externalize apps/analysis to Gitea repos, add analysis table
- Migration 007: repo_url on apps table + analysis table with FTS5 - Analysis struct, parser, CRUD, validation, hash computation - Selective purge: remote-only apps/analysis preserved across fn index - CLI: fn app list/clone/pull, fn analysis list/clone/pull - search/show/list now include analysis results - Apps removed from git tracking (content lives in Gitea repos) - .gitkeep for apps/ and analysis/ dirs - Bash functions: jupyter analysis pipeline, shell utilities - Browser domain: CDP functions moved from infra to browser Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package browser
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// CdpScreenshotOpts configura el screenshot.
|
||||
type CdpScreenshotOpts struct {
|
||||
// FullPage indica si capturar la pagina completa (scroll height) o solo el viewport.
|
||||
FullPage bool
|
||||
// Quality es la calidad JPEG (0-100). Solo aplica si Format es "jpeg". Por defecto 80.
|
||||
Quality int
|
||||
// Format es el formato de imagen: "png" o "jpeg". Por defecto "png".
|
||||
Format string
|
||||
}
|
||||
|
||||
// CdpScreenshot captura un screenshot de la pagina actual y lo guarda en outputPath.
|
||||
// Usa Page.captureScreenshot del protocolo CDP.
|
||||
// outputPath debe tener extension .png o .jpg/.jpeg segun el formato elegido.
|
||||
func CdpScreenshot(c *CDPConn, outputPath string, opts CdpScreenshotOpts) error {
|
||||
if c == nil {
|
||||
return fmt.Errorf("cdp screenshot: conexion nula")
|
||||
}
|
||||
|
||||
if opts.Format == "" {
|
||||
opts.Format = "png"
|
||||
}
|
||||
if opts.Quality == 0 && opts.Format == "jpeg" {
|
||||
opts.Quality = 80
|
||||
}
|
||||
|
||||
params := map[string]any{
|
||||
"format": opts.Format,
|
||||
"captureBeyondViewport": opts.FullPage,
|
||||
}
|
||||
if opts.Format == "jpeg" {
|
||||
params["quality"] = opts.Quality
|
||||
}
|
||||
|
||||
if opts.FullPage {
|
||||
// Expandir clip para capturar toda la pagina
|
||||
scrollHeight, err := CdpEvaluate(c, "document.documentElement.scrollHeight")
|
||||
if err == nil {
|
||||
params["clip"] = nil // dejar que Chrome capture todo
|
||||
_ = scrollHeight
|
||||
}
|
||||
}
|
||||
|
||||
result, err := c.sendCDP("Page.captureScreenshot", params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cdp screenshot: %w", err)
|
||||
}
|
||||
|
||||
dataStr, ok := result["data"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("cdp screenshot: campo data ausente en respuesta")
|
||||
}
|
||||
|
||||
imgData, err := base64.StdEncoding.DecodeString(dataStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cdp screenshot: decodificar base64: %w", err)
|
||||
}
|
||||
|
||||
// Crear directorio si no existe
|
||||
if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
|
||||
return fmt.Errorf("cdp screenshot: crear directorio: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(outputPath, imgData, 0644); err != nil {
|
||||
return fmt.Errorf("cdp screenshot: guardar archivo: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user