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  }