Files
fn_registry/apps/script_navegador/wsl.go
T
egutierrez 3c250a9252 feat: app script_navegador y dashboard Metabase
App Go para ejecutar scripts de navegación automatizada usando las
funciones CDP del registry. Incluye script de creación de dashboard
en Metabase para monitoreo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 14:24:39 +02:00

103 lines
2.8 KiB
Go

package main
import (
"fmt"
"io"
"net"
"os"
"strings"
"time"
)
// getWindowsHostIP obtiene la IP del host Windows desde WSL2.
// Lee /etc/resolv.conf que WSL2 configura con la IP del host.
func getWindowsHostIP() string {
data, err := os.ReadFile("/etc/resolv.conf")
if err != nil {
return ""
}
for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "nameserver ") {
ip := strings.TrimPrefix(line, "nameserver ")
ip = strings.TrimSpace(ip)
if ip != "" {
return ip
}
}
}
return ""
}
// getWindowsGatewayIP obtiene la IP del gateway (host Windows) desde la tabla de rutas.
func getWindowsGatewayIP() string {
data, err := os.ReadFile("/proc/net/route")
if err != nil {
return ""
}
for _, line := range strings.Split(string(data), "\n") {
fields := strings.Fields(line)
if len(fields) >= 3 && fields[1] == "00000000" { // default route
hexIP := fields[2]
if len(hexIP) == 8 {
// /proc/net/route stores IPs as little-endian 32-bit hex
// "011017AC" -> bytes [01,10,17,AC] -> IP 172.23.16.1 (reversed)
var a, b, c, d uint8
fmt.Sscanf(hexIP[0:2], "%02x", &a)
fmt.Sscanf(hexIP[2:4], "%02x", &b)
fmt.Sscanf(hexIP[4:6], "%02x", &c)
fmt.Sscanf(hexIP[6:8], "%02x", &d)
return fmt.Sprintf("%d.%d.%d.%d", d, c, b, a)
}
}
}
return ""
}
// waitForCDP espera a que el puerto CDP esté accesible desde WSL.
func waitForCDP(host string, port int, timeout time.Duration) error {
deadline := time.Now().Add(timeout)
addr := fmt.Sprintf("%s:%d", host, port)
for time.Now().Before(deadline) {
conn, err := net.DialTimeout("tcp", addr, 300*time.Millisecond)
if err == nil {
conn.Close()
return nil
}
time.Sleep(300 * time.Millisecond)
}
return fmt.Errorf("CDP %s no disponible despues de %s", addr, timeout)
}
// startCDPProxy levanta un proxy TCP local que reenvía conexiones al host Windows.
// Chrome CDP solo acepta conexiones desde localhost, así que el proxy en WSL
// conecta al host Windows vía portproxy/netsh y expone el puerto localmente.
// Retorna el puerto local del proxy y una función para cerrarlo.
func startCDPProxy(windowsHost string, remotePort, localPort int) (net.Listener, error) {
ln, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", localPort))
if err != nil {
return nil, fmt.Errorf("proxy listen: %w", err)
}
go func() {
for {
client, err := ln.Accept()
if err != nil {
return // listener cerrado
}
go proxyConn(client, windowsHost, remotePort)
}
}()
return ln, nil
}
func proxyConn(client net.Conn, host string, port int) {
defer client.Close()
remote, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 5*time.Second)
if err != nil {
return
}
defer remote.Close()
go io.Copy(remote, client)
io.Copy(client, remote)
}