statbot/statbotweb.go

212 lines
5.3 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"os"
"text/template"
"time"
"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
InlineScript 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
type webModule interface {
GetName() string
GetRoutes() map[string]func(http.ResponseWriter, *http.Request)
Register()
GetMenuEntries() []menuItem
GetBottomMenuEntries() []menuItem
}
var webModules []webModule
// 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))
registerWebModule(new(generalWebModule))
registerWebModule(new(levelUpWebModule))
registerWebModule(new(levelUpAchieveWebModule))
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) {
writeToLog(" " + time.Now().Format(time.RFC3339) + " >> Web Request Received\n")
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.Scripts = append(site.Scripts, "/assets/js/highcharts.js")
site.Scripts = append(site.Scripts, "/assets/js/B.js")
site.Scripts = append(site.Scripts, "/assets/js/B_purecss.js")
site.Scripts = append(site.Scripts, "/assets/js/B_cookies.js")
site.InlineScript = ""
site.Menu = make([]menuItem, 0, 0)
site.BottomMenu = make([]menuItem, 0, 0)
site.BottomMenu = append(site.BottomMenu, menuItem{Text: "Admin", Link: "/admin/"})
for _, mod := range webModules {
for _, m := range mod.GetMenuEntries() {
site.Menu = append(site.Menu, m)
}
for _, m := range mod.GetBottomMenuEntries() {
site.BottomMenu = append(site.BottomMenu, m)
}
}
}
func registerWebModule(b webModule) {
// Register a web module
// Make sure that we haven't already registered it (or another that has the same route)
for _, mod := range webModules {
if mod.GetName() == b.GetName() {
panic(fmt.Errorf("Attempted to Re-register Web Module %s", b.GetName()))
} else {
for k := range mod.GetRoutes() {
for nk := range b.GetRoutes() {
if k == nk {
panic(fmt.Errorf("Attempted to Re-register Web Route %s", k))
}
}
}
}
}
b.Register()
webModules = append(webModules, b)
}
// 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 setFlashMessage(msg string, stat string) {
site.Flash = flashMessage{Message: msg, Status: stat}
}
func addToInlineScript(s string) {
site.InlineScript = fmt.Sprintf("%s%s", site.InlineScript, s)
}
func pageNotFound(err error, w http.ResponseWriter) {
if err == nil {
err = fmt.Errorf("Page Not Found")
}
http.Error(w, err.Error(), 404)
}
func assertError(err error, w http.ResponseWriter) bool {
if err != nil {
http.Error(w, err.Error(), 500)
return true
}
return false
}