diff --git a/client/builders.go b/client/builders.go index c6ec02ae..e321b789 100644 --- a/client/builders.go +++ b/client/builders.go @@ -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() diff --git a/client/client.go b/client/client.go index 8e753d7e..1d89bba8 100644 --- a/client/client.go +++ b/client/client.go @@ -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(`%s: %s`, 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 { diff --git a/client/decoders.go b/client/decoders.go index 9b3ac41e..b0c576a5 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -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())) diff --git a/client/group_file.go b/client/group_file.go index 3c323d3b..183eee18 100644 --- a/client/group_file.go +++ b/client/group_file.go @@ -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 { diff --git a/client/group_info.go b/client/group_info.go index f10d8957..9c6e01c4 100644 --- a/client/group_info.go +++ b/client/group_info.go @@ -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 { diff --git a/client/group_msg.go b/client/group_msg.go new file mode 100644 index 00000000..f7e6cb9d --- /dev/null +++ b/client/group_msg.go @@ -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(`%s: %s`, 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 +} diff --git a/client/offline_file.go b/client/offline_file.go index 1f172978..63d2db09 100644 --- a/client/offline_file.go +++ b/client/offline_file.go @@ -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{ diff --git a/client/pb/msg/msg.pb.go b/client/pb/msg/msg.pb.go index 1819e3b2..409b42f6 100644 --- a/client/pb/msg/msg.pb.go +++ b/client/pb/msg/msg.pb.go @@ -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, }, diff --git a/client/pb/msg/msg.proto b/client/pb/msg/msg.proto index 1dc4ef57..01757128 100644 --- a/client/pb/msg/msg.proto +++ b/client/pb/msg/msg.proto @@ -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; } \ No newline at end of file