Files
napcat/event.go

161 lines
4.8 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 napcat
import (
"encoding/json"
"fmt"
)
// Event 是收到的一条 OneBot 事件。按 PostType 取对应的子事件指针。
type Event struct {
Time int64 `json:"time"`
SelfID int64 `json:"self_id"`
PostType string `json:"post_type"`
Raw json.RawMessage `json:"-"`
Message *MessageEvent // post_type == "message" / "message_sent"
Notice *NoticeEvent // post_type == "notice"
Request *RequestEvent // post_type == "request"
Meta *MetaEvent // post_type == "meta_event"
}
type BaseEvent struct {
Time int64 `json:"time"`
SelfID int64 `json:"self_id"`
PostType string `json:"post_type"`
}
// MessageEvent 是私聊/群聊消息事件。bot 自己发出的消息以 message_sent 上报。
type MessageEvent struct {
BaseEvent
MessageType string `json:"message_type"` // private | group
SubType string `json:"sub_type"` // friend/group/normal/anonymous/notice
MessageID int64 `json:"message_id"`
UserID int64 `json:"user_id"`
GroupID int64 `json:"group_id"`
TargetID int64 `json:"target_id"` // 群临时会话目标
TempSource int64 `json:"temp_source"` // 群临时会话来源
Message json.RawMessage `json:"message"` // 段数组或 CQ 码字符串
RawMessage string `json:"raw_message"`
Font int64 `json:"font"`
Sender Sender `json:"sender"`
}
// NoticeEvent 是通知事件(撤回、入群、禁言、戳一戳等)。
// 未映射的字段收进 Extra,避免 NapCat 增加字段时丢数据。
type NoticeEvent struct {
BaseEvent
NoticeType string `json:"notice_type"`
SubType string `json:"sub_type"`
GroupID int64 `json:"group_id"`
UserID int64 `json:"user_id"`
OperatorID int64 `json:"operator_id"`
TargetID int64 `json:"target_id"`
MessageID int64 `json:"message_id"`
Duration int64 `json:"duration"` // 禁言时长(秒)
File *FileNotice `json:"file"`
HonorType string `json:"honor_type"`
CardNew string `json:"card_new"`
CardOld string `json:"card_old"`
Extra map[string]any `json:"-"`
}
func (n *NoticeEvent) UnmarshalJSON(data []byte) error {
type alias NoticeEvent
var a alias
if err := json.Unmarshal(data, &a); err != nil {
return err
}
*n = NoticeEvent(a)
var m map[string]any
if err := json.Unmarshal(data, &m); err == nil {
for k := range knownNoticeKeys {
delete(m, k)
}
if len(m) > 0 {
n.Extra = m
}
}
return nil
}
var knownNoticeKeys = map[string]struct{}{
"time": {}, "self_id": {}, "post_type": {}, "notice_type": {}, "sub_type": {},
"group_id": {}, "user_id": {}, "operator_id": {}, "target_id": {},
"message_id": {}, "duration": {}, "file": {}, "honor_type": {},
"card_new": {}, "card_old": {},
}
// FileNotice 是群文件上传/离线文件通知里的文件信息。
type FileNotice struct {
ID string `json:"id"`
Name string `json:"name"`
Size int64 `json:"size"`
BusID int64 `json:"busid"`
}
// RequestEvent 是好友/群请求事件(加好友、加群、被邀请入群)。
type RequestEvent struct {
BaseEvent
RequestType string `json:"request_type"` // friend | group
SubType string `json:"sub_type"` // group 时为 add/invite
UserID int64 `json:"user_id"`
GroupID int64 `json:"group_id"`
Comment string `json:"comment"`
Flag string `json:"flag"`
}
// MetaEvent 是元事件(连接生命周期与心跳)。
type MetaEvent struct {
BaseEvent
MetaType string `json:"meta_event_type"` // lifecycle | heartbeat
SubType string `json:"sub_type"` // connect/enable/disable
HeartbeatInterval int64 `json:"interval"`
Status *Status `json:"status,omitempty"`
}
func decodeEvent(data []byte) (*Event, error) {
var probe struct {
PostType string `json:"post_type"`
}
if err := json.Unmarshal(data, &probe); err != nil {
return nil, err
}
if probe.PostType == "" {
return nil, fmt.Errorf("napcat: missing post_type: %s", truncate(data))
}
ev := &Event{Raw: append(json.RawMessage(nil), data...)}
var base BaseEvent
_ = json.Unmarshal(data, &base)
ev.Time, ev.SelfID, ev.PostType = base.Time, base.SelfID, probe.PostType
switch probe.PostType {
case "message", "message_sent":
var m MessageEvent
if err := json.Unmarshal(data, &m); err != nil {
return nil, err
}
ev.Message = &m
case "notice":
var n NoticeEvent
if err := json.Unmarshal(data, &n); err != nil {
return nil, err
}
ev.Notice = &n
case "request":
var r RequestEvent
if err := json.Unmarshal(data, &r); err != nil {
return nil, err
}
ev.Request = &r
case "meta_event":
var m MetaEvent
if err := json.Unmarshal(data, &m); err != nil {
return nil, err
}
ev.Meta = &m
}
return ev, nil
}