action.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package server
  2. import "bytes"
  3. import "errors"
  4. import "regexp"
  5. // imporgitlab.comomm/beoran/woe/telnet"
  6. import "gitlab.com/beoran/woe/world"
  7. import "gitlab.com/beoran/woe/monolog"
  8. /* Actiondata are the params passed to an Actin, neatly wrapped in
  9. * a struct */
  10. type ActionData struct {
  11. Client *Client
  12. Server *Server
  13. World *world.World
  14. Account *world.Account
  15. Action *Action
  16. Command []byte
  17. Rest []byte
  18. Argv [][]byte
  19. }
  20. /* A handler for an action. */
  21. type ActionHandler func(data *ActionData) (err error)
  22. /* Actions that a client can perform on a server or in
  23. * the server's world. */
  24. type Action struct {
  25. Name string
  26. Privilege world.Privilege
  27. Handler ActionHandler
  28. }
  29. var ActionMap map[string]Action
  30. func AddAction(name string, privilege world.Privilege, handler ActionHandler) {
  31. monolog.Info("Adding new action %s with privilege %d", name, privilege)
  32. action := Action{name, privilege, handler}
  33. ActionMap[name] = action
  34. }
  35. func doShout(data *ActionData) (err error) {
  36. data.Server.Broadcast("Client said %s\r\n", data.Rest)
  37. return nil
  38. }
  39. func doShutdown(data *ActionData) (err error) {
  40. data.Server.Broadcast("Shutting down server NOW!\n")
  41. data.Server.Restart()
  42. return nil
  43. }
  44. func doRestart(data *ActionData) (err error) {
  45. data.Server.Broadcast("Restarting server NOW!\n")
  46. data.Server.Restart()
  47. return nil
  48. }
  49. func doQuit(data *ActionData) (err error) {
  50. data.Client.Printf("Byebye!\n")
  51. data.Client.Disconnect()
  52. return nil
  53. }
  54. func doEnableLog(data *ActionData) (err error) {
  55. // strings. string(data.Rest)
  56. return nil
  57. }
  58. func ParseCommand(command []byte, data *ActionData) (err error) {
  59. /* strip any leading blanks */
  60. trimmed := bytes.TrimLeft(command, " \t")
  61. re := regexp.MustCompile("[^ \t,]+")
  62. parts := re.FindAll(command, -1)
  63. bytes.SplitN(trimmed, []byte(" \t,"), 2)
  64. if len(parts) < 1 {
  65. data.Command = nil
  66. return errors.New("Come again?")
  67. }
  68. data.Command = parts[0]
  69. if len(parts) > 1 {
  70. data.Rest = parts[1]
  71. data.Argv = parts
  72. } else {
  73. data.Rest = nil
  74. data.Argv = nil
  75. }
  76. return nil
  77. }
  78. func init() {
  79. ActionMap = make(map[string]Action)
  80. AddAction("/shutdown", world.PRIVILEGE_LORD, doShutdown)
  81. AddAction("/restart", world.PRIVILEGE_LORD, doRestart)
  82. AddAction("/quit", world.PRIVILEGE_ZERO, doQuit)
  83. }
  84. func (client *Client) ProcessCommand(command []byte) {
  85. ad := &ActionData{client, client.GetServer(),
  86. client.GetWorld(), client.GetAccount(), nil, nil, nil, nil}
  87. _ = ad
  88. err := ParseCommand(command, ad)
  89. if err != nil {
  90. client.Printf("%s", err)
  91. return
  92. }
  93. action, ok := ActionMap[string(ad.Command)]
  94. ad.Action = &action
  95. if ad.Action == nil || (!ok) {
  96. client.Printf("Unknown command %s.", ad.Command)
  97. return
  98. }
  99. // Check if sufficient rights to perform the action
  100. if ad.Action.Privilege > client.GetAccount().Privilege {
  101. client.Printf("You lack the privilege to %s (%d vs %d).",
  102. ad.Command, ad.Action.Privilege, client.GetAccount().Privilege)
  103. return
  104. }
  105. // Finally run action
  106. ad.Action.Handler(ad)
  107. }