package server import "bytes" import "errors" import "regexp" // imporgitlab.comomm/beoran/woe/telnet" import "gitlab.com/beoran/woe/world" import "gitlab.com/beoran/woe/monolog" /* Actiondata are the params passed to an Actin, neatly wrapped in * a struct */ type ActionData struct { Client *Client Server *Server World *world.World Account *world.Account Action *Action Command []byte Rest []byte Argv [][]byte } /* A handler for an action. */ type ActionHandler func(data *ActionData) (err error) /* Actions that a client can perform on a server or in * the server's world. */ type Action struct { Name string Privilege world.Privilege Handler ActionHandler } var ActionMap map[string]Action func AddAction(name string, privilege world.Privilege, handler ActionHandler) { monolog.Info("Adding new action %s with privilege %d", name, privilege) action := Action{name, privilege, handler} ActionMap[name] = action } func doShout(data *ActionData) (err error) { data.Server.Broadcast("Client said %s\r\n", data.Rest) return nil } func doShutdown(data *ActionData) (err error) { data.Server.Broadcast("Shutting down server NOW!\n") data.Server.Restart() return nil } func doRestart(data *ActionData) (err error) { data.Server.Broadcast("Restarting server NOW!\n") data.Server.Restart() return nil } func doQuit(data *ActionData) (err error) { data.Client.Printf("Byebye!\n") data.Client.Disconnect() return nil } func doEnableLog(data *ActionData) (err error) { // strings. string(data.Rest) return nil } func ParseCommand(command []byte, data *ActionData) (err error) { /* strip any leading blanks */ trimmed := bytes.TrimLeft(command, " \t") re := regexp.MustCompile("[^ \t,]+") parts := re.FindAll(command, -1) bytes.SplitN(trimmed, []byte(" \t,"), 2) if len(parts) < 1 { data.Command = nil return errors.New("Come again?") } data.Command = parts[0] if len(parts) > 1 { data.Rest = parts[1] data.Argv = parts } else { data.Rest = nil data.Argv = nil } return nil } func init() { ActionMap = make(map[string]Action) AddAction("/shutdown", world.PRIVILEGE_LORD, doShutdown) AddAction("/restart", world.PRIVILEGE_LORD, doRestart) AddAction("/quit", world.PRIVILEGE_ZERO, doQuit) } func (client *Client) ProcessCommand(command []byte) { ad := &ActionData{client, client.GetServer(), client.GetWorld(), client.GetAccount(), nil, nil, nil, nil} _ = ad err := ParseCommand(command, ad) if err != nil { client.Printf("%s", err) return } action, ok := ActionMap[string(ad.Command)] ad.Action = &action if ad.Action == nil || (!ok) { client.Printf("Unknown command %s.", ad.Command) return } // Check if sufficient rights to perform the action if ad.Action.Privilege > client.GetAccount().Privilege { client.Printf("You lack the privilege to %s (%d vs %d).", ad.Command, ad.Action.Privilege, client.GetAccount().Privilege) return } // Finally run action ad.Action.Handler(ad) }