From 67670778670ac2c596ce925c6f1c55e36ce7bd3e Mon Sep 17 00:00:00 2001 From: lixiangwuxian Date: Mon, 16 Jun 2025 10:49:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=8C=96=E6=B6=88=E6=81=AFjson=E8=A7=A3=E6=9E=90=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E8=A1=A5=E5=85=85=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- action/action.go | 6 +++--- handler/auth/auth.go | 4 ++-- handler/beatleader/beatleader.go | 26 +++++++++++------------ handler/drawback/drawback.go | 4 ++-- handler/getweb/getweb.go | 6 +++--- handler/handler.go | 24 ++------------------- handler/help/help.go | 6 +++--- handler/raid/raid.go | 16 +++++++------- handler/scoresaber/score.go | 26 +++++++++++------------ handler/xibao/xibao.go | 18 ++++++++-------- model/message.go | 13 +++++++----- model/upstream_message.go | 10 ++++----- {message => qq_message}/at.go | 8 +++++-- {message => qq_message}/const.go | 2 +- {message => qq_message}/contact.go | 8 +++++-- {message => qq_message}/cq_message.go | 27 ++++++++++++++---------- {message => qq_message}/face.go | 8 +++++-- {message => qq_message}/file.go | 8 +++++-- {message => qq_message}/forward.go | 14 ++++++++++--- {message => qq_message}/image.go | 8 +++++-- {message => qq_message}/json.go | 8 +++++-- {message => qq_message}/lightapp.go | 8 +++++-- {message => qq_message}/location.go | 8 +++++-- {message => qq_message}/mface.go | 8 +++++-- {message => qq_message}/music.go | 8 +++++-- {message => qq_message}/record.go | 8 +++++-- {message => qq_message}/reply.go | 8 +++++-- {message => qq_message}/share.go | 8 +++++-- {message => qq_message}/text.go | 8 +++++-- {message => qq_message}/video.go | 8 +++++-- service/beatleader/model.go | 8 +++---- service/scoresaber/model.go | 14 ++++++------- service/xibao/image_gen.go | 4 ++-- util/message.go | 6 +++--- util/panic_report.go | 30 +++++++++++++++++++++++++++ ws_client/client.go | 17 +++++++++++---- 36 files changed, 248 insertions(+), 153 deletions(-) rename {message => qq_message}/at.go (86%) rename {message => qq_message}/const.go (98%) rename {message => qq_message}/contact.go (87%) rename {message => qq_message}/cq_message.go (69%) rename {message => qq_message}/face.go (85%) rename {message => qq_message}/file.go (91%) rename {message => qq_message}/forward.go (88%) rename {message => qq_message}/image.go (95%) rename {message => qq_message}/json.go (85%) rename {message => qq_message}/lightapp.go (86%) rename {message => qq_message}/location.go (90%) rename {message => qq_message}/mface.go (91%) rename {message => qq_message}/music.go (93%) rename {message => qq_message}/record.go (88%) rename {message => qq_message}/reply.go (87%) rename {message => qq_message}/share.go (90%) rename {message => qq_message}/text.go (81%) rename {message => qq_message}/video.go (90%) create mode 100644 util/panic_report.go diff --git a/action/action.go b/action/action.go index 475141a..95011ae 100644 --- a/action/action.go +++ b/action/action.go @@ -8,8 +8,8 @@ import ( "sync" "time" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "github.com/gorilla/websocket" ) @@ -39,9 +39,9 @@ func (am *actionManager) SendMsg(reply *model.Reply) error { am.sendMtx.Lock() defer am.sendMtx.Unlock() if reply.ReferOriginMsg { - replyMsg := message.ReplyMessage{ + replyMsg := qq_message.ReplyMessage{ Type: "reply", - Data: message.ReplyMessageData{ + Data: qq_message.ReplyMessageData{ ID: int(reply.FromMsg.OriginMsgId), }, } diff --git a/handler/auth/auth.go b/handler/auth/auth.go index 713e2fb..836d04a 100644 --- a/handler/auth/auth.go +++ b/handler/auth/auth.go @@ -8,8 +8,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/auth" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" ) func init() { @@ -37,7 +37,7 @@ func setUserLevel(msg model.Message) (reply *model.Reply) { } } userText := tokens[1] - atMsg := message.AtMessage{} + atMsg := qq_message.AtMessage{} if err := atMsg.ParseMessage(userText); err == nil { userText = atMsg.Data.QQ } diff --git a/handler/beatleader/beatleader.go b/handler/beatleader/beatleader.go index 091338d..78d135c 100644 --- a/handler/beatleader/beatleader.go +++ b/handler/beatleader/beatleader.go @@ -10,8 +10,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/action" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/service/beatleader" "git.lxtend.com/lixiangwuxian/qqbot/service/scoresaber" "git.lxtend.com/lixiangwuxian/qqbot/util" @@ -219,9 +219,9 @@ func getMyBLPic(msg model.Message) (reply *model.Reply) { resultStr = data.LastDiffToImage(*data, onlyFirstFrame) } - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: resultStr, }, } @@ -305,15 +305,15 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { } wg.Wait() for _, record := range records { - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: coverImageMap[record.SongHash], }, } - textMsg := message.TextMessage{ + textMsg := qq_message.TextMessage{ Type: "text", - Data: message.TextMessageData{ + Data: qq_message.TextMessageData{ Text: record.ToString(), }, } @@ -332,9 +332,9 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { if len(records) > 5 { nodeMsg := util.NewSelfNodeMessage(append( []any{ - &message.TextMessage{ + &qq_message.TextMessage{ Type: "text", - Data: message.TextMessageData{ + Data: qq_message.TextMessageData{ Text: "玩家 " + userName + " 的" + strconv.Itoa(recordCount) + "条最近记录为:\n", }, }, @@ -353,9 +353,9 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { return &model.Reply{ ReplyMsg: append( []any{ - message.TextMessage{ + qq_message.TextMessage{ Type: "text", - Data: message.TextMessageData{ + Data: qq_message.TextMessageData{ Text: "玩家 " + userName + " 的" + strconv.Itoa(recordCount) + "条最近记录为:\n", }, }, @@ -368,9 +368,9 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { } func screenShotBL(msg model.Message) (reply *model.Reply) { - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: "file:///tmp/qqbot/" + beatleader.GetBLPicture(strconv.Itoa(int(msg.UserId))), }, } diff --git a/handler/drawback/drawback.go b/handler/drawback/drawback.go index 6817f2a..df405a2 100644 --- a/handler/drawback/drawback.go +++ b/handler/drawback/drawback.go @@ -4,8 +4,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/action" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" ) func init() { @@ -14,7 +14,7 @@ func init() { } func drawback(msg model.Message) *model.Reply { - msgIdToDrawback := message.ReplyMessage{} + msgIdToDrawback := qq_message.ReplyMessage{} if err := msgIdToDrawback.ParseMessage(msg.RawMsg); err != nil { return &model.Reply{ ReplyMsg: "", diff --git a/handler/getweb/getweb.go b/handler/getweb/getweb.go index 1692845..66f3368 100644 --- a/handler/getweb/getweb.go +++ b/handler/getweb/getweb.go @@ -1,8 +1,8 @@ package getweb import ( - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/util" ) @@ -25,9 +25,9 @@ func getweb(msg model.Message) (reply *model.Reply) { FromMsg: msg, } } - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: "file:///tmp/qqbot/getweb/url.png", }, } diff --git a/handler/handler.go b/handler/handler.go index c00cf4d..bd7cd6e 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -1,18 +1,14 @@ package handler import ( - "fmt" "log" "regexp" - "runtime/debug" "strings" - "time" - "git.lxtend.com/lixiangwuxian/qqbot/action" "git.lxtend.com/lixiangwuxian/qqbot/auth" - "git.lxtend.com/lixiangwuxian/qqbot/config" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/util" ) var allGroupHandlers = make(map[string]model.HandlerInfo[model.Handler]) @@ -91,23 +87,7 @@ func RegisterRegexHandler(trigger string, handler model.Handler, level constants } func MsgInHandler(msg model.Message) (reply *model.Reply) { - defer func() { - if r := recover(); r != nil { - stack := debug.Stack() - errMsg := fmt.Sprintf("[%s] Panic recovered:\nError: %v\nStack Trace:\n%s\n", - time.Now().Format("2006-01-02 15:04:05"), r, stack) - log.Print(errMsg) - action.ActionManager.SendMsg(&model.Reply{ - ReplyMsg: "出现了Panic:\n" + errMsg, - ReferOriginMsg: false, - FromMsg: model.Message{ - GroupInfo: model.GroupInfo{ - GroupId: config.ConfigManager.GetConfig().Management.ReportGroup, - }, - }, - }) - } - }() + defer util.ReportPanicToDev() if msg.RawMsg != "" { log.Default().Printf("\033[31m↓\033[0m:%v", msg) } else { diff --git a/handler/help/help.go b/handler/help/help.go index 5c37914..19453ec 100644 --- a/handler/help/help.go +++ b/handler/help/help.go @@ -7,8 +7,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/action" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/util" ) @@ -32,9 +32,9 @@ func help(msg model.Message) *model.Reply { helpInfo += "\n" + v.Trigger + " : " + v.Inform } } - textMsg := message.NewTextMessage() + textMsg := qq_message.NewTextMessage() textMsg.Data.Text = helpInfo - nodeMsg := message.NewNodeMessage() + nodeMsg := qq_message.NewNodeMessage() loginAccountInfo, err := action.GetLoginAccountInfo() if err != nil { log.Println("GetLoginAccountInfo error:", err) diff --git a/handler/raid/raid.go b/handler/raid/raid.go index 32a40fb..054f31c 100644 --- a/handler/raid/raid.go +++ b/handler/raid/raid.go @@ -13,8 +13,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/config" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" ) func init() { @@ -106,7 +106,7 @@ func sendAlertMessage(alertMsgs []string) { return } - nodes := []message.NodeMessage{} + nodes := []qq_message.NodeMessage{} selfInfo, err := action.GetLoginAccountInfo() if err != nil { log.Println("获取登录账号信息失败:", err) @@ -115,8 +115,8 @@ func sendAlertMessage(alertMsgs []string) { userId := strconv.FormatInt(int64(selfInfo.Data.UserID), 10) nickname := selfInfo.Data.Nickname for _, alertMsg := range alertMsgs { - textMsg := message.NewTextMessage().ParseMessage(alertMsg) - nodes = append(nodes, *message.NewNodeMessage().ParseMessage(userId, nickname, []any{textMsg})) + textMsg := qq_message.NewTextMessage().ParseMessage(alertMsg) + nodes = append(nodes, *qq_message.NewNodeMessage().ParseMessage(userId, nickname, []any{textMsg})) } action.ActionManager.SendForward(&model.Reply{ @@ -143,7 +143,7 @@ func RaidHandler(msg model.Message) (reply *model.Reply) { } } - nodes := []message.NodeMessage{} + nodes := []qq_message.NodeMessage{} selfInfo, err := action.GetLoginAccountInfo() if err != nil { log.Println("获取登录账号信息失败:", err) @@ -151,10 +151,10 @@ func RaidHandler(msg model.Message) (reply *model.Reply) { } userId := strconv.FormatInt(int64(selfInfo.Data.UserID), 10) nickname := selfInfo.Data.Nickname - nodes = append(nodes, *message.NewNodeMessage().ParseMessage(userId, nickname, []any{message.NewTextMessage().ParseMessage("阵列信息:")})) + nodes = append(nodes, *qq_message.NewNodeMessage().ParseMessage(userId, nickname, []any{qq_message.NewTextMessage().ParseMessage("阵列信息:")})) for _, diskInfo := range diskInfoList { - textMsg := message.NewTextMessage().ParseMessage(diskInfo.String()) - nodes = append(nodes, *message.NewNodeMessage().ParseMessage(userId, nickname, []any{textMsg})) + textMsg := qq_message.NewTextMessage().ParseMessage(diskInfo.String()) + nodes = append(nodes, *qq_message.NewNodeMessage().ParseMessage(userId, nickname, []any{textMsg})) } action.ActionManager.SendForward(&model.Reply{ diff --git a/handler/scoresaber/score.go b/handler/scoresaber/score.go index dae1f02..ca441f1 100644 --- a/handler/scoresaber/score.go +++ b/handler/scoresaber/score.go @@ -10,8 +10,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/action" "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/service/scoresaber" "git.lxtend.com/lixiangwuxian/qqbot/util" ) @@ -53,9 +53,9 @@ func getBS50(msg model.Message) (reply *model.Reply) { FromMsg: msg, } } - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: util.GenTempFilePath("bs50.png"), }, } @@ -246,9 +246,9 @@ func getMySSPic(msg model.Message) (reply *model.Reply) { resultStr = data.LastDiffToImage(*data, onlyFirstFrame) } - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: resultStr, }, } @@ -332,15 +332,15 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { } wg.Wait() for _, record := range records { - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: coverImageMap[record.SongHash], }, } - textMsg := message.TextMessage{ + textMsg := qq_message.TextMessage{ Type: "text", - Data: message.TextMessageData{ + Data: qq_message.TextMessageData{ Text: record.ToString(), }, } @@ -359,9 +359,9 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { if len(records) > 5 { nodeMsg := util.NewSelfNodeMessage(append( []any{ - &message.TextMessage{ + &qq_message.TextMessage{ Type: "text", - Data: message.TextMessageData{ + Data: qq_message.TextMessageData{ Text: "玩家 " + userName + " 的" + strconv.Itoa(recordCount) + "条最近记录为:\n", }, }, @@ -380,9 +380,9 @@ func getMyRecentScore(msg model.Message) (reply *model.Reply) { return &model.Reply{ ReplyMsg: append( []any{ - message.TextMessage{ + qq_message.TextMessage{ Type: "text", - Data: message.TextMessageData{ + Data: qq_message.TextMessageData{ Text: "玩家 " + userName + " 的" + strconv.Itoa(recordCount) + "条最近记录为:", }, }, diff --git a/handler/xibao/xibao.go b/handler/xibao/xibao.go index 8a15097..ad50b2f 100644 --- a/handler/xibao/xibao.go +++ b/handler/xibao/xibao.go @@ -6,8 +6,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" - "git.lxtend.com/lixiangwuxian/qqbot/message" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/service/xibao" "git.lxtend.com/lixiangwuxian/qqbot/util" "github.com/google/uuid" @@ -34,9 +34,9 @@ func xiBao(msg model.Message) (reply *model.Reply) { } } xibao.GenerateCongratulationImageNew(tokens[1], "./resource/xibao_background.png", filePath, true) - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: "file://" + filePath, }, } @@ -52,9 +52,9 @@ func xiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { fileName := uuid.New().String() filePath := util.GenTempFilePath(fmt.Sprintf("%s.png", fileName)) xibao.GenerateCongratulationImageNew(msg.RawMsg, "./resource/xibao_background.png", filePath, true) - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: "file://" + filePath, }, } @@ -79,9 +79,9 @@ func beiBao(msg model.Message) (reply *model.Reply) { } } xibao.GenerateCongratulationImageNew(tokens[1], "./resource/beibao_background.png", filePath, false) - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: "file://" + filePath, }, } @@ -97,9 +97,9 @@ func beiBaoTemp(msg model.Message) (reply *model.Reply, isTrigger bool) { fileName := uuid.New().String() filePath := util.GenTempFilePath(fmt.Sprintf("%s.png", fileName)) xibao.GenerateCongratulationImageNew(msg.RawMsg, "./resource/beibao_background.png", filePath, false) - imageMsg := message.ImageMessage{ + imageMsg := qq_message.ImageMessage{ Type: "image", - Data: message.ImageMessageData{ + Data: qq_message.ImageMessageData{ File: "file://" + filePath, }, } diff --git a/model/message.go b/model/message.go index 69255f5..f9293fe 100644 --- a/model/message.go +++ b/model/message.go @@ -1,11 +1,14 @@ package model +import "git.lxtend.com/lixiangwuxian/qqbot/qq_message" + type Message struct { - UserId int64 `json:"userId"` - GroupInfo GroupInfo `json:"groupInfo"` - OriginMsgId int32 `json:"originMsgId"` - RawMsg string `json:"msg"` - UserNickName string `json:"userNickName"` + UserId int64 `json:"userId"` + GroupInfo GroupInfo `json:"groupInfo"` + OriginMsgId int32 `json:"originMsgId"` + RawMsg string `json:"msg"` + StructuredMsg []qq_message.QQMessage `json:"structuredMsg"` + UserNickName string `json:"userNickName"` } type GroupInfo struct { diff --git a/model/upstream_message.go b/model/upstream_message.go index bee178e..bb84087 100644 --- a/model/upstream_message.go +++ b/model/upstream_message.go @@ -71,11 +71,11 @@ type EventMessage struct { SubType string `json:"sub_type"` MessageID int32 `json:"message_id"` UserID int64 `json:"user_id"` - // Message string `json:"message"` //just ignore it - RawMessage string `json:"raw_message"` - Font int32 `json:"font"` - Sender Sender `json:"sender"` - GroupID int64 `json:"group_id"` + Message string `json:"message"` //just ignore it + RawMessage string `json:"raw_message"` + Font int32 `json:"font"` + Sender Sender `json:"sender"` + GroupID int64 `json:"group_id"` } type Sender struct { diff --git a/message/at.go b/qq_message/at.go similarity index 86% rename from message/at.go rename to qq_message/at.go index a337f00..ff80930 100644 --- a/message/at.go +++ b/qq_message/at.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -17,7 +17,7 @@ type AtMessageData struct { } func init() { - RegisterMessageType(TypeAt, func() CQMessage { + RegisterMessageType(TypeAt, func() QQMessage { return NewAtMessage() }) } @@ -26,6 +26,10 @@ func NewAtMessage() *AtMessage { return &AtMessage{Type: TypeAt} } +func (msg *AtMessage) GetMessageType() string { + return TypeAt +} + func (msg *AtMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/const.go b/qq_message/const.go similarity index 98% rename from message/const.go rename to qq_message/const.go index 53f853f..9f28ecc 100644 --- a/message/const.go +++ b/qq_message/const.go @@ -1,4 +1,4 @@ -package message +package qq_message // 消息类型常量定义 const ( diff --git a/message/contact.go b/qq_message/contact.go similarity index 87% rename from message/contact.go rename to qq_message/contact.go index 46ec6a3..7fa63b2 100644 --- a/message/contact.go +++ b/qq_message/contact.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -18,7 +18,7 @@ type ContactMessageData struct { } func init() { - RegisterMessageType(TypeContact, func() CQMessage { + RegisterMessageType(TypeContact, func() QQMessage { return NewContactMessage() }) } @@ -27,6 +27,10 @@ func NewContactMessage() *ContactMessage { return &ContactMessage{Type: TypeContact} } +func (msg *ContactMessage) GetMessageType() string { + return TypeContact +} + func (msg *ContactMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/cq_message.go b/qq_message/cq_message.go similarity index 69% rename from message/cq_message.go rename to qq_message/cq_message.go index 1bfb9ce..70ee66a 100644 --- a/message/cq_message.go +++ b/qq_message/cq_message.go @@ -1,15 +1,16 @@ -package message +package qq_message import ( "encoding/json" "fmt" + "log" "sync" ) -// CQMessage 接口定义了所有 CQ 消息必须实现的方法 -type CQMessage interface { +// QQMessage 接口定义了所有 CQ 消息必须实现的方法 +type QQMessage interface { ToCQString() string - // ParseMessage(data string) error + GetMessageType() string } // RawMessage 用于初始解析 JSON 的通用结构 @@ -19,7 +20,7 @@ type RawMessage struct { } // messageFactory 用于创建具体的消息实例 -type messageFactory func() CQMessage +type messageFactory func() QQMessage var ( messageFactories = make(map[string]messageFactory) @@ -34,7 +35,7 @@ func RegisterMessageType(messageType string, factory messageFactory) { } // CreateMessage 根据类型创建具体的消息实例 -func CreateMessage(messageType string) (CQMessage, error) { +func CreateMessage(messageType string) (QQMessage, error) { factoryMutex.RLock() factory, exists := messageFactories[messageType] factoryMutex.RUnlock() @@ -47,26 +48,30 @@ func CreateMessage(messageType string) (CQMessage, error) { } // ParseCQMessages 解析消息数组 -func ParseCQMessages(jsonData []byte) ([]CQMessage, error) { +func ParseCQMessages(jsonData []byte) ([]QQMessage, error) { var rawMessages []RawMessage if err := json.Unmarshal(jsonData, &rawMessages); err != nil { return nil, fmt.Errorf("解析 JSON 数组失败: %v", err) } - messages := make([]CQMessage, 0, len(rawMessages)) + messages := make([]QQMessage, 0, len(rawMessages)) for _, raw := range rawMessages { msg, err := CreateMessage(raw.Type) if err != nil { - return nil, err + log.Println("创建消息失败:", err) + continue } // 使用类型断言获取具体类型的Data字段 if v, ok := msg.(interface{ SetData(json.RawMessage) error }); ok { if err := v.SetData(raw.Data); err != nil { - return nil, fmt.Errorf("解析消息数据失败: %v", err) + // return nil, fmt.Errorf("解析消息数据失败: %v", err) + log.Println("解析消息数据失败:", err) + continue } } else { - return nil, fmt.Errorf("消息类型 %s 未实现 SetData 方法", raw.Type) + log.Printf("消息类型 %s 未实现 SetData 方法\n", raw.Type) + continue } messages = append(messages, msg) diff --git a/message/face.go b/qq_message/face.go similarity index 85% rename from message/face.go rename to qq_message/face.go index 467dfa8..2c5043c 100644 --- a/message/face.go +++ b/qq_message/face.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -17,7 +17,7 @@ type FaceMessageData struct { } func init() { - RegisterMessageType(TypeFace, func() CQMessage { + RegisterMessageType(TypeFace, func() QQMessage { return NewFaceMessage() }) } @@ -26,6 +26,10 @@ func NewFaceMessage() *FaceMessage { return &FaceMessage{Type: TypeFace} } +func (msg *FaceMessage) GetMessageType() string { + return TypeFace +} + func (msg *FaceMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/file.go b/qq_message/file.go similarity index 91% rename from message/file.go rename to qq_message/file.go index 10b7888..9adde35 100644 --- a/message/file.go +++ b/qq_message/file.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -23,7 +23,7 @@ type FileMessageData struct { } func init() { - RegisterMessageType(TypeFile, func() CQMessage { + RegisterMessageType(TypeFile, func() QQMessage { return NewFileMessage() }) } @@ -32,6 +32,10 @@ func NewFileMessage() *FileMessage { return &FileMessage{Type: TypeFile} } +func (msg *FileMessage) GetMessageType() string { + return TypeFile +} + func (msg *FileMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/forward.go b/qq_message/forward.go similarity index 88% rename from message/forward.go rename to qq_message/forward.go index ce18d2f..83fc417 100644 --- a/message/forward.go +++ b/qq_message/forward.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -31,10 +31,10 @@ type NodeMessageData struct { } func init() { - RegisterMessageType(TypeForward, func() CQMessage { + RegisterMessageType(TypeForward, func() QQMessage { return NewForwardMessage() }) - RegisterMessageType(TypeNode, func() CQMessage { + RegisterMessageType(TypeNode, func() QQMessage { return NewNodeMessage() }) } @@ -43,6 +43,10 @@ func NewForwardMessage() *ForwardMessage { return &ForwardMessage{Type: TypeForward} } +func (msg *ForwardMessage) GetMessageType() string { + return TypeForward +} + // ForwardMessage methods func (msg *ForwardMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) @@ -52,6 +56,10 @@ func NewNodeMessage() *NodeMessage { return &NodeMessage{Type: TypeNode} } +func (msg *NodeMessage) GetMessageType() string { + return TypeNode +} + func (msg *ForwardMessage) ToCQString() string { return fmt.Sprintf("[CQ:forward,id=%s]", msg.Data.ID) } diff --git a/message/image.go b/qq_message/image.go similarity index 95% rename from message/image.go rename to qq_message/image.go index 848a151..5bbee6c 100644 --- a/message/image.go +++ b/qq_message/image.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -27,7 +27,7 @@ type ImageMessageData struct { } func init() { - RegisterMessageType(TypeImage, func() CQMessage { + RegisterMessageType(TypeImage, func() QQMessage { return NewImageMessage() }) } @@ -39,6 +39,10 @@ func NewImageMessage() *ImageMessage { } } +func (msg *ImageMessage) GetMessageType() string { + return TypeImage +} + func (msg *ImageMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/json.go b/qq_message/json.go similarity index 85% rename from message/json.go rename to qq_message/json.go index 9beda9a..0ac341d 100644 --- a/message/json.go +++ b/qq_message/json.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -17,7 +17,7 @@ type JsonMessageData struct { } func init() { - RegisterMessageType(TypeJson, func() CQMessage { + RegisterMessageType(TypeJson, func() QQMessage { return NewJsonMessage() }) } @@ -26,6 +26,10 @@ func NewJsonMessage() *JsonMessage { return &JsonMessage{Type: TypeJson} } +func (msg *JsonMessage) GetMessageType() string { + return TypeJson +} + func (msg *JsonMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/lightapp.go b/qq_message/lightapp.go similarity index 86% rename from message/lightapp.go rename to qq_message/lightapp.go index c177468..8f82bd0 100644 --- a/message/lightapp.go +++ b/qq_message/lightapp.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -17,7 +17,7 @@ type LightappMessageData struct { } func init() { - RegisterMessageType(TypeLightapp, func() CQMessage { + RegisterMessageType(TypeLightapp, func() QQMessage { return NewLightappMessage() }) } @@ -26,6 +26,10 @@ func NewLightappMessage() *LightappMessage { return &LightappMessage{Type: TypeLightapp} } +func (msg *LightappMessage) GetMessageType() string { + return TypeLightapp +} + func (msg *LightappMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/location.go b/qq_message/location.go similarity index 90% rename from message/location.go rename to qq_message/location.go index 671b4a5..dd7691c 100644 --- a/message/location.go +++ b/qq_message/location.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -20,7 +20,7 @@ type LocationMessageData struct { } func init() { - RegisterMessageType(TypeLocation, func() CQMessage { + RegisterMessageType(TypeLocation, func() QQMessage { return NewLocationMessage() }) } @@ -29,6 +29,10 @@ func NewLocationMessage() *LocationMessage { return &LocationMessage{Type: TypeLocation} } +func (msg *LocationMessage) GetMessageType() string { + return TypeLocation +} + func (msg *LocationMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/mface.go b/qq_message/mface.go similarity index 91% rename from message/mface.go rename to qq_message/mface.go index e345f2a..f07799c 100644 --- a/message/mface.go +++ b/qq_message/mface.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -20,7 +20,7 @@ type MfaceMessageData struct { } func init() { - RegisterMessageType(TypeMface, func() CQMessage { + RegisterMessageType(TypeMface, func() QQMessage { return NewMfaceMessage() }) } @@ -29,6 +29,10 @@ func NewMfaceMessage() *MfaceMessage { return &MfaceMessage{Type: TypeMface} } +func (msg *MfaceMessage) GetMessageType() string { + return TypeMface +} + func (msg *MfaceMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/music.go b/qq_message/music.go similarity index 93% rename from message/music.go rename to qq_message/music.go index 4ed5ffc..e417323 100644 --- a/message/music.go +++ b/qq_message/music.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -23,7 +23,7 @@ type MusicMessageData struct { } func init() { - RegisterMessageType(TypeMusic, func() CQMessage { + RegisterMessageType(TypeMusic, func() QQMessage { return NewMusicMessage() }) } @@ -32,6 +32,10 @@ func NewMusicMessage() *MusicMessage { return &MusicMessage{Type: TypeMusic} } +func (msg *MusicMessage) GetMessageType() string { + return TypeMusic +} + func (msg *MusicMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/record.go b/qq_message/record.go similarity index 88% rename from message/record.go rename to qq_message/record.go index 52ba6cd..4a49ae8 100644 --- a/message/record.go +++ b/qq_message/record.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -23,7 +23,7 @@ type RecordMessageData struct { } func init() { - RegisterMessageType(TypeRecord, func() CQMessage { + RegisterMessageType(TypeRecord, func() QQMessage { return NewRecordMessage() }) } @@ -32,6 +32,10 @@ func NewRecordMessage() *RecordMessage { return &RecordMessage{Type: TypeRecord} } +func (msg *RecordMessage) GetMessageType() string { + return TypeRecord +} + func (msg *RecordMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/reply.go b/qq_message/reply.go similarity index 87% rename from message/reply.go rename to qq_message/reply.go index 6204d87..2ba48dd 100644 --- a/message/reply.go +++ b/qq_message/reply.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -17,7 +17,7 @@ type ReplyMessageData struct { } func init() { - RegisterMessageType(TypeReply, func() CQMessage { + RegisterMessageType(TypeReply, func() QQMessage { return NewReplyMessage() }) } @@ -26,6 +26,10 @@ func NewReplyMessage() *ReplyMessage { return &ReplyMessage{Type: TypeReply} } +func (msg *ReplyMessage) GetMessageType() string { + return TypeReply +} + func (msg *ReplyMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/share.go b/qq_message/share.go similarity index 90% rename from message/share.go rename to qq_message/share.go index e878f0a..88aa3eb 100644 --- a/message/share.go +++ b/qq_message/share.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -20,7 +20,7 @@ type ShareMessageData struct { } func init() { - RegisterMessageType(TypeShare, func() CQMessage { + RegisterMessageType(TypeShare, func() QQMessage { return NewShareMessage() }) } @@ -29,6 +29,10 @@ func NewShareMessage() *ShareMessage { return &ShareMessage{Type: TypeShare} } +func (msg *ShareMessage) GetMessageType() string { + return TypeShare +} + func (msg *ShareMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/text.go b/qq_message/text.go similarity index 81% rename from message/text.go rename to qq_message/text.go index dd8975e..3b5301f 100644 --- a/message/text.go +++ b/qq_message/text.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -15,7 +15,7 @@ type TextMessageData struct { } func init() { - RegisterMessageType(TypeText, func() CQMessage { + RegisterMessageType(TypeText, func() QQMessage { return NewTextMessage() }) } @@ -24,6 +24,10 @@ func NewTextMessage() *TextMessage { return &TextMessage{Type: TypeText} } +func (msg *TextMessage) GetMessageType() string { + return TypeText +} + func (msg *TextMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/message/video.go b/qq_message/video.go similarity index 90% rename from message/video.go rename to qq_message/video.go index c6e55dc..617dd3c 100644 --- a/message/video.go +++ b/qq_message/video.go @@ -1,4 +1,4 @@ -package message +package qq_message import ( "encoding/json" @@ -24,7 +24,7 @@ type VideoMessageData struct { } func init() { - RegisterMessageType(TypeVideo, func() CQMessage { + RegisterMessageType(TypeVideo, func() QQMessage { return NewVideoMessage() }) } @@ -33,6 +33,10 @@ func NewVideoMessage() *VideoMessage { return &VideoMessage{Type: TypeVideo} } +func (msg *VideoMessage) GetMessageType() string { + return TypeVideo +} + func (msg *VideoMessage) SetData(data json.RawMessage) error { return json.Unmarshal(data, &msg.Data) } diff --git a/service/beatleader/model.go b/service/beatleader/model.go index ce74c9d..0e36ba9 100644 --- a/service/beatleader/model.go +++ b/service/beatleader/model.go @@ -12,7 +12,7 @@ import ( "git.lxtend.com/lixiangwuxian/imagedd/sprite" "git.lxtend.com/lixiangwuxian/imagedd/text2img" - "git.lxtend.com/lixiangwuxian/qqbot/message" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/util" ) @@ -443,9 +443,9 @@ func (p PlayerDataLite) LastDiffToString(lastQueryData PlayerDataLite) string { if err != nil { log.Default().Printf("缩放头像失败,url:%s,err:%v", p.Avatar, err) } - picMsg := message.ImageMessage{ - Type: message.TypeImage, - Data: message.ImageMessageData{ + picMsg := qq_message.ImageMessage{ + Type: qq_message.TypeImage, + Data: qq_message.ImageMessageData{ File: outFile, }, } diff --git a/service/scoresaber/model.go b/service/scoresaber/model.go index aca6ace..7e81b75 100644 --- a/service/scoresaber/model.go +++ b/service/scoresaber/model.go @@ -12,7 +12,7 @@ import ( "git.lxtend.com/lixiangwuxian/imagedd/sprite" "git.lxtend.com/lixiangwuxian/imagedd/text2img" - "git.lxtend.com/lixiangwuxian/qqbot/message" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/util" ) @@ -239,9 +239,9 @@ func (p PlayerData) ToString() string { if err != nil { log.Default().Printf("缩放头像失败,url:%s,err:%v", p.ProfilePicture, err) } - picMsg := message.ImageMessage{ - Type: message.TypeImage, - Data: message.ImageMessageData{ + picMsg := qq_message.ImageMessage{ + Type: qq_message.TypeImage, + Data: qq_message.ImageMessageData{ File: outFile, }, } @@ -296,9 +296,9 @@ func (p PlayerData) LastDiffToString(lastDayQueryData PlayerDataLite) string { if err != nil { log.Default().Printf("缩放头像失败,url:%s,err:%v", p.ProfilePicture, err) } - picMsg := message.ImageMessage{ - Type: message.TypeImage, - Data: message.ImageMessageData{ + picMsg := qq_message.ImageMessage{ + Type: qq_message.TypeImage, + Data: qq_message.ImageMessageData{ File: outFile, }, } diff --git a/service/xibao/image_gen.go b/service/xibao/image_gen.go index e00cc19..b12476d 100644 --- a/service/xibao/image_gen.go +++ b/service/xibao/image_gen.go @@ -9,7 +9,7 @@ import ( "git.lxtend.com/lixiangwuxian/imagedd/sprite" "git.lxtend.com/lixiangwuxian/imagedd/text2img" - "git.lxtend.com/lixiangwuxian/qqbot/message" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" "git.lxtend.com/lixiangwuxian/qqbot/util" "github.com/fogleman/gg" "golang.org/x/image/font/opentype" @@ -189,7 +189,7 @@ func GenerateCongratulationImageNew(text string, inputFile, outputFile string, i } func isImageCQ(text string) (string, bool) { - imgMsg := message.ImageMessage{} + imgMsg := qq_message.ImageMessage{} if err := imgMsg.ParseMessage(text); err == nil { return imgMsg.Data.URL, true } diff --git a/util/message.go b/util/message.go index 515a802..7894c21 100644 --- a/util/message.go +++ b/util/message.go @@ -5,10 +5,10 @@ import ( "strconv" "git.lxtend.com/lixiangwuxian/qqbot/action" - "git.lxtend.com/lixiangwuxian/qqbot/message" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" ) -func NewSelfNodeMessage(content ...any) *message.NodeMessage { +func NewSelfNodeMessage(content ...any) *qq_message.NodeMessage { loginAccountInfo, err := action.GetLoginAccountInfo() if err != nil { log.Println("GetLoginAccountInfo error:", err) @@ -17,5 +17,5 @@ func NewSelfNodeMessage(content ...any) *message.NodeMessage { if loginAccountInfo == nil { return nil } - return &message.NodeMessage{Type: message.TypeNode, Data: message.NodeMessageData{UserID: strconv.FormatInt(int64(loginAccountInfo.Data.UserID), 10), Nickname: loginAccountInfo.Data.Nickname, Content: content}} + return &qq_message.NodeMessage{Type: qq_message.TypeNode, Data: qq_message.NodeMessageData{UserID: strconv.FormatInt(int64(loginAccountInfo.Data.UserID), 10), Nickname: loginAccountInfo.Data.Nickname, Content: content}} } diff --git a/util/panic_report.go b/util/panic_report.go new file mode 100644 index 0000000..3029555 --- /dev/null +++ b/util/panic_report.go @@ -0,0 +1,30 @@ +package util + +import ( + "fmt" + "log" + "runtime/debug" + "time" + + "git.lxtend.com/lixiangwuxian/qqbot/action" + "git.lxtend.com/lixiangwuxian/qqbot/config" + "git.lxtend.com/lixiangwuxian/qqbot/model" +) + +func ReportPanicToDev() { + if r := recover(); r != nil { + stack := debug.Stack() + errMsg := fmt.Sprintf("[%s] Panic recovered:\nError: %v\nStack Trace:\n%s\n", + time.Now().Format("2006-01-02 15:04:05"), r, stack) + log.Print(errMsg) + action.ActionManager.SendMsg(&model.Reply{ + ReplyMsg: "出现了Panic:\n" + errMsg, + ReferOriginMsg: false, + FromMsg: model.Message{ + GroupInfo: model.GroupInfo{ + GroupId: config.ConfigManager.GetConfig().Management.ReportGroup, + }, + }, + }) + } +} diff --git a/ws_client/client.go b/ws_client/client.go index 9fb28e5..ab0aed8 100644 --- a/ws_client/client.go +++ b/ws_client/client.go @@ -13,6 +13,8 @@ import ( "git.lxtend.com/lixiangwuxian/qqbot/constants" "git.lxtend.com/lixiangwuxian/qqbot/handler" "git.lxtend.com/lixiangwuxian/qqbot/model" + "git.lxtend.com/lixiangwuxian/qqbot/qq_message" + "git.lxtend.com/lixiangwuxian/qqbot/util" "github.com/gorilla/websocket" ) @@ -58,6 +60,7 @@ func NewWebSocketClient(scheme, host, path string) (*WebSocketClient, error) { func (c *WebSocketClient) receiveMessages() { defer close(c.Done) + defer util.ReportPanicToDev() for !c.closed { _, message, err := c.conn.ReadMessage() if err != nil { @@ -69,11 +72,17 @@ func (c *WebSocketClient) receiveMessages() { log.Println("Error unmarshalling message:", err) return } + structuredMsg, err := qq_message.ParseCQMessages([]byte(event.RawMessage)) + if err != nil { + log.Println("Error parsing message:", err) + return + } msg := model.Message{ - UserId: event.UserID, - OriginMsgId: event.MessageID, - RawMsg: event.RawMessage, - UserNickName: event.Sender.Nickname, + UserId: event.UserID, + OriginMsgId: event.MessageID, + RawMsg: event.RawMessage, + StructuredMsg: structuredMsg, + UserNickName: event.Sender.Nickname, } if event.MessageType == constants.GROUP_MSG {