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:
parent
feb482e0e3
commit
cb396f0f56
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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]})
|
||||
|
@ -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()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user