github.com/fumiama/NanoBot@v0.0.0-20231122134259-c22d8183efca/matcher.go (about) 1 package nano 2 3 import ( 4 "sort" 5 "sync" 6 7 "github.com/wdvxdr1123/ZeroBot/extension/rate" 8 ) 9 10 type ( 11 // Rule filter the event 12 Rule func(ctx *Ctx) bool 13 // Process 事件处理函数 14 Process func(ctx *Ctx) 15 ) 16 17 // Matcher 是 ZeroBot 匹配和处理事件的最小单元 18 type Matcher struct { 19 // Temp 是否为临时Matcher,临时 Matcher 匹配一次后就会删除当前 Matcher 20 Temp bool 21 // Block 是否阻断后续 Matcher,为 true 时当前Matcher匹配成功后,后续Matcher不参与匹配 22 Block bool 23 // Break 是否退出后续匹配流程, 只有 rule 返回 false 且此值为真才会退出, 且不对 mid handler 以下的 rule 生效 24 Break bool 25 // priority 优先级,越小优先级越高 26 priority int 27 // Event 当前匹配到的事件 28 Event *Event 29 // Type 匹配的事件类型 30 Type string 31 // Rules 匹配规则 32 Rules []Rule 33 // Process 处理事件的函数 34 Process Process 35 // Engine 注册 Matcher 的 Engine,Engine可为一系列 Matcher 添加通用 Rule 和 其他钩子 36 Engine *Engine 37 } 38 39 var ( 40 // 所有主匹配器列表 41 matcherMap = make(map[string][]*Matcher, 0) 42 // Matcher 修改读写锁 43 matcherLock = sync.RWMutex{} 44 ) 45 46 // State store the context of a matcher. 47 type State map[string]any 48 49 func sortMatcher(typ string) { 50 sort.Slice(matcherMap[typ], func(i, j int) bool { // 按优先级排序 51 return matcherMap[typ][i].priority < matcherMap[typ][j].priority 52 }) 53 } 54 55 // SetBlock 设置是否阻断后面的 Matcher 触发 56 func (m *Matcher) SetBlock(block bool) *Matcher { 57 m.Block = block 58 return m 59 } 60 61 // setPriority 设置当前 Matcher 优先级 62 func (m *Matcher) setPriority(priority int) *Matcher { 63 matcherLock.Lock() 64 defer matcherLock.Unlock() 65 m.priority = priority 66 sortMatcher(m.Type) 67 return m 68 } 69 70 /* 71 // firstPriority 设置当前 Matcher 优先级 - 0 72 func (m *Matcher) firstPriority() *Matcher { 73 return m.setPriority(0) 74 } 75 */ 76 77 // secondPriority 设置当前 Matcher 优先级 - 1 78 func (m *Matcher) secondPriority() *Matcher { 79 return m.setPriority(1) 80 } 81 82 /* 83 // thirdPriority 设置当前 Matcher 优先级 - 2 84 func (m *Matcher) thirdPriority() *Matcher { 85 return m.setPriority(2) 86 } 87 */ 88 89 // Limit 限速器 90 // 91 // postfn 当请求被拒绝时的操作 92 func (m *Matcher) Limit(limiterfn func(*Ctx) *rate.Limiter, postfn ...func(*Ctx)) *Matcher { 93 m.Rules = append(m.Rules, func(ctx *Ctx) bool { 94 if limiterfn(ctx).Acquire() { 95 return true 96 } 97 if len(postfn) > 0 { 98 for _, fn := range postfn { 99 fn(ctx) 100 } 101 } 102 return false 103 }) 104 return m 105 } 106 107 // StoreMatcher store a matcher to matcher list. 108 func StoreMatcher(m *Matcher) *Matcher { 109 matcherLock.Lock() 110 defer matcherLock.Unlock() 111 matcherMap[m.Type] = append(matcherMap[m.Type], m) 112 sortMatcher(m.Type) 113 return m 114 } 115 116 // StoreTempMatcher store a matcher only triggered once. 117 func StoreTempMatcher(m *Matcher) *Matcher { 118 m.Temp = true 119 StoreMatcher(m) 120 return m 121 } 122 123 // Delete remove the matcher from list 124 func (m *Matcher) Delete() { 125 matcherLock.Lock() 126 defer matcherLock.Unlock() 127 for i, matcher := range matcherMap[m.Type] { 128 if m == matcher { 129 matcherMap[m.Type] = append(matcherMap[m.Type][:i], matcherMap[m.Type][i+1:]...) 130 } 131 } 132 } 133 134 func (m *Matcher) copy() *Matcher { 135 return &Matcher{ 136 Type: m.Type, 137 Rules: m.Rules, 138 Block: m.Block, 139 priority: m.priority, 140 Process: m.Process, 141 Temp: m.Temp, 142 Engine: m.Engine, 143 } 144 } 145 146 // Handle 直接处理事件 147 func (m *Matcher) Handle(handler Process) *Matcher { 148 m.Process = handler 149 return m 150 }