mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-05 03:23:50 +08:00
send forward msg套娃
💩
This commit is contained in:
parent
e884637ecc
commit
6ce32da5a1
@ -9,6 +9,7 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -575,21 +576,27 @@ func packUniRequestData(data []byte) (r []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func genForwardTemplate(resId, preview, title, brief, source, summary string, ts int64) *message.SendingMessage {
|
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>`,
|
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,
|
brief, resId, ts, title, preview, summary, source,
|
||||||
)
|
)
|
||||||
return &message.SendingMessage{Elements: []message.IMessageElement{
|
for index, item := range items {
|
||||||
&message.ServiceElement{
|
if item.GetFileName() == "MultiMsg" {
|
||||||
|
items[index].FileName = proto.String(strconv.FormatInt(ts, 10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &message.ForwardElement{
|
||||||
|
ServiceElement: message.ServiceElement{
|
||||||
Id: 35,
|
Id: 35,
|
||||||
Content: template,
|
Content: template,
|
||||||
ResId: resId,
|
ResId: resId,
|
||||||
SubType: "Forward",
|
SubType: "Forward",
|
||||||
},
|
},
|
||||||
}}
|
Items: items,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genLongTemplate(resId, brief string, ts int64) *message.SendingMessage {
|
func genLongTemplate(resId, brief string, ts int64) *message.ServiceElement {
|
||||||
limited := func() string {
|
limited := func() string {
|
||||||
if len(brief) > 30 {
|
if len(brief) > 30 {
|
||||||
return brief[:30] + "…"
|
return brief[:30] + "…"
|
||||||
@ -599,14 +606,12 @@ func genLongTemplate(resId, brief string, ts int64) *message.SendingMessage {
|
|||||||
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>`,
|
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>`,
|
||||||
limited, resId, ts, limited,
|
limited, resId, ts, limited,
|
||||||
)
|
)
|
||||||
return &message.SendingMessage{Elements: []message.IMessageElement{
|
return &message.ServiceElement{
|
||||||
&message.ServiceElement{
|
|
||||||
Id: 35,
|
Id: 35,
|
||||||
Content: template,
|
Content: template,
|
||||||
ResId: resId,
|
ResId: resId,
|
||||||
SubType: "Long",
|
SubType: "Long",
|
||||||
},
|
}
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) Error(msg string, args ...interface{}) {
|
func (c *QQClient) Error(msg string, args ...interface{}) {
|
||||||
|
@ -40,14 +40,20 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if (msgLen > 200 || imgCount > 1) && !useFram {
|
if (msgLen > 200 || imgCount > 1) && !useFram {
|
||||||
ret := c.sendGroupLongOrForwardMessage(groupCode, true, &message.ForwardMessage{Nodes: []*message.ForwardNode{
|
ret := c.sendGroupMessage(groupCode, true,
|
||||||
|
&message.SendingMessage{Elements: []message.IMessageElement{
|
||||||
|
c.uploadGroupLongMessage(groupCode,
|
||||||
|
&message.ForwardMessage{Nodes: []*message.ForwardNode{
|
||||||
{
|
{
|
||||||
SenderId: c.Uin,
|
SenderId: c.Uin,
|
||||||
SenderName: c.Nickname,
|
SenderName: c.Nickname,
|
||||||
Time: int32(time.Now().Unix()),
|
Time: int32(time.Now().Unix()),
|
||||||
Message: m.Elements,
|
Message: m.Elements,
|
||||||
},
|
},
|
||||||
}})
|
}},
|
||||||
|
),
|
||||||
|
}},
|
||||||
|
)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
return c.sendGroupMessage(groupCode, false, m)
|
return c.sendGroupMessage(groupCode, false, m)
|
||||||
@ -55,7 +61,12 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
|
|||||||
|
|
||||||
// SendGroupForwardMessage 发送群合并转发消息
|
// SendGroupForwardMessage 发送群合并转发消息
|
||||||
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.GroupMessage {
|
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.GroupMessage {
|
||||||
return c.sendGroupLongOrForwardMessage(groupCode, false, m)
|
mg := c.UploadGroupForwardMessage(groupCode, m)
|
||||||
|
return c.sendGroupMessage(groupCode, true,
|
||||||
|
&message.SendingMessage{Elements: []message.IMessageElement{
|
||||||
|
&mg.ServiceElement,
|
||||||
|
}},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGroupMessages 从服务器获取历史信息
|
// GetGroupMessages 从服务器获取历史信息
|
||||||
@ -134,20 +145,14 @@ func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.Se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) sendGroupLongOrForwardMessage(groupCode int64, isLong bool, m *message.ForwardMessage) *message.GroupMessage {
|
func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMessage) *message.ServiceElement {
|
||||||
if len(m.Nodes) >= 200 {
|
if len(m.Nodes) >= 200 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ts := time.Now().Unix()
|
ts := time.Now().UnixNano()
|
||||||
seq := c.nextGroupSeq()
|
seq := c.nextGroupSeq()
|
||||||
data, hash := m.CalculateValidationData(seq, rand.Int31(), groupCode)
|
data, hash := m.CalculateValidationData(seq, rand.Int31(), groupCode)
|
||||||
i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, func() int32 {
|
i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, 1, utils.ToGroupUin(groupCode)))
|
||||||
if isLong {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
}(), utils.ToGroupUin(groupCode)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -169,13 +174,6 @@ func (c *QQClient) sendGroupLongOrForwardMessage(groupCode int64, isLong bool, m
|
|||||||
for i, ip := range rsp.Uint32UpIp {
|
for i, ip := range rsp.Uint32UpIp {
|
||||||
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
|
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if !isLong {
|
|
||||||
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>`, m.Nodes[i].SenderName, message.ToReadableString(m.Nodes[i].Message))
|
|
||||||
}
|
|
||||||
return c.sendGroupMessage(groupCode, true, genForwardTemplate(rsp.MsgResid, pv, "群聊的聊天记录", "[聊天记录]", "聊天记录", fmt.Sprintf("查看 %d 条转发消息", len(m.Nodes)), ts))
|
|
||||||
}
|
|
||||||
bri := func() string {
|
bri := func() string {
|
||||||
var r string
|
var r string
|
||||||
for _, n := range m.Nodes {
|
for _, n := range m.Nodes {
|
||||||
@ -186,7 +184,46 @@ func (c *QQClient) sendGroupLongOrForwardMessage(groupCode int64, isLong bool, m
|
|||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}()
|
}()
|
||||||
return c.sendGroupMessage(groupCode, false, genLongTemplate(rsp.MsgResid, bri, ts))
|
return genLongTemplate(rsp.MsgResid, bri, ts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.ForwardElement {
|
||||||
|
if len(m.Nodes) >= 200 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ts := time.Now().UnixNano()
|
||||||
|
seq := c.nextGroupSeq()
|
||||||
|
data, hash, items := m.CalculateValidationDataForward(seq, rand.Int31(), groupCode)
|
||||||
|
i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, 2, utils.ToGroupUin(groupCode)))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rsp := i.(*multimsg.MultiMsgApplyUpRsp)
|
||||||
|
body, _ := proto.Marshal(&longmsg.LongReqBody{
|
||||||
|
Subcmd: 1,
|
||||||
|
TermType: 5,
|
||||||
|
PlatformType: 9,
|
||||||
|
MsgUpReq: []*longmsg.LongMsgUpReq{
|
||||||
|
{
|
||||||
|
MsgType: 3,
|
||||||
|
DstUin: utils.ToGroupUin(groupCode),
|
||||||
|
MsgContent: data,
|
||||||
|
StoreType: 2,
|
||||||
|
MsgUkey: rsp.MsgUkey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
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>`, m.Nodes[i].SenderName, message.ToReadableString(m.Nodes[i].Message))
|
||||||
|
}
|
||||||
|
return genForwardTemplate(rsp.MsgResid, pv, "群聊的聊天记录", "[聊天记录]", "聊天记录", fmt.Sprintf("查看 %d 条转发消息", len(m.Nodes)), ts, items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -103,7 +103,8 @@ type ServiceElement struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ForwardElement struct {
|
type ForwardElement struct {
|
||||||
ResId string
|
ServiceElement
|
||||||
|
Items []*msg.PbMultiMsgItem
|
||||||
}
|
}
|
||||||
|
|
||||||
type LightAppElement struct {
|
type LightAppElement struct {
|
||||||
|
@ -434,7 +434,7 @@ func ParseMessageElems(elems []*msg.Elem) []IMessageElement {
|
|||||||
reg := regexp.MustCompile(`m_resid="(\w+?.*?)"`)
|
reg := regexp.MustCompile(`m_resid="(\w+?.*?)"`)
|
||||||
sub := reg.FindAllStringSubmatch(content, -1)
|
sub := reg.FindAllStringSubmatch(content, -1)
|
||||||
if len(sub) > 0 && len(sub[0]) > 1 {
|
if len(sub) > 0 && len(sub[0]) > 1 {
|
||||||
res = append(res, &ForwardElement{ResId: reg.FindAllStringSubmatch(content, -1)[0][1]})
|
res = append(res, &ForwardElement{ServiceElement: ServiceElement{ResId: reg.FindAllStringSubmatch(content, -1)[0][1]}})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -575,6 +575,55 @@ func (forMsg *ForwardMessage) CalculateValidationData(seq, random int32, groupCo
|
|||||||
return data, hash[:]
|
return data, hash[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalculateValidationDataForward 屎代码
|
||||||
|
func (forMsg *ForwardMessage) CalculateValidationDataForward(seq, random int32, groupCode int64) ([]byte, []byte, []*msg.PbMultiMsgItem) {
|
||||||
|
var msgs []*msg.Message
|
||||||
|
for _, node := range forMsg.Nodes {
|
||||||
|
msgs = append(msgs, &msg.Message{
|
||||||
|
Head: &msg.MessageHead{
|
||||||
|
FromUin: &node.SenderId,
|
||||||
|
MsgSeq: &seq,
|
||||||
|
MsgTime: &node.Time,
|
||||||
|
MsgUid: proto.Int64(0x01000000000000000 | (int64(random) & 0xFFFFFFFF)),
|
||||||
|
MutiltransHead: &msg.MutilTransHead{
|
||||||
|
MsgId: proto.Int32(1),
|
||||||
|
},
|
||||||
|
MsgType: proto.Int32(82),
|
||||||
|
GroupInfo: &msg.GroupInfo{
|
||||||
|
GroupCode: &groupCode,
|
||||||
|
GroupRank: []byte{},
|
||||||
|
GroupName: []byte{},
|
||||||
|
GroupCard: &node.SenderName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Body: &msg.MessageBody{
|
||||||
|
RichText: &msg.RichText{
|
||||||
|
Elems: func() []*msg.Elem {
|
||||||
|
return ToProtoElems(node.Message, false)
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
trans := &msg.PbMultiMsgTransmit{Msg: msgs, PbItemList: []*msg.PbMultiMsgItem{
|
||||||
|
{
|
||||||
|
FileName: proto.String("MultiMsg"),
|
||||||
|
Buffer: &msg.PbMultiMsgNew{Msg: msgs},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
for _, item1 := range forMsg.Nodes {
|
||||||
|
for _, item2 := range item1.Message {
|
||||||
|
if item3, ok := item2.(*ForwardElement); ok {
|
||||||
|
trans.PbItemList = append(trans.PbItemList, item3.Items...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b, _ := proto.Marshal(trans)
|
||||||
|
data := binary.GZipCompress(b)
|
||||||
|
hash := md5.Sum(data)
|
||||||
|
return data, hash[:], trans.PbItemList
|
||||||
|
}
|
||||||
|
|
||||||
func ToReadableString(m []IMessageElement) (r string) {
|
func ToReadableString(m []IMessageElement) (r string) {
|
||||||
for _, elem := range m {
|
for _, elem := range m {
|
||||||
switch e := elem.(type) {
|
switch e := elem.(type) {
|
||||||
@ -586,6 +635,12 @@ func ToReadableString(m []IMessageElement) (r string) {
|
|||||||
r += "/" + e.Name
|
r += "/" + e.Name
|
||||||
case *GroupImageElement:
|
case *GroupImageElement:
|
||||||
r += "[图片]"
|
r += "[图片]"
|
||||||
|
case *ServiceElement:
|
||||||
|
if e.SubType == "Forward" {
|
||||||
|
r += "[聊天记录]"
|
||||||
|
}
|
||||||
|
case *ForwardElement:
|
||||||
|
r += "[聊天记录]"
|
||||||
// NOTE: flash pic is singular
|
// NOTE: flash pic is singular
|
||||||
// To be clarified
|
// To be clarified
|
||||||
// case *GroupFlashImgElement:
|
// case *GroupFlashImgElement:
|
||||||
|
@ -162,6 +162,23 @@ func (e *ServiceElement) Pack() (r []*msg.Elem) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *ForwardElement) Pack() (r []*msg.Elem) {
|
||||||
|
r = []*msg.Elem{}
|
||||||
|
r = append(r, &msg.Elem{
|
||||||
|
RichMsg: &msg.RichMsg{
|
||||||
|
Template1: append([]byte{1}, binary.ZlibCompress([]byte(e.Content))...),
|
||||||
|
ServiceId: &e.Id,
|
||||||
|
MsgResId: []byte{},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
r = append(r, &msg.Elem{
|
||||||
|
Text: &msg.Text{
|
||||||
|
Str: proto.String("你的QQ暂不支持查看[转发多条消息],请期待后续版本。"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (e *LightAppElement) Pack() (r []*msg.Elem) {
|
func (e *LightAppElement) Pack() (r []*msg.Elem) {
|
||||||
r = []*msg.Elem{}
|
r = []*msg.Elem{}
|
||||||
r = append(r, &msg.Elem{
|
r = append(r, &msg.Elem{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user