package main import ( "code.mrmelon54.xyz/sean/melon-tools/module/discord" "code.mrmelon54.xyz/sean/melon-tools/module/gitea" "code.mrmelon54.xyz/sean/melon-tools/utils" _ "embed" "encoding/gob" "fmt" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/gorilla/sessions" "github.com/joho/godotenv" "html/template" "log" "net/http" "os" "sync" ) var ( modules = []utils.IModule{ gitea.New(), discord.New(), } sessionStore = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY"))) //go:embed pages/index.go.html indexTemplate string ) func main() { err := godotenv.Load() if err != nil { fmt.Println(err) os.Exit(1) } stateManager := StateManager{&sync.RWMutex{}, make(map[uuid.UUID]*utils.State)} router := mux.NewRouter() router.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Content-Type", "text/html") rw.WriteHeader(http.StatusOK) modTmp := make([]template.HTML, 0) for _, v := range modules { modTmp = append(modTmp, template.HTML(fmt.Sprintf("%s", v.GetEndpoint(), v.GetName()))) } tmp, err := template.New("homepage").Parse(indexTemplate) if err != nil { fmt.Println("Template parse error:", err) return } err = tmp.Execute(rw, struct { Modules []template.HTML }{ Modules: modTmp, }) if err != nil { fmt.Println("Template execute error:", err) return } }) gob.Register(uuid.UUID{}) for _, v := range modules { a := v.GetEndpoint() router.HandleFunc(a, func(rw http.ResponseWriter, req *http.Request) { http.Redirect(rw, req, a+"/", http.StatusTemporaryRedirect) }) v.SetupModule(router.PathPrefix(v.GetEndpoint()).Subrouter(), stateManager.sessionWrapper) } s := &http.Server{ Addr: os.Getenv("LISTEN"), Handler: router, } err = s.ListenAndServe() if err != nil { if err == http.ErrServerClosed { log.Println("Server closed successfully") } else { log.Fatalln(err) } return } } type StateManager struct { MSync *sync.RWMutex States map[uuid.UUID]*utils.State } func (m *StateManager) sessionWrapper(cb func(http.ResponseWriter, *http.Request, *utils.State)) func(rw http.ResponseWriter, req *http.Request) { return func(rw http.ResponseWriter, req *http.Request) { session, _ := sessionStore.Get(req, "melon-tools-session") if a, ok := session.Values["session-key"]; ok { if b, ok := a.(uuid.UUID); ok { m.MSync.RLock() c, ok := m.States[b] m.MSync.RUnlock() if ok { cb(rw, req, c) return } } } u := utils.NewState() m.MSync.Lock() m.States[u.Uuid] = u m.MSync.Unlock() session.Values["session-key"] = u.Uuid _ = session.Save(req, rw) cb(rw, req, u) } }