2015-10-29 16:16:25 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"text/template"
|
2015-11-06 01:36:09 +00:00
|
|
|
"time"
|
2015-10-29 16:16:25 +00:00
|
|
|
|
|
|
|
"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
|
|
|
|
|
2015-11-02 19:48:29 +00:00
|
|
|
Stylesheets []string
|
|
|
|
Scripts []string
|
|
|
|
InlineScript string
|
2015-10-29 16:16:25 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2015-11-02 19:48:29 +00:00
|
|
|
type webModule interface {
|
|
|
|
GetName() string
|
|
|
|
GetRoutes() map[string]func(http.ResponseWriter, *http.Request)
|
|
|
|
Register()
|
|
|
|
GetMenuEntries() []menuItem
|
|
|
|
GetBottomMenuEntries() []menuItem
|
|
|
|
}
|
|
|
|
|
|
|
|
var webModules []webModule
|
|
|
|
|
2015-10-29 16:16:25 +00:00
|
|
|
// 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))
|
2015-11-02 19:48:29 +00:00
|
|
|
|
|
|
|
registerWebModule(new(generalWebModule))
|
2015-11-05 12:55:49 +00:00
|
|
|
registerWebModule(new(levelUpWebModule))
|
2015-11-06 01:36:09 +00:00
|
|
|
registerWebModule(new(levelUpAchieveWebModule))
|
2015-11-02 19:48:29 +00:00
|
|
|
|
2015-10-29 16:16:25 +00:00
|
|
|
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) {
|
2015-11-06 01:36:09 +00:00
|
|
|
writeToLog(" " + time.Now().Format(time.RFC3339) + " >> Web Request Received\n")
|
2015-10-29 16:16:25 +00:00
|
|
|
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)
|
2015-11-02 19:48:29 +00:00
|
|
|
site.Scripts = append(site.Scripts, "/assets/js/highcharts.js")
|
2015-11-05 12:55:49 +00:00
|
|
|
site.Scripts = append(site.Scripts, "/assets/js/B.js")
|
2015-11-09 23:58:12 +00:00
|
|
|
site.Scripts = append(site.Scripts, "/assets/js/B_purecss.js")
|
2015-11-09 21:20:41 +00:00
|
|
|
site.Scripts = append(site.Scripts, "/assets/js/B_cookies.js")
|
2015-11-05 12:55:49 +00:00
|
|
|
|
|
|
|
site.InlineScript = ""
|
2015-10-29 16:16:25 +00:00
|
|
|
|
|
|
|
site.Menu = make([]menuItem, 0, 0)
|
|
|
|
site.BottomMenu = make([]menuItem, 0, 0)
|
|
|
|
site.BottomMenu = append(site.BottomMenu, menuItem{Text: "Admin", Link: "/admin/"})
|
2015-11-02 19:48:29 +00:00
|
|
|
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)
|
|
|
|
}
|
2015-10-30 13:10:05 +00:00
|
|
|
}
|
2015-11-02 19:48:29 +00:00
|
|
|
}
|
2015-10-29 16:16:25 +00:00
|
|
|
|
2015-11-02 19:48:29 +00:00
|
|
|
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))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-30 14:33:18 +00:00
|
|
|
}
|
2015-11-02 19:48:29 +00:00
|
|
|
b.Register()
|
|
|
|
webModules = append(webModules, b)
|
2015-10-29 16:16:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2015-11-02 19:48:29 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2015-11-06 01:36:09 +00:00
|
|
|
func pageNotFound(err error, w http.ResponseWriter) {
|
|
|
|
if err == nil {
|
|
|
|
err = fmt.Errorf("Page Not Found")
|
|
|
|
}
|
|
|
|
http.Error(w, err.Error(), 404)
|
|
|
|
}
|
|
|
|
|
2015-10-29 16:16:25 +00:00
|
|
|
func assertError(err error, w http.ResponseWriter) bool {
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), 500)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|