-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommand.go
91 lines (75 loc) · 2.15 KB
/
command.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
package main
import (
"os/exec"
"regexp"
"strings"
"github.com/osm/irc"
)
// command holds the information needed to process a command.
type command struct {
acceptArgs bool
bin string
args []string
}
// parseCommand returns a command based om the given input data.
func parseCommand(acceptArgs bool, data string) command {
parts := strings.Split(data, " ")
var args []string
if len(parts) > 1 {
args = parts[1:]
}
return command{
acceptArgs: acceptArgs,
bin: parts[0],
args: args,
}
}
// initFactoidDefaults sets default values for all settings.
func (b *bot) initCommandDefaults() {
if b.IRC.CommandErrExec == "" {
b.IRC.CommandErrExec = "command execution error"
}
}
// commandArgumentRegexp is a regexp that makes sure that we don't get
// unwanted characters passed to the external commands that are to be
// executed.
var commandArgumentRegexp = regexp.MustCompile("^[a-zA-Z0-9åäöÅÄÖ0-9+*-\\/?=#_.\"' ]*$")
// commandHandler exposes external commands that are defined in the Commands
// secion of the configuration file. If the IRC message matches a key of the
// defined command it executes it and returns the output to the user. If the
// message was seen in a channel it will return it back to the channel,
// otherwise it will be sent back to the user.
func (b *bot) commandHandler(m *irc.Message) {
a := b.parseAction(m).(*privmsgAction)
c, ok := b.IRC.commands[a.cmd]
if !ok {
return
}
if b.shouldIgnore(m) {
return
}
if c.acceptArgs && len(a.args) > 0 && !commandArgumentRegexp.MatchString(strings.Join(a.args, " ")) {
return
}
args := c.args
if c.acceptArgs && len(a.args) > 0 {
args = append(args, a.args...)
}
cmd := exec.Command(c.bin, args...)
out, err := cmd.CombinedOutput()
if err != nil {
b.logger.Printf("commandHandler: %v", err)
b.privmsg(b.IRC.CommandErrExec)
return
}
// The output can span over multiple lines. Since the IRC protocol
// doesn't support sending multiple lines in the same message we'll
// have to split it and send each line separately.
rows := strings.Split(string(out), "\n")
for _, o := range rows {
if o == "" {
continue
}
b.privmsg(o)
}
}