1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-06-18 21:45:04 +08:00

refactor(message): ForwardMessage don't impl IMessageElement interface

use ForwardMessage to upload and get the ForwardElement.
This commit is contained in:
wdvxdr 2021-08-03 15:36:20 +08:00
parent feb482e0e3
commit cb396f0f56
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
6 changed files with 94 additions and 67 deletions

View File

@ -1,10 +1,8 @@
package client
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/xml"
"fmt"
"math/rand"
"net"
@ -13,6 +11,9 @@ import (
"strings"
"time"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/binary/jce"
devinfo "github.com/Mrs4s/MiraiGo/client/pb"
@ -20,8 +21,6 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
)
type (
@ -586,12 +585,6 @@ func packUniRequestData(data []byte) (r []byte) {
return
}
func XmlEscape(c string) string {
buf := new(bytes.Buffer)
_ = xml.EscapeText(buf, []byte(c))
return buf.String()
}
func genForwardTemplate(resID, preview, title, brief, source, summary string, ts int64, items []*msg.PbMultiMsgItem) *message.ForwardElement {
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8'?><msg serviceID="35" templateID="1" action="viewMultiMsg" brief="%s" m_resid="%s" m_fileName="%d" tSum="3" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="0"><item layout="1"><title color="#000000" size="34">%s</title> %s<hr></hr><summary size="26" color="#808080">%s</summary></item><source name="%s"></source></msg>`,
brief, resID, ts, title, preview, summary, source,
@ -617,7 +610,7 @@ func genLongTemplate(resID, brief string, ts int64) *message.ServiceElement {
return brief
}()
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="35" templateID="1" action="viewMultiMsg" brief="%s" m_resid="%s" m_fileName="%d" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="1"> <item layout="1"> <title>%s</title> <hr hidden="false" style="0"/> <summary>点击查看完整消息</summary> </item> <source name="聊天记录" icon="" action="" appid="-1"/> </msg>`,
XmlEscape(limited), resID, ts, XmlEscape(limited),
utils.XmlEscape(limited), resID, ts, utils.XmlEscape(limited),
)
return &message.ServiceElement{
Id: 35,

View File

@ -7,6 +7,7 @@ import (
"math"
"math/rand"
"strconv"
"strings"
"time"
"github.com/Mrs4s/MiraiGo/client/pb/longmsg"
@ -53,14 +54,12 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
ret := c.sendGroupMessage(groupCode, false,
&message.SendingMessage{Elements: []message.IMessageElement{
c.uploadGroupLongMessage(groupCode,
&message.ForwardMessage{Nodes: []*message.ForwardNode{
{
SenderId: c.Uin,
SenderName: c.Nickname,
Time: int32(time.Now().Unix()),
Message: m.Elements,
},
}},
message.NewForwardMessage().AddNode(&message.ForwardNode{
SenderId: c.Uin,
SenderName: c.Nickname,
Time: int32(time.Now().Unix()),
Message: m.Elements,
}),
),
}},
)
@ -71,9 +70,9 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
}
// SendGroupForwardMessage 发送群合并转发消息
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.GroupMessage {
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardElement) *message.GroupMessage {
return c.sendGroupMessage(groupCode, true,
&message.SendingMessage{Elements: []message.IMessageElement{c.UploadGroupForwardMessage(groupCode, m)}},
&message.SendingMessage{Elements: []message.IMessageElement{m}},
)
}
@ -161,7 +160,7 @@ func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.Se
}
func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMessage) *message.ServiceElement {
if len(m.Nodes) >= 200 {
if m.Length() >= 200 {
return nil
}
ts := time.Now().UnixNano()
@ -173,25 +172,16 @@ func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMes
}
for i, ip := range rsp.Uint32UpIp {
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
if err == nil {
bri := func() string {
var r string
for _, n := range m.Nodes {
r += message.ToReadableString(n.Message)
if len(r) >= 27 {
break
}
}
return r
}()
return genLongTemplate(rsp.MsgResid, bri, ts)
if err != nil {
continue
}
return genLongTemplate(rsp.MsgResid, m.Brief(), ts)
}
return nil
}
func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.ForwardElement {
if len(m.Nodes) > 200 {
if m.Length() > 200 {
return nil
}
ts := time.Now().UnixNano()
@ -203,13 +193,10 @@ func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.Forward
}
for i, ip := range rsp.Uint32UpIp {
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
if err == nil {
var pv string
for i := 0; i < int(math.Min(4, float64(len(m.Nodes)))); i++ {
pv += fmt.Sprintf(`<title size="26" color="#777777">%s: %s</title>`, XmlEscape(m.Nodes[i].SenderName), XmlEscape(message.ToReadableString(m.Nodes[i].Message)))
}
return genForwardTemplate(rsp.MsgResid, pv, "群聊的聊天记录", "[聊天记录]", "聊天记录", fmt.Sprintf("查看 %d 条转发消息", len(m.Nodes)), ts, items)
if err != nil {
continue
}
return genForwardTemplate(rsp.MsgResid, m.Preview(), "群聊的聊天记录", "[聊天记录]", "聊天记录", fmt.Sprintf("查看 %d 条转发消息", m.Length()), ts, items)
}
return nil
}
@ -529,10 +516,11 @@ func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage {
if extInfo != nil && len(extInfo.GroupCard) > 0 && extInfo.GroupCard[0] == 0x0A {
buf := oidb.D8FCCommCardNameBuf{}
if err := proto.Unmarshal(extInfo.GroupCard, &buf); err == nil && len(buf.RichCardName) > 0 {
groupCard = ""
var gcard strings.Builder
for _, e := range buf.RichCardName {
groupCard += string(e.Text)
gcard.Write(e.Text)
}
groupCard = gcard.String()
}
}
if m.Head.GroupInfo != nil && groupCard != "" && mem.CardName != groupCard {

View File

@ -178,8 +178,7 @@ func NewPrivateReply(m *PrivateMessage) *ReplyElement {
func NewUrlShare(url, title, content, image string) *ServiceElement {
template := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?><msg templateID="12345" action="web" brief="[分享] %s" serviceID="1" url="%s"><item layout="2"><picture cover="%v"/><title>%v</title><summary>%v</summary></item><source/></msg>`,
title, url, image, title, content,
)
title, url, image, title, content)
/*
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes'?><msg templateID="123" url="%s" serviceID="33" action="web" actionData="" brief="【链接】%s" flag="8"><item layout="2"><picture cover="%s"/><title>%s</title><summary>%s</summary></item></msg>`,
url, url, image, title, content,

View File

@ -1,18 +1,22 @@
package message
import (
"bytes"
"crypto/md5"
"google.golang.org/protobuf/proto"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/utils"
)
// *----- Definitions -----* //
// ForwardMessage 添加 Node 请用 AddNode 方法
type ForwardMessage struct {
Nodes []*ForwardNode
items []*msg.PbMultiMsgItem
}
type ForwardNode struct {
@ -36,26 +40,67 @@ func (e *ForwardElement) Type() ElementType {
return Forward
}
func (e *ForwardElement) Pack() (r []*msg.Elem) {
r = []*msg.Elem{}
r = append(r, &msg.Elem{
func (e *ForwardElement) Pack() []*msg.Elem {
rich := &msg.Elem{
RichMsg: &msg.RichMsg{
Template1: append([]byte{1}, binary.ZlibCompress([]byte(e.Content))...),
Template1: append([]byte{1}, binary.ZlibCompress(utils.S2B(e.Content))...),
ServiceId: proto.Int32(35),
MsgResId: []byte{},
},
})
r = append(r, &msg.Elem{
}
txt := &msg.Elem{
Text: &msg.Text{
Str: proto.String("你的QQ暂不支持查看[转发多条消息],请期待后续版本。"),
},
})
return
}
return []*msg.Elem{rich, txt}
}
// Type impl IMessageElement
func (f *ForwardMessage) Type() ElementType {
return Forward
func NewForwardMessage() *ForwardMessage {
return &ForwardMessage{}
}
// AddNode adds a node to the forward message. return for method chaining.
func (f *ForwardMessage) AddNode(node *ForwardNode) *ForwardMessage {
f.Nodes = append(f.Nodes, node)
for _, item := range node.Message {
if item.Type() != Forward { // quick path
continue
}
if forward, ok := item.(*ForwardElement); ok {
f.items = append(f.items, forward.Items...)
}
}
return f
}
// Length return the length of Nodes.
func (f *ForwardMessage) Length() int { return len(f.Nodes) }
func (f *ForwardMessage) Brief() string {
var brief bytes.Buffer
for _, n := range f.Nodes {
brief.WriteString(ToReadableString(n.Message))
if brief.Len() >= 27 {
break
}
}
return brief.String()
}
func (f *ForwardMessage) Preview() string {
var pv bytes.Buffer
for i, node := range f.Nodes {
if i >= 4 {
break
}
pv.WriteString(`<title size="26" color="#777777">`)
pv.WriteString(utils.XmlEscape(node.SenderName))
pv.WriteString(": ")
pv.WriteString(utils.XmlEscape(ToReadableString(node.Message)))
pv.WriteString("</title>")
}
return pv.String()
}
func (f *ForwardMessage) CalculateValidationData(seq, random int32, groupCode int64) ([]byte, []byte) {
@ -81,13 +126,7 @@ func (f *ForwardMessage) CalculateValidationDataForward(seq, random int32, group
Buffer: &msg.PbMultiMsgNew{Msg: msgs},
},
}}
for _, node := range f.Nodes {
for _, message := range node.Message {
if forwardElement, ok := message.(*ForwardElement); ok {
trans.PbItemList = append(trans.PbItemList, forwardElement.Items...)
}
}
}
trans.PbItemList = append(trans.PbItemList, f.items...)
b, _ := proto.Marshal(trans)
data := binary.GZipCompress(b)
hash := md5.Sum(data)
@ -95,9 +134,9 @@ func (f *ForwardMessage) CalculateValidationDataForward(seq, random int32, group
}
func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64) []*msg.Message {
msgs := make([]*msg.Message, 0, len(f.Nodes))
ml := make([]*msg.Message, 0, len(f.Nodes))
for _, node := range f.Nodes {
msgs = append(msgs, &msg.Message{
ml = append(ml, &msg.Message{
Head: &msg.MessageHead{
FromUin: &node.SenderId,
MsgSeq: &seq,
@ -121,5 +160,5 @@ func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64
},
})
}
return msgs
return ml
}

View File

@ -418,7 +418,7 @@ func ParseMessageElems(elems []*msg.Elem) []IMessageElement {
}
if content != "" {
if elem.RichMsg.GetServiceId() == 35 {
reg := regexp.MustCompile(`m_resid="(.+)"`)
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]})

View File

@ -1,6 +1,7 @@
package utils
import (
"encoding/xml"
"math/rand"
"reflect"
"strconv"
@ -66,3 +67,10 @@ func S2B(s string) (b []byte) {
bh.Len = sh.Len
return
}
// XmlEscape xml escape string
func XmlEscape(c string) string {
buf := new(strings.Builder)
_ = xml.EscapeText(buf, []byte(c))
return buf.String()
}