Optimize Backend

This commit is contained in:
aceberg 2025-07-23 21:30:18 +07:00
parent 2957a51613
commit b51161bb3e
19 changed files with 360 additions and 305 deletions

View file

@ -1,6 +1,10 @@
# Change Log
All notable changes to this project will be documented in this file.
## [v2.1.3] - 2025-0
### Added
- go 1.24.5
## [v2.1.2] - 2025-03-30
### Fixed
- Edit names bug

View file

@ -6,6 +6,7 @@ import (
// _ "net/http/pprof"
"github.com/aceberg/WatchYourLAN/internal/conf"
"github.com/aceberg/WatchYourLAN/internal/web"
)
@ -26,5 +27,8 @@ func main() {
// http.ListenAndServe("localhost:8085", nil)
// }()
web.Gui(*dirPtr, *nodePtr) // webgui.go
// Generate AppConfig
conf.Generate(*dirPtr, *nodePtr)
web.Gui() // webgui.go
}

21
go.mod
View file

@ -1,16 +1,16 @@
module github.com/aceberg/WatchYourLAN
go 1.23.6
go 1.24.5
require (
github.com/containrrr/shoutrrr v0.8.0
github.com/gin-gonic/gin v1.10.0
github.com/gin-gonic/gin v1.10.1
github.com/influxdata/influxdb-client-go/v2 v2.14.0
github.com/jmoiron/sqlx v1.4.0
github.com/lib/pq v1.10.9
github.com/prometheus/client_golang v1.21.1
github.com/spf13/viper v1.20.0
modernc.org/sqlite v1.36.2
github.com/prometheus/client_golang v1.22.0
github.com/spf13/viper v1.20.1
modernc.org/sqlite v1.38.0
)
require (
@ -34,7 +34,6 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
@ -61,13 +60,13 @@ require (
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/protobuf v1.36.1 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.61.13 // indirect
modernc.org/libc v1.65.10 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.8.2 // indirect
modernc.org/memory v1.11.0 // indirect
)

72
go.sum
View file

@ -33,8 +33,8 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
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/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@ -55,8 +55,8 @@ 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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
@ -73,8 +73,8 @@ github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@ -115,8 +115,8 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
@ -137,8 +137,8 @@ github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@ -165,51 +165,51 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo=
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
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.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.65.10 h1:ZwEk8+jhW7qBjHIT+wd0d9VjitRyQef9BnzlzGwMODc=
modernc.org/libc v1.65.10/go.mod h1:StFvYpx7i/mXtBAfVOjaU0PWZOvIRoZSgXhrwXzr8Po=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=
modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.36.2 h1:vjcSazuoFve9Wm0IVNHgmJECoOXLZM1KfMXbcX2axHA=
modernc.org/sqlite v1.36.2/go.mod h1:ADySlx7K4FdY5MaJcEv86hTJ0PjedAloTUuif0YS3ws=
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View file

@ -1,4 +1,4 @@
package web
package api
import (
"log/slog"
@ -7,6 +7,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/aceberg/WatchYourLAN/internal/check"
"github.com/aceberg/WatchYourLAN/internal/conf"
"github.com/aceberg/WatchYourLAN/internal/db"
"github.com/aceberg/WatchYourLAN/internal/models"
"github.com/aceberg/WatchYourLAN/internal/notify"
@ -20,24 +21,24 @@ func apiAll(c *gin.Context) {
c.IndentedJSON(http.StatusOK, allHosts)
}
func apiVersion(c *gin.Context) {
// func apiVersion(c *gin.Context) {
file, err := pubFS.ReadFile("public/version")
check.IfError(err)
version := string(file)[8:]
// file, err := pubFS.ReadFile("public/version")
// check.IfError(err)
// version := string(file)[8:]
c.IndentedJSON(http.StatusOK, version)
}
// c.IndentedJSON(http.StatusOK, version)
// }
func apiGetConfig(c *gin.Context) {
c.IndentedJSON(http.StatusOK, appConfig)
c.IndentedJSON(http.StatusOK, conf.AppConfig)
}
func apiHistory(c *gin.Context) {
var hosts []models.Host
if appConfig.HistInDB {
if conf.AppConfig.HistInDB {
histHosts = db.Select("history")
}
@ -58,7 +59,7 @@ func apiHost(c *gin.Context) {
idStr := c.Param("id")
host := getHostByID(idStr, allHosts) // functions.go
_, host.DNS = updateDNS(host)
_, host.DNS = check.DNS(host)
c.IndentedJSON(http.StatusOK, host)
}
@ -109,7 +110,7 @@ func apiEdit(c *gin.Context) {
func apiNotifyTest(c *gin.Context) {
msg := "WatchYourLAN: test notification"
notify.Shout(msg, appConfig.ShoutURL)
notify.Shout(msg, conf.AppConfig.ShoutURL)
c.Status(http.StatusOK)
}

106
internal/api/config.go Normal file
View file

@ -0,0 +1,106 @@
package api
import (
"log/slog"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/aceberg/WatchYourLAN/internal/conf"
)
func saveConfigHandler(c *gin.Context) {
conf.AppConfig.Host = c.PostForm("host")
conf.AppConfig.Port = c.PostForm("port")
conf.AppConfig.Theme = c.PostForm("theme")
conf.AppConfig.Color = c.PostForm("color")
conf.AppConfig.NodePath = c.PostForm("node")
conf.AppConfig.ShoutURL = c.PostForm("shout")
conf.Write(conf.AppConfig)
slog.Info("Writing new config to " + conf.AppConfig.ConfPath)
c.Redirect(http.StatusFound, c.Request.Referer())
}
func saveSettingsHandler(c *gin.Context) {
conf.AppConfig.LogLevel = c.PostForm("log")
conf.AppConfig.ArpArgs = c.PostForm("arpargs")
conf.AppConfig.Ifaces = c.PostForm("ifaces")
conf.AppConfig.UseDB = c.PostForm("usedb")
conf.AppConfig.PGConnect = c.PostForm("pgconnect")
timeout := c.PostForm("timeout")
trimHist := c.PostForm("trim")
conf.AppConfig.Timeout, _ = strconv.Atoi(timeout)
conf.AppConfig.TrimHist, _ = strconv.Atoi(trimHist)
histdb := c.PostForm("histdb")
if histdb == "on" {
conf.AppConfig.HistInDB = true
} else {
conf.AppConfig.HistInDB = false
}
arpStrs := c.PostFormArray("arpstrs")
conf.AppConfig.ArpStrs = []string{}
for _, s := range arpStrs {
if s != "" {
conf.AppConfig.ArpStrs = append(conf.AppConfig.ArpStrs, s)
}
}
conf.Write(conf.AppConfig)
slog.Debug("ARP_STRS", "", conf.AppConfig.ArpArgs)
slog.Info("Writing new config to " + conf.AppConfig.ConfPath)
// TODO:
// updateRoutines() // routines-upd.go
c.Redirect(http.StatusFound, c.Request.Referer())
}
func saveInfluxHandler(c *gin.Context) {
conf.AppConfig.InfluxAddr = c.PostForm("addr")
conf.AppConfig.InfluxToken = c.PostForm("token")
conf.AppConfig.InfluxOrg = c.PostForm("org")
conf.AppConfig.InfluxBucket = c.PostForm("bucket")
enable := c.PostForm("enable")
skip := c.PostForm("skip")
if enable == "on" {
conf.AppConfig.InfluxEnable = true
} else {
conf.AppConfig.InfluxEnable = false
}
if skip == "on" {
conf.AppConfig.InfluxSkipTLS = true
} else {
conf.AppConfig.InfluxSkipTLS = false
}
conf.Write(conf.AppConfig)
slog.Info("Writing new config to " + conf.AppConfig.ConfPath)
c.Redirect(http.StatusFound, c.Request.Referer())
}
func savePrometheusHandler(c *gin.Context) {
enable := c.PostForm("enable")
conf.AppConfig.PrometheusEnable = enable == "on"
conf.Write(conf.AppConfig)
slog.Info("Writing new config to " + conf.AppConfig.ConfPath)
c.Redirect(http.StatusFound, c.Request.Referer())
}

View file

@ -1,9 +1,7 @@
package web
package api
import (
"net"
"strconv"
"strings"
"github.com/aceberg/WatchYourLAN/internal/models"
)
@ -22,18 +20,6 @@ func getHostByID(idStr string, hosts []models.Host) (oneHost models.Host) {
return oneHost
}
func updateDNS(host models.Host) (name, dns string) {
dnsNames, _ := net.LookupAddr(host.IP)
if len(dnsNames) > 0 {
name = dnsNames[0]
dns = strings.Join(dnsNames, " ")
}
return name, dns
}
func getHostsByMAC(mac string, hosts []models.Host) (foundHosts []models.Host) {
for _, host := range hosts {

32
internal/api/routes.go Normal file
View file

@ -0,0 +1,32 @@
package api
import (
"github.com/gin-gonic/gin"
"github.com/aceberg/WatchYourLAN/internal/models"
)
var (
allHosts []models.Host
histHosts []models.Host
)
// Routes - start API routes
func Routes(router *gin.Engine) {
router.GET("/api/all", apiAll) // api.go
router.GET("/api/config", apiGetConfig) // api.go
router.GET("/api/edit/:id/:name/*known", apiEdit) // api.go
router.GET("/api/history/*mac", apiHistory) // api.go
router.GET("/api/host/:id", apiHost) // api.go
router.GET("/api/host/del/:id", apiHostDel) // api.go
router.GET("/api/notify_test", apiNotifyTest) // api.go
router.GET("/api/port/:addr/:port", apiPort) // api.go
router.GET("/api/status/*iface", apiStatus) // api.go
// router.GET("/api/version", apiVersion) // api.go
router.POST("/api/config/", saveConfigHandler) // config.go
router.POST("/api/config_settings/", saveSettingsHandler) // config.go
router.POST("/api/config_influx/", saveInfluxHandler) // config.go
router.POST("/api/config_prometheus/", savePrometheusHandler) // config.go
}

21
internal/check/network.go Normal file
View file

@ -0,0 +1,21 @@
package check
import (
"net"
"strings"
"github.com/aceberg/WatchYourLAN/internal/models"
)
// DNS - returns DNS names of a host
func DNS(host models.Host) (name, dns string) {
dnsNames, _ := net.LookupAddr(host.IP)
if len(dnsNames) > 0 {
name = dnsNames[0]
dns = strings.Join(dnsNames, " ")
}
return name, dns
}

25
internal/conf/generate.go Normal file
View file

@ -0,0 +1,25 @@
package conf
import (
"github.com/aceberg/WatchYourLAN/internal/check"
"github.com/aceberg/WatchYourLAN/internal/models"
)
// AppConfig - app config
var AppConfig models.Conf
// Generate - initial config
func Generate(dirPath, nodePath string) {
confPath := dirPath + "/config_v2.yaml"
check.Path(confPath)
AppConfig = read(confPath)
AppConfig.DirPath = dirPath
AppConfig.ConfPath = confPath
AppConfig.DBPath = dirPath + "/scan.db"
if nodePath != "" {
AppConfig.NodePath = nodePath
}
}

View file

@ -10,8 +10,7 @@ import (
"github.com/aceberg/WatchYourLAN/internal/models"
)
// Get - get app config
func Get(path string) (config models.Conf) {
func read(path string) (config models.Conf) {
viper.SetDefault("HOST", "0.0.0.0")
viper.SetDefault("PORT", "8840")
@ -76,40 +75,3 @@ func Get(path string) (config models.Conf) {
return config
}
// Write - write config to file
func Write(config models.Conf) {
viper.SetConfigFile(config.ConfPath)
viper.SetConfigType("yaml")
viper.Set("HOST", config.Host)
viper.Set("PORT", config.Port)
viper.Set("THEME", config.Theme)
viper.Set("COLOR", config.Color)
viper.Set("NODEPATH", config.NodePath)
viper.Set("LOG_LEVEL", config.LogLevel)
viper.Set("ARP_ARGS", config.ArpArgs)
viper.Set("ARP_STRS", config.ArpStrs)
viper.Set("ARP_STRS_JOINED", "") // Can be set only with ENV
viper.Set("IFACES", config.Ifaces)
viper.Set("TIMEOUT", config.Timeout)
viper.Set("TRIM_HIST", config.TrimHist)
viper.Set("HIST_IN_DB", config.HistInDB)
viper.Set("SHOUTRRR_URL", config.ShoutURL)
viper.Set("USE_DB", config.UseDB)
viper.Set("PG_CONNECT", config.PGConnect)
viper.Set("influx_enable", config.InfluxEnable)
viper.Set("influx_skip_tls", config.InfluxSkipTLS)
viper.Set("influx_addr", config.InfluxAddr)
viper.Set("influx_token", config.InfluxToken)
viper.Set("influx_org", config.InfluxOrg)
viper.Set("influx_bucket", config.InfluxBucket)
viper.Set("PROMETHEUS_ENABLE", config.PrometheusEnable)
err := viper.WriteConfig()
check.IfError(err)
}

45
internal/conf/write.go Normal file
View file

@ -0,0 +1,45 @@
package conf
import (
"github.com/spf13/viper"
"github.com/aceberg/WatchYourLAN/internal/check"
"github.com/aceberg/WatchYourLAN/internal/models"
)
// Write - write config to file
func Write(config models.Conf) {
viper.SetConfigFile(config.ConfPath)
viper.SetConfigType("yaml")
viper.Set("HOST", config.Host)
viper.Set("PORT", config.Port)
viper.Set("THEME", config.Theme)
viper.Set("COLOR", config.Color)
viper.Set("NODEPATH", config.NodePath)
viper.Set("LOG_LEVEL", config.LogLevel)
viper.Set("ARP_ARGS", config.ArpArgs)
viper.Set("ARP_STRS", config.ArpStrs)
viper.Set("ARP_STRS_JOINED", "") // Can be set only with ENV
viper.Set("IFACES", config.Ifaces)
viper.Set("TIMEOUT", config.Timeout)
viper.Set("TRIM_HIST", config.TrimHist)
viper.Set("HIST_IN_DB", config.HistInDB)
viper.Set("SHOUTRRR_URL", config.ShoutURL)
viper.Set("USE_DB", config.UseDB)
viper.Set("PG_CONNECT", config.PGConnect)
viper.Set("influx_enable", config.InfluxEnable)
viper.Set("influx_skip_tls", config.InfluxSkipTLS)
viper.Set("influx_addr", config.InfluxAddr)
viper.Set("influx_token", config.InfluxToken)
viper.Set("influx_org", config.InfluxOrg)
viper.Set("influx_bucket", config.InfluxBucket)
viper.Set("PROMETHEUS_ENABLE", config.PrometheusEnable)
err := viper.WriteConfig()
check.IfError(err)
}

View file

@ -12,10 +12,10 @@ import (
)
// Handler - display Prometheus metrics
func Handler(appConfig *models.Conf) func(c *gin.Context) {
func Handler(enabled bool) func(c *gin.Context) {
h := promhttp.Handler()
return func(c *gin.Context) {
if !appConfig.PrometheusEnable {
if !enabled {
c.AbortWithStatus(http.StatusNotFound)
return
}

View file

@ -1,19 +1,30 @@
package web
package routines
import (
"log/slog"
"github.com/aceberg/WatchYourLAN/internal/conf"
"github.com/aceberg/WatchYourLAN/internal/db"
"github.com/aceberg/WatchYourLAN/internal/models"
)
func updateRoutines() {
var (
allHosts []models.Host
histHosts []models.Host
quitScan = make(chan bool)
)
// Update - start or update routines
func Update() {
slog.Debug("Restarting scan routine")
close(quitScan)
setLogLevel()
db.SetCurrent(appConfig)
db.SetCurrent(conf.AppConfig)
db.Create()
allHosts = db.Select("now")
@ -25,7 +36,7 @@ func updateRoutines() {
func setLogLevel() {
var level slog.Level
switch appConfig.LogLevel {
switch conf.AppConfig.LogLevel {
case "debug":
slog.Info("Log level=DEBUG")
level = slog.LevelDebug
@ -40,7 +51,7 @@ func setLogLevel() {
level = slog.LevelError
default:
slog.Error("Invalid log level. Setting default level INFO")
slog.SetLogLoggerLevel(slog.LevelInfo)
level = slog.LevelInfo
}
slog.SetLogLoggerLevel(level)
}

View file

@ -1,4 +1,4 @@
package web
package routines
import (
"fmt"
@ -6,6 +6,8 @@ import (
"time"
"github.com/aceberg/WatchYourLAN/internal/arp"
"github.com/aceberg/WatchYourLAN/internal/check"
"github.com/aceberg/WatchYourLAN/internal/conf"
"github.com/aceberg/WatchYourLAN/internal/db"
"github.com/aceberg/WatchYourLAN/internal/influx"
"github.com/aceberg/WatchYourLAN/internal/models"
@ -23,11 +25,11 @@ func startScan(quit chan bool) {
return
default:
nowDate = time.Now()
plusDate = lastDate.Add(time.Duration(appConfig.Timeout) * time.Second)
plusDate = lastDate.Add(time.Duration(conf.AppConfig.Timeout) * time.Second)
if nowDate.After(plusDate) {
foundHosts = arp.Scan(appConfig.Ifaces, appConfig.ArpArgs, appConfig.ArpStrs)
foundHosts = arp.Scan(conf.AppConfig.Ifaces, conf.AppConfig.ArpArgs, conf.AppConfig.ArpStrs)
compareHosts(foundHosts)
allHosts = db.Select("now")
@ -66,24 +68,24 @@ func compareHosts(foundHosts []models.Host) {
aHost.Date = time.Now().Format("2006-01-02 15:04:05")
histHosts = append(histHosts, aHost)
if appConfig.HistInDB {
if conf.AppConfig.HistInDB {
db.Insert("history", aHost)
}
if appConfig.InfluxEnable {
influx.Add(appConfig, aHost)
if conf.AppConfig.InfluxEnable {
influx.Add(conf.AppConfig, aHost)
}
if appConfig.PrometheusEnable {
if conf.AppConfig.PrometheusEnable {
prometheus.Add(aHost)
}
}
for _, fHost := range foundHostsMap {
fHost.Name, fHost.DNS = updateDNS(fHost)
fHost.Name, fHost.DNS = check.DNS(fHost)
msg := fmt.Sprintf("WatchYourLAN: unknown host found. Names: '%s', IP: '%s', MAC: '%s', Hw: '%s', Iface: '%s'", fHost.DNS, fHost.IP, fHost.Mac, fHost.Hw, fHost.Iface)
slog.Warn(msg)
notify.Shout(msg, appConfig.ShoutURL) // Notify through Shoutrrr
notify.Shout(msg, conf.AppConfig.ShoutURL) // Notify through Shoutrrr
db.Insert("now", fHost)
}

View file

@ -1,31 +1,35 @@
package web
package routines
import (
"log/slog"
"time"
"github.com/aceberg/WatchYourLAN/internal/conf"
"github.com/aceberg/WatchYourLAN/internal/db"
"github.com/aceberg/WatchYourLAN/internal/models"
)
func trimHistoryRoutine() {
// HistoryTrim - routine for History
func HistoryTrim() {
go func() {
for {
trimHistory()
time.Sleep(time.Duration(1) * time.Hour) // Every hour
}
}()
}
func trimHistory() {
hours := appConfig.TrimHist
hours := conf.AppConfig.TrimHist
nowStr := time.Now().Format("2006-01-02 15:04:05") // This needed so all time is
now, _ := time.Parse("2006-01-02 15:04:05", nowStr) // in one format
nowMinus := now.Add(-time.Duration(hours) * time.Hour)
if appConfig.HistInDB {
if conf.AppConfig.HistInDB {
histHosts = db.Select("history")
}
@ -40,7 +44,7 @@ func trimHistory() {
if date.Before(nowMinus) {
n = n + 1
if appConfig.HistInDB {
if conf.AppConfig.HistInDB {
ids = append(ids, hist.ID)
}
} else {

View file

@ -1,105 +0,0 @@
package web
import (
"log/slog"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/aceberg/WatchYourLAN/internal/conf"
)
func saveConfigHandler(c *gin.Context) {
appConfig.Host = c.PostForm("host")
appConfig.Port = c.PostForm("port")
appConfig.Theme = c.PostForm("theme")
appConfig.Color = c.PostForm("color")
appConfig.NodePath = c.PostForm("node")
appConfig.ShoutURL = c.PostForm("shout")
conf.Write(appConfig)
slog.Info("Writing new config to " + appConfig.ConfPath)
c.Redirect(http.StatusFound, c.Request.Referer())
}
func saveSettingsHandler(c *gin.Context) {
appConfig.LogLevel = c.PostForm("log")
appConfig.ArpArgs = c.PostForm("arpargs")
appConfig.Ifaces = c.PostForm("ifaces")
appConfig.UseDB = c.PostForm("usedb")
appConfig.PGConnect = c.PostForm("pgconnect")
timeout := c.PostForm("timeout")
trimHist := c.PostForm("trim")
appConfig.Timeout, _ = strconv.Atoi(timeout)
appConfig.TrimHist, _ = strconv.Atoi(trimHist)
histdb := c.PostForm("histdb")
if histdb == "on" {
appConfig.HistInDB = true
} else {
appConfig.HistInDB = false
}
arpStrs := c.PostFormArray("arpstrs")
appConfig.ArpStrs = []string{}
for _, s := range arpStrs {
if s != "" {
appConfig.ArpStrs = append(appConfig.ArpStrs, s)
}
}
conf.Write(appConfig)
slog.Debug("ARP_STRS", "", appConfig.ArpArgs)
slog.Info("Writing new config to " + appConfig.ConfPath)
updateRoutines() // routines-upd.go
c.Redirect(http.StatusFound, c.Request.Referer())
}
func saveInfluxHandler(c *gin.Context) {
appConfig.InfluxAddr = c.PostForm("addr")
appConfig.InfluxToken = c.PostForm("token")
appConfig.InfluxOrg = c.PostForm("org")
appConfig.InfluxBucket = c.PostForm("bucket")
enable := c.PostForm("enable")
skip := c.PostForm("skip")
if enable == "on" {
appConfig.InfluxEnable = true
} else {
appConfig.InfluxEnable = false
}
if skip == "on" {
appConfig.InfluxSkipTLS = true
} else {
appConfig.InfluxSkipTLS = false
}
conf.Write(appConfig)
slog.Info("Writing new config to " + appConfig.ConfPath)
c.Redirect(http.StatusFound, c.Request.Referer())
}
func savePrometheusHandler(c *gin.Context) {
enable := c.PostForm("enable")
appConfig.PrometheusEnable = enable == "on"
conf.Write(appConfig)
slog.Info("Writing new config to " + appConfig.ConfPath)
c.Redirect(http.StatusFound, c.Request.Referer())
}

View file

@ -1,27 +0,0 @@
package web
import (
"embed"
"github.com/aceberg/WatchYourLAN/internal/models"
)
var (
// appConfig - config for Web Gui
appConfig models.Conf
allHosts []models.Host
histHosts []models.Host
quitScan chan bool
)
// templFS - html templates
//
//go:embed templates/*
var templFS embed.FS
// pubFS - public folder
//
//go:embed public/*
var pubFS embed.FS

View file

@ -1,45 +1,44 @@
package web
import (
"embed"
"html/template"
"log/slog"
"net/http"
"github.com/aceberg/WatchYourLAN/internal/api"
"github.com/aceberg/WatchYourLAN/internal/check"
"github.com/aceberg/WatchYourLAN/internal/conf"
"github.com/aceberg/WatchYourLAN/internal/prometheus"
"github.com/aceberg/WatchYourLAN/internal/routines"
"github.com/gin-gonic/gin"
)
// templFS - html templates
//
//go:embed templates/*
var templFS embed.FS
// pubFS - public folder
//
//go:embed public/*
var pubFS embed.FS
// Gui - start web server
func Gui(dirPath, nodePath string) {
func Gui() {
confPath := dirPath + "/config_v2.yaml"
check.Path(confPath)
routines.Update()
routines.HistoryTrim()
appConfig = conf.Get(confPath)
slog.Info("Config dir", "path", conf.AppConfig.DirPath)
appConfig.DirPath = dirPath
appConfig.ConfPath = confPath
appConfig.DBPath = dirPath + "/scan.db"
if nodePath != "" {
appConfig.NodePath = nodePath
}
quitScan = make(chan bool)
updateRoutines() // routines-upd.go
go trimHistoryRoutine() // trim-history.go
slog.Info("Config dir", "path", appConfig.DirPath)
address := appConfig.Host + ":" + appConfig.Port
address := conf.AppConfig.Host + ":" + conf.AppConfig.Port
slog.Info("=================================== ")
slog.Info("Web GUI at http://" + address)
slog.Info("=================================== ")
gin.SetMode(gin.ReleaseMode)
// router := gin.Default()
router := gin.New()
router.Use(gin.Recovery())
@ -52,23 +51,9 @@ func Gui(dirPath, nodePath string) {
router.GET("/config", indexHandler) // index.go
router.GET("/history", indexHandler) // index.go
router.GET("/host/*any", indexHandler) // index.go
router.GET("/metrics", prometheus.Handler(&appConfig))
router.GET("/metrics", prometheus.Handler(conf.AppConfig.PrometheusEnable))
router.GET("/api/all", apiAll) // api.go
router.GET("/api/config", apiGetConfig) // api.go
router.GET("/api/edit/:id/:name/*known", apiEdit) // api.go
router.GET("/api/history/*mac", apiHistory) // api.go
router.GET("/api/host/:id", apiHost) // api.go
router.GET("/api/host/del/:id", apiHostDel) // api.go
router.GET("/api/notify_test", apiNotifyTest) // api.go
router.GET("/api/port/:addr/:port", apiPort) // api.go
router.GET("/api/status/*iface", apiStatus) // api.go
router.GET("/api/version", apiVersion) // api.go
router.POST("/api/config/", saveConfigHandler) // config.go
router.POST("/api/config_settings/", saveSettingsHandler) // config.go
router.POST("/api/config_influx/", saveInfluxHandler) // config.go
router.POST("/api/config_prometheus/", savePrometheusHandler) // config.go
api.Routes(router)
err := router.Run(address)
check.IfError(err)