From 8b86fe4d9cd0833342d2494acb6beb684f986330 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Mon, 21 Mar 2022 21:37:12 +0800 Subject: [PATCH] client: refactor forward message api --- client/global.go | 5 --- client/group_msg.go | 28 --------------- client/multimsg.go | 83 +++++++++++++++++++++++++++++++++++++++++++++ message/forward.go | 26 ++------------ 4 files changed, 86 insertions(+), 56 deletions(-) diff --git a/client/global.go b/client/global.go index d1c5db79..5b4cc48e 100644 --- a/client/global.go +++ b/client/global.go @@ -296,11 +296,6 @@ func packUniRequestData(data []byte) []byte { func genForwardTemplate(resID, preview, summary string, ts int64, items []*msg.PbMultiMsgItem) *message.ForwardElement { template := forwardDisplay(resID, strconv.FormatInt(ts, 10), preview, summary) - for _, item := range items { - if item.GetFileName() == "MultiMsg" { - *item.FileName = strconv.FormatInt(ts, 10) - } - } return &message.ForwardElement{ FileName: strconv.FormatInt(ts, 10), Content: template, diff --git a/client/group_msg.go b/client/group_msg.go index 18216c09..9c1a5578 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/base64" "encoding/json" - "fmt" "math" "math/rand" "strconv" @@ -186,33 +185,6 @@ func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMes return nil, errors.New("upload long message error: highway server list is empty or not available server.") } -func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.ForwardElement { - if m.Length() > 200 { - return nil - } - ts := time.Now().UnixNano() - seq := c.nextGroupSeq() - data, hash, items := m.CalculateValidationDataForward(seq, rand.Int31(), groupCode) - rsp, body, err := c.multiMsgApplyUp(groupCode, data, hash, 2) - if err != nil { - return nil - } - for i, ip := range rsp.Uint32UpIp { - addr := highway.Addr{IP: uint32(ip), Port: int(rsp.Uint32UpPort[i])} - input := highway.Input{ - CommandID: 27, - Key: rsp.MsgSig, - Body: bytes.NewReader(body), - } - err := c.highwaySession.Upload(addr, input) - if err != nil { - continue - } - return genForwardTemplate(rsp.MsgResid, m.Preview(), fmt.Sprintf("查看 %d 条转发消息", m.Length()), ts, items) - } - return nil -} - func (c *QQClient) multiMsgApplyUp(groupCode int64, data []byte, hash []byte, buType int32) (*multimsg.MultiMsgApplyUpRsp, []byte, error) { i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, buType, utils.ToGroupUin(groupCode))) if err != nil { diff --git a/client/multimsg.go b/client/multimsg.go index f72a6941..1050a17b 100644 --- a/client/multimsg.go +++ b/client/multimsg.go @@ -2,14 +2,18 @@ package client import ( "bytes" + "crypto/md5" "fmt" "math" + "math/rand" + "strconv" "strings" "time" "github.com/pkg/errors" "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/MiraiGo/client/internal/highway" "github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/pb/longmsg" "github.com/Mrs4s/MiraiGo/client/pb/msg" @@ -228,3 +232,82 @@ func forwardDisplay(resID, fileName, preview, summary string) string { sb.WriteString(``) return sb.String() } + +func (c *QQClient) NewForwardMessageBuilder(groupCode int64) *ForwardMessageBuilder { + return &ForwardMessageBuilder{ + c: c, + groupCode: groupCode, + } +} + +type ForwardMessageBuilder struct { + c *QQClient + groupCode int64 + objs []*msg.PbMultiMsgItem +} + +// NestedNode 返回一个嵌套转发节点,其内容将会被 Builder 重定位 +func (builder *ForwardMessageBuilder) NestedNode() *message.ForwardElement { + filename := strconv.FormatInt(time.Now().UnixNano(), 10) // 大概率不会重复 + return &message.ForwardElement{FileName: filename} +} + +// Link 将真实的消息内容填充 reloc +func (builder *ForwardMessageBuilder) Link(reloc *message.ForwardElement, fmsg *message.ForwardMessage) { + seq := builder.c.nextGroupSeq() + m := fmsg.PackForwardMessage(seq, rand.Int31(), builder.groupCode) + builder.objs = append(builder.objs, &msg.PbMultiMsgItem{ + FileName: proto.String(reloc.FileName), + Buffer: &msg.PbMultiMsgNew{ + Msg: m, + }, + }) + reloc.Content = forwardDisplay("", reloc.FileName, fmsg.Preview(), fmt.Sprintf("查看 %d 条转发消息", fmsg.Length())) +} + +// Main 最外层的转发消息, 调用该方法后即上传消息 +func (builder *ForwardMessageBuilder) Main(m *message.ForwardMessage) *message.ForwardElement { + if m.Length() > 200 { + return nil + } + c := builder.c + seq := c.nextGroupSeq() + fm := m.PackForwardMessage(seq, rand.Int31(), builder.groupCode) + const filename = "MultiMsg" + builder.objs = append(builder.objs, &msg.PbMultiMsgItem{ + FileName: proto.String(filename), + Buffer: &msg.PbMultiMsgNew{ + Msg: fm, + }, + }) + trans := &msg.PbMultiMsgTransmit{ + Msg: fm, + PbItemList: builder.objs, + } + b, _ := proto.Marshal(trans) + data := binary.GZipCompress(b) + hash := md5.Sum(data) + rsp, body, err := c.multiMsgApplyUp(builder.groupCode, data, hash[:], 2) + if err != nil { + return nil + } + content := forwardDisplay(rsp.MsgResid, filename, m.Preview(), fmt.Sprintf("查看 %d 条转发消息", m.Length())) + for i, ip := range rsp.Uint32UpIp { + addr := highway.Addr{IP: uint32(ip), Port: int(rsp.Uint32UpPort[i])} + input := highway.Input{ + CommandID: 27, + Key: rsp.MsgSig, + Body: bytes.NewReader(body), + } + err := c.highwaySession.Upload(addr, input) + if err != nil { + continue + } + return &message.ForwardElement{ + FileName: filename, + Content: content, + ResId: rsp.MsgResid, + } + } + return nil +} diff --git a/message/forward.go b/message/forward.go index 9062f11d..689d4cd8 100644 --- a/message/forward.go +++ b/message/forward.go @@ -14,10 +14,9 @@ import ( // *----- Definitions -----* // -// ForwardMessage 添加 Node 请用 AddNode 方法 +// ForwardMessage 合并转发消息 type ForwardMessage struct { Nodes []*ForwardNode - items []*msg.PbMultiMsgItem } type ForwardNode struct { @@ -72,9 +71,6 @@ func (f *ForwardMessage) AddNode(node *ForwardNode) *ForwardMessage { if item.Type() != Forward { // quick path continue } - if forward, ok := item.(*ForwardElement); ok { - f.items = append(f.items, forward.Items...) - } } return f } @@ -109,7 +105,7 @@ func (f *ForwardMessage) Preview() string { } func (f *ForwardMessage) CalculateValidationData(seq, random int32, groupCode int64) ([]byte, []byte) { - msgs := f.packForwardMsg(seq, random, groupCode) + msgs := f.PackForwardMessage(seq, random, groupCode) trans := &msg.PbMultiMsgTransmit{Msg: msgs, PbItemList: []*msg.PbMultiMsgItem{ { FileName: proto.String("MultiMsg"), @@ -122,23 +118,7 @@ func (f *ForwardMessage) CalculateValidationData(seq, random int32, groupCode in return data, hash[:] } -// CalculateValidationDataForward 屎代码 -func (f *ForwardMessage) CalculateValidationDataForward(seq, random int32, groupCode int64) ([]byte, []byte, []*msg.PbMultiMsgItem) { - msgs := f.packForwardMsg(seq, random, groupCode) - trans := &msg.PbMultiMsgTransmit{Msg: msgs, PbItemList: []*msg.PbMultiMsgItem{ - { - FileName: proto.String("MultiMsg"), - Buffer: &msg.PbMultiMsgNew{Msg: msgs}, - }, - }} - trans.PbItemList = append(trans.PbItemList, f.items...) - b, _ := proto.Marshal(trans) - data := binary.GZipCompress(b) - hash := md5.Sum(data) - return data, hash[:], trans.PbItemList -} - -func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64) []*msg.Message { +func (f *ForwardMessage) PackForwardMessage(seq int32, random int32, groupCode int64) []*msg.Message { ml := make([]*msg.Message, 0, len(f.Nodes)) for _, node := range f.Nodes { ml = append(ml, &msg.Message{