-
Notifications
You must be signed in to change notification settings - Fork 1
/
commands.go
113 lines (93 loc) · 2.97 KB
/
commands.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package messagerouter
import (
"errors"
"fmt"
"log"
"strings"
"sync"
"github.com/nlopes/slack"
)
var lock = new(sync.Mutex)
var commands = make(map[string]MessageHandler)
var msgprocessing = make([]MessageHandler, 0)
type CommandRequest struct {
Username string
Text string
Message *slack.Msg
}
// MessageHandler responds to a slack or cli message request.
type MessageHandler func(*CommandRequest, ResponseWriter) error
// usernameCache stores usernames to protect against slack API exhaustion
var usernameCache = map[string]string{"0": "nii236"}
// GetUsername retrieves human readable username information from SLACK API using Slack username ID
func (mr *MessageRouter) GetUsername(msg *slack.Msg) (string, error) {
if username, ok := usernameCache[msg.User]; ok {
return username, nil
}
userInfo, err := mr.API.GetUserInfo(msg.User)
if err != nil {
log.Println("No user information: "+msg.Text, err.Error(), msg)
return "", err
}
return userInfo.Name, nil
}
// BuildResponseWriter checks the MessageRouter and returns the appropriate response writer
func (mr *MessageRouter) BuildResponseWriter(msg *slack.Msg) ResponseWriter {
var w ResponseWriter
if mr.IsDev {
w = new(CLIResponseWriter)
} else {
w = NewSlackResponseWriter(msg, mr.RTM)
}
return w
}
// ProcessMessage performs basic routing on Slack messages in the channel #puddle
// Eventually, this will feed into two routers
// One for admin commands & one for mud commands
func (mr *MessageRouter) ProcessMessage(msg *slack.Msg) error {
username, _ := mr.GetUsername(msg)
cr := CommandRequest{username, msg.Text, msg}
w := mr.BuildResponseWriter(msg)
if hasPrefix(msg.Text) {
words := strings.Split(msg.Text, " ")
cmdString := strings.ToLower(words[0])
if fn, ok := commands[cmdString]; ok {
err := fn(&cr, w)
if err != nil {
w.WriteError(err.Error())
}
return err
} else {
return errors.New("Invalid command. Get it together")
}
} else {
for _, handler := range msgprocessing {
handler(&cr, w)
}
}
return nil
}
// hasPrefix checks for command prefix
func hasPrefix(s string) bool {
return strings.HasPrefix(s, "!") || strings.HasPrefix(s, "%") || strings.HasPrefix(s, "#")
}
// Handle registers the handler for the given command, or register a standard message parsing function
// Must match a command prefix, `!` for admin commands, `%` for general commands & `#` for MUD commands
// For functions that will parse all messages (sans command prefix), the cmdString must equal "*"
func (mr *MessageRouter) Handle(cmdString string, fn MessageHandler) error {
if !hasPrefix(cmdString) && cmdString != "*" {
log.Fatal(cmdString, " does not have a command prefix")
}
log.Println(fmt.Sprintf("Registering new admin command <%s>", cmdString))
lock.Lock()
defer lock.Unlock()
if cmdString == "*" {
msgprocessing = append(msgprocessing, fn)
return nil
}
if _, ok := commands[cmdString]; !ok {
commands[cmdString] = fn
return nil
}
return errors.New("Command exists")
}