package infra import ( "regexp" "strings" ) // NordVPNStatus representa el estado parseado de nordvpn status. type NordVPNStatus struct { Connected bool // true si hay conexion activa Status string // "Connected" o "Disconnected" Hostname string // ej: "es42.nordvpn.com" IP string // IP del servidor VPN Country string // ej: "Spain" City string // ej: "Madrid" Technology string // ej: "NordLynx" Protocol string // ej: "nordlynx" Transfer string // ej: "1.2 MiB received, 500 KiB sent" Uptime string // ej: "5 minutes 32 seconds" } // ansiRegexp elimina codigos de escape ANSI. var ansiRegexp = regexp.MustCompile(`\x1b\[[0-9;]*m`) // ParseNordVPNStatus parsea la salida de texto de `nordvpn status` // a un struct tipado. Funcion pura — no ejecuta comandos. func ParseNordVPNStatus(output string) NordVPNStatus { var s NordVPNStatus lines := strings.Split(output, "\n") for _, line := range lines { line = ansiRegexp.ReplaceAllString(line, "") line = strings.TrimSpace(line) line = strings.TrimLeft(line, "- ") idx := strings.Index(line, ":") if idx < 0 { continue } key := strings.ToLower(strings.TrimSpace(line[:idx])) val := strings.TrimSpace(line[idx+1:]) switch key { case "status": s.Status = val s.Connected = strings.EqualFold(val, "connected") case "hostname", "server": s.Hostname = val case "ip": s.IP = val case "country": s.Country = val case "city": s.City = val case "current technology": s.Technology = val case "current protocol": s.Protocol = val case "transfer": s.Transfer = val case "uptime": s.Uptime = val } } return s }