github.com/fumiama/NanoBot@v0.0.0-20231122134259-c22d8183efca/future.go (about) 1 package nano 2 3 // FutureEvent 是 ZeroBot 交互式的核心,用于异步获取指定事件 4 type FutureEvent struct { 5 Type string 6 Priority int 7 Rule []Rule 8 Block bool 9 } 10 11 // NewFutureEvent 创建一个FutureEvent, 并返回其指针 12 func NewFutureEvent(Type string, Priority int, Block bool, rule ...Rule) *FutureEvent { 13 return &FutureEvent{ 14 Type: Type, 15 Priority: Priority, 16 Rule: rule, 17 Block: Block, 18 } 19 } 20 21 // FutureEvent 返回一个 FutureEvent 实例指针,用于获取满足 Rule 的 未来事件 22 func (m *Matcher) FutureEvent(Type string, rule ...Rule) *FutureEvent { 23 return &FutureEvent{ 24 Type: Type, 25 Priority: m.priority, 26 Block: m.Block, 27 Rule: rule, 28 } 29 } 30 31 // Next 返回一个 chan 用于接收下一个指定事件 32 // 33 // 该 chan 必须接收,如需手动取消监听,请使用 Repeat 方法 34 func (n *FutureEvent) Next() <-chan *Ctx { 35 ch := make(chan *Ctx, 1) 36 StoreTempMatcher(&Matcher{ 37 Type: n.Type, 38 Block: n.Block, 39 priority: n.Priority, 40 Rules: n.Rule, 41 Engine: defaultEngine, 42 Process: func(ctx *Ctx) { 43 ch <- ctx 44 close(ch) 45 }, 46 }) 47 return ch 48 } 49 50 // Repeat 返回一个 chan 用于接收无穷个指定事件,和一个取消监听的函数 51 // 52 // 如果没有取消监听,将不断监听指定事件 53 func (n *FutureEvent) Repeat() (recv <-chan *Ctx, cancel func()) { 54 ch, done := make(chan *Ctx, 1), make(chan struct{}) 55 go func() { 56 defer close(ch) 57 in := make(chan *Ctx, 1) 58 matcher := StoreMatcher(&Matcher{ 59 Type: n.Type, 60 Block: n.Block, 61 priority: n.Priority, 62 Rules: n.Rule, 63 Engine: defaultEngine, 64 Process: func(ctx *Ctx) { 65 in <- ctx 66 }, 67 }) 68 for { 69 select { 70 case e := <-in: 71 ch <- e 72 case <-done: 73 matcher.Delete() 74 close(in) 75 return 76 } 77 } 78 }() 79 return ch, func() { 80 close(done) 81 } 82 } 83 84 // Take 基于 Repeat 封装,返回一个 chan 接收指定数量的事件 85 // 86 // 该 chan 对象必须接收,否则将有 goroutine 泄漏,如需手动取消请使用 Repeat 87 func (n *FutureEvent) Take(num int) <-chan *Ctx { 88 recv, cancel := n.Repeat() 89 ch := make(chan *Ctx, num) 90 go func() { 91 defer close(ch) 92 for i := 0; i < num; i++ { 93 ch <- <-recv 94 } 95 cancel() 96 }() 97 return ch 98 }