diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08cb523 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +go.sum diff --git a/backend/.env b/backend/.env new file mode 100644 index 0000000..b85a9f6 --- /dev/null +++ b/backend/.env @@ -0,0 +1,7 @@ +ENABLE_TLS=false +ROOT_DIRECTORY=../ +INDEX_FILE=index.html +SERVER_ADDRESS=0.0.0.0 +SERVER_PORT=8090 +SERVICES_FILE=services.json +IMG_UPLOAD_PATH=../img diff --git a/backend/api/addservice.go b/backend/api/addservice.go new file mode 100644 index 0000000..e7b5579 --- /dev/null +++ b/backend/api/addservice.go @@ -0,0 +1,67 @@ +package api + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + + "github.com/google/uuid" +) + +func AddService(w http.ResponseWriter, req *http.Request) { + req.ParseMultipartForm(10 << 20) + file, handler, err := req.FormFile("img") + if err != nil { + fmt.Println("error retrieving the file: ", err) + return + } + defer file.Close() + + fmt.Printf("Uploaded File: %+v\n", handler.Filename) + fmt.Printf("File Size: %+v\n", handler.Size) + fmt.Printf("MIME Header: %+v\n", handler.Header) + + dst, err := os.Create(os.Getenv("IMG_UPLOAD_PATH") + "/" + handler.Filename) + if err != nil { + fmt.Println("Error creating destination file:", err) + return + } + defer dst.Close() + if _, err := io.Copy(dst, file); err != nil { + fmt.Println("Error copying file:", err) + return + } + newService := make(map[string]any) + newService["img"] = "img/" + handler.Filename + newService["href"] = req.FormValue("href") + newService["text"] = req.FormValue("text") + newService["alt"] = req.FormValue("text") + "icon" + newService["key"] = uuid.New().String() + fmt.Println(newService) + allservices := ReadServicesFile() + var allservicesmap []map[string]any + err = json.Unmarshal([]byte(allservices), &allservicesmap) + if err != nil { + panic(err) + } + exists := false + for i := range allservicesmap { + if allservicesmap[i]["href"] == newService["href"] { + exists = true + break + } + } + if !exists { + allservicesmap = append(allservicesmap, newService) + res, err := json.Marshal(allservicesmap) + if err != nil { + panic(err) + } + os.WriteFile(os.Getenv("SERVICES_FILE"), res, 4755) + fmt.Fprintf(w, "%s", res) + return + } + fmt.Fprint(w, "{\"status\":\"already exists\"}") +} diff --git a/backend/api/services.go b/backend/api/services.go new file mode 100644 index 0000000..2c7fdd8 --- /dev/null +++ b/backend/api/services.go @@ -0,0 +1,32 @@ +package api + +import ( + "fmt" + "io" + "net/http" + "os" +) + +func ReadServicesFile() string { + data, e := os.ReadFile(os.Getenv("SERVICES_FILE")) + if e != nil { + panic(e) + } + return string(data) +} + +func Services(w http.ResponseWriter, req *http.Request) { + switch req.Method { + case "GET": + fmt.Fprintf(w, "%s", ReadServicesFile()) + case "POST": + data, err := io.ReadAll(req.Body) + if err != nil { + fmt.Fprintf(w, "Error to read body: %v", err) + return + } + fmt.Println(string(data)) + os.WriteFile(os.Getenv("SERVICES_FILE"), data, 4755) + fmt.Fprint(w, string(data)) + } +} diff --git a/backend/api/spa.go b/backend/api/spa.go new file mode 100644 index 0000000..4bcf49e --- /dev/null +++ b/backend/api/spa.go @@ -0,0 +1,38 @@ +package api + +import ( + "net/http" + "os" + "path/filepath" + "slices" + "strings" +) + +func SpaHandler(staticPath, indexPath string) http.Handler { + fs := http.FileServer(http.Dir(staticPath)) + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Игнорируем API-запросы + if strings.HasPrefix(r.URL.Path, "/api/") { + http.NotFound(w, r) + return + } + + // Проверяем существование файла + filePath := filepath.Join(staticPath, r.URL.Path) + _, err := os.Stat(filePath) + + // Если файл не существует или путь - SPA-маршрут + if os.IsNotExist(err) || isSPARoute(r.URL.Path) { + r.URL.Path = "/" // Переписываем путь для index.html + } + + // Отдаем статический файл + fs.ServeHTTP(w, r) + }) +} + +func isSPARoute(path string) bool { + spaRoutes := []string{"/", "/update", "/trx"} // Добавьте свои маршруты + return slices.Contains(spaRoutes, path) +} diff --git a/backend/go.mod b/backend/go.mod new file mode 100644 index 0000000..8bd40a6 --- /dev/null +++ b/backend/go.mod @@ -0,0 +1,7 @@ +module dshbrd + +go 1.24.5 + +require github.com/joho/godotenv v1.5.1 + +require github.com/google/uuid v1.6.0 // indirect diff --git a/backend/main.go b/backend/main.go new file mode 100644 index 0000000..c256a7b --- /dev/null +++ b/backend/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "dshbrd/api" + "log" + "net/http" + "os" + + "github.com/joho/godotenv" +) + +func main() { + err := godotenv.Load(".env") + if err != nil { + log.Fatal("error loading .env file") + } + + http.Handle("/", api.SpaHandler(os.Getenv("ROOT_DIRECTORY"), os.Getenv("INDEX_FILE"))) + http.HandleFunc("/api/services", api.Services) + http.HandleFunc("/api/services/add", api.AddService) + + if os.Getenv("ENABLE_TLS") == "true" { + http.ListenAndServeTLS( + os.Getenv("SERVER_ADDRESS")+":"+os.Getenv("SERVER_PORT"), + os.Getenv("CERT_FILE"), + os.Getenv("KEY_FILE"), + nil, + ) + } else { + http.ListenAndServe( + os.Getenv("SERVER_ADDRESS")+":"+os.Getenv("SERVER_PORT"), + nil, + ) + } +} diff --git a/backend/services.json b/backend/services.json new file mode 100644 index 0000000..a00f13e --- /dev/null +++ b/backend/services.json @@ -0,0 +1 @@ +[{"alt":"telegram-icon","href":"https://web.telegram.org/k/","img":"img/telegram-icon.jpeg","key":"0","text":"Telegram"},{"alt":"github-icon","href":"https://github.com","img":"img/github-icon.png","key":"1","text":"github.com"},{"alt":"gitea-icon","href":"https://gitea.home.com:3000","img":"img/gitea-icon.png","key":"2","text":"gitea.home.com"},{"alt":"jellyfin-icon","href":"http://jellyfin.home.com:8096","img":"img/jellyfin.png","key":"3","text":"jellyfin.home.com"},{"alt":"immich-icon","href":"http://immich.home.com:2283","img":"img/immich-icon.png","key":"4","text":"immich.home.com"},{"alt":"navidrome-icon","href":"http://navidrome.home.com:4533","img":"img/navidrome-icon.png","key":"4","text":"navidrome.home.com"},{"alt":"portainer-icon","href":"https://portainer.home.com:9443","img":"img/portainer-icon.webp","key":"5","text":"portainer.home.com"},{"alt":"dnsmasq-icon","href":"https://dns.home.com","img":"img/dnsmasq-icon.jpeg","key":"6","text":"dns.home.com"},{"alt":"router-icon","href":"http://router.home.com","img":"img/router-icon.svg","key":"7","text":"router.home.com"}] \ No newline at end of file diff --git a/index.html b/index.html index c101918..f172b65 100644 --- a/index.html +++ b/index.html @@ -6,12 +6,12 @@ + -