-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
89 lines (74 loc) · 2.17 KB
/
router.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
package bottom
import (
"regexp"
"time"
"github.com/lrstanley/girc"
)
// RouterFunc is used in routing events
//
// Functions should expect the following information:
// 1. sender - the nick of the author of the message
// 2. channel - the channel the message was sent in (if sender == channel, then assume a private message)
// 3. groups - any regexp groups extracted from the message. groups[0] is *always* the full message
type RouterFunc func(sender, channel string, groups []string) error
// Router is a Middleware implementation, containing routing logic
// for different Events.
//
// These events are pattern matched to a specific RouterFunc
type Router struct {
routes map[*regexp.Regexp]RouterFunc
}
// NewRouter returns a new, empty Router, with no routes setup
func NewRouter() *Router {
return &Router{
routes: make(map[*regexp.Regexp]RouterFunc),
}
}
// AddRoute configures a RouterFunc to run when a certain route
// pattern matches.
//
// If many patterns match, the first pattern wins
// If the pattern contains groups, then these are passed as the second arg
// to RouterFunc
func (r *Router) AddRoute(pattern string, f RouterFunc) (err error) {
re, err := regexp.Compile(pattern)
if err != nil {
return
}
r.routes[re] = f
return
}
// Do implements the Middleware interface.
//
// It matches message contents to route patterns, as passed to AddRoute,
// and calls the associated RouterFunc, passing any regexp groups as it
// goes.
func (r *Router) Do(ctx Context, e girc.Event) (err error) {
// skip messages older than a minute (assume it's the replayer)
cutOff := time.Now().Add(0 - time.Minute)
if e.Timestamp.Before(cutOff) {
// ignore
return
}
msg := []byte(ctx["message"].(string))
sender := ctx["sender"].(string)
recipient := ctx["recipient"].(string)
channel := e.Params[0]
if channel == recipient {
// direct message, so respond to the sender
channel = sender
}
for r, f := range r.routes {
if r.Match(msg) {
return f(sender, channel, groupsStrings(r.FindAllSubmatch(msg, -1)[0]))
}
}
return
}
func groupsStrings(b [][]byte) (s []string) {
s = make([]string, len(b))
for idx, group := range b {
s[idx] = string(group)
}
return
}