Skip to content

Commit

Permalink
Merge branch 'main' of github.com:help-14/magma
Browse files Browse the repository at this point in the history
  • Loading branch information
NhanPT committed Mar 4, 2023
2 parents 6859b42 + 692cd64 commit 1d37fdd
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 215 deletions.
203 changes: 22 additions & 181 deletions src/main.go
Original file line number Diff line number Diff line change
@@ -1,220 +1,61 @@
package main

import (
"html/template"
"io/ioutil"
"errors"
"fmt"
"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)
mux := http.NewServeMux()

modules.SetupLanguage(mux)
modules.SetupTemplate(mux)
modules.SetupWeather(mux)
//loadAddons()

server := http.Server{
Addr: fmt.Sprintf(":%d", 7001),
Handler: mux,
}
log.Println("Listening on http://localhost:7001 ...")
err := http.ListenAndServe(":7001", nil)
if err != nil {
log.Fatal(err)
if err := server.ListenAndServe(); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
fmt.Printf("error running http server: %s\n", err)
}
}
// err := http.ListenAndServe(":7001", nil)
// if err != nil {
// log.Fatal(err)
// }
}

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":
healthcheckserver.Setup()
}
}
}

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)
}
}
14 changes: 8 additions & 6 deletions src/modules/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package modules

import (
"fmt"
"io/ioutil"
"path/filepath"

"gopkg.in/yaml.v2"
Expand All @@ -29,7 +28,9 @@ type OpenWeatherMapConfig struct {
Latitude string `yaml:"lat"`
}

func LoadConfig() Config {
var AppConfig Config

func LoadConfig() {
defaultConfig := Config{
Website: WebsiteConfig{
Title: "Magma Dashboard",
Expand All @@ -41,20 +42,21 @@ func LoadConfig() Config {
},
Addons: []string{},
}
AppConfig = defaultConfig

yamlFile, err := ioutil.ReadFile(filepath.Join("data", "config.yaml"))
yamlFile, err := 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
}
12 changes: 6 additions & 6 deletions src/modules/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package modules
import (
"fmt"
"index/suffixarray"
"io/ioutil"
"path/filepath"
"regexp"
"strings"
Expand All @@ -28,16 +27,17 @@ 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 {
emptyData := ContentData{}

yamlFile, err := ioutil.ReadFile(filepath.Join("data", "data.yaml"))
yamlFile, err := ReadFile(filepath.Join("data", "data.yaml"))
if err != nil {
fmt.Printf("Error reading YAML file: %s\n", err)
return emptyData
Expand Down
21 changes: 19 additions & 2 deletions src/modules/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,36 @@ 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
}
return false
}

func ReadFile(path string) ([]byte, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
return io.ReadAll(file)
}

func CopyFile(source string, dest string) (err error) {
sourcefile, err := os.Open(source)
if err != nil {
return err
}

defer sourcefile.Close()

destfile, err := os.Create(dest)
Expand All @@ -33,7 +50,7 @@ func CopyFile(source string, dest string) (err error) {
if err == nil {
sourceinfo, err := os.Stat(source)
if err != nil {
err = os.Chmod(dest, sourceinfo.Mode())
_ = os.Chmod(dest, sourceinfo.Mode())
}

}
Expand Down
9 changes: 7 additions & 2 deletions src/modules/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ package modules

import (
"fmt"
"io/ioutil"
"net/http"
"path/filepath"

"gopkg.in/yaml.v2"
)

func SetupLanguage(mux *http.ServeMux) {
languagefs := http.FileServer(http.Dir(filepath.Join(CurrentPath(), "languages")))
mux.Handle("/languages/", http.StripPrefix("/languages/", languagefs))
}

type Language struct {
Greeting LanguageGreeting `yaml:"greeting"`
Weather LanguageWeather `yaml:"weather"`
Expand Down Expand Up @@ -36,7 +41,7 @@ type LanguageWeather struct {
}

func LoadLanguage(language string) Language {
yamlFile, err := ioutil.ReadFile(filepath.Join("languages", language+".yaml"))
yamlFile, err := ReadFile(filepath.Join("languages", language+".yaml"))
if err != nil {
fmt.Printf("Error reading YAML file: %s\n", err)
return LoadLanguage("en")
Expand Down
Loading

0 comments on commit 1d37fdd

Please sign in to comment.