1
0
mirror of https://github.com/fumiama/NanoBot.git synced 2026-06-08 04:00:23 +08:00
This commit is contained in:
源文雨
2023-10-16 00:26:04 +09:00
parent 6a1019d201
commit ce34c996ef
25 changed files with 2844 additions and 8 deletions

131
context.go Normal file
View File

@@ -0,0 +1,131 @@
package nano
import (
"fmt"
"reflect"
"strings"
"sync"
)
type Ctx struct {
Event
State
Caller *Bot
Message *Message
ma *Matcher
IsToMe bool
}
// decoder 反射获取的数据
type decoder []dec
type dec struct {
index int
key string
}
// decoder 缓存
var decoderCache = sync.Map{}
// Parse 将 Ctx.State 映射到结构体
func (ctx *Ctx) Parse(model interface{}) (err error) {
var (
rv = reflect.ValueOf(model).Elem()
t = rv.Type()
modelDec decoder
)
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("parse state error: %v", r)
}
}()
d, ok := decoderCache.Load(t)
if ok {
modelDec = d.(decoder)
} else {
modelDec = decoder{}
for i := 0; i < t.NumField(); i++ {
t1 := t.Field(i)
if key, ok := t1.Tag.Lookup("zero"); ok {
modelDec = append(modelDec, dec{
index: i,
key: key,
})
}
}
decoderCache.Store(t, modelDec)
}
for _, d := range modelDec { // decoder类型非小内存无法被编译器优化为快速拷贝
rv.Field(d.index).Set(reflect.ValueOf(ctx.State[d.key]))
}
return nil
}
// CheckSession 判断会话连续性
func (ctx *Ctx) CheckSession() Rule {
msg := ctx.Value.(*Message)
return func(ctx2 *Ctx) bool {
msg2, ok := ctx.Value.(*Message)
if !ok || msg.Author == nil || msg2.Author == nil { // 确保无空
return false
}
return msg.Author.ID == msg2.Author.ID && msg.ChannelID == msg2.ChannelID
}
}
// Send 发送消息到对方
func (ctx *Ctx) Send(replytosender bool, post *MessagePost) (*Message, error) {
msg := ctx.Value.(*Message)
post.ReplyMessageID = msg.ID
if replytosender {
post.MessageReference = &MessageReference{
MessageID: msg.ID,
}
}
return ctx.Caller.PostMessageToChannel(msg.ChannelID, post)
}
// SendPlainMessage 发送纯文本消息到对方
func (ctx *Ctx) SendPlainMessage(replytosender bool, printable ...any) (*Message, error) {
msg := ctx.Value.(*Message)
post := &MessagePost{
ReplyMessageID: msg.ID,
}
if replytosender {
post.MessageReference = &MessageReference{
MessageID: msg.ID,
}
}
post.Content = fmt.Sprint(printable...)
return ctx.Caller.PostMessageToChannel(msg.ChannelID, post)
}
// SendImage 发送带图片消息到对方
func (ctx *Ctx) SendImage(file string, replytosender bool, caption ...any) (*Message, error) {
msg := ctx.Value.(*Message)
post := &MessagePost{
ReplyMessageID: msg.ID,
}
if strings.HasPrefix(file, "http") {
post.Image = file
} else {
post.ImageFile = file
}
if replytosender {
post.MessageReference = &MessageReference{
MessageID: msg.ID,
}
}
post.Content = fmt.Sprint(caption...)
return ctx.Caller.PostMessageToChannel(msg.ChannelID, post)
}
// Block 匹配成功后阻止后续触发
func (ctx *Ctx) Block() {
ctx.ma.SetBlock(true)
}
// Block 在 pre, rules, mid 阶段阻止后续触发
func (ctx *Ctx) Break() {
ctx.ma.Break = true
}