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

client: merge fragmented private message

This commit is contained in:
wdvxdr 2022-02-14 16:27:17 +08:00
parent d53bf8503e
commit 0e68a1e7b7
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
5 changed files with 61 additions and 26 deletions

View File

@ -117,6 +117,20 @@ func privateMessageDecoder(c *QQClient, pMsg *msg.Message, _ *network.IncomingPa
if pMsg.Body.RichText == nil || pMsg.Body.RichText.Elems == nil { if pMsg.Body.RichText == nil || pMsg.Body.RichText.Elems == nil {
return return
} }
// handle fragmented message
if pMsg.Content != nil && pMsg.Content.GetPkgNum() > 1 {
seq := pMsg.Content.GetDivSeq()
builder := c.messageBuilder(seq)
builder.append(pMsg)
if builder.len() < pMsg.Content.GetPkgNum() {
// continue to receive other fragments
return
}
c.msgBuilders.Delete(seq)
pMsg = builder.build()
}
if pMsg.Head.GetFromUin() == c.Uin { if pMsg.Head.GetFromUin() == c.Uin {
c.dispatchPrivateMessageSelf(c.parsePrivateMessage(pMsg)) c.dispatchPrivateMessageSelf(c.parsePrivateMessage(pMsg))
return return

View File

@ -82,14 +82,14 @@ type QQClient struct {
lastC2CMsgTime int64 lastC2CMsgTime int64
transCache *utils.Cache transCache *utils.Cache
groupSysMsgCache *GroupSystemMessages groupSysMsgCache *GroupSystemMessages
groupMsgBuilders sync.Map msgBuilders sync.Map
onlinePushCache *utils.Cache onlinePushCache *utils.Cache
heartbeatEnabled bool heartbeatEnabled bool
requestPacketRequestID atomic.Int32 requestPacketRequestID atomic.Int32
groupSeq atomic.Int32 groupSeq atomic.Int32
friendSeq atomic.Int32 friendSeq atomic.Int32
highwayApplyUpSeq atomic.Int32 highwayApplyUpSeq atomic.Int32
eventHandlers *eventHandlers eventHandlers eventHandlers
groupListLock sync.Mutex groupListLock sync.Mutex
} }
@ -165,7 +165,6 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
sig: &auth.SigInfo{ sig: &auth.SigInfo{
OutPacketSessionID: []byte{0x02, 0xB0, 0x5B, 0x8B}, OutPacketSessionID: []byte{0x02, 0xB0, 0x5B, 0x8B},
}, },
eventHandlers: &eventHandlers{},
msgSvcCache: utils.NewCache(time.Second * 15), msgSvcCache: utils.NewCache(time.Second * 15),
transCache: utils.NewCache(time.Second * 15), transCache: utils.NewCache(time.Second * 15),
onlinePushCache: utils.NewCache(time.Second * 15), onlinePushCache: utils.NewCache(time.Second * 15),

View File

@ -9,6 +9,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -26,10 +27,6 @@ import (
type ( type (
DeviceInfo = auth.Device DeviceInfo = auth.Device
Version = auth.OSVersion Version = auth.OSVersion
groupMessageBuilder struct {
MessageSlices []*msg.Message
}
) )
var SystemDeviceInfo = &DeviceInfo{ var SystemDeviceInfo = &DeviceInfo{
@ -246,12 +243,43 @@ func (c *QQClient) parseTempMessage(msg *msg.Message) *message.TempMessage {
} }
} }
func (b *groupMessageBuilder) build() *msg.Message { func (c *QQClient) messageBuilder(seq int32) *messageBuilder {
sort.Slice(b.MessageSlices, func(i, j int) bool { builder := &messageBuilder{}
return b.MessageSlices[i].Content.GetPkgIndex() < b.MessageSlices[j].Content.GetPkgIndex() actual, ok := c.msgBuilders.LoadOrStore(seq, builder)
if !ok {
time.AfterFunc(time.Minute, func() {
c.msgBuilders.Delete(seq) // delete avoid memory leak
})
}
return actual.(*messageBuilder)
}
type messageBuilder struct {
lock sync.Mutex
slices []*msg.Message
}
func (b *messageBuilder) append(msg *msg.Message) {
b.lock.Lock()
defer b.lock.Unlock()
b.slices = append(b.slices, msg)
}
func (b *messageBuilder) len() int32 {
b.lock.Lock()
x := len(b.slices)
b.lock.Unlock()
return int32(x)
}
func (b *messageBuilder) build() *msg.Message {
b.lock.Lock()
defer b.lock.Unlock()
sort.Slice(b.slices, func(i, j int) bool {
return b.slices[i].Content.GetPkgIndex() < b.slices[j].Content.GetPkgIndex()
}) })
base := b.MessageSlices[0] base := b.slices[0]
for _, m := range b.MessageSlices[1:] { for _, m := range b.slices[1:] {
base.Body.RichText.Elems = append(base.Body.RichText.Elems, m.Body.RichText.Elems...) base.Body.RichText.Elems = append(base.Body.RichText.Elems, m.Body.RichText.Elems...)
} }
return base return base

View File

@ -311,17 +311,11 @@ func decodeGroupMessagePacket(c *QQClient, _ *network.IncomingPacketInfo, payloa
}) })
} }
if pkt.Message.Content != nil && pkt.Message.Content.GetPkgNum() > 1 { if pkt.Message.Content != nil && pkt.Message.Content.GetPkgNum() > 1 {
var builder *groupMessageBuilder seq := pkt.Message.Content.GetDivSeq()
i, ok := c.groupMsgBuilders.Load(pkt.Message.Content.GetDivSeq()) builder := c.messageBuilder(pkt.Message.Content.GetDivSeq())
if !ok { builder.append(pkt.Message)
builder = &groupMessageBuilder{} if builder.len() >= pkt.Message.Content.GetPkgNum() {
c.groupMsgBuilders.Store(pkt.Message.Content.GetDivSeq(), builder) c.msgBuilders.Delete(seq)
} else {
builder = i.(*groupMessageBuilder)
}
builder.MessageSlices = append(builder.MessageSlices, pkt.Message)
if int32(len(builder.MessageSlices)) >= pkt.Message.Content.GetPkgNum() {
c.groupMsgBuilders.Delete(pkt.Message.Content.GetDivSeq())
if pkt.Message.Head.GetFromUin() == c.Uin { if pkt.Message.Head.GetFromUin() == c.Uin {
c.dispatchGroupMessageSelf(c.parseGroupMessage(builder.build())) c.dispatchGroupMessageSelf(c.parseGroupMessage(builder.build()))
} else { } else {
@ -371,7 +365,7 @@ func decodeGetGroupMsgResponse(c *QQClient, info *network.IncomingPacketInfo, pa
if m.Content.GetPkgIndex() == 0 { if m.Content.GetPkgIndex() == 0 {
c.Debug("build fragmented message from history") c.Debug("build fragmented message from history")
i := m.Head.GetMsgSeq() - m.Content.GetPkgNum() i := m.Head.GetMsgSeq() - m.Content.GetPkgNum()
builder := &groupMessageBuilder{} builder := &messageBuilder{}
for { for {
end := int32(math.Min(float64(i+19), float64(m.Head.GetMsgSeq()+m.Content.GetPkgNum()))) end := int32(math.Min(float64(i+19), float64(m.Head.GetMsgSeq()+m.Content.GetPkgNum())))
seq, pkt := c.buildGetGroupMsgRequest(m.Head.GroupInfo.GetGroupCode(), int64(i), int64(end)) seq, pkt := c.buildGetGroupMsgRequest(m.Head.GroupInfo.GetGroupCode(), int64(i), int64(end))
@ -381,7 +375,7 @@ func decodeGetGroupMsgResponse(c *QQClient, info *network.IncomingPacketInfo, pa
} }
for _, fm := range data.([]*message.GroupMessage) { for _, fm := range data.([]*message.GroupMessage) {
if fm.OriginalObject.Content != nil && fm.OriginalObject.Content.GetDivSeq() == m.Content.GetDivSeq() { if fm.OriginalObject.Content != nil && fm.OriginalObject.Content.GetDivSeq() == m.Content.GetDivSeq() {
builder.MessageSlices = append(builder.MessageSlices, fm.OriginalObject) builder.append(fm.OriginalObject)
} }
} }
if end >= m.Head.GetMsgSeq()+m.Content.GetPkgNum() { if end >= m.Head.GetMsgSeq()+m.Content.GetPkgNum() {

View File

@ -126,7 +126,7 @@ func (c *QQClient) UploadGroupImageByFile(groupCode int64, path string) (*messag
Ticket: rsp.UploadKey, Ticket: rsp.UploadKey,
Ext: EmptyBytes, Ext: EmptyBytes,
Encrypt: false, Encrypt: false,
}, 1); err == nil { }, 4); err == nil {
goto ok goto ok
} }
return nil, errors.Wrap(err, "upload failed") return nil, errors.Wrap(err, "upload failed")