diff --git a/main.go b/main.go index 1fcb83c..365a9d0 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "net" "net/http" "os" + "os/exec" "os/user" "runtime" "sort" @@ -31,6 +32,7 @@ type NetInterface struct { MAC string `json:"mac"` Addresses []string `json:"addresses"` IsLoopback bool `json:"is_loopback"` + Profile string `json:"profile"` } type DiskInfo struct { @@ -206,6 +208,10 @@ func getInterfaces() []NetInterface { if err != nil { return nil } + + // Profile holen (best effort) + profilesByIndex, _ := getWinNetProfiles() + var out []NetInterface for _, ifc := range ifaces { if (ifc.Flags & net.FlagUp) == 0 { @@ -222,10 +228,7 @@ func getInterfaces() []NetInterface { case *net.IPAddr: ip = v.IP } - if ip == nil { - continue - } - if ip.IsLoopback() { + if ip == nil || ip.IsLoopback() { continue } ips = append(ips, ip.String()) @@ -233,11 +236,15 @@ func getInterfaces() []NetInterface { if isLoop { continue } + + profile := profilesByIndex[ifc.Index] // 👈 jetzt sicher über Index + out = append(out, NetInterface{ Name: ifc.Name, MAC: ifc.HardwareAddr.String(), Addresses: ips, IsLoopback: isLoop, + Profile: profile, }) } return out @@ -358,25 +365,28 @@ var page = template.Must(template.New("index").Parse(` h1{font-size:22px;margin:0 0 16px 0} .grid{display:flex;flex-direction:column;gap:12px} .card{width:100%} - .k{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em} + .k{font-size:16px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em} .v{font-weight:600} .row{display:flex;justify-content:space-between;gap:8px;align-items:center;margin:6px 0} .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace} - .pill{display:inline-block;background:#0b2547;color:#b8d4ff;border-radius:999px;padding:2px 8px;margin:2px 6px 0 0;font-size:12px} + .stereo{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;color: #ffd500ff} + .pill{display:inline-block;background: #0b2547;color: #00ff2aff;border-radius:999px;padding:2px 8px;margin:2px 6px 0 0;font-size:14px} + .pill2{display:inline-block;background: #ffe100ff;color: #282828ff;border-radius:999px;padding:2px 8px;margin:2px 6px 0 0;font-size:14px} .bar{height:10px;background:#091428;border-radius:999px;overflow:hidden} .fill{height:100%;background:var(--accent);width:0%} footer{margin-top:18px;color:var(--muted);font-size:12px} .disks table{width:100%;border-collapse:collapse} .disks th,.disks td{padding:8px;border-bottom:1px solid #1b2a4a;text-align:left;font-size:14px} +

Windows Systeminfo

-

+

Host
-
Hostname
+
Hostname
User
Uptime
Boot
@@ -482,7 +492,14 @@ async function load(){ (j.interfaces||[]).forEach(n=>{ const div = document.createElement('div'); div.innerHTML = '
'+n.name+'
'+(n.mac||'-')+'
'; + if (n.profile) { + const p = document.createElement('span'); + p.className = 'pill2'; + p.textContent = n.profile; + div.appendChild(p); + } (n.addresses||[]).forEach(ip=>{ const span=document.createElement('span'); span.className='pill mono'; span.textContent=ip; div.appendChild(span); }); + wrap.appendChild(div); }); @@ -660,3 +677,77 @@ func main() { log.Fatal(err) } } + +type psConnProfile struct { + Name string `json:"Name"` + InterfaceAlias string `json:"InterfaceAlias"` + InterfaceIndex int `json:"InterfaceIndex"` + NetworkCategory string `json:"NetworkCategory"` // "Public", "Private", "DomainAuthenticated" +} + +func getWinNetProfiles() (map[int]string, error) { + cmd := exec.Command( + "powershell", + "-NoProfile", + "-NonInteractive", + "-Command", + `Get-NetConnectionProfile | Select-Object InterfaceAlias,InterfaceIndex,NetworkCategory | ConvertTo-Json -Depth 3`, + ) + + out, err := cmd.Output() + if err != nil { + log.Printf("getWinNetProfiles: powershell error: %v", err) + return nil, err + } + if len(out) == 0 { + return map[int]string{}, nil + } + + // Wir wissen nicht, ob PS ein Objekt oder ein Array zurückgibt → erst Array versuchen + type psConnProfile struct { + InterfaceAlias string `json:"InterfaceAlias"` + InterfaceIndex int `json:"InterfaceIndex"` + NetworkCategory interface{} `json:"NetworkCategory"` + } + + normalizeCat := func(v interface{}) string { + switch vv := v.(type) { + case string: + // "Public", "Private", "DomainAuthenticated" + return vv + case float64: + switch int(vv) { + case 0: + return "Public" + case 1: + return "Private" + case 2: + return "DomainAuthenticated" + default: + return "Unknown" + } + default: + return "" + } + } + + // 1) Array probieren + var arr []psConnProfile + if err := json.Unmarshal(out, &arr); err == nil { + res := make(map[int]string, len(arr)) + for _, p := range arr { + res[p.InterfaceIndex] = normalizeCat(p.NetworkCategory) + } + return res, nil + } + + // 2) Einzelnes Objekt probieren + var single psConnProfile + if err := json.Unmarshal(out, &single); err != nil { + log.Printf("getWinNetProfiles: cannot unmarshal: %v -- out: %s", err, string(out)) + return nil, err + } + res := make(map[int]string, 1) + res[single.InterfaceIndex] = normalizeCat(single.NetworkCategory) + return res, nil +}