Got some stats displaying
This commit is contained in:
parent
1f5eae33b9
commit
083f9f3901
@ -186,6 +186,31 @@ ul.menu-list-dropped {
|
|||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
padding: 0.3em 1em;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other Styles :D */
|
||||||
|
.success {
|
||||||
|
background: rgb(28, 184, 65); /* this is a green */
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background: rgb(202, 60, 60); /* this is a maroon */
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
background: rgb(223, 117, 20); /* this is an orange */
|
||||||
|
}
|
||||||
|
.secondary {
|
||||||
|
background: rgb(66, 184, 221); /* this is a light blue*/
|
||||||
|
}
|
||||||
|
.primary {
|
||||||
|
background: #1f8dd6;
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Responsive Styles (Media Queries) ------------------------------------- */
|
/* -- Responsive Styles (Media Queries) ------------------------------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
29014
assets/js/highcharts.js
Normal file
29014
assets/js/highcharts.js
Normal file
File diff suppressed because it is too large
Load Diff
113
assets/js/main_stats.js
Normal file
113
assets/js/main_stats.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
document.addEventListener("DOMContentLoaded", function(event) {
|
||||||
|
var main_channel_names = ['general','random'],
|
||||||
|
main_member_numbers = [],
|
||||||
|
main_message_numbers = [],
|
||||||
|
other_channel_names = [],
|
||||||
|
other_member_numbers = [],
|
||||||
|
other_message_numbers = [];
|
||||||
|
for(var i = 0; i < stats.channels.length; i++){
|
||||||
|
if(stats.channels[i].name == "general") {
|
||||||
|
main_member_numbers[0] = stats.channels[i].member_count;
|
||||||
|
main_message_numbers[0] = stats.channels[i].message_count;
|
||||||
|
} else if(stats.channels[i].name == "random") {
|
||||||
|
main_member_numbers[1] = stats.channels[i].member_count;
|
||||||
|
main_message_numbers[1] = stats.channels[i].message_count;
|
||||||
|
} else {
|
||||||
|
other_channel_names.push(stats.channels[i].name);
|
||||||
|
other_member_numbers.push(stats.channels[i].member_count);
|
||||||
|
other_message_numbers.push(stats.channels[i].message_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mainChart = new Highcharts.Chart({
|
||||||
|
chart: {
|
||||||
|
renderTo: 'mainStatsBarChart',
|
||||||
|
type: 'column'
|
||||||
|
},
|
||||||
|
|
||||||
|
title: {
|
||||||
|
text: 'Main Channels'
|
||||||
|
},
|
||||||
|
|
||||||
|
yAxis: [{
|
||||||
|
min: 0,
|
||||||
|
title: { text: 'Messages' }
|
||||||
|
},{
|
||||||
|
min: 0,
|
||||||
|
title: { text: 'Members' },
|
||||||
|
opposite: true
|
||||||
|
}],
|
||||||
|
|
||||||
|
plotOptions: {
|
||||||
|
column: {
|
||||||
|
grouping: false,
|
||||||
|
shadow: false,
|
||||||
|
borderWidth: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
xAxis: {
|
||||||
|
categories: main_channel_names
|
||||||
|
},
|
||||||
|
|
||||||
|
series: [{
|
||||||
|
name: 'Messages',
|
||||||
|
color: 'rgba(126,86,134,0.9)',
|
||||||
|
data: main_message_numbers,
|
||||||
|
pointPadding: 0.3
|
||||||
|
},{
|
||||||
|
name: 'Members',
|
||||||
|
color: 'rgba(165,170,217,1)',
|
||||||
|
data: main_member_numbers,
|
||||||
|
pointPadding: 0.4,
|
||||||
|
yAxis: 1
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
var otherChart = new Highcharts.Chart({
|
||||||
|
chart: {
|
||||||
|
renderTo: 'statsBarChart',
|
||||||
|
type: 'column'
|
||||||
|
},
|
||||||
|
|
||||||
|
title: {
|
||||||
|
text: 'Other Channels'
|
||||||
|
},
|
||||||
|
|
||||||
|
yAxis: [{
|
||||||
|
min: 0,
|
||||||
|
title: { text: 'Members' }
|
||||||
|
},{
|
||||||
|
min: 0,
|
||||||
|
title: { text: 'Messages' },
|
||||||
|
opposite: true
|
||||||
|
}],
|
||||||
|
|
||||||
|
tooltip: { shared: true },
|
||||||
|
|
||||||
|
plotOptions: {
|
||||||
|
column: {
|
||||||
|
grouping: false,
|
||||||
|
shadow: false,
|
||||||
|
borderWidth: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
xAxis: {
|
||||||
|
categories: other_channel_names
|
||||||
|
},
|
||||||
|
|
||||||
|
series: [{
|
||||||
|
name: 'Messages',
|
||||||
|
color: 'rgba(126,86,134,0.9)',
|
||||||
|
data: other_message_numbers,
|
||||||
|
pointPadding: 0.3
|
||||||
|
},{
|
||||||
|
name: 'Members',
|
||||||
|
color: 'rgba(165,170,217,1)',
|
||||||
|
data: other_member_numbers,
|
||||||
|
pointPadding: 0.4,
|
||||||
|
yAxis: 1
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ func (p *generalStatProcessor) GetStatKeys() []string {
|
|||||||
func (p *generalStatProcessor) ProcessMessage(m *Message) {
|
func (p *generalStatProcessor) ProcessMessage(m *Message) {
|
||||||
incrementUserStat(m.User, "message-hour-"+m.Time.Format("15"))
|
incrementUserStat(m.User, "message-hour-"+m.Time.Format("15"))
|
||||||
incrementUserStat(m.User, "message-dow-"+m.Time.Format("Mon"))
|
incrementUserStat(m.User, "message-dow-"+m.Time.Format("Mon"))
|
||||||
incrementUserStat(m.User, "message-dom-"+m.Time.Format("_2"))
|
incrementUserStat(m.User, "message-dom-"+m.Time.Format("02"))
|
||||||
}
|
}
|
||||||
func (p *generalStatProcessor) ProcessBotMessage(m *Message) {}
|
func (p *generalStatProcessor) ProcessBotMessage(m *Message) {}
|
||||||
|
|
||||||
@ -111,6 +112,99 @@ func (p *generalStatProcessor) ProcessChannelMessage(m *Message) {
|
|||||||
|
|
||||||
incrementChannelStat(m.Channel, "message-hour-"+m.Time.Format("15"))
|
incrementChannelStat(m.Channel, "message-hour-"+m.Time.Format("15"))
|
||||||
incrementChannelStat(m.Channel, "message-dow-"+m.Time.Format("Mon"))
|
incrementChannelStat(m.Channel, "message-dow-"+m.Time.Format("Mon"))
|
||||||
incrementChannelStat(m.Channel, "message-dom-"+m.Time.Format("_2"))
|
incrementChannelStat(m.Channel, "message-dom-"+m.Time.Format("02"))
|
||||||
}
|
}
|
||||||
func (p *generalStatProcessor) ProcessBotChannelMessage(m *Message) {}
|
func (p *generalStatProcessor) ProcessBotChannelMessage(m *Message) {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Web Site Module
|
||||||
|
*/
|
||||||
|
type generalWebModule struct{}
|
||||||
|
|
||||||
|
func (wm *generalWebModule) GetName() string {
|
||||||
|
return "General Web Module"
|
||||||
|
}
|
||||||
|
func (wm *generalWebModule) GetRoutes() map[string]func(http.ResponseWriter, *http.Request) {
|
||||||
|
ret := make(map[string]func(http.ResponseWriter, *http.Request))
|
||||||
|
ret["/"] = wm.handleStats
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func (wm *generalWebModule) Register() {
|
||||||
|
for k, v := range wm.GetRoutes() {
|
||||||
|
r.HandleFunc(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *generalWebModule) GetMenuEntries() []menuItem {
|
||||||
|
var ret []menuItem
|
||||||
|
ret = append(ret, menuItem{Text: "Stats", Link: "/"})
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *generalWebModule) GetBottomMenuEntries() []menuItem {
|
||||||
|
var ret []menuItem
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *generalWebModule) handleStats(w http.ResponseWriter, req *http.Request) {
|
||||||
|
initRequest(w, req)
|
||||||
|
|
||||||
|
type ChannelStat struct {
|
||||||
|
Name string
|
||||||
|
MemberCount int
|
||||||
|
MessageCount int
|
||||||
|
}
|
||||||
|
type StatData struct {
|
||||||
|
TotalChannelMessages int
|
||||||
|
TotalChannels int
|
||||||
|
ChannelStats []ChannelStat
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the global stats
|
||||||
|
var s StatData
|
||||||
|
var err error
|
||||||
|
|
||||||
|
openDatabase()
|
||||||
|
chanlst := getChannelList()
|
||||||
|
var chanstats []ChannelStat
|
||||||
|
for _, k := range chanlst {
|
||||||
|
chanstats = append(chanstats, ChannelStat{
|
||||||
|
Name: getChannelName(k),
|
||||||
|
MemberCount: getChannelMemberCount(k),
|
||||||
|
MessageCount: getChannelMessageCount(k),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
s.ChannelStats = chanstats
|
||||||
|
s.TotalChannelMessages = getTotalChannelMsgCount()
|
||||||
|
s.TotalChannels = len(chanlst)
|
||||||
|
closeDatabase()
|
||||||
|
|
||||||
|
sc := "var stats = {totalchannelmessages:"
|
||||||
|
sc = fmt.Sprintf("%s%d,", sc, s.TotalChannelMessages)
|
||||||
|
sc = sc + "\"channels\":["
|
||||||
|
for _, k := range s.ChannelStats {
|
||||||
|
sc = fmt.Sprintf("%s{name:\"%s\",member_count:%d,message_count:%d},",
|
||||||
|
sc,
|
||||||
|
k.Name,
|
||||||
|
k.MemberCount,
|
||||||
|
k.MessageCount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Trim the last ,
|
||||||
|
sc = sc[:len(sc)-1]
|
||||||
|
sc = sc + "]"
|
||||||
|
sc = sc + "};"
|
||||||
|
|
||||||
|
addToInlineScript(sc)
|
||||||
|
|
||||||
|
site.Scripts = append(site.Scripts, "/assets/js/main_stats.js")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
setFlashMessage("Error Counting Channel Messages", "error")
|
||||||
|
}
|
||||||
|
site.TemplateData = s
|
||||||
|
|
||||||
|
setMenuItemActive("Stats")
|
||||||
|
showPage("stats.html", site, w)
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
type levelUpStatProcessor struct{}
|
type levelUpStatProcessor struct{}
|
||||||
|
|
||||||
func (p *levelUpStatProcessor) GetName() string {
|
func (p *levelUpStatProcessor) GetName() string {
|
||||||
@ -39,3 +41,36 @@ func (p *levelUpStatProcessor) ProcessChannelMessage(m *Message) {
|
|||||||
}
|
}
|
||||||
func (p *levelUpStatProcessor) ProcessAdminChannelMessage(m *Message) {}
|
func (p *levelUpStatProcessor) ProcessAdminChannelMessage(m *Message) {}
|
||||||
func (p *levelUpStatProcessor) ProcessBotChannelMessage(m *Message) {}
|
func (p *levelUpStatProcessor) ProcessBotChannelMessage(m *Message) {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Web Site Module
|
||||||
|
*/
|
||||||
|
type levelUpWebModule struct{}
|
||||||
|
|
||||||
|
func (wm *levelUpWebModule) GetName() string {
|
||||||
|
return "LevelUp Web Module"
|
||||||
|
}
|
||||||
|
func (wm *levelUpWebModule) GetRoutes() map[string]func(http.ResponseWriter, *http.Request) {
|
||||||
|
ret := make(map[string]func(http.ResponseWriter, *http.Request))
|
||||||
|
//ret["/levelup/"] = wm.
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func (wm *levelUpWebModule) Register() {
|
||||||
|
for k, v := range wm.GetRoutes() {
|
||||||
|
r.HandleFunc(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (wm *levelUpWebModule) GetMenuEntries() []menuItem {
|
||||||
|
var ret []menuItem
|
||||||
|
ret = append(ret, menuItem{Text: "LevelUp!", Link: "/levelup/"})
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func (wm *levelUpWebModule) GetBottomMenuEntries() []menuItem {
|
||||||
|
var ret []menuItem
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *levelUpWebModule) handleLevelUpGeneral(w http.ResponseWriter, req *http.Request) {
|
||||||
|
initRequest(w, req)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -55,7 +55,6 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, we're not running the web server
|
|
||||||
statWebMain(slack)
|
statWebMain(slack)
|
||||||
statBotMain(slack)
|
statBotMain(slack)
|
||||||
}
|
}
|
||||||
|
105
statbot_model.go
105
statbot_model.go
@ -398,6 +398,7 @@ func addChannelStat(channel string, key string, addVal int) error {
|
|||||||
openDatabase()
|
openDatabase()
|
||||||
v, err := getChannelStat(channel, key)
|
v, err := getChannelStat(channel, key)
|
||||||
err = saveChannelStat(channel, key, v+addVal)
|
err = saveChannelStat(channel, key, v+addVal)
|
||||||
|
v, err = getChannelStat(channel, key)
|
||||||
closeDatabase()
|
closeDatabase()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -410,6 +411,55 @@ func decrementChannelStat(channel string, key string) error {
|
|||||||
return addChannelStat(channel, key, -1)
|
return addChannelStat(channel, key, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getChannelName(chnl string) string {
|
||||||
|
var ret string
|
||||||
|
openDatabase()
|
||||||
|
db.View(func(tx *bolt.Tx) error {
|
||||||
|
var b, chB, chIB *bolt.Bucket
|
||||||
|
var err error
|
||||||
|
|
||||||
|
b = tx.Bucket([]byte("channels"))
|
||||||
|
if b == nil {
|
||||||
|
return fmt.Errorf("Error opening 'channels' bucket")
|
||||||
|
}
|
||||||
|
if chB = b.Bucket([]byte(chnl)); chB == nil {
|
||||||
|
return fmt.Errorf("Error opening channel bucket (%s)", chnl)
|
||||||
|
}
|
||||||
|
if chIB = chB.Bucket([]byte("info")); chIB == nil {
|
||||||
|
return fmt.Errorf("Error opening channel info bucket (%s/info)", chnl)
|
||||||
|
}
|
||||||
|
ret, err = bktGetString(chIB, "name")
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
closeDatabase()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func getChannelMemberCount(chnl string) int {
|
||||||
|
var ret int
|
||||||
|
openDatabase()
|
||||||
|
db.View(func(tx *bolt.Tx) error {
|
||||||
|
var b, chB, chIB *bolt.Bucket
|
||||||
|
|
||||||
|
b = tx.Bucket([]byte("channels"))
|
||||||
|
if b == nil {
|
||||||
|
return fmt.Errorf("Error opening 'channels' bucket")
|
||||||
|
}
|
||||||
|
if chB = b.Bucket([]byte(chnl)); chB == nil {
|
||||||
|
return fmt.Errorf("Error opening channel bucket (%s)", chnl)
|
||||||
|
}
|
||||||
|
if chIB = chB.Bucket([]byte("info")); chIB == nil {
|
||||||
|
return fmt.Errorf("Error opening channel info bucket (%s/info)", chnl)
|
||||||
|
}
|
||||||
|
// Get all of the members into a []string
|
||||||
|
chMembersB := chIB.Bucket([]byte("members"))
|
||||||
|
ret = chMembersB.Stats().KeyN
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
closeDatabase()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func getChannelStat(channel string, key string) (int, error) {
|
func getChannelStat(channel string, key string) (int, error) {
|
||||||
openDatabase()
|
openDatabase()
|
||||||
var ret int
|
var ret int
|
||||||
@ -421,8 +471,8 @@ func getChannelStat(channel string, key string) (int, error) {
|
|||||||
if b == nil {
|
if b == nil {
|
||||||
return fmt.Errorf("Unable to open 'channels' bucket")
|
return fmt.Errorf("Unable to open 'channels' bucket")
|
||||||
}
|
}
|
||||||
if chB, err = b.CreateBucketIfNotExists([]byte(channel)); err == nil {
|
if chB = b.Bucket([]byte(channel)); chB != nil {
|
||||||
if chSB, err = chB.CreateBucketIfNotExists([]byte("stats")); err == nil {
|
if chSB = chB.Bucket([]byte("stats")); chSB != nil {
|
||||||
ret, err = bktGetInt(chSB, key)
|
ret, err = bktGetInt(chSB, key)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -671,8 +721,8 @@ func getUserStat(user string, key string) (int, error) {
|
|||||||
if b == nil {
|
if b == nil {
|
||||||
return fmt.Errorf("Unable to open 'users' bucket")
|
return fmt.Errorf("Unable to open 'users' bucket")
|
||||||
}
|
}
|
||||||
if uB, err = b.CreateBucketIfNotExists([]byte(user)); err == nil {
|
if uB = b.Bucket([]byte(user)); uB != nil {
|
||||||
if uSB, err = uB.CreateBucketIfNotExists([]byte("stats")); err == nil {
|
if uSB = uB.Bucket([]byte("stats")); uSB != nil {
|
||||||
ret, err = bktGetInt(uSB, key)
|
ret, err = bktGetInt(uSB, key)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -705,6 +755,7 @@ func addUserStat(user string, key string, addVal int) error {
|
|||||||
openDatabase()
|
openDatabase()
|
||||||
v, err := getUserStat(user, key)
|
v, err := getUserStat(user, key)
|
||||||
err = saveUserStat(user, key, v+addVal)
|
err = saveUserStat(user, key, v+addVal)
|
||||||
|
v, err = getUserStat(user, key)
|
||||||
closeDatabase()
|
closeDatabase()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -777,6 +828,52 @@ func getAllUsersStats() (map[string]int, error) {
|
|||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getChannelMessageCount(channel string) int {
|
||||||
|
var ret int
|
||||||
|
openDatabase()
|
||||||
|
db.View(func(tx *bolt.Tx) error {
|
||||||
|
var b, chB, chMB *bolt.Bucket
|
||||||
|
var err error
|
||||||
|
|
||||||
|
b = tx.Bucket([]byte("channels"))
|
||||||
|
if chB = b.Bucket([]byte(channel)); chB != nil {
|
||||||
|
if chMB = chB.Bucket([]byte("messages")); chMB != nil {
|
||||||
|
ret = chMB.Stats().BucketN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
closeDatabase()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func getChannelList() []string {
|
||||||
|
openDatabase()
|
||||||
|
// First build channel list
|
||||||
|
var chans []string
|
||||||
|
db.Update(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte("channels"))
|
||||||
|
return b.ForEach(func(k, v []byte) error {
|
||||||
|
chans = append(chans, string(k))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
closeDatabase()
|
||||||
|
return chans
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTotalChannelMsgCount() int {
|
||||||
|
var ret int
|
||||||
|
openDatabase()
|
||||||
|
// First build channel list
|
||||||
|
chans := getChannelList()
|
||||||
|
for _, k := range chans {
|
||||||
|
ret = ret + getChannelMessageCount(k)
|
||||||
|
}
|
||||||
|
closeDatabase()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func bktGetBucket(b *bolt.Bucket, key string) (*bolt.Bucket, error) {
|
func bktGetBucket(b *bolt.Bucket, key string) (*bolt.Bucket, error) {
|
||||||
bkt := b.Bucket([]byte(key))
|
bkt := b.Bucket([]byte(key))
|
||||||
if bkt != nil {
|
if bkt != nil {
|
||||||
|
@ -21,6 +21,7 @@ type SiteData struct {
|
|||||||
|
|
||||||
Stylesheets []string
|
Stylesheets []string
|
||||||
Scripts []string
|
Scripts []string
|
||||||
|
InlineScript string
|
||||||
|
|
||||||
Flash flashMessage // Quick message at top of page
|
Flash flashMessage // Quick message at top of page
|
||||||
Menu []menuItem // Top-aligned menu items
|
Menu []menuItem // Top-aligned menu items
|
||||||
@ -46,6 +47,16 @@ var site SiteData
|
|||||||
var sessionStore = sessions.NewCookieStore([]byte("gostatbot secret cookie nobody will guess"))
|
var sessionStore = sessions.NewCookieStore([]byte("gostatbot secret cookie nobody will guess"))
|
||||||
var r *mux.Router
|
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
|
// This is the main function for the web server
|
||||||
func statWebMain(slack *Slack) {
|
func statWebMain(slack *Slack) {
|
||||||
site.Title = "stat_bot"
|
site.Title = "stat_bot"
|
||||||
@ -58,7 +69,9 @@ func statWebMain(slack *Slack) {
|
|||||||
|
|
||||||
assetHandler := http.FileServer(http.Dir("./assets/"))
|
assetHandler := http.FileServer(http.Dir("./assets/"))
|
||||||
http.Handle("/assets/", http.StripPrefix("/assets/", assetHandler))
|
http.Handle("/assets/", http.StripPrefix("/assets/", assetHandler))
|
||||||
r.HandleFunc("/", handleStats)
|
|
||||||
|
registerWebModule(new(generalWebModule))
|
||||||
|
|
||||||
http.Handle("/", r)
|
http.Handle("/", r)
|
||||||
go func() {
|
go func() {
|
||||||
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", site.Port), context.ClearHandler(http.DefaultServeMux)))
|
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", site.Port), context.ClearHandler(http.DefaultServeMux)))
|
||||||
@ -73,33 +86,39 @@ func initRequest(w http.ResponseWriter, req *http.Request) {
|
|||||||
site.Stylesheets = append(site.Stylesheets, "https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.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 = make([]string, 0, 0)
|
||||||
|
site.Scripts = append(site.Scripts, "/assets/js/highcharts.js")
|
||||||
|
|
||||||
site.Menu = make([]menuItem, 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 = make([]menuItem, 0, 0)
|
||||||
site.BottomMenu = append(site.BottomMenu, menuItem{Text: "Admin", Link: "/admin/"})
|
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 handleStats(w http.ResponseWriter, req *http.Request) {
|
func registerWebModule(b webModule) {
|
||||||
initRequest(w, req)
|
// Register a web module
|
||||||
|
// Make sure that we haven't already registered it (or another that has the same route)
|
||||||
type StatData struct {
|
for _, mod := range webModules {
|
||||||
TotalChannelMessages int
|
if mod.GetName() == b.GetName() {
|
||||||
Error string
|
panic(fmt.Errorf("Attempted to Re-register Web Module %s", b.GetName()))
|
||||||
}
|
|
||||||
|
|
||||||
// Get the global stats
|
|
||||||
var s StatData
|
|
||||||
if stats, err := getAllUsersStats(); err == nil {
|
|
||||||
s = StatData{TotalChannelMessages: stats["channel-message"], Error: ""}
|
|
||||||
} else {
|
} else {
|
||||||
s = StatData{TotalChannelMessages: -1, Error: fmt.Sprintf("%s", err)}
|
for k := range mod.GetRoutes() {
|
||||||
|
for nk := range b.GetRoutes() {
|
||||||
|
if k == nk {
|
||||||
|
panic(fmt.Errorf("Attempted to Re-register Web Route %s", k))
|
||||||
}
|
}
|
||||||
site.TemplateData = s
|
}
|
||||||
|
}
|
||||||
setMenuItemActive("Stats")
|
}
|
||||||
showPage("stats.html", site, w)
|
}
|
||||||
|
b.Register()
|
||||||
|
webModules = append(webModules, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// showPage
|
// showPage
|
||||||
@ -159,6 +178,14 @@ func getSessionStringValue(key string, w http.ResponseWriter, req *http.Request)
|
|||||||
return retVal, nil
|
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 assertError(err error, w http.ResponseWriter) bool {
|
func assertError(err error, w http.ResponseWriter) bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
|
@ -3,5 +3,6 @@
|
|||||||
{{ range $i, $v := .Scripts }}
|
{{ range $i, $v := .Scripts }}
|
||||||
<script src="{{ $v }}"></script>
|
<script src="{{ $v }}"></script>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
<script>{{ .InlineScript }}</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,21 +1,6 @@
|
|||||||
<div>
|
|
||||||
devICT Slack!
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
{{ .TemplateData.Error }}
|
{{ .TemplateData.Error }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id="mainStatsBarChart"></div>
|
||||||
<table class="pure-table">
|
<hr />
|
||||||
<thead>
|
<div id="statsBarChart"></div>
|
||||||
<tr>
|
|
||||||
<th colspan="2">Statistics</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Total Channel Messages</td>
|
|
||||||
<td>{{ .TemplateData.TotalChannelMessages }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
Loading…
Reference in New Issue
Block a user