-
Notifications
You must be signed in to change notification settings - Fork 73
/
matcher.go
146 lines (129 loc) · 3.45 KB
/
matcher.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package zero
import (
"sort"
"sync"
)
type (
// Rule filter the event
Rule func(ctx *Ctx) bool
// Handler 事件处理函数
Handler func(ctx *Ctx)
)
// Matcher 是 ZeroBot 匹配和处理事件的最小单元
type Matcher struct {
// Temp 是否为临时Matcher,临时 Matcher 匹配一次后就会删除当前 Matcher
Temp bool
// Block 是否阻断后续 Matcher,为 true 时当前Matcher匹配成功后,后续Matcher不参与匹配
Block bool
// Break 是否退出后续匹配流程, 只有 rule 返回 false 且此值为真才会退出, 且不对 mid handler 以下的 rule 生效
Break bool
// NoTimeout 处理是否不设超时
NoTimeout bool
// Priority 优先级,越小优先级越高
Priority int
// Event 当前匹配到的事件
Event *Event
// Type 匹配的事件类型
Type Rule
// Rules 匹配规则
Rules []Rule
// Handler 处理事件的函数
Handler Handler
// Engine 注册 Matcher 的 Engine,Engine可为一系列 Matcher 添加通用 Rule 和 其他钩子
Engine *Engine
}
var (
// 所有主匹配器列表
matcherList = make([]*Matcher, 0)
// Matcher 修改读写锁
matcherLock = sync.RWMutex{}
// 用于迭代的所有主匹配器列表
matcherListForRanging []*Matcher
// 是否 matcherList 已经改变
// 如果改变,下次迭代需要更新
// matcherListForRanging
hasMatcherListChanged bool
)
// State store the context of a matcher.
type State map[string]interface{}
func sortMatcher() {
sort.SliceStable(matcherList, func(i, j int) bool { // 按优先级排序
return matcherList[i].Priority < matcherList[j].Priority
})
hasMatcherListChanged = true
}
// SetBlock 设置是否阻断后面的 Matcher 触发
func (m *Matcher) SetBlock(block bool) *Matcher {
m.Block = block
return m
}
// SetPriority 设置当前 Matcher 优先级
func (m *Matcher) SetPriority(priority int) *Matcher {
matcherLock.Lock()
defer matcherLock.Unlock()
m.Priority = priority
sortMatcher()
return m
}
// FirstPriority 设置当前 Matcher 优先级 - 0
func (m *Matcher) FirstPriority() *Matcher {
return m.SetPriority(0)
}
// SecondPriority 设置当前 Matcher 优先级 - 1
func (m *Matcher) SecondPriority() *Matcher {
return m.SetPriority(1)
}
// ThirdPriority 设置当前 Matcher 优先级 - 2
func (m *Matcher) ThirdPriority() *Matcher {
return m.SetPriority(2)
}
// BindEngine bind the matcher to a engine
func (m *Matcher) BindEngine(e *Engine) *Matcher {
m.Engine = e
return m
}
// StoreMatcher store a matcher to matcher list.
func StoreMatcher(m *Matcher) *Matcher {
matcherLock.Lock()
defer matcherLock.Unlock()
// todo(wdvxdr): move to engine.
if m.Engine != nil {
m.Block = m.Block || m.Engine.block
}
matcherList = append(matcherList, m)
sortMatcher()
return m
}
// StoreTempMatcher store a matcher only triggered once.
func StoreTempMatcher(m *Matcher) *Matcher {
m.Temp = true
StoreMatcher(m)
return m
}
// Delete remove the matcher from list
func (m *Matcher) Delete() {
matcherLock.Lock()
defer matcherLock.Unlock()
for i, matcher := range matcherList {
if m == matcher {
matcherList = append(matcherList[:i], matcherList[i+1:]...)
hasMatcherListChanged = true
}
}
}
func (m *Matcher) copy() *Matcher {
return &Matcher{
Type: m.Type,
Rules: m.Rules,
Block: m.Block,
Priority: m.Priority,
Handler: m.Handler,
Temp: m.Temp,
Engine: m.Engine,
}
}
// Handle 直接处理事件
func (m *Matcher) Handle(handler Handler) *Matcher {
m.Handler = handler
return m
}