diff --git a/.github/workflows/docker-readme.yml b/.github/workflows/docker-readme.yml index 314718a..8205277 100644 --- a/.github/workflows/docker-readme.yml +++ b/.github/workflows/docker-readme.yml @@ -2,10 +2,10 @@ name: DockerHub-README on: workflow_dispatch: - # push: - # branches: [ "main" ] - # paths: - # - 'README.md' + push: + branches: [ "main" ] + paths: + - 'README.md' env: IMAGE_NAME: watchyourlan diff --git a/.version b/.version index 20fe357..5409a84 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -VERSION=0.7.5 \ No newline at end of file +VERSION=0.8.1 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d9c51..4554548 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [v0.8.1] - 2022-12-29 +### Changed +- Full code refactoring + +### Added +- Embed templates +- GUI config page + ## [v0.7.5] - 2022-09-14 ### Fixed - Sort by IP [Issue #4](https://github.com/aceberg/WatchYourLAN/issues/4), [Issue #14](https://github.com/aceberg/WatchYourLAN/issues/14) diff --git a/cmd/WatchYourLAN/main.go b/cmd/WatchYourLAN/main.go index 6ba3b5c..9298114 100644 --- a/cmd/WatchYourLAN/main.go +++ b/cmd/WatchYourLAN/main.go @@ -1,21 +1,19 @@ package main import ( - "fmt" + "flag" - "github.com/aceberg/WatchYourLAN/internal/conf" - "github.com/aceberg/WatchYourLAN/internal/db" + "github.com/aceberg/WatchYourLAN/internal/check" "github.com/aceberg/WatchYourLAN/internal/web" ) const configPath = "/data/config" func main() { - appConfig := conf.Get(configPath) // Get config from Defaults, Config file, Env + confPtr := flag.String("c", configPath, "Path to config file") + flag.Parse() - fmt.Println("CONF =", appConfig) + check.Path(*confPtr) - db.Create(appConfig.DbPath) // Check if DB exists. Create if not - - web.Gui(appConfig) // Start web GUI + web.Gui(*confPtr) // Start web GUI } diff --git a/internal/check/path.go b/internal/check/path.go new file mode 100644 index 0000000..c4d1643 --- /dev/null +++ b/internal/check/path.go @@ -0,0 +1,23 @@ +package check + +import ( + "os" + "path/filepath" +) + +// Path - create path if not exist +func Path(path string) { + + _, err := os.Stat(path) + + if path != "" && err != nil { + + dir := filepath.Dir(path) + + err = os.MkdirAll(dir, os.ModePerm) + IfError(err) + + _, err = os.Create(path) + IfError(err) + } +} diff --git a/internal/conf/getconfig.go b/internal/conf/get-config.go similarity index 70% rename from internal/conf/getconfig.go rename to internal/conf/get-config.go index 327ccfe..a758c4b 100644 --- a/internal/conf/getconfig.go +++ b/internal/conf/get-config.go @@ -35,10 +35,19 @@ func Get(path string) (config models.Conf) { return config } -// // Write - write config to file -// func Write(path, theme string) { -// viper.SetConfigFile(path) -// viper.SetConfigType("env") -// viper.Set("THEME", theme) -// viper.WriteConfig() -// } +// Write - write config to file +func Write(path string, config models.Conf) { + + viper.SetConfigFile(path) + viper.SetConfigType("env") + + viper.Set("IFACE", config.Iface) + viper.Set("GUIIP", config.GuiIP) + viper.Set("GUIPORT", config.GuiPort) + viper.Set("TIMEOUT", config.Timeout) + viper.Set("SHOUTRRR_URL", config.ShoutURL) + viper.Set("THEME", config.Theme) + + err := viper.WriteConfig() + check.IfError(err) +} diff --git a/internal/scan/start.go b/internal/scan/start.go index 68d78ee..ada0efa 100644 --- a/internal/scan/start.go +++ b/internal/scan/start.go @@ -8,14 +8,29 @@ import ( ) // Start - start arp-scan goroutine -func Start(appConfig models.Conf) { +func Start(appConfig models.Conf, quit chan bool) { var foundHosts []models.Host var dbHosts []models.Host - for { // Endless - foundHosts = arpScan(appConfig.Iface) // Scan interfaces - dbHosts = db.Select(appConfig.DbPath) // Select everything from DB - db.SetNow(appConfig.DbPath) // Mark hosts in DB as offline - hostsCompare(appConfig, foundHosts, dbHosts) // Compare hosts online and in DB and add them to DB - time.Sleep(time.Duration(appConfig.Timeout) * time.Second) // Timeout + var lastDate time.Time + + for { + select { + case <-quit: + return + default: + nowDate := time.Now() + plusDate := lastDate.Add(time.Duration(appConfig.Timeout) * time.Second) + + if nowDate.After(plusDate) { + foundHosts = arpScan(appConfig.Iface) + dbHosts = db.Select(appConfig.DbPath) + db.SetNow(appConfig.DbPath) + hostsCompare(appConfig, foundHosts, dbHosts) + + lastDate = time.Now() + } + + time.Sleep(time.Duration(1) * time.Second) + } } } diff --git a/internal/web/config.go b/internal/web/config.go new file mode 100644 index 0000000..1130c67 --- /dev/null +++ b/internal/web/config.go @@ -0,0 +1,51 @@ +package web + +import ( + "html/template" + "net/http" + "strconv" + + "github.com/aceberg/WatchYourLAN/internal/check" + "github.com/aceberg/WatchYourLAN/internal/conf" + "github.com/aceberg/WatchYourLAN/internal/models" + "github.com/aceberg/WatchYourLAN/internal/scan" +) + +func configHandler(w http.ResponseWriter, r *http.Request) { + var guiData models.GuiData + + guiData.Config = AppConfig + guiData.Icon = Icon + + guiData.Themes = []string{"cerulean", "cosmo", "cyborg", "darkly", "flatly", "journal", "litera", "lumen", "lux", "materia", "minty", "morph", "pulse", "quartz", "sandstone", "simplex", "sketchy", "slate", "solar", "spacelab", "superhero", "united", "vapor", "yeti", "zephyr"} + + tmpl, err := template.ParseFS(TemplHTML, TemplPath+"config.html", TemplPath+"header.html", TemplPath+"footer.html") + check.IfError(err) + err = tmpl.ExecuteTemplate(w, "header", guiData) + check.IfError(err) + err = tmpl.ExecuteTemplate(w, "config", guiData) + check.IfError(err) +} + +func saveConfigHandler(w http.ResponseWriter, r *http.Request) { + var err error + + AppConfig.Iface = r.FormValue("iface") + AppConfig.GuiIP = r.FormValue("host") + AppConfig.GuiPort = r.FormValue("port") + AppConfig.ShoutURL = r.FormValue("shout") + AppConfig.Theme = r.FormValue("theme") + + timeout := r.FormValue("timeout") + AppConfig.Timeout, err = strconv.Atoi(timeout) + check.IfError(err) + + close(QuitScan) + + conf.Write(ConfigPath, AppConfig) + + QuitScan = make(chan bool) + go scan.Start(AppConfig, QuitScan) + + http.Redirect(w, r, r.Header.Get("Referer"), 302) +} diff --git a/internal/web/index.go b/internal/web/index-home.go similarity index 68% rename from internal/web/index.go rename to internal/web/index-home.go index d3a06f8..f880a63 100644 --- a/internal/web/index.go +++ b/internal/web/index-home.go @@ -17,9 +17,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { guiData.Hosts = AllHosts guiData.Icon = Icon - // tmpl, _ := template.ParseFiles(TemplPath+"index.html", TemplPath+"header.html", TemplPath+"footer.html") - tmpl, _ := template.ParseFS(TemplHTML, TemplPath+"index.html", TemplPath+"header.html", TemplPath+"footer.html") - err := tmpl.ExecuteTemplate(w, "header", guiData) + tmpl, err := template.ParseFS(TemplHTML, TemplPath+"index.html", TemplPath+"header.html", TemplPath+"footer.html") + check.IfError(err) + err = tmpl.ExecuteTemplate(w, "header", guiData) check.IfError(err) err = tmpl.ExecuteTemplate(w, "index", guiData) check.IfError(err) diff --git a/internal/web/on-off-line.go b/internal/web/on-off-line.go index d38af11..93d6674 100644 --- a/internal/web/on-off-line.go +++ b/internal/web/on-off-line.go @@ -21,7 +21,6 @@ func offlineHandler(w http.ResponseWriter, r *http.Request) { } } - // tmpl, _ := template.ParseFiles(TemplPath+"offline.html", TemplPath+"header.html", TemplPath+"footer.html") tmpl, _ := template.ParseFS(TemplHTML, TemplPath+"offline.html", TemplPath+"header.html", TemplPath+"footer.html") err := tmpl.ExecuteTemplate(w, "header", guiData) check.IfError(err) @@ -42,7 +41,6 @@ func onlineHandler(w http.ResponseWriter, r *http.Request) { } } - // tmpl, _ := template.ParseFiles(TemplPath+"offline.html", TemplPath+"header.html", TemplPath+"footer.html") tmpl, _ := template.ParseFS(TemplHTML, TemplPath+"offline.html", TemplPath+"header.html", TemplPath+"footer.html") err := tmpl.ExecuteTemplate(w, "header", guiData) check.IfError(err) diff --git a/internal/web/templates/config.html b/internal/web/templates/config.html new file mode 100644 index 0000000..b19b84b --- /dev/null +++ b/internal/web/templates/config.html @@ -0,0 +1,56 @@ +{{ define "config" }} + +
+After changing Host or Port you need to restart the app
+