1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00

feat: link nested forward message

This commit is contained in:
wdvxdr 2021-12-17 12:26:50 +08:00
parent a5410846cb
commit dc66c61d57
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
4 changed files with 126 additions and 69 deletions

View File

@ -3,7 +3,6 @@ package client
import ( import (
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"math"
"math/rand" "math/rand"
"net" "net"
"sort" "sort"
@ -19,7 +18,6 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/internal/crypto" "github.com/Mrs4s/MiraiGo/internal/crypto"
"github.com/Mrs4s/MiraiGo/internal/packets" "github.com/Mrs4s/MiraiGo/internal/packets"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
) )
@ -546,68 +544,6 @@ func (c *QQClient) GetFriendList() (*FriendListResponse, error) {
return r, nil 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(`<title size="26" color="#777777">%s: %s</title>`,
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) { func (c *QQClient) SendGroupPoke(groupCode, target int64) {
_, _ = c.sendAndWait(c.buildGroupPokePacket(groupCode, target)) _, _ = c.sendAndWait(c.buildGroupPokePacket(groupCode, target))
} }

View File

@ -2,6 +2,8 @@ package client
import ( import (
"fmt" "fmt"
"math"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -11,6 +13,7 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/multimsg" "github.com/Mrs4s/MiraiGo/client/pb/multimsg"
"github.com/Mrs4s/MiraiGo/internal/packets" "github.com/Mrs4s/MiraiGo/internal/packets"
"github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/internal/proto"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
) )
@ -132,3 +135,84 @@ func decodeMultiApplyDownResponse(_ *QQClient, _ *incomingPacketInfo, payload []
} }
return &mt, nil 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(`<title size="26" color="#777777">%s: %s</title>`,
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(),
)
}

View File

@ -3,6 +3,8 @@ package message
import ( import (
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"regexp"
"sync"
"github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
@ -34,6 +36,10 @@ type ForwardElement struct {
// *----- Implementations -----* // // *----- Implementations -----* //
func (f *ForwardMessage) Type() ElementType {
return Forward
}
// Type impl IMessageElement // Type impl IMessageElement
func (e *ForwardElement) Type() ElementType { func (e *ForwardElement) Type() ElementType {
return Forward return Forward
@ -161,3 +167,36 @@ func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64
} }
return ml 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}
}

View File

@ -3,7 +3,6 @@ package message
import ( import (
"encoding/json" "encoding/json"
"reflect" "reflect"
"regexp"
"strconv" "strconv"
"strings" "strings"
@ -415,10 +414,9 @@ func ParseMessageElems(elems []*msg.Elem) []IMessageElement {
} }
if content != "" { if content != "" {
if elem.RichMsg.GetServiceId() == 35 { if elem.RichMsg.GetServiceId() == 35 {
reg := regexp.MustCompile(`m_resid="(.*?)"`) elem := forwardMsgFromXML(content)
sub := reg.FindAllStringSubmatch(content, -1) if elem != nil {
if len(sub) > 0 && len(sub[0]) > 1 { res = append(res, elem)
res = append(res, &ForwardElement{ResId: reg.FindAllStringSubmatch(content, -1)[0][1]})
continue continue
} }
} }