1
0
mirror of https://github.com/fumiama/ReiBot.git synced 2026-06-05 09:00:24 +08:00
Files
ReiBot/matcher.go
2022-10-11 00:14:05 +08:00

151 lines
3.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package rei
import (
"sort"
"sync"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
)
type (
// Rule filter the event
Rule func(ctx *Ctx) bool
// Process 事件处理函数
Process 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
// priority 优先级,越小优先级越高
priority int
// Event 当前匹配到的事件
Event *Event
// Type 匹配的事件类型
Type string
// Rules 匹配规则
Rules []Rule
// Process 处理事件的函数
Process Process
// Engine 注册 Matcher 的 EngineEngine可为一系列 Matcher 添加通用 Rule 和 其他钩子
Engine *Engine
}
var (
// 所有主匹配器列表
matcherMap = make(map[string][]*Matcher, 0)
// Matcher 修改读写锁
matcherLock = sync.RWMutex{}
)
// State store the context of a matcher.
type State map[string]interface{}
func sortMatcher(typ string) {
sort.Slice(matcherMap[typ], func(i, j int) bool { // 按优先级排序
return matcherMap[typ][i].priority < matcherMap[typ][j].priority
})
}
// 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(m.Type)
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)
}
*/
// Limit 限速器
//
// postfn 当请求被拒绝时的操作
func (m *Matcher) Limit(limiterfn func(*Ctx) *rate.Limiter, postfn ...func(*Ctx)) *Matcher {
m.Rules = append(m.Rules, func(ctx *Ctx) bool {
if limiterfn(ctx).Acquire() {
return true
}
if len(postfn) > 0 {
for _, fn := range postfn {
fn(ctx)
}
}
return false
})
return m
}
// StoreMatcher store a matcher to matcher list.
func StoreMatcher(m *Matcher) *Matcher {
matcherLock.Lock()
defer matcherLock.Unlock()
matcherMap[m.Type] = append(matcherMap[m.Type], m)
sortMatcher(m.Type)
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 matcherMap[m.Type] {
if m == matcher {
matcherMap[m.Type] = append(matcherMap[m.Type][:i], matcherMap[m.Type][i+1:]...)
}
}
}
func (m *Matcher) copy() *Matcher {
return &Matcher{
Type: m.Type,
Rules: m.Rules,
Block: m.Block,
priority: m.priority,
Process: m.Process,
Temp: m.Temp,
Engine: m.Engine,
}
}
// Handle 直接处理事件
func (m *Matcher) Handle(handler Process) *Matcher {
m.Process = handler
return m
}