snowluma: SnowLuma (OneBot 11) Go SDK, drop-in compatible with napcat
This commit is contained in:
136
context.go
Normal file
136
context.go
Normal file
@ -0,0 +1,136 @@
|
||||
package snowluma
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Context 是交给处理函数的上下文:携带事件,并把 API 调用路由到
|
||||
// 产生该事件的连接;HTTP 上报模式下 Reply/Approve 走快速操作。
|
||||
type Context struct {
|
||||
// API 内嵌全部类型化 API 方法,调用时路由到本事件的来源连接。
|
||||
API
|
||||
Bot *Client
|
||||
Event *Event
|
||||
|
||||
quick *quickBox
|
||||
segOnce sync.Once
|
||||
segs []Segment
|
||||
segErr error
|
||||
}
|
||||
|
||||
// Call 在本事件来源的连接上执行任意 action(未收录 API 的兜底入口)。
|
||||
func (c *Context) Call(ctx context.Context, action string, params any, out any) error {
|
||||
return c.API.call.Call(ctx, action, params, out)
|
||||
}
|
||||
|
||||
// Segments 返回消息事件的消息段数组(CQ 码字符串也会被解析),结果带缓存。
|
||||
func (c *Context) Segments() []Segment {
|
||||
c.segOnce.Do(func() {
|
||||
if c.Event.Message != nil {
|
||||
c.segs, c.segErr = DecodeMessage(c.Event.Message.Message)
|
||||
}
|
||||
})
|
||||
if c.segErr != nil {
|
||||
return nil
|
||||
}
|
||||
return c.segs
|
||||
}
|
||||
|
||||
// PlainText 返回消息里所有 text 段拼接出的文本。
|
||||
func (c *Context) PlainText() string { return SegmentsText(c.Segments()) }
|
||||
|
||||
// SelfID 返回产生本事件的机器人 QQ 号。
|
||||
func (c *Context) SelfID() int64 { return c.Event.SelfID }
|
||||
|
||||
// IsGroup 判断是否群聊消息事件。
|
||||
func (c *Context) IsGroup() bool {
|
||||
return c.Event.Message != nil && c.Event.Message.MessageType == "group"
|
||||
}
|
||||
|
||||
// IsPrivate 判断是否私聊消息事件。
|
||||
func (c *Context) IsPrivate() bool {
|
||||
return c.Event.Message != nil && c.Event.Message.MessageType == "private"
|
||||
}
|
||||
|
||||
// IsSelfMessage 判断是否 bot 自己发出的消息(message_sent)。
|
||||
func (c *Context) IsSelfMessage() bool { return c.Event.PostType == "message_sent" }
|
||||
|
||||
// HasAtMe 判断消息是否 @ 了机器人(不含 @全体)。
|
||||
func (c *Context) HasAtMe() bool {
|
||||
me := c.SelfID()
|
||||
for _, s := range c.Segments() {
|
||||
if s.Type == "at" && intOf(s.Data["qq"]) == me {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Reply 回复当前消息:群聊发 send_group_msg,私聊发 send_private_msg。
|
||||
// HTTP 上报模式下改为随响应返回快速操作 reply(此时 message_id 返回 0)。
|
||||
func (c *Context) Reply(message ...Segment) (MessageID, error) {
|
||||
ev := c.Event
|
||||
if ev.Message == nil {
|
||||
return 0, errReplyNotMessage
|
||||
}
|
||||
if c.quick != nil {
|
||||
c.quick.set("reply", message)
|
||||
return 0, nil
|
||||
}
|
||||
if ev.Message.MessageType == "group" {
|
||||
return c.SendGroupMsg(nil, ev.Message.GroupID, message...)
|
||||
}
|
||||
return c.SendPrivateMsg(nil, ev.Message.UserID, message...)
|
||||
}
|
||||
|
||||
// ReplyText 回复一段纯文本。
|
||||
func (c *Context) ReplyText(text string) (MessageID, error) { return c.Reply(Text(text)) }
|
||||
|
||||
// Recall 撤回触发本事件的那条消息(需要 bot 有管理员权限/为私聊双方)。
|
||||
func (c *Context) Recall() error {
|
||||
if c.Event.Message == nil {
|
||||
return errReplyNotMessage
|
||||
}
|
||||
return c.DeleteMsg(nil, c.Event.Message.MessageID)
|
||||
}
|
||||
|
||||
// Approve 同意当前好友/群请求。
|
||||
func (c *Context) Approve() error { return c.approveRequest(true, "") }
|
||||
|
||||
// Reject 拒绝当前好友/群请求,reason 为拒绝理由(好友请求则为验证备注)。
|
||||
func (c *Context) Reject(reason string) error { return c.approveRequest(false, reason) }
|
||||
|
||||
func (c *Context) approveRequest(approve bool, text string) error {
|
||||
ev := c.Event
|
||||
if ev.Request == nil {
|
||||
return errRequestOnly
|
||||
}
|
||||
if c.quick != nil {
|
||||
c.quick.set("approve", approve)
|
||||
if text != "" {
|
||||
if ev.Request.RequestType == "friend" {
|
||||
c.quick.set("remark", text)
|
||||
} else {
|
||||
c.quick.set("reason", text)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if ev.Request.RequestType == "friend" {
|
||||
return c.SetFriendAddRequest(nil, ev.Request.Flag, approve, text)
|
||||
}
|
||||
return c.SetGroupAddRequest(nil, ev.Request.Flag, ev.Request.SubType, approve, text)
|
||||
}
|
||||
|
||||
var (
|
||||
errReplyNotMessage = &frameError{"reply is only available for message events"}
|
||||
errRequestOnly = &frameError{"approve/reject is only available for request events"}
|
||||
)
|
||||
|
||||
type frameError struct{ msg string }
|
||||
|
||||
func (e *frameError) Error() string { return "snowluma: " + e.msg }
|
||||
|
||||
// MessageID 是 OneBot 消息 ID。
|
||||
type MessageID = int64
|
||||
Reference in New Issue
Block a user