1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

feature get group messages & clear code.

This commit is contained in:
Mrs4s 2020-12-02 00:01:50 +08:00
parent e705f96efd
commit 6c18a70565
9 changed files with 631 additions and 299 deletions

View File

@ -550,46 +550,6 @@ func (c *QQClient) buildDeleteOnlinePushPacket(uin int64, seq uint16, delMsg []j
return packets.BuildUniPacket(c.Uin, seq, "OnlinePush.RespPush", 1, c.OutGoingPacketSessionId, []byte{}, c.sigInfo.d2Key, pkt.ToBytes())
}
// MessageSvc.PbSendMsg
func (c *QQClient) buildGroupSendingPacket(groupCode int64, r, pkgNum, pkgIndex, pkgDiv int32, forward bool, m []message.IMessageElement) (uint16, []byte) {
seq := c.nextSeq()
var ptt *message.GroupVoiceElement
if len(m) > 0 {
if p, ok := m[0].(*message.GroupVoiceElement); ok {
ptt = p
m = []message.IMessageElement{}
}
}
req := &msg.SendMessageRequest{
RoutingHead: &msg.RoutingHead{Grp: &msg.Grp{GroupCode: &groupCode}},
ContentHead: &msg.ContentHead{PkgNum: &pkgNum, PkgIndex: &pkgIndex, DivSeq: &pkgDiv},
MsgBody: &msg.MessageBody{
RichText: &msg.RichText{
Elems: message.ToProtoElems(m, true),
Ptt: func() *msg.Ptt {
if ptt != nil {
return ptt.Ptt
}
return nil
}(),
},
},
MsgSeq: proto.Int32(c.nextGroupSeq()),
MsgRand: &r,
SyncCookie: EmptyBytes,
MsgVia: proto.Int32(1),
MsgCtrl: func() *msg.MsgCtrl {
if forward {
return &msg.MsgCtrl{MsgFlag: proto.Int32(4)}
}
return nil
}(),
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbSendMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
// MessageSvc.PbSendMsg
func (c *QQClient) buildFriendSendingPacket(target int64, msgSeq, r, pkgNum, pkgIndex, pkgDiv int32, time int64, m []message.IMessageElement) (uint16, []byte) {
seq := c.nextSeq()

View File

@ -8,7 +8,6 @@ import (
"fmt"
"image"
"io"
"math"
"math/rand"
"net"
"runtime/debug"
@ -21,12 +20,8 @@ import (
"github.com/pkg/errors"
"github.com/golang/protobuf/proto"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client/pb/longmsg"
"github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/client/pb/multimsg"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/protocol/packets"
"github.com/Mrs4s/MiraiGo/utils"
@ -51,7 +46,6 @@ type QQClient struct {
Conn net.Conn
ConnectTime time.Time
decoders map[string]func(*QQClient, uint16, []byte) (interface{}, error)
handlers sync.Map
servers []*net.TCPAddr
currServerIndex int
@ -114,6 +108,39 @@ type loginSigInfo struct {
pt4TokenMap map[string][]byte
}
var decoders = map[string]func(*QQClient, uint16, []byte) (interface{}, error){
"wtlogin.login": decodeLoginResponse,
"wtlogin.exchange_emp": decodeExchangeEmpResponse,
"StatSvc.register": decodeClientRegisterResponse,
"StatSvc.ReqMSFOffline": decodeMSFOfflinePacket,
"StatSvc.GetDevLoginInfo": decodeDevListResponse,
"MessageSvc.PushNotify": decodeSvcNotify,
"OnlinePush.ReqPush": decodeOnlinePushReqPacket,
"OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket,
"ConfigPushSvc.PushReq": decodePushReqPacket,
"MessageSvc.PbGetMsg": decodeMessageSvcPacket,
"MessageSvc.PushForceOffline": decodeForceOfflinePacket,
"PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse,
"friendlist.getFriendGroupList": decodeFriendGroupListResponse,
"friendlist.GetTroopListReqV2": decodeGroupListResponse,
"friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse,
"group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse,
"ImgStore.GroupPicUp": decodeGroupImageStoreResponse,
"PttStore.GroupPttUp": decodeGroupPttStoreResponse,
"LongConn.OffPicUp": decodeOffPicUpResponse,
"ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket,
"ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket,
"MultiMsg.ApplyUp": decodeMultiApplyUpResponse,
"MultiMsg.ApplyDown": decodeMultiApplyDownResponse,
"OidbSvc.0xe07_0": decodeImageOcrResponse,
"OidbSvc.0xd79": decodeWordSegmentation,
"OidbSvc.0x990": decodeTranslateResponse,
"SummaryCard.ReqSummaryCard": decodeSummaryCardResponse,
"PttCenterSvr.ShortVideoDownReq": decodePttShortVideoDownResponse,
"LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse,
"PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500": decodePrivatePttStoreResponse,
}
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}
@ -130,59 +157,19 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
SequenceId: 0x3635,
RandomKey: make([]byte, 16),
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
decoders: map[string]func(*QQClient, uint16, []byte) (interface{}, error){
"wtlogin.login": decodeLoginResponse,
"wtlogin.exchange_emp": decodeExchangeEmpResponse,
"StatSvc.register": decodeClientRegisterResponse,
"StatSvc.ReqMSFOffline": decodeMSFOfflinePacket,
"StatSvc.GetDevLoginInfo": decodeDevListResponse,
"MessageSvc.PushNotify": decodeSvcNotify,
"OnlinePush.PbPushGroupMsg": decodeGroupMessagePacket,
"OnlinePush.ReqPush": decodeOnlinePushReqPacket,
"OnlinePush.PbPushTransMsg": decodeOnlinePushTransPacket,
"ConfigPushSvc.PushReq": decodePushReqPacket,
"MessageSvc.PbGetMsg": decodeMessageSvcPacket,
"MessageSvc.PbSendMsg": decodeMsgSendResponse,
"MessageSvc.PushForceOffline": decodeForceOfflinePacket,
"PbMessageSvc.PbMsgWithDraw": decodeMsgWithDrawResponse,
"friendlist.getFriendGroupList": decodeFriendGroupListResponse,
"friendlist.GetTroopListReqV2": decodeGroupListResponse,
"friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse,
"group_member_card.get_group_member_card_info": decodeGroupMemberInfoResponse,
"ImgStore.GroupPicUp": decodeGroupImageStoreResponse,
"PttStore.GroupPttUp": decodeGroupPttStoreResponse,
"LongConn.OffPicUp": decodeOffPicUpResponse,
"ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket,
"ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket,
"MultiMsg.ApplyUp": decodeMultiApplyUpResponse,
"MultiMsg.ApplyDown": decodeMultiApplyDownResponse,
"OidbSvc.0x6d6_2": decodeOIDB6d62Response,
"OidbSvc.0x6d6_3": decodeOIDB6d63Response,
"OidbSvc.0x6d8_1": decodeOIDB6d81Response,
"OidbSvc.0x88d_0": decodeGroupInfoResponse,
"OidbSvc.0xe07_0": decodeImageOcrResponse,
"OidbSvc.0xd79": decodeWordSegmentation,
"OidbSvc.0x990": decodeTranslateResponse,
"SummaryCard.ReqSummaryCard": decodeSummaryCardResponse,
"SummaryCard.ReqSearch": decodeGroupSearchResponse,
"PttCenterSvr.ShortVideoDownReq": decodePttShortVideoDownResponse,
"LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse,
"OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_DOWNLOAD-1200": decodeOfflineFileDownloadResponse,
"PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_UPLOAD-500": decodePrivatePttStoreResponse,
},
sigInfo: &loginSigInfo{},
requestPacketRequestId: 1921334513,
groupSeq: int32(rand.Intn(20000)),
friendSeq: 22911,
highwayApplyUpSeq: 77918,
ksid: []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", SystemDeviceInfo.IMEI)),
eventHandlers: &eventHandlers{},
msgSvcCache: utils.NewCache(time.Second * 15),
transCache: utils.NewCache(time.Second * 15),
onlinePushCache: utils.NewCache(time.Second * 15),
version: genVersionInfo(SystemDeviceInfo.Protocol),
servers: []*net.TCPAddr{},
stat: &Statistics{},
sigInfo: &loginSigInfo{},
requestPacketRequestId: 1921334513,
groupSeq: int32(rand.Intn(20000)),
friendSeq: 22911,
highwayApplyUpSeq: 77918,
ksid: []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", SystemDeviceInfo.IMEI)),
eventHandlers: &eventHandlers{},
msgSvcCache: utils.NewCache(time.Second * 15),
transCache: utils.NewCache(time.Second * 15),
onlinePushCache: utils.NewCache(time.Second * 15),
version: genVersionInfo(SystemDeviceInfo.Protocol),
servers: []*net.TCPAddr{},
stat: &Statistics{},
}
sso, err := getSSOAddress()
if err == nil && len(sso) > 0 {
@ -425,84 +412,6 @@ func (c *QQClient) GetShortVideoUrl(uuid, md5 []byte) string {
return i.(string)
}
func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage, f ...bool) *message.GroupMessage {
useFram := false
if len(f) > 0 {
useFram = f[0]
}
imgCount := m.Count(func(e message.IMessageElement) bool { return e.Type() == message.Image })
if useFram {
if m.Any(func(e message.IMessageElement) bool { return e.Type() == message.Reply }) {
useFram = false
}
}
msgLen := message.EstimateLength(m.Elements, 703)
if msgLen > 5000 || imgCount > 50 {
return nil
}
if (msgLen > 200 || imgCount > 1) && !useFram {
ret := c.sendGroupLongOrForwardMessage(groupCode, true, &message.ForwardMessage{Nodes: []*message.ForwardNode{
{
SenderId: c.Uin,
SenderName: c.Nickname,
Time: int32(time.Now().Unix()),
Message: m.Elements,
},
}})
return ret
}
return c.sendGroupMessage(groupCode, false, m)
}
func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.SendingMessage) *message.GroupMessage {
eid := utils.RandomString(6)
mr := int32(rand.Uint32())
ch := make(chan int32)
c.onGroupMessageReceipt(eid, func(c *QQClient, e *groupMessageReceiptEvent) {
if e.Rand == mr {
ch <- e.Seq
}
})
defer c.onGroupMessageReceipt(eid)
imgCount := m.Count(func(e message.IMessageElement) bool { return e.Type() == message.Image })
msgLen := message.EstimateLength(m.Elements, 703)
if (msgLen > 200 || imgCount > 1) && !forward && !m.Any(func(e message.IMessageElement) bool {
_, ok := e.(*message.GroupVoiceElement)
_, ok2 := e.(*message.ServiceElement)
return ok || ok2
}) {
div := int32(rand.Uint32())
fragmented := m.ToFragmented()
for i, elems := range fragmented {
_, pkt := c.buildGroupSendingPacket(groupCode, mr, int32(len(fragmented)), int32(i), div, forward, elems)
_ = c.send(pkt)
}
} else {
_, pkt := c.buildGroupSendingPacket(groupCode, mr, 1, 0, 0, forward, m.Elements)
_ = c.send(pkt)
}
var mid int32
ret := &message.GroupMessage{
Id: -1,
InternalId: mr,
GroupCode: groupCode,
Sender: &message.Sender{
Uin: c.Uin,
Nickname: c.Nickname,
IsFriend: true,
},
Time: int32(time.Now().Unix()),
Elements: m.Elements,
}
select {
case mid = <-ch:
case <-time.After(time.Second * 5):
return ret
}
ret.Id = mid
return ret
}
func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) *message.PrivateMessage {
mr := int32(rand.Uint32())
seq := c.nextFriendSeq()
@ -595,68 +504,6 @@ func (c *QQClient) GetForwardMessage(resId string) *message.ForwardMessage {
return ret
}
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.GroupMessage {
return c.sendGroupLongOrForwardMessage(groupCode, false, m)
}
func (c *QQClient) sendGroupLongOrForwardMessage(groupCode int64, isLong bool, m *message.ForwardMessage) *message.GroupMessage {
if len(m.Nodes) >= 200 {
return nil
}
ts := time.Now().Unix()
seq := c.nextGroupSeq()
data, hash := m.CalculateValidationData(seq, rand.Int31(), groupCode)
i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, func() int32 {
if isLong {
return 1
} else {
return 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 {
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 {
var r string
for _, n := range m.Nodes {
r += message.ToReadableString(n.Message)
if len(r) >= 27 {
break
}
}
return r
}()
return c.sendGroupMessage(groupCode, false, genLongTemplate(rsp.MsgResid, bri, ts))
}
}
return nil
}
func (c *QQClient) sendGroupPoke(groupCode, target int64) {
_, _ = c.sendAndWait(c.buildGroupPokePacket(groupCode, target))
}
@ -1163,7 +1010,7 @@ func (c *QQClient) netLoop() {
}
}()
if decoder, ok := c.decoders[pkt.CommandName]; ok {
if decoder, ok := decoders[pkt.CommandName]; ok {
// found predefined decoder
rsp, err := decoder(c, pkt.SequenceId, payload)
if err != nil {

View File

@ -378,53 +378,6 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{},
return nil, err
}
// OnlinePush.PbPushGroupMsg
func decodeGroupMessagePacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
pkt := msg.PushMessagePacket{}
err := proto.Unmarshal(payload, &pkt)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if pkt.Message.Head.GetFromUin() == c.Uin {
c.dispatchGroupMessageReceiptEvent(&groupMessageReceiptEvent{
Rand: pkt.Message.Body.RichText.Attr.GetRandom(),
Seq: pkt.Message.Head.GetMsgSeq(),
Msg: c.parseGroupMessage(pkt.Message),
})
return nil, nil
}
if pkt.Message.Content != nil && pkt.Message.Content.GetPkgNum() > 1 {
var builder *groupMessageBuilder // TODO: 支持多SEQ
i, ok := c.groupMsgBuilders.Load(pkt.Message.Content.DivSeq)
if !ok {
builder = &groupMessageBuilder{}
c.groupMsgBuilders.Store(pkt.Message.Content.DivSeq, builder)
} 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.DivSeq)
c.dispatchGroupMessage(c.parseGroupMessage(builder.build()))
}
return nil, nil
}
c.dispatchGroupMessage(c.parseGroupMessage(pkt.Message))
return nil, nil
}
// MessageSvc.PbSendMsg
func decodeMsgSendResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
rsp := msg.SendMessageResponse{}
if err := proto.Unmarshal(payload, &rsp); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if rsp.GetResult() != 0 {
c.Error("send msg error: %v %v", rsp.GetResult(), rsp.GetErrMsg())
}
return nil, nil
}
// MessageSvc.PushNotify
func decodeSvcNotify(c *QQClient, _ uint16, _ []byte) (interface{}, error) {
_, err := c.sendAndWait(c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix()))

View File

@ -47,6 +47,12 @@ type (
}
)
func init() {
decoders["OidbSvc.0x6d8_1"] = decodeOIDB6d81Response
decoders["OidbSvc.0x6d6_2"] = decodeOIDB6d62Response
decoders["OidbSvc.0x6d6_3"] = decodeOIDB6d63Response
}
func (c *QQClient) GetGroupFileSystem(groupCode int64) (fs *GroupFileSystem, err error) {
defer func() {
if pan := recover(); pan != nil {

View File

@ -9,6 +9,11 @@ import (
"google.golang.org/protobuf/proto"
)
func init() {
decoders["SummaryCard.ReqSearch"] = decodeGroupSearchResponse
decoders["OidbSvc.0x88d_0"] = decodeGroupInfoResponse
}
func (c *QQClient) GetGroupInfo(groupCode int64) (*GroupInfo, error) {
i, err := c.sendAndWait(c.buildGroupInfoRequestPacket(groupCode))
if err != nil {

291
client/group_msg.go Normal file
View File

@ -0,0 +1,291 @@
package client
import (
"fmt"
"github.com/Mrs4s/MiraiGo/client/pb/longmsg"
"github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/client/pb/multimsg"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/protocol/packets"
"github.com/Mrs4s/MiraiGo/utils"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
"math"
"math/rand"
"time"
)
func init() {
decoders["OnlinePush.PbPushGroupMsg"] = decodeGroupMessagePacket
decoders["MessageSvc.PbSendMsg"] = decodeMsgSendResponse
decoders["MessageSvc.PbGetGroupMsg"] = decodeGetGroupMsgResponse
}
// SendGroupMessage 发送群消息
func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage, f ...bool) *message.GroupMessage {
useFram := false
if len(f) > 0 {
useFram = f[0]
}
imgCount := m.Count(func(e message.IMessageElement) bool { return e.Type() == message.Image })
if useFram {
if m.Any(func(e message.IMessageElement) bool { return e.Type() == message.Reply }) {
useFram = false
}
}
msgLen := message.EstimateLength(m.Elements, 703)
if msgLen > 5000 || imgCount > 50 {
return nil
}
if (msgLen > 200 || imgCount > 1) && !useFram {
ret := c.sendGroupLongOrForwardMessage(groupCode, true, &message.ForwardMessage{Nodes: []*message.ForwardNode{
{
SenderId: c.Uin,
SenderName: c.Nickname,
Time: int32(time.Now().Unix()),
Message: m.Elements,
},
}})
return ret
}
return c.sendGroupMessage(groupCode, false, m)
}
// SendGroupForwardMessage 发送群合并转发消息
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.GroupMessage {
return c.sendGroupLongOrForwardMessage(groupCode, false, m)
}
// GetGroupMessages 从服务器获取历史信息
func (c *QQClient) GetGroupMessages(groupCode, beginSeq, endSeq int64) ([]*message.GroupMessage, error) {
i, err := c.sendAndWait(c.buildGetGroupMsgRequest(groupCode, beginSeq, endSeq))
if err != nil {
return nil, err
}
return i.([]*message.GroupMessage), nil
}
func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.SendingMessage) *message.GroupMessage {
eid := utils.RandomString(6)
mr := int32(rand.Uint32())
ch := make(chan int32)
c.onGroupMessageReceipt(eid, func(c *QQClient, e *groupMessageReceiptEvent) {
if e.Rand == mr {
ch <- e.Seq
}
})
defer c.onGroupMessageReceipt(eid)
imgCount := m.Count(func(e message.IMessageElement) bool { return e.Type() == message.Image })
msgLen := message.EstimateLength(m.Elements, 703)
if (msgLen > 200 || imgCount > 1) && !forward && !m.Any(func(e message.IMessageElement) bool {
_, ok := e.(*message.GroupVoiceElement)
_, ok2 := e.(*message.ServiceElement)
return ok || ok2
}) {
div := int32(rand.Uint32())
fragmented := m.ToFragmented()
for i, elems := range fragmented {
_, pkt := c.buildGroupSendingPacket(groupCode, mr, int32(len(fragmented)), int32(i), div, forward, elems)
_ = c.send(pkt)
}
} else {
_, pkt := c.buildGroupSendingPacket(groupCode, mr, 1, 0, 0, forward, m.Elements)
_ = c.send(pkt)
}
var mid int32
ret := &message.GroupMessage{
Id: -1,
InternalId: mr,
GroupCode: groupCode,
Sender: &message.Sender{
Uin: c.Uin,
Nickname: c.Nickname,
IsFriend: true,
},
Time: int32(time.Now().Unix()),
Elements: m.Elements,
}
select {
case mid = <-ch:
case <-time.After(time.Second * 5):
return ret
}
ret.Id = mid
return ret
}
func (c *QQClient) sendGroupLongOrForwardMessage(groupCode int64, isLong bool, m *message.ForwardMessage) *message.GroupMessage {
if len(m.Nodes) >= 200 {
return nil
}
ts := time.Now().Unix()
seq := c.nextGroupSeq()
data, hash := m.CalculateValidationData(seq, rand.Int31(), groupCode)
i, err := c.sendAndWait(c.buildMultiApplyUpPacket(data, hash, func() int32 {
if isLong {
return 1
} else {
return 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 {
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 {
var r string
for _, n := range m.Nodes {
r += message.ToReadableString(n.Message)
if len(r) >= 27 {
break
}
}
return r
}()
return c.sendGroupMessage(groupCode, false, genLongTemplate(rsp.MsgResid, bri, ts))
}
}
return nil
}
// MessageSvc.PbSendMsg
func (c *QQClient) buildGroupSendingPacket(groupCode int64, r, pkgNum, pkgIndex, pkgDiv int32, forward bool, m []message.IMessageElement) (uint16, []byte) {
seq := c.nextSeq()
var ptt *message.GroupVoiceElement
if len(m) > 0 {
if p, ok := m[0].(*message.GroupVoiceElement); ok {
ptt = p
m = []message.IMessageElement{}
}
}
req := &msg.SendMessageRequest{
RoutingHead: &msg.RoutingHead{Grp: &msg.Grp{GroupCode: &groupCode}},
ContentHead: &msg.ContentHead{PkgNum: &pkgNum, PkgIndex: &pkgIndex, DivSeq: &pkgDiv},
MsgBody: &msg.MessageBody{
RichText: &msg.RichText{
Elems: message.ToProtoElems(m, true),
Ptt: func() *msg.Ptt {
if ptt != nil {
return ptt.Ptt
}
return nil
}(),
},
},
MsgSeq: proto.Int32(c.nextGroupSeq()),
MsgRand: &r,
SyncCookie: EmptyBytes,
MsgVia: proto.Int32(1),
MsgCtrl: func() *msg.MsgCtrl {
if forward {
return &msg.MsgCtrl{MsgFlag: proto.Int32(4)}
}
return nil
}(),
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbSendMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
func (c *QQClient) buildGetGroupMsgRequest(groupCode, beginSeq, endSeq int64) (uint16, []byte) {
seq := c.nextSeq()
req := &msg.GetGroupMsgReq{
GroupCode: proto.Uint64(uint64(groupCode)),
BeginSeq: proto.Uint64(uint64(beginSeq)),
EndSeq: proto.Uint64(uint64(endSeq)),
PublicGroup: proto.Bool(false),
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbGetGroupMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
// OnlinePush.PbPushGroupMsg
func decodeGroupMessagePacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
pkt := msg.PushMessagePacket{}
err := proto.Unmarshal(payload, &pkt)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if pkt.Message.Head.GetFromUin() == c.Uin {
c.dispatchGroupMessageReceiptEvent(&groupMessageReceiptEvent{
Rand: pkt.Message.Body.RichText.Attr.GetRandom(),
Seq: pkt.Message.Head.GetMsgSeq(),
Msg: c.parseGroupMessage(pkt.Message),
})
return nil, nil
}
if pkt.Message.Content != nil && pkt.Message.Content.GetPkgNum() > 1 {
var builder *groupMessageBuilder // TODO: 支持多SEQ
i, ok := c.groupMsgBuilders.Load(pkt.Message.Content.DivSeq)
if !ok {
builder = &groupMessageBuilder{}
c.groupMsgBuilders.Store(pkt.Message.Content.DivSeq, builder)
} 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.DivSeq)
c.dispatchGroupMessage(c.parseGroupMessage(builder.build()))
}
return nil, nil
}
c.dispatchGroupMessage(c.parseGroupMessage(pkt.Message))
return nil, nil
}
func decodeMsgSendResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
rsp := msg.SendMessageResponse{}
if err := proto.Unmarshal(payload, &rsp); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if rsp.GetResult() != 0 {
c.Error("send msg error: %v %v", rsp.GetResult(), rsp.GetErrMsg())
}
return nil, nil
}
func decodeGetGroupMsgResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
rsp := msg.GetGroupMsgResp{}
if err := proto.Unmarshal(payload, &rsp); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if rsp.GetResult() != 0 {
c.Error("get msg error: %v %v", rsp.GetResult(), rsp.GetErrmsg())
return nil, errors.Errorf("get msg error: %v msg: %v", rsp.GetResult(), rsp.GetErrmsg())
}
var ret []*message.GroupMessage
for _, m := range rsp.Msg {
if m.Head.FromUin == nil {
continue
}
ret = append(ret, c.parseGroupMessage(m))
}
return ret, nil
}

View File

@ -7,6 +7,10 @@ import (
"google.golang.org/protobuf/proto"
)
func init() {
decoders["OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_DOWNLOAD-1200"] = decodeOfflineFileDownloadResponse
}
func (c *QQClient) buildOfflineFileDownloadRequestPacket(uuid []byte) (uint16, []byte) {
seq := c.nextSeq()
req := &cmd0x346.C346ReqBody{

View File

@ -6547,6 +6547,196 @@ func (x *UinTypeUserDef) GetFileUuid() string {
return ""
}
type GetGroupMsgReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
GroupCode *uint64 `protobuf:"varint,1,opt,name=groupCode" json:"groupCode,omitempty"`
BeginSeq *uint64 `protobuf:"varint,2,opt,name=beginSeq" json:"beginSeq,omitempty"`
EndSeq *uint64 `protobuf:"varint,3,opt,name=endSeq" json:"endSeq,omitempty"`
Filter *uint32 `protobuf:"varint,4,opt,name=filter" json:"filter,omitempty"`
MemberSeq *uint64 `protobuf:"varint,5,opt,name=memberSeq" json:"memberSeq,omitempty"`
PublicGroup *bool `protobuf:"varint,6,opt,name=publicGroup" json:"publicGroup,omitempty"`
ShieldFlag *uint32 `protobuf:"varint,7,opt,name=shieldFlag" json:"shieldFlag,omitempty"`
SaveTrafficFlag *uint32 `protobuf:"varint,8,opt,name=saveTrafficFlag" json:"saveTrafficFlag,omitempty"`
}
func (x *GetGroupMsgReq) Reset() {
*x = GetGroupMsgReq{}
if protoimpl.UnsafeEnabled {
mi := &file_msg_proto_msgTypes[65]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetGroupMsgReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetGroupMsgReq) ProtoMessage() {}
func (x *GetGroupMsgReq) ProtoReflect() protoreflect.Message {
mi := &file_msg_proto_msgTypes[65]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetGroupMsgReq.ProtoReflect.Descriptor instead.
func (*GetGroupMsgReq) Descriptor() ([]byte, []int) {
return file_msg_proto_rawDescGZIP(), []int{65}
}
func (x *GetGroupMsgReq) GetGroupCode() uint64 {
if x != nil && x.GroupCode != nil {
return *x.GroupCode
}
return 0
}
func (x *GetGroupMsgReq) GetBeginSeq() uint64 {
if x != nil && x.BeginSeq != nil {
return *x.BeginSeq
}
return 0
}
func (x *GetGroupMsgReq) GetEndSeq() uint64 {
if x != nil && x.EndSeq != nil {
return *x.EndSeq
}
return 0
}
func (x *GetGroupMsgReq) GetFilter() uint32 {
if x != nil && x.Filter != nil {
return *x.Filter
}
return 0
}
func (x *GetGroupMsgReq) GetMemberSeq() uint64 {
if x != nil && x.MemberSeq != nil {
return *x.MemberSeq
}
return 0
}
func (x *GetGroupMsgReq) GetPublicGroup() bool {
if x != nil && x.PublicGroup != nil {
return *x.PublicGroup
}
return false
}
func (x *GetGroupMsgReq) GetShieldFlag() uint32 {
if x != nil && x.ShieldFlag != nil {
return *x.ShieldFlag
}
return 0
}
func (x *GetGroupMsgReq) GetSaveTrafficFlag() uint32 {
if x != nil && x.SaveTrafficFlag != nil {
return *x.SaveTrafficFlag
}
return 0
}
type GetGroupMsgResp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Result *uint32 `protobuf:"varint,1,opt,name=result" json:"result,omitempty"`
Errmsg *string `protobuf:"bytes,2,opt,name=errmsg" json:"errmsg,omitempty"`
GroupCode *uint64 `protobuf:"varint,3,opt,name=groupCode" json:"groupCode,omitempty"`
ReturnBeginSeq *uint64 `protobuf:"varint,4,opt,name=returnBeginSeq" json:"returnBeginSeq,omitempty"`
ReturnEndSeq *uint64 `protobuf:"varint,5,opt,name=returnEndSeq" json:"returnEndSeq,omitempty"`
Msg []*Message `protobuf:"bytes,6,rep,name=msg" json:"msg,omitempty"`
}
func (x *GetGroupMsgResp) Reset() {
*x = GetGroupMsgResp{}
if protoimpl.UnsafeEnabled {
mi := &file_msg_proto_msgTypes[66]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetGroupMsgResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetGroupMsgResp) ProtoMessage() {}
func (x *GetGroupMsgResp) ProtoReflect() protoreflect.Message {
mi := &file_msg_proto_msgTypes[66]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetGroupMsgResp.ProtoReflect.Descriptor instead.
func (*GetGroupMsgResp) Descriptor() ([]byte, []int) {
return file_msg_proto_rawDescGZIP(), []int{66}
}
func (x *GetGroupMsgResp) GetResult() uint32 {
if x != nil && x.Result != nil {
return *x.Result
}
return 0
}
func (x *GetGroupMsgResp) GetErrmsg() string {
if x != nil && x.Errmsg != nil {
return *x.Errmsg
}
return ""
}
func (x *GetGroupMsgResp) GetGroupCode() uint64 {
if x != nil && x.GroupCode != nil {
return *x.GroupCode
}
return 0
}
func (x *GetGroupMsgResp) GetReturnBeginSeq() uint64 {
if x != nil && x.ReturnBeginSeq != nil {
return *x.ReturnBeginSeq
}
return 0
}
func (x *GetGroupMsgResp) GetReturnEndSeq() uint64 {
if x != nil && x.ReturnEndSeq != nil {
return *x.ReturnEndSeq
}
return 0
}
func (x *GetGroupMsgResp) GetMsg() []*Message {
if x != nil {
return x.Msg
}
return nil
}
var File_msg_proto protoreflect.FileDescriptor
var file_msg_proto_rawDesc = []byte{
@ -7558,11 +7748,40 @@ var file_msg_proto_rawDesc = []byte{
0x6d, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
0x52, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12,
0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x75, 0x69, 0x64, 0x2a, 0x2e, 0x0a, 0x08, 0x53,
0x79, 0x6e, 0x63, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54,
0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x4d, 0x45, 0x10,
0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x42, 0x07, 0x5a, 0x05, 0x2e,
0x3b, 0x6d, 0x73, 0x67,
0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x75, 0x69, 0x64, 0x22, 0x84, 0x02, 0x0a, 0x0e,
0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x12, 0x1c,
0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08,
0x62, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
0x62, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x64, 0x53,
0x65, 0x71, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x65, 0x6e, 0x64, 0x53, 0x65, 0x71,
0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x62,
0x65, 0x72, 0x53, 0x65, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x65, 0x6d,
0x62, 0x65, 0x72, 0x53, 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x68, 0x69, 0x65,
0x6c, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x68,
0x69, 0x65, 0x6c, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x61, 0x76, 0x65,
0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x46, 0x6c, 0x61, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0f, 0x73, 0x61, 0x76, 0x65, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x46, 0x6c,
0x61, 0x67, 0x22, 0xc7, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d,
0x73, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16,
0x0a, 0x06, 0x65, 0x72, 0x72, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x65, 0x72, 0x72, 0x6d, 0x73, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43,
0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x43, 0x6f, 0x64, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x42, 0x65,
0x67, 0x69, 0x6e, 0x53, 0x65, 0x71, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x65, 0x71, 0x12, 0x22, 0x0a, 0x0c,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x53, 0x65, 0x71, 0x18, 0x05, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0c, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x53, 0x65, 0x71,
0x12, 0x1a, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x2a, 0x2e, 0x0a, 0x08,
0x53, 0x79, 0x6e, 0x63, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52,
0x54, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x4d, 0x45,
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x42, 0x07, 0x5a, 0x05,
0x2e, 0x3b, 0x6d, 0x73, 0x67,
}
var (
@ -7578,7 +7797,7 @@ func file_msg_proto_rawDescGZIP() []byte {
}
var file_msg_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 65)
var file_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 67)
var file_msg_proto_goTypes = []interface{}{
(SyncFlag)(0), // 0: SyncFlag
(*GetMessageRequest)(nil), // 1: GetMessageRequest
@ -7646,6 +7865,8 @@ var file_msg_proto_goTypes = []interface{}{
(*ResvAttr)(nil), // 63: ResvAttr
(*AnimationImageShow)(nil), // 64: AnimationImageShow
(*UinTypeUserDef)(nil), // 65: UinTypeUserDef
(*GetGroupMsgReq)(nil), // 66: GetGroupMsgReq
(*GetGroupMsgResp)(nil), // 67: GetGroupMsgResp
}
var file_msg_proto_depIdxs = []int32{
0, // 0: GetMessageRequest.syncFlag:type_name -> SyncFlag
@ -7713,11 +7934,12 @@ var file_msg_proto_depIdxs = []int32{
34, // 62: MsgElemInfo_servtype3.flash_c2c_pic:type_name -> NotOnlineImage
35, // 63: SubMsgType0x4Body.notOnlineFile:type_name -> NotOnlineFile
64, // 64: ResvAttr.image_show:type_name -> AnimationImageShow
65, // [65:65] is the sub-list for method output_type
65, // [65:65] is the sub-list for method input_type
65, // [65:65] is the sub-list for extension type_name
65, // [65:65] is the sub-list for extension extendee
0, // [0:65] is the sub-list for field type_name
20, // 65: GetGroupMsgResp.msg:type_name -> Message
66, // [66:66] is the sub-list for method output_type
66, // [66:66] is the sub-list for method input_type
66, // [66:66] is the sub-list for extension type_name
66, // [66:66] is the sub-list for extension extendee
0, // [0:66] is the sub-list for field type_name
}
func init() { file_msg_proto_init() }
@ -8506,6 +8728,30 @@ func file_msg_proto_init() {
return nil
}
}
file_msg_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetGroupMsgReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_msg_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetGroupMsgResp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -8513,7 +8759,7 @@ func file_msg_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_msg_proto_rawDesc,
NumEnums: 1,
NumMessages: 65,
NumMessages: 67,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -748,4 +748,24 @@ message UinTypeUserDef {
optional int32 fromUinType = 1;
optional int64 fromGroupCode = 2;
optional string fileUuid = 3;
}
message GetGroupMsgReq {
optional uint64 groupCode = 1;
optional uint64 beginSeq = 2;
optional uint64 endSeq = 3;
optional uint32 filter = 4;
optional uint64 memberSeq = 5;
optional bool publicGroup = 6;
optional uint32 shieldFlag = 7;
optional uint32 saveTrafficFlag = 8;
}
message GetGroupMsgResp {
optional uint32 result = 1;
optional string errmsg = 2;
optional uint64 groupCode = 3;
optional uint64 returnBeginSeq = 4;
optional uint64 returnEndSeq = 5;
repeated Message msg = 6;
}