package main import ( "fmt" "log" "net/http" "os" "text/template" "github.com/gorilla/context" "github.com/gorilla/mux" "github.com/gorilla/sessions" ) // SiteData is the basic data needed for the site/pages type SiteData struct { Title string SubTitle string Port int SessionName string Stylesheets []string Scripts []string Flash flashMessage // Quick message at top of page Menu []menuItem // Top-aligned menu items BottomMenu []menuItem // Bottom-aligned menu items // Any other template data TemplateData interface{} } type flashMessage struct { Message string Status string } type menuItem struct { Text string Link string Active bool } var site SiteData var sessionStore = sessions.NewCookieStore([]byte("gostatbot secret cookie nobody will guess")) var r *mux.Router // This is the main function for the web server func statWebMain(slack *Slack) { site.Title = "stat_bot" site.SubTitle = "" site.Port = 3000 site.SessionName = "statbot" r = mux.NewRouter() r.StrictSlash(true) assetHandler := http.FileServer(http.Dir("./assets/")) http.Handle("/assets/", http.StripPrefix("/assets/", assetHandler)) r.HandleFunc("/", handleStats) http.Handle("/", r) go func() { log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", site.Port), context.ClearHandler(http.DefaultServeMux))) }() } func initRequest(w http.ResponseWriter, req *http.Request) { site.SubTitle = "" site.Stylesheets = make([]string, 0, 0) site.Stylesheets = append(site.Stylesheets, "/assets/css/pure-min.css") site.Stylesheets = append(site.Stylesheets, "/assets/css/statbot.css") site.Stylesheets = append(site.Stylesheets, "https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css") site.Scripts = make([]string, 0, 0) site.Menu = make([]menuItem, 0, 0) site.Menu = append(site.Menu, menuItem{Text: "Stats", Link: "/stats/"}) site.BottomMenu = make([]menuItem, 0, 0) site.BottomMenu = append(site.BottomMenu, menuItem{Text: "Admin", Link: "/admin/"}) } func handleStats(w http.ResponseWriter, req *http.Request) { initRequest(w, req) type StatData struct { Stats map[string]int } // Get the global stats stats := getAllUsersStats() s := StatData{Stats: stats} setMenuItemActive("Stats") showPage("stats.html", site, w) } // showPage // Load a template and all of the surrounding templates func showPage(tmplName string, tmplData interface{}, w http.ResponseWriter) error { for _, tmpl := range []string{ "htmlheader.html", "menu.html", "header.html", tmplName, "footer.html", "htmlfooter.html", } { if err := outputTemplate(tmpl, tmplData, w); err != nil { writeToLog(fmt.Sprintf("%s\n", err)) return err } } return nil } // outputTemplate // Spit out a template func outputTemplate(tmplName string, tmplData interface{}, w http.ResponseWriter) error { _, err := os.Stat("templates/" + tmplName) if err == nil { t := template.New(tmplName) t, _ = t.ParseFiles("templates/" + tmplName) return t.Execute(w, tmplData) } return fmt.Errorf("WebServer: Cannot load template (templates/%s): File not found", tmplName) } // setMenuItemActive // Sets a menu item to active, all others to inactive func setMenuItemActive(which string) { for i := range site.Menu { if site.Menu[i].Text == which { site.Menu[i].Active = true } else { site.Menu[i].Active = false } } } func getSessionStringValue(key string, w http.ResponseWriter, req *http.Request) (string, error) { session, err := sessionStore.Get(req, site.SessionName) if err != nil { return "", err } val := session.Values[key] var retVal string var ok bool if retVal, ok = val.(string); !ok { return "", fmt.Errorf("Unable to create string from %s", key) } return retVal, nil } func assertError(err error, w http.ResponseWriter) bool { if err != nil { http.Error(w, err.Error(), 500) return true } return false }