diff --git a/client/client.go b/client/client.go
index 9a0127ec..c7533f39 100644
--- a/client/client.go
+++ b/client/client.go
@@ -3,7 +3,6 @@ package client
import (
"crypto/md5"
"fmt"
- "math"
"math/rand"
"net"
"sort"
@@ -19,7 +18,6 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/internal/crypto"
"github.com/Mrs4s/MiraiGo/internal/packets"
- "github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils"
)
@@ -546,68 +544,6 @@ func (c *QQClient) GetFriendList() (*FriendListResponse, error) {
return r, nil
}
-func (c *QQClient) GetForwardMessage(resID string) *message.ForwardMessage {
- m := c.DownloadForwardMessage(resID)
- if m == nil {
- return nil
- }
- var item *msg.PbMultiMsgItem
- ret := &message.ForwardMessage{Nodes: []*message.ForwardNode{}}
- for _, iter := range m.Items {
- if iter.GetFileName() == m.FileName {
- item = iter
- }
- }
- if item == nil {
- return nil
- }
- for _, m := range item.GetBuffer().GetMsg() {
- name := m.Head.GetFromNick()
- if m.Head.GetMsgType() == 82 && m.Head.GroupInfo != nil {
- name = m.Head.GroupInfo.GetGroupCard()
- }
- ret.Nodes = append(ret.Nodes, &message.ForwardNode{
- SenderId: m.Head.GetFromUin(),
- SenderName: name,
- Time: m.Head.GetMsgTime(),
- Message: message.ParseMessageElems(m.Body.RichText.Elems),
- })
- }
- return ret
-}
-
-func (c *QQClient) DownloadForwardMessage(resId string) *message.ForwardElement {
- i, err := c.sendAndWait(c.buildMultiApplyDownPacket(resId))
- if err != nil {
- return nil
- }
- multiMsg := i.(*msg.PbMultiMsgTransmit)
- if multiMsg.GetPbItemList() == nil {
- return nil
- }
- var pv string
- for i := 0; i < int(math.Min(4, float64(len(multiMsg.GetMsg())))); i++ {
- m := multiMsg.Msg[i]
- pv += fmt.Sprintf(`
%s: %s`,
- func() string {
- if m.Head.GetMsgType() == 82 && m.Head.GroupInfo != nil {
- return m.Head.GroupInfo.GetGroupCard()
- }
- return m.Head.GetFromNick()
- }(),
- message.ToReadableString(
- message.ParseMessageElems(multiMsg.Msg[i].GetBody().GetRichText().Elems),
- ),
- )
- }
- return genForwardTemplate(
- resId, pv, "群聊的聊天记录", "[聊天记录]", "聊天记录",
- fmt.Sprintf("查看 %d 条转发消息", len(multiMsg.GetMsg())),
- time.Now().UnixNano(),
- multiMsg.GetPbItemList(),
- )
-}
-
func (c *QQClient) SendGroupPoke(groupCode, target int64) {
_, _ = c.sendAndWait(c.buildGroupPokePacket(groupCode, target))
}
diff --git a/client/multimsg.go b/client/multimsg.go
index b5e7696c..6be8a606 100644
--- a/client/multimsg.go
+++ b/client/multimsg.go
@@ -2,6 +2,8 @@ package client
import (
"fmt"
+ "math"
+ "time"
"github.com/pkg/errors"
@@ -11,6 +13,7 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/multimsg"
"github.com/Mrs4s/MiraiGo/internal/packets"
"github.com/Mrs4s/MiraiGo/internal/proto"
+ "github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils"
)
@@ -132,3 +135,84 @@ func decodeMultiApplyDownResponse(_ *QQClient, _ *incomingPacketInfo, payload []
}
return &mt, nil
}
+
+type forwardMsgLinker struct {
+ items map[string]*msg.PbMultiMsgItem
+}
+
+func (l *forwardMsgLinker) link(name string) *message.ForwardMessage {
+ item := l.items[name]
+ if item == nil {
+ return nil
+ }
+ nodes := make([]*message.ForwardNode, 0, len(item.GetBuffer().GetMsg()))
+ for _, m := range item.GetBuffer().GetMsg() {
+ name := m.Head.GetFromNick()
+ if m.Head.GetMsgType() == 82 && m.Head.GroupInfo != nil {
+ name = m.Head.GroupInfo.GetGroupCard()
+ }
+
+ msgElems := message.ParseMessageElems(m.Body.RichText.Elems)
+ for i, elem := range msgElems {
+ if forward, ok := elem.(*message.ForwardElement); ok {
+ if forward.FileName != "" {
+ msgElems[i] = l.link(forward.FileName) // 递归处理嵌套转发
+ }
+ }
+ }
+
+ nodes = append(nodes, &message.ForwardNode{
+ SenderId: m.Head.GetFromUin(),
+ SenderName: name,
+ Time: m.Head.GetMsgTime(),
+ Message: msgElems,
+ })
+ }
+ return &message.ForwardMessage{Nodes: nodes}
+}
+
+func (c *QQClient) GetForwardMessage(resID string) *message.ForwardMessage {
+ m := c.DownloadForwardMessage(resID)
+ if m == nil {
+ return nil
+ }
+ linker := forwardMsgLinker{
+ items: make(map[string]*msg.PbMultiMsgItem),
+ }
+ for _, item := range m.Items {
+ linker.items[item.GetFileName()] = item
+ }
+ return linker.link(m.FileName)
+}
+
+func (c *QQClient) DownloadForwardMessage(resId string) *message.ForwardElement {
+ i, err := c.sendAndWait(c.buildMultiApplyDownPacket(resId))
+ if err != nil {
+ return nil
+ }
+ multiMsg := i.(*msg.PbMultiMsgTransmit)
+ if multiMsg.GetPbItemList() == nil {
+ return nil
+ }
+ var pv string
+ for i := 0; i < int(math.Min(4, float64(len(multiMsg.GetMsg())))); i++ {
+ m := multiMsg.Msg[i]
+ pv += fmt.Sprintf(`%s: %s`,
+ func() string {
+ if m.Head.GetMsgType() == 82 && m.Head.GroupInfo != nil {
+ return m.Head.GroupInfo.GetGroupCard()
+ }
+ return m.Head.GetFromNick()
+ }(),
+ message.ToReadableString(
+ message.ParseMessageElems(multiMsg.Msg[i].GetBody().GetRichText().Elems),
+ ),
+ )
+ }
+ return genForwardTemplate(
+ resId, pv, "群聊的聊天记录", "[聊天记录]", "聊天记录",
+ fmt.Sprintf("查看 %d 条转发消息", len(multiMsg.GetMsg())),
+ time.Now().UnixNano(),
+ multiMsg.GetPbItemList(),
+ )
+}
diff --git a/message/forward.go b/message/forward.go
index 62cc8e45..9062f11d 100644
--- a/message/forward.go
+++ b/message/forward.go
@@ -3,6 +3,8 @@ package message
import (
"bytes"
"crypto/md5"
+ "regexp"
+ "sync"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client/pb/msg"
@@ -34,6 +36,10 @@ type ForwardElement struct {
// *----- Implementations -----* //
+func (f *ForwardMessage) Type() ElementType {
+ return Forward
+}
+
// Type impl IMessageElement
func (e *ForwardElement) Type() ElementType {
return Forward
@@ -161,3 +167,36 @@ func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64
}
return ml
}
+
+type lazyRegex struct {
+ once sync.Once
+ reg *regexp.Regexp
+ Pattern string
+}
+
+func (l *lazyRegex) init() {
+ l.reg = regexp.MustCompile(l.Pattern)
+}
+
+func (l *lazyRegex) findMatch1(content string) string {
+ l.once.Do(l.init)
+ matches := l.reg.FindStringSubmatch(content)
+ if matches == nil {
+ return ""
+ }
+ return matches[1]
+}
+
+var (
+ mResID = lazyRegex{Pattern: `m_resid="(.*?)"`}
+ mFileName = lazyRegex{Pattern: `m_fileName="(.*?)"`}
+)
+
+func forwardMsgFromXML(xml string) *ForwardElement {
+ resid := mResID.findMatch1(xml)
+ fileName := mFileName.findMatch1(xml)
+ if resid == "" && fileName == "" {
+ return nil
+ }
+ return &ForwardElement{FileName: fileName, ResId: resid}
+}
diff --git a/message/message.go b/message/message.go
index 887e96b2..d3501273 100644
--- a/message/message.go
+++ b/message/message.go
@@ -3,7 +3,6 @@ package message
import (
"encoding/json"
"reflect"
- "regexp"
"strconv"
"strings"
@@ -415,10 +414,9 @@ func ParseMessageElems(elems []*msg.Elem) []IMessageElement {
}
if content != "" {
if elem.RichMsg.GetServiceId() == 35 {
- reg := regexp.MustCompile(`m_resid="(.*?)"`)
- sub := reg.FindAllStringSubmatch(content, -1)
- if len(sub) > 0 && len(sub[0]) > 1 {
- res = append(res, &ForwardElement{ResId: reg.FindAllStringSubmatch(content, -1)[0][1]})
+ elem := forwardMsgFromXML(content)
+ if elem != nil {
+ res = append(res, elem)
continue
}
}