NhanPT 2 éve
szülő
commit
e76a47f98a

+ 7 - 178
src/main.go

@@ -1,51 +1,22 @@
 package main
 
 import (
-	"html/template"
-	"io/ioutil"
 	"log"
 	"net/http"
-	"net"
 	"os"
-	"path"
 	"path/filepath"
-	"strings"
-	"time"
 
-	"github.com/fsnotify/fsnotify"
 	docker "github.com/help-14/magma/addons/docker"
 	healthcheckserver "github.com/help-14/magma/addons/health-check-server"
 	"github.com/help-14/magma/modules"
 )
 
-var pwd string
-var themeDir string
-var clientAddress string
-var appConfig modules.Config
-var websiteData = struct {
-	Config   modules.WebsiteConfig
-	Language modules.Language
-	Contents []modules.GroupData
-}{}
-var webTemplate *template.Template
-
 func main() {
 	prepare()
-	loadData()
-	go watchChanges()
-
-	commonfs := http.FileServer(http.Dir(filepath.Join(pwd, "data")))
-	http.Handle("/common/", http.StripPrefix("/common/", commonfs))
-
-	languagefs := http.FileServer(http.Dir(filepath.Join(pwd, "languages")))
-	http.Handle("/languages/", http.StripPrefix("/languages/", languagefs))
-
-	th := themeHandler{}
-	http.Handle("/theme/", th)
-
-	http.HandleFunc("/weather", serveWeather)
-	http.HandleFunc("/", serveTemplate)
 
+	modules.SetupLanguage()
+	modules.SetupTemplate()
+	modules.SetupWeather()
 	//loadAddons()
 
 	log.Println("Listening on http://localhost:7001 ...")
@@ -56,75 +27,19 @@ func main() {
 }
 
 func prepare() {
-	pwd, _ = os.Getwd()
-
-	dataPath := filepath.Join(pwd, "data")
+	dataPath := filepath.Join(modules.CurrentPath(), "data")
 	os.MkdirAll(dataPath, os.ModePerm)
 
 	iconPath := filepath.Join(dataPath, "icon")
 	os.RemoveAll(iconPath)
 	os.MkdirAll(iconPath, os.ModePerm)
 
-	modules.CopyDir(filepath.Join(pwd, "common"), dataPath, false)
-}
-
-func RemoveIndex(s []modules.BookmarkData, index int) {
-	copy(s[index:], s[index+1:])
-	s[len(s)-1] = modules.BookmarkData{"", "", "", false}
-	s = s[:len(s)-1]
-}
-
-func pruneData() {
-	// Remove local ressources access
-	for group := 0; group < len(websiteData.Contents); group++ {
-		for col := 0; col < len(websiteData.Contents[group].Columns); col++ {
-			bookmarks := websiteData.Contents[group].Columns[col].Bookmarks
-			for bookmark := 0; bookmark < len(websiteData.Contents[group].Columns[col].Bookmarks); bookmark++ {
-				bookmarkData := websiteData.Contents[group].Columns[col].Bookmarks[bookmark]
-				if bookmarkData.IsLocal {
-					RemoveIndex(bookmarks, bookmark)
-					bookmark--
-				}
-			}
-			websiteData.Contents[group].Columns[col].Bookmarks = bookmarks
-		}
-	}
-	loadTemplate()
-}
-
-func loadData() {
-	appConfig = modules.LoadConfig()
-	websiteData.Config = appConfig.Website
-	websiteData.Language = modules.LoadLanguage(appConfig.Website.Language)
-	websiteData.Contents = modules.LoadContent().Data
-
-	// Download icon to local and remove local ressources access
-	for group := 0; group < len(websiteData.Contents); group++ {
-		for col := 0; col < len(websiteData.Contents[group].Columns); col++ {
-			for bookmark := 0; bookmark < len(websiteData.Contents[group].Columns[col].Bookmarks); bookmark++ {
-				bookmarkData := websiteData.Contents[group].Columns[col].Bookmarks[bookmark]
-				if bookmarkData.IsImage() || bookmarkData.IsSVG() {
-					iconPath := bookmarkData.Icon
-					fileName := path.Base(iconPath)
-					if modules.DownloadFile(iconPath, filepath.Join(pwd, "data", "icon", fileName)) {
-						websiteData.Contents[group].Columns[col].Bookmarks[bookmark].Icon = "/common/icon/" + fileName
-					}
-				}
-			}
-		}
-	}
-	loadTemplate()
-}
-
-func loadTemplate() {
-	themeDir = filepath.Join(pwd, "themes", appConfig.Website.Theme)
-	tmpl, _ := template.ParseFiles(filepath.Join(themeDir, "index.html"))
-	webTemplate = tmpl
+	modules.CopyDir(filepath.Join(modules.CurrentPath(), "common"), dataPath, false)
 }
 
 func loadAddons() {
-	for i := 0; i < len(appConfig.Addons); i++ {
-		switch addonName := appConfig.Addons[i]; addonName {
+	for i := 0; i < len(modules.AppConfig.Addons); i++ {
+		switch addonName := modules.AppConfig.Addons[i]; addonName {
 		case "docker":
 			docker.Setup()
 		case "health-check-server":
@@ -132,89 +47,3 @@ func loadAddons() {
 		}
 	}
 }
-
-func watchChanges() {
-	watcher, err := fsnotify.NewWatcher()
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer watcher.Close()
-
-	done := make(chan bool)
-	go func() {
-		for {
-			select {
-			case event, ok := <-watcher.Events:
-				if !ok {
-					return
-				}
-				log.Println("Modified file:", event.Name)
-				loadData()
-			case err, ok := <-watcher.Errors:
-				if !ok {
-					return
-				}
-				log.Println("error:", err)
-			}
-		}
-	}()
-
-	watcher.Add(filepath.Join(pwd, "data", "data.yaml"))
-	watcher.Add(filepath.Join(pwd, "data", "config.yaml"))
-	watcher.Add(filepath.Join(pwd, "themes", appConfig.Website.Theme, "index.html"))
-	<-done
-}
-
-func ClientIsLocal(r *http.Request) bool {
-    IPAddress := net.ParseIP(r.Header.Get("X-Real-Ip"))
-    if IPAddress == nil {
-        IPAddress = net.ParseIP(r.Header.Get("X-Forwarded-For"))
-    }
-    if IPAddress == nil {
-	    IPAddress = net.ParseIP(strings.Split(r.RemoteAddr, ":")[0])
-    }
-    return IPAddress.IsPrivate()
-}
-
-func serveTemplate(w http.ResponseWriter, r *http.Request) {
-	if ! ClientIsLocal(r) {
-		pruneData()
-	} else {
-		loadData()
-	}
-	webTemplate.Execute(w, websiteData)
-}
-
-type themeHandler struct {
-	format string
-}
-
-func (th themeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	http.ServeFile(w, r, strings.Replace(r.URL.Path, "/theme", themeDir, 1))
-}
-
-var weatherTimeOut int64
-var weatherCache []byte
-
-func serveWeather(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "application/json")
-	if appConfig.OpenWeatherMap.ApiKey == "demo" {
-		w.Write([]byte("{\"coord\":{\"lon\":105.8085,\"lat\":21.0427},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"base\":\"stations\",\"main\":{\"temp\":301.14,\"feels_like\":305.69,\"temp_min\":301.14,\"temp_max\":301.14,\"pressure\":1004,\"humidity\":83},\"visibility\":10000,\"wind\":{\"speed\":6.17,\"deg\":120},\"clouds\":{\"all\":75},\"dt\":1650981392,\"sys\":{\"type\":1,\"id\":9308,\"country\":\"VN\",\"sunrise\":1650925786,\"sunset\":1650971952},\"timezone\":25200,\"id\":1581130,\"name\":\"Hanoi\",\"cod\":200}"))
-	} else {
-		if time.Now().UnixMilli() >= weatherTimeOut {
-			resp, err := http.Get("https://api.openweathermap.org/data/2.5/weather?lat=" + appConfig.OpenWeatherMap.Latitude + "&lon=" + appConfig.OpenWeatherMap.Longitude + "&limit=1&appid=" + appConfig.OpenWeatherMap.ApiKey)
-			if err != nil {
-				log.Fatalln(err)
-				return
-			}
-			body, err := ioutil.ReadAll(resp.Body)
-			if err != nil {
-				log.Fatalln(err)
-				return
-			}
-			weatherCache = body
-			weatherTimeOut = time.Now().UnixMilli() + 1800000
-		}
-		w.Write(weatherCache)
-	}
-}

+ 7 - 4
src/modules/config.go

@@ -29,7 +29,9 @@ type OpenWeatherMapConfig struct {
 	Latitude  string `yaml:"lat"`
 }
 
-func LoadConfig() Config {
+var AppConfig Config
+
+func LoadConfig() {
 	defaultConfig := Config{
 		Website: WebsiteConfig{
 			Title:        "Magma Dashboard",
@@ -41,20 +43,21 @@ func LoadConfig() Config {
 		},
 		Addons: []string{},
 	}
+	AppConfig = defaultConfig
 
 	yamlFile, err := ioutil.ReadFile(filepath.Join("data", "config.yaml"))
 	if err != nil {
 		fmt.Printf("Error reading YAML file: %s\n", err)
-		return defaultConfig
+		return
 	}
 
 	var yamlConfig Config
 	err = yaml.Unmarshal(yamlFile, &yamlConfig)
 	if err != nil {
 		fmt.Printf("Error parsing YAML file: %s\n", err)
-		return defaultConfig
+		return
 	}
 
 	fmt.Println("Loaded config:", yamlConfig)
-	return yamlConfig
+	AppConfig = yamlConfig
 }

+ 5 - 4
src/modules/content.go

@@ -28,10 +28,11 @@ type ColumnData struct {
 }
 
 type BookmarkData struct {
-	Name string `yaml:"name"`
-	Url  string `yaml:"url"`
-	Icon string `yaml:"icon"`
-	IsLocal bool `yaml:"isLocal"`
+	Name     string `yaml:"name"`
+	Url      string `yaml:"url"`
+	UrlLocal string `yaml:"urlLocal"`
+	Icon     string `yaml:"icon"`
+	IsLocal  bool   `yaml:"isLocal"`
 }
 
 func LoadContent() ContentData {

+ 9 - 0
src/modules/file.go

@@ -7,6 +7,15 @@ import (
 	"os"
 )
 
+var pwd string
+
+func CurrentPath() string {
+	if len(pwd) <= 0 {
+		pwd, _ = os.Getwd()
+	}
+	return pwd
+}
+
 func Exists(path string) bool {
 	if _, err := os.Stat(path); !os.IsNotExist(err) {
 		return true

+ 6 - 0
src/modules/language.go

@@ -3,11 +3,17 @@ package modules
 import (
 	"fmt"
 	"io/ioutil"
+	"net/http"
 	"path/filepath"
 
 	"gopkg.in/yaml.v2"
 )
 
+func SetupLanguage() {
+	languagefs := http.FileServer(http.Dir(filepath.Join(CurrentPath(), "languages")))
+	http.Handle("/languages/", http.StripPrefix("/languages/", languagefs))
+}
+
 type Language struct {
 	Greeting LanguageGreeting `yaml:"greeting"`
 	Weather  LanguageWeather  `yaml:"weather"`

+ 18 - 0
src/modules/network.go

@@ -0,0 +1,18 @@
+package modules
+
+import (
+	"net"
+	"net/http"
+	"strings"
+)
+
+func ClientIsLocal(r *http.Request) bool {
+	IPAddress := net.ParseIP(r.Header.Get("X-Real-Ip"))
+	if IPAddress == nil {
+		IPAddress = net.ParseIP(r.Header.Get("X-Forwarded-For"))
+	}
+	if IPAddress == nil {
+		IPAddress = net.ParseIP(strings.Split(r.RemoteAddr, ":")[0])
+	}
+	return IPAddress.IsPrivate()
+}

+ 155 - 0
src/modules/template.go

@@ -0,0 +1,155 @@
+package modules
+
+import (
+	"log"
+	"net/http"
+	"path"
+	"path/filepath"
+	"strings"
+	"text/template"
+
+	"github.com/fsnotify/fsnotify"
+)
+
+func SetupTemplate() {
+	loadData()
+	go watchChanges()
+
+	commonfs := http.FileServer(http.Dir(filepath.Join(pwd, "data")))
+	http.Handle("/common/", http.StripPrefix("/common/", commonfs))
+
+	th := themeHandler{}
+	http.Handle("/theme/", th)
+
+	http.HandleFunc("/", serveTemplate)
+}
+
+var websiteData = struct {
+	Config   WebsiteConfig
+	Language Language
+	Contents []GroupData
+	IsLocal  bool
+}{}
+var privateContent []GroupData
+var publicContent []GroupData
+var webTemplate *template.Template
+
+func loadData() {
+	LoadConfig()
+	websiteData.Config = AppConfig.Website
+	websiteData.Language = LoadLanguage(AppConfig.Website.Language)
+	websiteData.Contents = LoadContent().Data
+
+	// Download icon to local and remove local ressources access
+	for groupIndex := 0; groupIndex < len(websiteData.Contents); groupIndex++ {
+		group := websiteData.Contents[groupIndex]
+		groupDataPublic := []ColumnData{}
+		groupDataPrivate := []ColumnData{}
+
+		for colIndex := 0; colIndex < len(group.Columns); colIndex++ {
+			column := group.Columns[colIndex]
+			columnDataPublic := []BookmarkData{}
+			columnDataPrivate := []BookmarkData{}
+
+			for bookmarkIndex := 0; bookmarkIndex < len(column.Bookmarks); bookmarkIndex++ {
+				bookmarkData := column.Bookmarks[bookmarkIndex]
+				iconPath := bookmarkData.Icon
+
+				//download icon
+				if bookmarkData.IsImage() || bookmarkData.IsSVG() {
+					fileName := path.Base(iconPath)
+					if DownloadFile(iconPath, filepath.Join(pwd, "data", "icon", fileName)) {
+						iconPath = "/common/icon/" + fileName
+					}
+				}
+
+				//add to private array
+				if bookmarkData.IsLocal || len(bookmarkData.UrlLocal) > 0 {
+					url := bookmarkData.Url
+					if len(bookmarkData.UrlLocal) > 0 {
+						url = bookmarkData.UrlLocal
+					}
+					columnDataPrivate = append(columnDataPrivate, BookmarkData{bookmarkData.Name, url, bookmarkData.UrlLocal, iconPath, true})
+				}
+
+				//add to public array
+				if !bookmarkData.IsLocal && len(bookmarkData.Url) > 0 {
+					columnDataPublic = append(columnDataPublic, BookmarkData{bookmarkData.Name, bookmarkData.Url, bookmarkData.UrlLocal, iconPath, false})
+				}
+			}
+
+			if len(columnDataPublic) > 0 {
+				groupDataPublic = append(groupDataPublic, ColumnData{column.Title, columnDataPublic, column.Icon})
+			}
+			if len(columnDataPrivate) > 0 {
+				groupDataPrivate = append(groupDataPrivate, ColumnData{column.Title, columnDataPrivate, column.Icon})
+			}
+		}
+
+		if len(groupDataPublic) > 0 {
+			publicContent = append(publicContent, GroupData{group.Title, groupDataPublic, group.Icon})
+		}
+		if len(groupDataPrivate) > 0 {
+			privateContent = append(privateContent, GroupData{group.Title, groupDataPrivate, group.Icon})
+		}
+	}
+
+	loadTemplate()
+}
+
+var themeDir string
+
+type themeHandler struct {
+	format string
+}
+
+func (th themeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	http.ServeFile(w, r, strings.Replace(r.URL.Path, "/theme", themeDir, 1))
+}
+
+func loadTemplate() {
+	themeDir = filepath.Join(pwd, "themes", AppConfig.Website.Theme)
+	tmpl, _ := template.ParseFiles(filepath.Join(themeDir, "index.html"))
+	webTemplate = tmpl
+}
+
+func serveTemplate(w http.ResponseWriter, r *http.Request) {
+	if ClientIsLocal(r) {
+		websiteData.Contents = privateContent
+	} else {
+		websiteData.Contents = publicContent
+	}
+	webTemplate.Execute(w, websiteData)
+}
+
+func watchChanges() {
+	watcher, err := fsnotify.NewWatcher()
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer watcher.Close()
+
+	done := make(chan bool)
+	go func() {
+		for {
+			select {
+			case event, ok := <-watcher.Events:
+				if !ok {
+					return
+				}
+				log.Println("Modified file:", event.Name)
+				loadData()
+			case err, ok := <-watcher.Errors:
+				if !ok {
+					return
+				}
+				log.Println("error:", err)
+			}
+		}
+	}()
+
+	watcher.Add(filepath.Join(CurrentPath(), "data", "data.yaml"))
+	watcher.Add(filepath.Join(CurrentPath(), "data", "config.yaml"))
+	watcher.Add(filepath.Join(CurrentPath(), "themes", AppConfig.Website.Theme, "index.html"))
+	<-done
+}

+ 46 - 0
src/modules/weather.go

@@ -0,0 +1,46 @@
+package modules
+
+import (
+	"io/ioutil"
+	"log"
+	"net/http"
+	"time"
+)
+
+func SetupWeather() {
+	http.HandleFunc("/weather", serveWeather)
+}
+
+func serveWeather(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	data := GetWeather(AppConfig.OpenWeatherMap.ApiKey, AppConfig.OpenWeatherMap.Latitude, AppConfig.OpenWeatherMap.Longitude)
+	if data != nil {
+		w.Write(data)
+	}
+}
+
+var weatherTimeOut int64
+var weatherCache []byte
+var demoData = []byte("{\"coord\":{\"lon\":105.8085,\"lat\":21.0427},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"base\":\"stations\",\"main\":{\"temp\":301.14,\"feels_like\":305.69,\"temp_min\":301.14,\"temp_max\":301.14,\"pressure\":1004,\"humidity\":83},\"visibility\":10000,\"wind\":{\"speed\":6.17,\"deg\":120},\"clouds\":{\"all\":75},\"dt\":1650981392,\"sys\":{\"type\":1,\"id\":9308,\"country\":\"VN\",\"sunrise\":1650925786,\"sunset\":1650971952},\"timezone\":25200,\"id\":1581130,\"name\":\"Hanoi\",\"cod\":200}")
+
+func GetWeather(apiKey string, latitude string, longitude string) []byte {
+	if apiKey == "demo" {
+		return demoData
+	} else {
+		if time.Now().UnixMilli() >= weatherTimeOut {
+			resp, err := http.Get("https://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&limit=1&appid=" + apiKey)
+			if err != nil {
+				log.Fatalln(err)
+				return nil
+			}
+			body, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				log.Fatalln(err)
+				return nil
+			}
+			weatherCache = body
+			weatherTimeOut = time.Now().UnixMilli() + 1800000
+		}
+		return weatherCache
+	}
+}