From e10016d70175a92d1147cf16abf2bc7e4c93c44f Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Fri, 29 Jul 2022 23:07:01 -0400 Subject: [PATCH] First cut at nmvpn plugin Signed-off-by: Jim Ramsay --- .gitignore | 1 + README.md | 45 +++++++++++++++++++++++++++++++++ go.mod | 10 ++++++++ go.sum | 11 ++++++++ main.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++ pkg/nmvpn/nmvpn.go | 59 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 188 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 pkg/nmvpn/nmvpn.go diff --git a/.gitignore b/.gitignore index 66fd13c..dd2d647 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Binaries for programs and plugins +waybar-nmvpn *.exe *.exe~ *.dll diff --git a/README.md b/README.md index e568f0a..b1445ca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,47 @@ # waybar-nmvpn + Waybar plugin to display NetworkManager VPN status + +## Installation + +``` +go install github.com/lack/waybar-nmvpn@latest +``` + +## Configuration + +In `$XDG_CONFIG_HOME/waybar/config` +```json +{ + // ... other waybar configuration + "custom/nmvpn": { + "format": "{} {icon}", + "return-type": "json", + "exec": "$GOPATH/bin/waybar-nmvpn", + "format-icons": { + "connected": "", + "disconnected": "", + "none": "", + "error": "⚠" + } + } +} +``` + +In `$XDG_CONFIG_HOME/waybar/style.css` +```css +#custom-nmvpn.connected { + background-color: rgba(0x29, 0x80, 0xb9, 0.8); + box-shadow: inset 0 -3px rgba(0x29, 0x80, 0xb9, 1.0); +} + +#custom-nmvpn.disconnected { + background-color: rgba(0xf5, 0x3c, 0x3c, 0.8); + box-shadow: inset 0 -3px rgba(0xf5, 0x3c, 0x3c, 1.0); +} + +#custom-nmvpn.error { + background-color: rgba(0xeb, 0x4d, 0x4b, 0.8); + box-shadow: inset 0 -3px rgba(0xeb, 0x4d, 0x4b, 1.0); +} +``` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4c442ea --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/lack/waybar-nmvpn + +go 1.18 + +require ( + github.com/Wifx/gonetworkmanager v0.4.0 + github.com/lack/gowaybarplug v0.0.1 +) + +require github.com/godbus/dbus/v5 v5.0.2 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e9dc2ee --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/Wifx/gonetworkmanager v0.4.0 h1:iZ7o3z3YIqEEAa+bBOCwQkLLUQuxG02CdiE7NCe5y6A= +github.com/Wifx/gonetworkmanager v0.4.0/go.mod h1:EdhHf2O00IZXfMv9LC6CS6SgTwcMTg/ZSDhGvch0cs8= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/godbus/dbus/v5 v5.0.2 h1:QtWdZQyXTEn7S0LXv9nVxPUiT37d1i7UntpRTiKM86E= +github.com/godbus/dbus/v5 v5.0.2/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/lack/gowaybarplug v0.0.1 h1:v+ZURlUmXh1UXsEMQHAzBaojaRTrUmYUY+mJ7sOI/Yw= +github.com/lack/gowaybarplug v0.0.1/go.mod h1:JDAsRZJ0F337PSepC1prQUc+8NOdaqTqKjTYm3eR67Q= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/xorcare/pointer v1.1.0 h1:sFwXOhRF8QZ0tyVZrtxWGIoVZNEmRzBCaFWdONPQIUM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/main.go b/main.go new file mode 100644 index 0000000..d6504c3 --- /dev/null +++ b/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "time" + + "github.com/lack/waybar-nmvpn/pkg/nmvpn" + + waybar "github.com/lack/gowaybarplug" +) + +func loop(interval time.Duration) { + wb := waybar.NewUpdater() + + for true { + status := waybar.Status{ + Text: "VPN", + } + vpns, err := nmvpn.GetVPNs() + if err == nil && len(vpns) > 0 { + active := false + for _, v := range vpns { + if v.Active { + active = true + break + } + } + if active { + status.Alt = "connected" + status.Class = []string{"connected"} + } else { + status.Alt = "disconnected" + status.Class = []string{"disconnected"} + } + status.Tooltip = "" + for _, v := range vpns { + if status.Tooltip != "" { + status.Tooltip += "\n" + } + state := "down" + if v.Active { + state = "up" + } + status.Tooltip += fmt.Sprintf("%s: %s", v.Name, state) + } + } else if err != nil { + status.Alt = "error" + status.Class = []string{"error"} + status.Tooltip = fmt.Sprintf("Error fetching VPN information: %v", err) + } else { + status.Alt = "none" + status.Class = []string{"unconfigured"} + status.Tooltip = "No VPN connections configured" + } + wb.Status <- &status + time.Sleep(interval) + } +} + +func main() { + loop(5 * time.Second) +} diff --git a/pkg/nmvpn/nmvpn.go b/pkg/nmvpn/nmvpn.go new file mode 100644 index 0000000..0f723be --- /dev/null +++ b/pkg/nmvpn/nmvpn.go @@ -0,0 +1,59 @@ +package nmvpn + +import ( + gonm "github.com/Wifx/gonetworkmanager" +) + +type Vpn struct { + Name string + Uuid string + Active bool +} + +func GetVPNs() ([]Vpn, error) { + settings, err := gonm.NewSettings() + if err != nil { + return nil, err + } + + connections, err := settings.ListConnections() + if err != nil { + return nil, err + } + + vpns := make([]Vpn, 0, len(connections)) + for _, c := range connections { + s, err := c.GetSettings() + if err != nil { + return nil, err + } + ctype := s["connection"]["type"].(string) + if ctype == "vpn" { + vpn := Vpn{ + Name: s["connection"]["id"].(string), + Uuid: s["connection"]["uuid"].(string), + } + vpns = append(vpns, vpn) + } + } + if len(vpns) > 0 { + nm, err := gonm.NewNetworkManager() + if err != nil { + return nil, err + } + + actives, err := nm.GetPropertyActiveConnections() + for _, a := range actives { + uuid, err := a.GetPropertyUUID() + if err != nil { + return nil, err + } + for i, v := range vpns { + if uuid == v.Uuid { + vpns[i].Active = true + } + } + } + } + return vpns, nil +}