Notify, LogLevel

This commit is contained in:
aceberg 2024-08-25 17:08:25 +07:00
parent 6f703c51be
commit 90e4c07a37
12 changed files with 128 additions and 25 deletions

3
go.mod
View file

@ -3,6 +3,7 @@ module github.com/aceberg/WatchYourLAN
go 1.22.6
require (
github.com/containrrr/shoutrrr v0.8.0
github.com/gin-gonic/gin v1.10.0
github.com/influxdata/influxdb-client-go/v2 v2.14.0
github.com/jmoiron/sqlx v1.4.0
@ -17,6 +18,7 @@ require (
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
@ -32,6 +34,7 @@ require (
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect

20
go.sum
View file

@ -12,12 +12,16 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/containrrr/shoutrrr v0.8.0 h1:mfG2ATzIS7NR2Ec6XL+xyoHzN97H8WPjir8aYzJUSec=
github.com/containrrr/shoutrrr v0.8.0/go.mod h1:ioyQAyu1LJY6sILuNyKaQaw+9Ttik5QePU8atnAdO2o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
@ -28,6 +32,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@ -38,8 +44,12 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -55,6 +65,8 @@ github.com/influxdata/influxdb-client-go/v2 v2.14.0 h1:AjbBfJuq+QoaXNcrova8smSjw
github.com/influxdata/influxdb-client-go/v2 v2.14.0/go.mod h1:Ahpm3QXKMJslpXl3IftVLVezreAUtBOTZssDrjZEFHI=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -74,6 +86,9 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
@ -89,6 +104,10 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo=
github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A=
github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -146,6 +165,7 @@ golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=

View file

@ -1,7 +1,7 @@
package arp
import (
"log"
"log/slog"
"os/exec"
"strings"
"time"
@ -49,8 +49,8 @@ func Scan(ifaces string) []models.Host {
for _, iface := range perString {
text = scanIface(iface)
log.Println("INFO: scanning interface", iface)
log.Println("INFO: found IPs:", text)
slog.Debug("Scanning interface " + iface)
slog.Debug("Found IPs: \n" + text)
foundHosts = append(foundHosts, parseOutput(text, iface)...)
}

View file

@ -15,11 +15,12 @@ func Get(path string) (config models.Conf) {
viper.SetDefault("THEME", "solar")
viper.SetDefault("COLOR", "dark")
viper.SetDefault("NODEPATH", "")
// viper.SetDefault("SCANER", "arpscan")
viper.SetDefault("LOG_LEVEL", "info")
viper.SetDefault("ARP_ARGS", "")
viper.SetDefault("IFACES", "")
viper.SetDefault("TIMEOUT", 60)
viper.SetDefault("TRIM_HIST", 48)
viper.SetDefault("SHOUTRRR_URL", "")
viper.SetDefault("INFLUX_ENABLE", false)
viper.SetConfigFile(path)
@ -34,11 +35,13 @@ func Get(path string) (config models.Conf) {
config.Theme = viper.Get("THEME").(string)
config.Color = viper.Get("COLOR").(string)
config.NodePath = viper.Get("NODEPATH").(string)
// config.Scaner = viper.Get("SCANER").(string)
config.LogLevel = viper.Get("LOG_LEVEL").(string)
config.ArpArgs = viper.Get("ARP_ARGS").(string)
config.Ifaces = viper.Get("IFACES").(string)
config.Timeout = viper.GetInt("TIMEOUT")
config.TrimHist = viper.GetInt("TRIM_HIST")
config.ShoutURL = viper.Get("SHOUTRRR_URL").(string)
config.InfluxEnable = viper.GetBool("INFLUX_ENABLE")
config.InfluxSkipTLS = viper.GetBool("INFLUX_SKIP_TLS")
config.InfluxAddr, _ = viper.Get("INFLUX_ADDR").(string)
@ -60,11 +63,12 @@ func Write(config models.Conf) {
viper.Set("THEME", config.Theme)
viper.Set("COLOR", config.Color)
viper.Set("NODEPATH", config.NodePath)
// viper.Set("SCANER", config.Scaner)
viper.Set("LOG_LEVEL", config.LogLevel)
viper.Set("ARP_ARGS", config.ArpArgs)
viper.Set("IFACES", config.Ifaces)
viper.Set("TIMEOUT", config.Timeout)
viper.Set("TRIM_HIST", config.TrimHist)
viper.Set("SHOUTRRR_URL", config.ShoutURL)
viper.Set("influx_enable", config.InfluxEnable)
viper.Set("influx_skip_tls", config.InfluxSkipTLS)

View file

@ -10,10 +10,12 @@ type Conf struct {
ConfPath string
DBPath string
NodePath string
LogLevel string
Ifaces string
ArpArgs string
Timeout int
TrimHist int
ShoutURL string
InfluxEnable bool
InfluxAddr string
InfluxToken string

16
internal/notify/shout.go Normal file
View file

@ -0,0 +1,16 @@
package notify
import (
"github.com/containrrr/shoutrrr"
"log/slog"
)
// Shout - send message with shoutrrr
func Shout(message string, url string) {
if url != "" {
err := shoutrrr.Send(url, message)
if err != nil {
slog.Error("Notification failed (shoutrrr): ", err)
}
}
}

View file

@ -1,7 +1,7 @@
package web
import (
"log"
// "log"
"net/http"
"github.com/gin-gonic/gin"
@ -25,7 +25,6 @@ func apiHistory(c *gin.Context) {
if mac != "/" {
mac = mac[1:]
log.Println("MAC", mac)
hosts = getHostsByMAC(mac, histHosts)
} else {
hosts = histHosts

View file

@ -35,8 +35,10 @@ func saveConfigHandler(c *gin.Context) {
appConfig.Theme = c.PostForm("theme")
appConfig.Color = c.PostForm("color")
appConfig.NodePath = c.PostForm("node")
appConfig.LogLevel = c.PostForm("log")
appConfig.ArpArgs = c.PostForm("arpargs")
appConfig.Ifaces = c.PostForm("ifaces")
appConfig.ShoutURL = c.PostForm("shout")
timeout := c.PostForm("timeout")
trimHist := c.PostForm("trim")
@ -47,6 +49,8 @@ func saveConfigHandler(c *gin.Context) {
slog.Info("writing new config to " + appConfig.ConfPath)
updateRoutines() // routines-upd.go
c.Redirect(http.StatusFound, "/config")
}

View file

@ -0,0 +1,40 @@
package web
import (
"log/slog"
"github.com/aceberg/WatchYourLAN/internal/db"
)
func updateRoutines() {
close(quitScan)
setLogLevel()
db.Create(appConfig.DBPath)
allHosts = db.Select(appConfig.DBPath, "now")
histHosts = db.Select(appConfig.DBPath, "history")
quitScan = make(chan bool)
go startScan(quitScan) // scan-routine.go
}
func setLogLevel() {
var level slog.Level
switch appConfig.LogLevel {
case "debug":
level = slog.LevelDebug
case "info":
level = slog.LevelInfo
case "warn":
level = slog.LevelWarn
case "error":
level = slog.LevelError
default:
// invalid log level, handle error
}
slog.SetLogLoggerLevel(level)
}

View file

@ -1,31 +1,23 @@
package web
import (
// "log/slog"
"fmt"
"log/slog"
"time"
"github.com/aceberg/WatchYourLAN/internal/arp"
"github.com/aceberg/WatchYourLAN/internal/db"
"github.com/aceberg/WatchYourLAN/internal/influx"
"github.com/aceberg/WatchYourLAN/internal/models"
"github.com/aceberg/WatchYourLAN/internal/notify"
)
func updateScan() {
db.Create(appConfig.DBPath)
allHosts = db.Select(appConfig.DBPath, "now")
histHosts = db.Select(appConfig.DBPath, "history")
quitScan = make(chan bool)
go startScan()
}
func startScan() {
func startScan(quit chan bool) {
var lastDate time.Time
for {
select {
case <-quitScan:
case <-quit:
return
default:
nowDate := time.Now()
@ -80,7 +72,10 @@ func compareHosts(foundHosts []models.Host) {
for _, fHost := range foundHostsMap {
// NOTIFY, LOG
msg := fmt.Sprintf("Unknown host IP: '%s', MAC: '%s', Hw: '%s', Iface: '%s'", fHost.IP, fHost.Mac, fHost.Hw, fHost.Iface)
slog.Warn(msg)
notify.Shout(msg, appConfig.ShoutURL) // Notify through Shoutrrr
fHost.Name, fHost.DNS = updateDNS(fHost)
db.Insert(appConfig.DBPath, "now", fHost)
}

View file

@ -38,6 +38,23 @@
<td>Local node-bootstrap url</td>
<td><input name="node" type="text" class="form-control" value="{{ .Config.NodePath }}"></td>
</tr>
<tr>
<td>Shoutrrr URL</td>
<td>
<textarea name="shout" class="form-control" style="width: 100%;" rows="3" wrap="soft">{{ .Config.ShoutURL }}</textarea>
</td>
</tr>
<tr>
<td>Log level</td>
<td><select name="log" class="form-select">
<option selected>{{ .Config.LogLevel }}</option>
<option value="debug">debug</option>
<option value="info">info</option>
<option value="warn">warn</option>
<option value="error">error</option>
</select></td>
</tr>
<tr>
<tr>
<td>Interfaces</td>
<td><input name="ifaces" type="text" class="form-control" value="{{ .Config.Ifaces }}"></td>

View file

@ -24,7 +24,8 @@ func Gui(dirPath, nodePath string) {
appConfig.DBPath = dirPath + "/scan.db"
appConfig.NodePath = nodePath
updateScan() // scan.go
quitScan = make(chan bool)
updateRoutines() // routines-upd.go
slog.Info("config", "path", appConfig.DirPath)
@ -35,7 +36,9 @@ func Gui(dirPath, nodePath string) {
slog.Info("=================================== ")
gin.SetMode(gin.ReleaseMode)
router := gin.Default()
// router := gin.Default()
router := gin.New()
router.Use(gin.Recovery())
templ := template.Must(template.New("").ParseFS(templFS, "templates/*"))
router.SetHTMLTemplate(templ) // templates
@ -45,7 +48,7 @@ func Gui(dirPath, nodePath string) {
router.GET("/api/all", apiAll) // api.go
router.GET("/api/edit/:id/:name/*known", apiEdit) // api.go
router.GET("/api/history/*mac", apiHistory) // api.go
router.GET("/api/host", apiHost) // api.go
router.GET("/api/host/:id", apiHost) // api.go
router.GET("/api/host/del/:id", apiHostDel) // api.go
router.GET("/api/port/:addr/:port", apiPort) // api.go