From cd1bc16361aef0ce07fce0bc46e1aa32f6c7279a Mon Sep 17 00:00:00 2001 From: Brian Buller Date: Thu, 23 Apr 2015 11:09:59 -0500 Subject: [PATCH] Start building the Model --- mc_man.go | 8 +- util/config.go | 136 ++++++++++--------- util/message.go | 20 +-- util/model.go | 109 +++++++++++++++ util/user.go | 10 +- util/{webserver.go => webserver.go.disabled} | 66 +++++++-- 6 files changed, 249 insertions(+), 100 deletions(-) create mode 100644 util/model.go rename util/{webserver.go => webserver.go.disabled} (76%) diff --git a/mc_man.go b/mc_man.go index a94f6fc..e3ceff5 100644 --- a/mc_man.go +++ b/mc_man.go @@ -88,9 +88,11 @@ func main() { }() // Web Server Routine - go func() { - util.StartServer(ch) - }() + /* + go func() { + util.StartServer(ch) + }() + */ // The forever loop to monitor everything for { diff --git a/util/config.go b/util/config.go index a7aba39..02eea19 100644 --- a/util/config.go +++ b/util/config.go @@ -14,8 +14,8 @@ type Config struct { FeatureTPHome bool FeatureTPVisit bool FeatureDayNight bool - Users []*User - LoggedInUsers []*User + MCUsers []*MCUser + LoggedInMCUsers []*MCUser Whitelist []string Ops []string } @@ -28,6 +28,8 @@ func LoadConfig(mm *MessageManager) { message_manager = mm c = new(Config) + mc_model := InitializeModel() + // Load the whitelist whitelist_rd, err := ioutil.ReadFile("whitelist.json") // We have to make it an object to read it... @@ -64,7 +66,7 @@ func LoadConfig(mm *MessageManager) { // Add the "Stop" listener fmt.Println("> Activating 'stop' listener") AddListener(func(i *Message) bool { - if i.User.IsOp && i.Text == "!stop\n" { + if i.MCUser.IsOp && i.Text == "!stop\n" { mm.Output("stop") StopServer = true return true @@ -81,36 +83,36 @@ func LoadConfig(mm *MessageManager) { fmt.Println("> Activating 'home' listeners") // Add !set home listener AddListener(func(i *Message) bool { - if i.User.Name != "" && i.Text == "!set home\n" { + if i.MCUser.Name != "" && i.Text == "!set home\n" { AddTempListener(func(inp *Message) bool { - listen_for := "Teleported " + i.User.Name + " to " - if inp.User.Name == "" && strings.Contains(inp.Text, listen_for) { + listen_for := "Teleported " + i.MCUser.Name + " to " + if inp.MCUser.Name == "" && strings.Contains(inp.Text, listen_for) { // Found the text r := strings.Split(inp.Text, listen_for) if len(r) > 0 { p_str := r[1] p_str = strings.Replace(p_str, ",", "", -1) p_str = strings.Replace(p_str, "\n", "", -1) - SetHome(i.User.Name, p_str) - mm.Tell(i.User.Name, "Set your home to "+p_str, "blue") + SetHome(i.MCUser.Name, p_str) + mm.Tell(i.MCUser.Name, "Set your home to "+p_str, "blue") return true } } return false }) - mm.Output("tp " + i.User.Name + " ~ ~ ~") + mm.Output("tp " + i.MCUser.Name + " ~ ~ ~") return true } return false }) // Add !home listener AddListener(func(i *Message) bool { - if i.User.Name != "" && i.Text == "!home\n" { - home_str, found := GetHome(i.User.Name) + if i.MCUser.Name != "" && i.Text == "!home\n" { + home_str, found := GetHome(i.MCUser.Name) if found { - mm.Output("tp " + i.User.Name + " " + home_str) + mm.Output("tp " + i.MCUser.Name + " " + home_str) } else { - mm.Tell(i.User.Name, "I don't know where your home is. Set it to your current position by typing '!set home'", "red") + mm.Tell(i.MCUser.Name, "I don't know where your home is. Set it to your current position by typing '!set home'", "red") } } return false @@ -122,39 +124,39 @@ func LoadConfig(mm *MessageManager) { fmt.Println("> Activating 'visit' listeners") // Add !set porch listener AddListener(func(i *Message) bool { - if i.User.Name != "" && i.Text == "!set porch\n" { + if i.MCUser.Name != "" && i.Text == "!set porch\n" { AddTempListener(func(inp *Message) bool { - listen_for := "Teleported " + i.User.Name + " to " - if inp.User.Name == "" && strings.Contains(inp.Text, listen_for) { + listen_for := "Teleported " + i.MCUser.Name + " to " + if inp.MCUser.Name == "" && strings.Contains(inp.Text, listen_for) { // Found the text r := strings.Split(inp.Text, listen_for) if len(r) > 0 { p_str := r[1] p_str = strings.Replace(p_str, ",", "", -1) - SetPorch(i.User.Name, p_str) - mm.Tell(i.User.Name, "Set your porch to "+p_str, "blue") + SetPorch(i.MCUser.Name, p_str) + mm.Tell(i.MCUser.Name, "Set your porch to "+p_str, "blue") return true } } return false }) - mm.Output("tp " + i.User.Name + " ~ ~ ~") + mm.Output("tp " + i.MCUser.Name + " ~ ~ ~") return true } return false }) // Add !visit listener AddListener(func(i *Message) bool { - if i.User.Name != "" && strings.HasPrefix(i.Text, "!visit ") { + if i.MCUser.Name != "" && strings.HasPrefix(i.Text, "!visit ") { // Find the user we're trying to visit r := strings.Split(strings.Replace(i.Text, "\n", "", -1), "!visit ") if len(r) > 0 { username := r[1] porch_str, found := GetPorch(username) if found { - mm.Output("tp " + i.User.Name + " " + porch_str) + mm.Output("tp " + i.MCUser.Name + " " + porch_str) } else { - mm.Tell(i.User.Name, "I don't know where "+username+"'s porch is. They can set it to their current position by typing '!set porch'", "red") + mm.Tell(i.MCUser.Name, "I don't know where "+username+"'s porch is. They can set it to their current position by typing '!set porch'", "red") } } } @@ -167,20 +169,20 @@ func LoadConfig(mm *MessageManager) { fmt.Println("> Activating 'time' listeners") // Add !time day listener AddListener(func(i *Message) bool { - if i.User.Name != "" && i.Text == "!time day\n" { + if i.MCUser.Name != "" && i.Text == "!time day\n" { // TODO: Start vote mm.Output("time set day") - mm.Tell("@a", "Day Time time initiated by "+i.User.Name, "yellow") + mm.Tell("@a", "Day Time time initiated by "+i.MCUser.Name, "yellow") return true } return false }) // Add !time night listener AddListener(func(i *Message) bool { - if i.User.Name != "" && i.Text == "!time night\n" { + if i.MCUser.Name != "" && i.Text == "!time night\n" { // TODO: Start vote mm.Output("time set night") - mm.Tell("@a", "Night Time time initiated by "+i.User.Name, "blue") + mm.Tell("@a", "Night Time time initiated by "+i.MCUser.Name, "blue") return true } return false @@ -189,7 +191,7 @@ func LoadConfig(mm *MessageManager) { } // Add login listener AddListener(func(i *Message) bool { - if i.User.Name == "" && strings.Contains(i.Text, " logged in with entity id ") { + if i.MCUser.Name == "" && strings.Contains(i.Text, " logged in with entity id ") { // TODO: User Logged in Function // Find the user that just logged in r := strings.Split(i.Text, "]: ") @@ -200,7 +202,7 @@ func LoadConfig(mm *MessageManager) { if len(r) > 0 { find = r[0] // find should be the user name now - LoginUser(*FindUser(find, true)) + LoginMCUser(*FindMCUser(find, true)) return true } } @@ -209,7 +211,7 @@ func LoadConfig(mm *MessageManager) { }) // Add logout listener AddListener(func(i *Message) bool { - if i.User.Name == "" && strings.Contains(i.Text, " lost connection: ") { + if i.MCUser.Name == "" && strings.Contains(i.Text, " lost connection: ") { // Find the user that just logged out r := strings.Split(i.Text, "]: ") find := "" @@ -219,7 +221,7 @@ func LoadConfig(mm *MessageManager) { if len(r) > 0 { find = r[0] // find should be the user name now - LogoutUser(*FindUser(find, false)) + LogoutMCUser(*FindMCUser(find, false)) return true } } @@ -229,42 +231,42 @@ func LoadConfig(mm *MessageManager) { // Add !help listener AddListener(func(i *Message) bool { - if i.User.Name != "" && i.Text == "!help\n" { - mm.Tell(i.User.Name, "-=( mc_man Manager Help )=-", "blue") + if i.MCUser.Name != "" && i.Text == "!help\n" { + mm.Tell(i.MCUser.Name, "-=( mc_man Manager Help )=-", "blue") numFeatures := 0 if c.FeatureTPHome == true { numFeatures++ - mm.Tell(i.User.Name, "!set home -- Set your 'home' to your current position.", "white") - mm.Tell(i.User.Name, "!home -- Request a teleport to your 'home' position.", "white") + mm.Tell(i.MCUser.Name, "!set home -- Set your 'home' to your current position.", "white") + mm.Tell(i.MCUser.Name, "!home -- Request a teleport to your 'home' position.", "white") } if c.FeatureTPVisit == true { numFeatures++ - mm.Tell(i.User.Name, "!set porch -- Set your 'porch' to your current position.", "white") - mm.Tell(i.User.Name, "!visit -- Request a teleport to 's 'porch' position.", "white") + mm.Tell(i.MCUser.Name, "!set porch -- Set your 'porch' to your current position.", "white") + mm.Tell(i.MCUser.Name, "!visit -- Request a teleport to 's 'porch' position.", "white") } if c.FeatureDayNight == true { numFeatures++ - mm.Tell(i.User.Name, "!time day -- Ask the server to time the time to 'day'.", "white") - mm.Tell(i.User.Name, "!time night -- Ask the server to time the time to 'night'.", "white") + mm.Tell(i.MCUser.Name, "!time day -- Ask the server to time the time to 'day'.", "white") + mm.Tell(i.MCUser.Name, "!time night -- Ask the server to time the time to 'night'.", "white") } if numFeatures == 0 { - mm.Tell(i.User.Name, "mc_man currently has no user features loaded.", "white") + mm.Tell(i.MCUser.Name, "mc_man currently has no user features loaded.", "white") } - mm.Tell(i.User.Name, "-=========================-", "blue") + mm.Tell(i.MCUser.Name, "-=========================-", "blue") return true } return false }) } - c.Users = make([]*User, 0, 10) + c.MCUsers = make([]*MCUser, 0, 10) u, _ := j.GetObjectArray("users") for _, user := range u { user_name, err := user.GetString("name") if err == nil && user_name != "" { user_home, _ := user.GetString("home") user_porch, _ := user.GetString("porch") - us := NewUser(user_name) + us := NewMCUser(user_name) for _, un := range c.Ops { if un == user_name { us.IsOp = true @@ -272,39 +274,39 @@ func LoadConfig(mm *MessageManager) { } us.Home = user_home us.Porch = user_porch - c.Users = append(c.Users, us) + c.MCUsers = append(c.MCUsers, us) } } - fmt.Printf("> Loaded %d Users\n", len(c.Users)) + fmt.Printf("> Loaded %d Users\n", len(c.MCUsers)) } } -func LoginUser(u User) { - for _, user := range c.LoggedInUsers { +func LoginMCUser(u MCUser) { + for _, user := range c.LoggedInMCUsers { if user.Name == u.Name { // User is already logged in return } } - c.LoggedInUsers = append(c.LoggedInUsers, &u) + c.LoggedInMCUsers = append(c.LoggedInMCUsers, &u) } -func LogoutUser(u User) { - for idx, user := range c.LoggedInUsers { +func LogoutMCUser(u MCUser) { + for idx, user := range c.LoggedInMCUsers { if user.Name == u.Name { - t := append(c.LoggedInUsers[:idx], c.LoggedInUsers[idx+1:]...) - c.LoggedInUsers = make([]*User, len(t)) - copy(c.LoggedInUsers, t) + t := append(c.LoggedInMCUsers[:idx], c.LoggedInMCUsers[idx+1:]...) + c.LoggedInMCUsers = make([]*MCUser, len(t)) + copy(c.LoggedInMCUsers, t) return } } } -func AddUser(username string) { +func AddMCUser(username string) { if username != "" { - us := NewUser(username) + us := NewMCUser(username) fmt.Println("Adding new user: " + username) - c.Users = append(c.Users, us) + c.MCUsers = append(c.MCUsers, us) WriteConfig() } } @@ -335,7 +337,7 @@ func WriteConfig() { d = d + "}],\"users\":[" // Output users array num_users := 0 - for _, u := range c.Users { + for _, u := range c.MCUsers { if num_users > 0 { d = d + "," } @@ -348,17 +350,17 @@ func WriteConfig() { } func SetHome(user string, loc string) { - u := FindUser(user, true) + u := FindMCUser(user, true) if u.Index != -1 { u.Home = strings.Replace(loc, "\n", "", -1) // Replace the user in the Users array - c.Users[u.Index] = u + c.MCUsers[u.Index] = u WriteConfig() } } func GetHome(user string) (string, bool) { - u := FindUser(user, false) + u := FindMCUser(user, false) if u.Index == -1 || u.Home == "" { return "", false } @@ -366,33 +368,33 @@ func GetHome(user string) (string, bool) { } func SetPorch(user string, loc string) { - u := FindUser(user, true) + u := FindMCUser(user, true) if u.Index != -1 { u.Porch = strings.Replace(loc, "\n", "", -1) - c.Users[u.Index] = u + c.MCUsers[u.Index] = u WriteConfig() } } func GetPorch(user string) (string, bool) { - u := FindUser(user, false) + u := FindMCUser(user, false) if u.Index == -1 || u.Porch == "" { return "", false } return u.Porch, true } -func FindUser(name string, create bool) *User { - for _, user := range c.Users { +func FindMCUser(name string, create bool) *MCUser { + for _, user := range c.MCUsers { if user.Name == name { return user } } if create && name != "" { - AddUser(name) - return FindUser(name, false) + AddMCUser(name) + return FindMCUser(name, false) } - return NewUser("") + return NewMCUser("") } func GetConfig() *Config { diff --git a/util/message.go b/util/message.go index 7abdc3d..a351c75 100644 --- a/util/message.go +++ b/util/message.go @@ -6,8 +6,8 @@ import ( ) type Message struct { - User *User - Text string + MCUser *MCUser + Text string Output func() string } @@ -15,21 +15,21 @@ type Message struct { func NewMessage(t string) *Message { m := new(Message) msg_user := regexp.MustCompile("<[^>]+>") - tmpUser := msg_user.FindString(t) - tmpUser = strings.Replace(tmpUser, "<", "", -1) - tmpUser = strings.Replace(tmpUser, ">", "", -1) - m.User = FindUser(tmpUser, true) + tmpMCUser := msg_user.FindString(t) + tmpMCUser = strings.Replace(tmpMCUser, "<", "", -1) + tmpMCUser = strings.Replace(tmpMCUser, ">", "", -1) + m.MCUser = FindMCUser(tmpMCUser, true) m.Text = t - if m.User.Index != -1 && m.User.Name != "" { - res := strings.Split(t, "<"+m.User.Name+"> ") + if m.MCUser.Index != -1 && m.MCUser.Name != "" { + res := strings.Split(t, "<"+m.MCUser.Name+"> ") if len(res) > 0 { m.Text = res[1] } } m.Output = func() string { - if m.User.Index != -1 && m.User.Name != "" { - return "<" + m.User.Name + "> " + m.Text + if m.MCUser.Index != -1 && m.MCUser.Name != "" { + return "<" + m.MCUser.Name + "> " + m.Text } else { return m.Text } diff --git a/util/model.go b/util/model.go new file mode 100644 index 0000000..3b7b622 --- /dev/null +++ b/util/model.go @@ -0,0 +1,109 @@ +package util + +import ( + "bytes" + "github.com/boltdb/bolt" + "log" + "time" +) + +var users_bucket string +var user_prefix string + +type Model struct { + db *bolt.DB +} + +func InitializeModel() *Model { + var err error + var ret *Model + users_bucket = "mc_users" + user_prefix = "mc_user_" + ret.db, err = bolt.Open("mc_man.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + defer ret.db.Close() + return ret +} + +func (m *Model) getMcUsers() []MCUser { + var ret []MCUser + m.db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(users_bucket)) + c := b.Cursor() + srch_prefix := []byte(user_prefix) + for k, _ := c.Seek(srch_prefix); bytes.HasPrefix(k, srch_prefix); k, _ = c.Next() { + // v should be a mc_user bucket + if user_bucket := b.Bucket(k); user_bucket != nil { + if us_name := user_bucket.Get([]byte("name")); us_name != nil { + new_user := NewMCUser(string(us_name)) + new_user.IsOp = bytes.Equal(user_bucket.Get([]byte("op")), []byte("true")) + new_user.Home = string(user_bucket.Get([]byte("home"))) + new_user.Porch = string(user_bucket.Get([]byte("porch"))) + new_user.Quota, _ = time.ParseDuration(string(user_bucket.Get([]byte("quota")))) + new_user.quotaUsed, _ = time.ParseDuration(string(user_bucket.Get([]byte("quota_used")))) + ret = append(ret, *new_user) + } + } + } + return nil + }) + return ret +} + +// updateMcUser adds or updates a user +func (m *Model) updateMcUser(u MCUser) { + m.db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte(users_bucket)) + if err != nil { + return err + } + user_key := user_prefix + u.Name + ub, uberr := b.CreateBucketIfNotExists([]byte(user_key)) + if uberr != nil { + return uberr + } + addStringPairToBucket(ub, "name", u.Name) + addBooleanPairToBucket(ub, "op", u.IsOp) + addStringPairToBucket(ub, "home", u.Home) + addStringPairToBucket(ub, "porch", u.Porch) + addDurationPairToBucket(ub, "quota", u.Quota) + addDurationPairToBucket(ub, "quotaused", u.quotaUsed) + addTimePairToBucket(ub, "logintime", u.loginTime) + return nil + }) +} + +func addStringPairToBucket(b *bolt.Bucket, k, v string) error { + if err := b.Put([]byte(k), []byte(v)); err != nil { + return err + } + return nil +} + +func addBooleanPairToBucket(b *bolt.Bucket, k string, v bool) error { + write_v := "true" + if !v { + write_v = "false" + } + if err := b.Put([]byte(k), []byte(write_v)); err != nil { + return err + } + return nil +} + +func addDurationPairToBucket(b *bolt.Bucket, k string, v time.Duration) error { + write_v := v.String() + if err := b.Put([]byte(k), []byte(write_v)); err != nil { + return err + } + return nil +} + +func addTimePairToBucket(b *bolt.Bucket, k string, v time.Time) error { + if err := b.Put([]byte(k), []byte(v.String())); err != nil { + return err + } + return nil +} diff --git a/util/user.go b/util/user.go index dcc6e58..7c8e3e4 100644 --- a/util/user.go +++ b/util/user.go @@ -4,7 +4,7 @@ import ( "time" ) -type User struct { +type MCUser struct { Name string Index int IsOp bool @@ -16,8 +16,8 @@ type User struct { loginTime time.Time } -func NewUser(nm string) *User { - m := new(User) +func NewMCUser(nm string) *MCUser { + m := new(MCUser) m.Name = nm if nm == "" { m.Index = -1 @@ -33,7 +33,7 @@ func NewUser(nm string) *User { return m } -func (u *User) HasQuota() bool { +func (u *MCUser) HasQuota() bool { if u.Quota > 0 { return u.quotaUsed < u.Quota } else { @@ -41,7 +41,7 @@ func (u *User) HasQuota() bool { } } -func (u *User) RemainingQuota() time.Duration { +func (u *MCUser) RemainingQuota() time.Duration { if u.Quota > 0 { return u.Quota - u.quotaUsed } else { diff --git a/util/webserver.go b/util/webserver.go.disabled similarity index 76% rename from util/webserver.go rename to util/webserver.go.disabled index 3ce3ea8..072afb9 100644 --- a/util/webserver.go +++ b/util/webserver.go.disabled @@ -4,8 +4,11 @@ import ( //"database/sql" "fmt" //_ "github.com/mattn/go-sqlite3" + //"encoding/json" + "github.com/boltdb/bolt" "io" "io/ioutil" + //"log" "net/http" "os" "strings" @@ -13,6 +16,11 @@ import ( var output_channel chan string +type WebUser struct { + Username string `json:"username"` + Password string `json:"password"` +} + func StartServer(ch chan string) { output_channel = ch _, err := os.Stat("mapcrafter/index.html") @@ -20,10 +28,9 @@ func StartServer(ch chan string) { // Looks like mapcrafter is present output_channel <- "* Mapcrafter Directory is Present, routing to /map\n" fs := http.FileServer(http.Dir("mapcrafter")) - http.Handle("/map/", http.StripPrefix("/map/", fs)) + http.Handle("/", fs) } - http.HandleFunc("/api/", serveAPI) - http.HandleFunc("/", serveMcMan) + http.HandleFunc("/admin/", serveMcMan) http.ListenAndServe(":8080", nil) } @@ -31,12 +38,18 @@ func serveMcMan(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, htmlHeader("mc_man - Minecraft Manager")) the_path := r.URL.Path - output_channel <- the_path + output_channel <- the_path + "\n" - if strings.HasPrefix(the_path, "/login") || the_path == "/" { + the_path = strings.TrimPrefix(strings.ToLower(the_path), "/admin") + output_channel <- the_path + "\n" + + fmt.Fprintf(w, the_path) + if strings.HasPrefix(the_path, "/login") { fmt.Fprintf(w, loginScreen()) } else if strings.HasPrefix(the_path, "/dologin") { fmt.Fprintf(w, doLogin(w, r)) + } else if strings.HasPrefix(the_path, "/api/") { + fmt.Fprintf(w, serveAPI(w, r)) } fmt.Fprintf(w, htmlFooter()) @@ -56,17 +69,8 @@ func doLogin(w http.ResponseWriter, r *http.Request) string { ret := "Do Login
" ret = ret + r.FormValue("username") ret = ret + r.FormValue("password") - return ret - /* - //r.F - db, err := sql.Open("sqlite3", "mc_man.db") - if err == nil { - // Error opening the DB, can't log in - return false - } - // rows, err := db.Query("SELECT * FROM USERS") - */ + return ret } func serveAPI(w http.ResponseWriter, r *http.Request) { @@ -143,6 +147,38 @@ func getWhitelist() string { return ret } +func setupDatabase() bool { + /* + db, err := bolt.Open("mc_man.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + defer db.Close() + + err = db.Update(func(tx *bolt.Tx) error { + return nil + }) + */ + /* + var err error + web_database, err = sql.Open("sqlite3", "mc_man.db") + defer web_database.Close() + + if err == nil { + // Error opening the DB, can't log in + return false + } + rows, err := db.Query("SELECT name FROM sqlite_master WHERE type='table' AND name='users';") + defer rows.Close() + for rows.Next() { + err := rows.Scan + } + // rows, err := db.Query("SELECT * FROM USERS") + return true + */ + return true +} + /* HTML Functions */ func htmlHeader(title string) string { head := `