From d0b263402937842494940a093f000cfaf8c0e173 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 24 Jan 2021 02:20:02 +0800 Subject: [PATCH 1/5] save progress. --- client/builders.go | 178 +++---------------- client/client.go | 71 +------- client/global.go | 162 ++--------------- client/group_msg.go | 152 +++++++++++++++- client/pb/msg/msg.pb.go | 377 +++++++++++++++++++++++++++++++--------- client/pb/msg/msg.proto | 17 ++ client/private_msg.go | 165 ++++++++++++++++++ 7 files changed, 668 insertions(+), 454 deletions(-) create mode 100644 client/private_msg.go diff --git a/client/builders.go b/client/builders.go index b8595112..67440637 100644 --- a/client/builders.go +++ b/client/builders.go @@ -594,79 +594,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) buildFriendSendingPacket(target int64, msgSeq, r, pkgNum, pkgIndex, pkgDiv int32, time int64, m []message.IMessageElement) (uint16, []byte) { - seq := c.nextSeq() - var ptt *msg.Ptt - if len(m) > 0 { - if p, ok := m[0].(*message.PrivateVoiceElement); ok { - ptt = p.Ptt - m = []message.IMessageElement{} - } - } - req := &msg.SendMessageRequest{ - RoutingHead: &msg.RoutingHead{C2C: &msg.C2C{ToUin: &target}}, - ContentHead: &msg.ContentHead{PkgNum: &pkgNum, PkgIndex: &pkgIndex, DivSeq: &pkgDiv}, - MsgBody: &msg.MessageBody{ - RichText: &msg.RichText{ - Elems: message.ToProtoElems(m, false), - Ptt: ptt, - }, - }, - MsgSeq: &msgSeq, - MsgRand: &r, - SyncCookie: func() []byte { - cookie := &msg.SyncCookie{ - Time: &time, - Ran1: proto.Int64(rand.Int63()), - Ran2: proto.Int64(rand.Int63()), - Const1: &syncConst1, - Const2: &syncConst2, - Const3: proto.Int64(0x1d), - } - b, _ := proto.Marshal(cookie) - return b - }(), - } - 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) buildTempSendingPacket(groupUin, target int64, msgSeq, r int32, time int64, m *message.SendingMessage) (uint16, []byte) { - seq := c.nextSeq() - req := &msg.SendMessageRequest{ - RoutingHead: &msg.RoutingHead{GrpTmp: &msg.GrpTmp{ - GroupUin: &groupUin, - ToUin: &target, - }}, - ContentHead: &msg.ContentHead{PkgNum: proto.Int32(1)}, - MsgBody: &msg.MessageBody{ - RichText: &msg.RichText{ - Elems: message.ToProtoElems(m.Elements, false), - }, - }, - MsgSeq: &msgSeq, - MsgRand: &r, - SyncCookie: func() []byte { - cookie := &msg.SyncCookie{ - Time: &time, - Ran1: proto.Int64(rand.Int63()), - Ran2: proto.Int64(rand.Int63()), - Const1: &syncConst1, - Const2: &syncConst2, - Const3: proto.Int64(0x1d), - } - b, _ := proto.Marshal(cookie) - return b - }(), - } - payload, _ := proto.Marshal(req) - packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbSendMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) - return seq, packet -} - // LongConn.OffPicUp func (c *QQClient) buildOffPicUpPacket(target int64, md5 []byte, size int32) (uint16, []byte) { seq := c.nextSeq() @@ -825,12 +752,7 @@ func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTi }, } b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 2300, - ServiceType: 2, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(2300, 2, b) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8fc_2", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -839,11 +761,7 @@ func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTi func (c *QQClient) buildGroupOperationPacket(body *oidb.D89AReqBody) (uint16, []byte) { seq := c.nextSeq() b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 2202, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(2202, 0, b) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x89a_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -904,11 +822,7 @@ func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg stri KickMsg: []byte(kickMsg), } b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 2208, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(2208, 0, b) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8a0_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -916,18 +830,13 @@ func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg stri // OidbSvc.0x570_8 func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) (uint16, []byte) { seq := c.nextSeq() - req := &oidb.OIDBSSOPkg{ - Command: 1392, - ServiceType: 8, - Bodybuffer: binary.NewWriterF(func(w *binary.Writer) { - w.WriteUInt32(uint32(groupCode)) - w.WriteByte(32) - w.WriteUInt16(1) - w.WriteUInt32(uint32(memberUin)) - w.WriteUInt32(time) - }), - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(1392, 8, binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt32(uint32(groupCode)) + w.WriteByte(32) + w.WriteUInt16(1) + w.WriteUInt32(uint32(memberUin)) + w.WriteUInt32(time) + })) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x570_8", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -940,12 +849,7 @@ func (c *QQClient) buildGroupPokePacket(groupCode, target int64) (uint16, []byte GroupCode: groupCode, } b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 3795, - ServiceType: 1, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(3795, 1, b) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xed3", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -958,12 +862,7 @@ func (c *QQClient) buildFriendPokePacket(target int64) (uint16, []byte) { AioUin: target, } b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 3795, - ServiceType: 1, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(3795, 1, b) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xed3", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -971,21 +870,16 @@ func (c *QQClient) buildFriendPokePacket(target int64) (uint16, []byte) { // OidbSvc.0x55c_1 func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) (uint16, []byte) { seq := c.nextSeq() - req := &oidb.OIDBSSOPkg{ - Command: 1372, - ServiceType: 1, - Bodybuffer: binary.NewWriterF(func(w *binary.Writer) { - w.WriteUInt32(uint32(groupCode)) - w.WriteUInt32(uint32(member)) - w.WriteByte(func() byte { - if flag { - return 1 - } - return 0 - }()) - }), - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(1372, 1, binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt32(uint32(groupCode)) + w.WriteUInt32(uint32(member)) + w.WriteByte(func() byte { + if flag { + return 1 + } + return 0 + }()) + })) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x55c_1", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -1031,11 +925,7 @@ func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, hei }, } b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 3591, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + payload := c.packOIDBPackage(3591, 0, b) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xe07_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -1062,18 +952,11 @@ func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) { seq := c.nextSeq() - body := &oidb.D79ReqBody{ + payload := c.packOIDBPackageProto(3449, 1, &oidb.D79ReqBody{ Uin: uint64(c.Uin), Content: data, Qua: []byte("and_537065262_8.4.5"), - } - b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 3449, - ServiceType: 1, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + }) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xd79", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -1081,7 +964,7 @@ func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) { // OidbSvc.0xdad_1 func (c *QQClient) sendGroupGiftPacket(groupCode, uin uint64, productId message.GroupGift) (uint16, []byte) { seq := c.nextSeq() - body := &oidb.DADReqBody{ + payload := c.packOIDBPackageProto(3501, 1, &oidb.DADReqBody{ Client: 1, ProductId: uint64(productId), ToUin: uin, @@ -1091,14 +974,7 @@ func (c *QQClient) sendGroupGiftPacket(groupCode, uin uint64, productId message. Type: 1, Sig: []byte(c.getSKey()), }, - } - b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 3501, - ServiceType: 1, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + }) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xdad_1", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } diff --git a/client/client.go b/client/client.go index 28f654fb..74a16c83 100644 --- a/client/client.go +++ b/client/client.go @@ -426,75 +426,6 @@ func (c *QQClient) GetFriendList() (*FriendListResponse, error) { return r, nil } -func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) *message.PrivateMessage { - mr := int32(rand.Uint32()) - seq := c.nextFriendSeq() - t := time.Now().Unix() - imgCount := m.Count(func(e message.IMessageElement) bool { return e.Type() == message.Image }) - msgLen := message.EstimateLength(m.Elements, 703) - if msgLen > 5000 || imgCount > 50 { - return nil - } - if msgLen > 300 || imgCount > 2 { - div := int32(rand.Uint32()) - fragmented := m.ToFragmented() - for i, elems := range fragmented { - _, pkt := c.buildFriendSendingPacket(target, c.nextFriendSeq(), mr, int32(len(fragmented)), int32(i), div, t, elems) - _ = c.send(pkt) - } - } else { - _, pkt := c.buildFriendSendingPacket(target, seq, mr, 1, 0, 0, t, m.Elements) - _ = c.send(pkt) - } - c.stat.MessageSent++ - return &message.PrivateMessage{ - Id: seq, - InternalId: mr, - Target: target, - Time: int32(t), - Sender: &message.Sender{ - Uin: c.Uin, - Nickname: c.Nickname, - IsFriend: true, - }, - Elements: m.Elements, - } -} - -func (c *QQClient) SendTempMessage(groupCode, target int64, m *message.SendingMessage) *message.TempMessage { - group := c.FindGroup(groupCode) - if group == nil { - return nil - } - if c.FindFriend(target) != nil { - pm := c.SendPrivateMessage(target, m) - return &message.TempMessage{ - Id: pm.Id, - GroupCode: group.Code, - GroupName: group.Name, - Sender: pm.Sender, - Elements: m.Elements, - } - } - mr := int32(rand.Uint32()) - seq := c.nextFriendSeq() - t := time.Now().Unix() - _, pkt := c.buildTempSendingPacket(group.Uin, target, seq, mr, t, m) - _ = c.send(pkt) - c.stat.MessageSent++ - return &message.TempMessage{ - Id: seq, - GroupCode: group.Code, - GroupName: group.Name, - Sender: &message.Sender{ - Uin: c.Uin, - Nickname: c.Nickname, - IsFriend: true, - }, - Elements: m.Elements, - } -} - func (c *QQClient) GetForwardMessage(resId string) *message.ForwardMessage { m := c.DownloadForwardMessage(resId) if m == nil { @@ -972,7 +903,7 @@ func (c *QQClient) netLoop() { // does not need decoder f(nil, nil) } else { - c.Debug("\nUnhandled Command: %s\nSeq: %d\nThis message can be ignored.", pkt.CommandName, pkt.SequenceId) + c.Debug("Unhandled Command: %s\nSeq: %d\nThis message can be ignored.", pkt.CommandName, pkt.SequenceId) } }() } diff --git a/client/global.go b/client/global.go index e994ed66..18a6b357 100644 --- a/client/global.go +++ b/client/global.go @@ -3,10 +3,10 @@ package client import ( "bytes" "crypto/md5" - "encoding/base64" "encoding/hex" "encoding/xml" "fmt" + "github.com/Mrs4s/MiraiGo/client/pb/oidb" "math/rand" "net" "sort" @@ -18,7 +18,6 @@ import ( "github.com/Mrs4s/MiraiGo/binary/jce" devinfo "github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb/msg" - "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/utils" "github.com/pkg/errors" @@ -382,7 +381,7 @@ func GenIMEI() string { sum += toAdd final.WriteString(fmt.Sprintf("%d", toAdd)) // and even printing them here! } - var ctrlDigit int = (sum * 9) % 10 // calculating the control digit + var ctrlDigit = (sum * 9) % 10 // calculating the control digit final.WriteString(fmt.Sprintf("%d", ctrlDigit)) return final.String() } @@ -507,147 +506,6 @@ func (c *QQClient) parseTempMessage(msg *msg.Message) *message.TempMessage { } } -func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage { - group := c.FindGroup(m.Head.GroupInfo.GetGroupCode()) - if group == nil { - c.Debug("sync group %v.", m.Head.GroupInfo.GetGroupCode()) - info, err := c.GetGroupInfo(m.Head.GroupInfo.GetGroupCode()) - if err != nil { - c.Error("error to sync group %v : %+v", m.Head.GroupInfo.GetGroupCode(), err) - return nil - } - group = info - c.GroupList = append(c.GroupList, info) - } - if len(group.Members) == 0 { - mem, err := c.GetGroupMembers(group) - if err != nil { - c.Error("error to sync group %v member : %+v", m.Head.GroupInfo.GroupCode, err) - return nil - } - group.Members = mem - } - var anonInfo *msg.AnonymousGroupMessage - for _, e := range m.Body.RichText.Elems { - if e.AnonGroupMsg != nil { - anonInfo = e.AnonGroupMsg - } - } - var sender *message.Sender - if anonInfo != nil { - sender = &message.Sender{ - Uin: 80000000, - Nickname: string(anonInfo.AnonNick), - AnonymousInfo: &message.AnonymousInfo{ - AnonymousId: base64.StdEncoding.EncodeToString(anonInfo.AnonId), - AnonymousNick: string(anonInfo.AnonNick), - }, - IsFriend: false, - } - } else { - mem := group.FindMember(m.Head.GetFromUin()) - if mem == nil { - group.Update(func(_ *GroupInfo) { - if mem = group.FindMemberWithoutLock(m.Head.GetFromUin()); mem != nil { - return - } - info, _ := c.getMemberInfo(group.Code, m.Head.GetFromUin()) - if info == nil { - return - } - mem = info - group.Members = append(group.Members, mem) - go c.dispatchNewMemberEvent(&MemberJoinGroupEvent{ - Group: group, - Member: info, - }) - }) - if mem == nil { - return nil - } - } - sender = &message.Sender{ - Uin: mem.Uin, - Nickname: mem.Nickname, - CardName: mem.CardName, - IsFriend: c.FindFriend(mem.Uin) != nil, - } - } - var g *message.GroupMessage - g = &message.GroupMessage{ - Id: m.Head.GetMsgSeq(), - GroupCode: group.Code, - GroupName: string(m.Head.GroupInfo.GroupName), - Sender: sender, - Time: m.Head.GetMsgTime(), - Elements: message.ParseMessageElems(m.Body.RichText.Elems), - OriginalObject: m, - } - var extInfo *msg.ExtraInfo - // pre parse - for _, elem := range m.Body.RichText.Elems { - // is rich long msg - if elem.GeneralFlags != nil && elem.GeneralFlags.GetLongTextResid() != "" { - if f := c.GetForwardMessage(elem.GeneralFlags.GetLongTextResid()); f != nil && len(f.Nodes) == 1 { - g = &message.GroupMessage{ - Id: m.Head.GetMsgSeq(), - GroupCode: group.Code, - GroupName: string(m.Head.GroupInfo.GroupName), - Sender: sender, - Time: m.Head.GetMsgTime(), - Elements: f.Nodes[0].Message, - OriginalObject: m, - } - } - } - if elem.ExtraInfo != nil { - extInfo = elem.ExtraInfo - } - } - if !sender.IsAnonymous() { - mem := group.FindMember(m.Head.GetFromUin()) - groupCard := m.Head.GroupInfo.GetGroupCard() - 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 = "" - for _, e := range buf.RichCardName { - groupCard += string(e.Text) - } - } - } - if m.Head.GroupInfo != nil && groupCard != "" && mem.CardName != groupCard { - old := mem.CardName - if mem.Nickname == groupCard { - mem.CardName = "" - } else { - mem.CardName = groupCard - } - if old != mem.CardName { - go c.dispatchMemberCardUpdatedEvent(&MemberCardUpdatedEvent{ - Group: group, - OldCard: old, - Member: mem, - }) - } - } - } - if m.Body.RichText.Ptt != nil { - g.Elements = []message.IMessageElement{ - &message.VoiceElement{ - Name: m.Body.RichText.Ptt.GetFileName(), - Md5: m.Body.RichText.Ptt.FileMd5, - Size: m.Body.RichText.Ptt.GetFileSize(), - Url: "http://grouptalk.c2c.qq.com" + string(m.Body.RichText.Ptt.DownPara), - }, - } - } - if m.Body.RichText.Attr != nil { - g.InternalId = m.Body.RichText.Attr.GetRandom() - } - return g -} - func (b *groupMessageBuilder) build() *msg.Message { sort.Slice(b.MessageSlices, func(i, j int) bool { return b.MessageSlices[i].Content.GetPkgIndex() < b.MessageSlices[j].Content.GetPkgIndex() @@ -706,6 +564,22 @@ func genLongTemplate(resId, brief string, ts int64) *message.ServiceElement { } } +func (c *QQClient) packOIDBPackage(cmd, serviceType int32, body []byte) []byte { + pkg := &oidb.OIDBSSOPkg{ + Command: cmd, + ServiceType: serviceType, + Bodybuffer: body, + ClientVersion: "Android " + c.version.SortVersionName, + } + r, _ := proto.Marshal(pkg) + return r +} + +func (c *QQClient) packOIDBPackageProto(cmd, serviceType int32, msg proto.Message) []byte { + b, _ := proto.Marshal(msg) + return c.packOIDBPackage(cmd, serviceType, b) +} + func (c *QQClient) Error(msg string, args ...interface{}) { c.dispatchLogEvent(&LogEvent{ Type: "ERROR", diff --git a/client/group_msg.go b/client/group_msg.go index 15f96d8e..69350bc6 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -1,6 +1,7 @@ package client import ( + "encoding/base64" "fmt" "github.com/Mrs4s/MiraiGo/client/pb/longmsg" "github.com/Mrs4s/MiraiGo/client/pb/msg" @@ -278,19 +279,13 @@ func (c *QQClient) buildGetGroupMsgRequest(groupCode, beginSeq, endSeq int64) (u func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) (uint16, []byte) { seq := c.nextSeq() - body := &oidb.D8A7ReqBody{ + payload := c.packOIDBPackageProto(2215, 0, &oidb.D8A7ReqBody{ SubCmd: proto.Uint32(1), LimitIntervalTypeForUin: proto.Uint32(2), LimitIntervalTypeForGroup: proto.Uint32(1), Uin: proto.Uint64(uint64(c.Uin)), GroupCode: proto.Uint64(uint64(groupCode)), - } - b, _ := proto.Marshal(body) - req := &oidb.OIDBSSOPkg{ - Command: 2215, - Bodybuffer: b, - } - payload, _ := proto.Marshal(req) + }) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8a7_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } @@ -377,3 +372,144 @@ func decodeAtAllRemainResponse(_ *QQClient, _ uint16, payload []byte) (interface RemainAtAllCountForUin: rsp.GetRemainAtAllCountForUin(), }, nil } + +func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage { + group := c.FindGroup(m.Head.GroupInfo.GetGroupCode()) + if group == nil { + c.Debug("sync group %v.", m.Head.GroupInfo.GetGroupCode()) + info, err := c.GetGroupInfo(m.Head.GroupInfo.GetGroupCode()) + if err != nil { + c.Error("error to sync group %v : %+v", m.Head.GroupInfo.GetGroupCode(), err) + return nil + } + group = info + c.GroupList = append(c.GroupList, info) + } + if len(group.Members) == 0 { + mem, err := c.GetGroupMembers(group) + if err != nil { + c.Error("error to sync group %v member : %+v", m.Head.GroupInfo.GroupCode, err) + return nil + } + group.Members = mem + } + var anonInfo *msg.AnonymousGroupMessage + for _, e := range m.Body.RichText.Elems { + if e.AnonGroupMsg != nil { + anonInfo = e.AnonGroupMsg + } + } + var sender *message.Sender + if anonInfo != nil { + sender = &message.Sender{ + Uin: 80000000, + Nickname: string(anonInfo.AnonNick), + AnonymousInfo: &message.AnonymousInfo{ + AnonymousId: base64.StdEncoding.EncodeToString(anonInfo.AnonId), + AnonymousNick: string(anonInfo.AnonNick), + }, + IsFriend: false, + } + } else { + mem := group.FindMember(m.Head.GetFromUin()) + if mem == nil { + group.Update(func(_ *GroupInfo) { + if mem = group.FindMemberWithoutLock(m.Head.GetFromUin()); mem != nil { + return + } + info, _ := c.getMemberInfo(group.Code, m.Head.GetFromUin()) + if info == nil { + return + } + mem = info + group.Members = append(group.Members, mem) + go c.dispatchNewMemberEvent(&MemberJoinGroupEvent{ + Group: group, + Member: info, + }) + }) + if mem == nil { + return nil + } + } + sender = &message.Sender{ + Uin: mem.Uin, + Nickname: mem.Nickname, + CardName: mem.CardName, + IsFriend: c.FindFriend(mem.Uin) != nil, + } + } + var g *message.GroupMessage + g = &message.GroupMessage{ + Id: m.Head.GetMsgSeq(), + GroupCode: group.Code, + GroupName: string(m.Head.GroupInfo.GroupName), + Sender: sender, + Time: m.Head.GetMsgTime(), + Elements: message.ParseMessageElems(m.Body.RichText.Elems), + OriginalObject: m, + } + var extInfo *msg.ExtraInfo + // pre parse + for _, elem := range m.Body.RichText.Elems { + // is rich long msg + if elem.GeneralFlags != nil && elem.GeneralFlags.GetLongTextResid() != "" { + if f := c.GetForwardMessage(elem.GeneralFlags.GetLongTextResid()); f != nil && len(f.Nodes) == 1 { + g = &message.GroupMessage{ + Id: m.Head.GetMsgSeq(), + GroupCode: group.Code, + GroupName: string(m.Head.GroupInfo.GroupName), + Sender: sender, + Time: m.Head.GetMsgTime(), + Elements: f.Nodes[0].Message, + OriginalObject: m, + } + } + } + if elem.ExtraInfo != nil { + extInfo = elem.ExtraInfo + } + } + if !sender.IsAnonymous() { + mem := group.FindMember(m.Head.GetFromUin()) + groupCard := m.Head.GroupInfo.GetGroupCard() + 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 = "" + for _, e := range buf.RichCardName { + groupCard += string(e.Text) + } + } + } + if m.Head.GroupInfo != nil && groupCard != "" && mem.CardName != groupCard { + old := mem.CardName + if mem.Nickname == groupCard { + mem.CardName = "" + } else { + mem.CardName = groupCard + } + if old != mem.CardName { + go c.dispatchMemberCardUpdatedEvent(&MemberCardUpdatedEvent{ + Group: group, + OldCard: old, + Member: mem, + }) + } + } + } + if m.Body.RichText.Ptt != nil { + g.Elements = []message.IMessageElement{ + &message.VoiceElement{ + Name: m.Body.RichText.Ptt.GetFileName(), + Md5: m.Body.RichText.Ptt.FileMd5, + Size: m.Body.RichText.Ptt.GetFileSize(), + Url: "http://grouptalk.c2c.qq.com" + string(m.Body.RichText.Ptt.DownPara), + }, + } + } + if m.Body.RichText.Attr != nil { + g.InternalId = m.Body.RichText.Attr.GetRandom() + } + return g +} diff --git a/client/pb/msg/msg.pb.go b/client/pb/msg/msg.pb.go index b427899e..d2e0aed4 100644 --- a/client/pb/msg/msg.pb.go +++ b/client/pb/msg/msg.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.13.0 +// protoc v3.11.4 // source: msg.proto package msg @@ -6737,6 +6737,172 @@ func (x *GetGroupMsgResp) GetMsg() []*Message { return nil } +type PbGetOneDayRoamMsgReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PeerUin *uint64 `protobuf:"varint,1,opt,name=peerUin" json:"peerUin,omitempty"` + LastMsgTime *uint64 `protobuf:"varint,2,opt,name=lastMsgTime" json:"lastMsgTime,omitempty"` + Random *uint64 `protobuf:"varint,3,opt,name=random" json:"random,omitempty"` + ReadCnt *uint32 `protobuf:"varint,4,opt,name=readCnt" json:"readCnt,omitempty"` +} + +func (x *PbGetOneDayRoamMsgReq) Reset() { + *x = PbGetOneDayRoamMsgReq{} + if protoimpl.UnsafeEnabled { + mi := &file_msg_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PbGetOneDayRoamMsgReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PbGetOneDayRoamMsgReq) ProtoMessage() {} + +func (x *PbGetOneDayRoamMsgReq) ProtoReflect() protoreflect.Message { + mi := &file_msg_proto_msgTypes[67] + 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 PbGetOneDayRoamMsgReq.ProtoReflect.Descriptor instead. +func (*PbGetOneDayRoamMsgReq) Descriptor() ([]byte, []int) { + return file_msg_proto_rawDescGZIP(), []int{67} +} + +func (x *PbGetOneDayRoamMsgReq) GetPeerUin() uint64 { + if x != nil && x.PeerUin != nil { + return *x.PeerUin + } + return 0 +} + +func (x *PbGetOneDayRoamMsgReq) GetLastMsgTime() uint64 { + if x != nil && x.LastMsgTime != nil { + return *x.LastMsgTime + } + return 0 +} + +func (x *PbGetOneDayRoamMsgReq) GetRandom() uint64 { + if x != nil && x.Random != nil { + return *x.Random + } + return 0 +} + +func (x *PbGetOneDayRoamMsgReq) GetReadCnt() uint32 { + if x != nil && x.ReadCnt != nil { + return *x.ReadCnt + } + return 0 +} + +type PbGetOneDayRoamMsgResp 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"` + PeerUin *uint64 `protobuf:"varint,3,opt,name=peerUin" json:"peerUin,omitempty"` + LastMsgTime *uint64 `protobuf:"varint,4,opt,name=lastMsgTime" json:"lastMsgTime,omitempty"` + Random *uint64 `protobuf:"varint,5,opt,name=random" json:"random,omitempty"` + Msg []*Message `protobuf:"bytes,6,rep,name=msg" json:"msg,omitempty"` + IsComplete *uint32 `protobuf:"varint,7,opt,name=isComplete" json:"isComplete,omitempty"` +} + +func (x *PbGetOneDayRoamMsgResp) Reset() { + *x = PbGetOneDayRoamMsgResp{} + if protoimpl.UnsafeEnabled { + mi := &file_msg_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PbGetOneDayRoamMsgResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PbGetOneDayRoamMsgResp) ProtoMessage() {} + +func (x *PbGetOneDayRoamMsgResp) ProtoReflect() protoreflect.Message { + mi := &file_msg_proto_msgTypes[68] + 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 PbGetOneDayRoamMsgResp.ProtoReflect.Descriptor instead. +func (*PbGetOneDayRoamMsgResp) Descriptor() ([]byte, []int) { + return file_msg_proto_rawDescGZIP(), []int{68} +} + +func (x *PbGetOneDayRoamMsgResp) GetResult() uint32 { + if x != nil && x.Result != nil { + return *x.Result + } + return 0 +} + +func (x *PbGetOneDayRoamMsgResp) GetErrMsg() string { + if x != nil && x.ErrMsg != nil { + return *x.ErrMsg + } + return "" +} + +func (x *PbGetOneDayRoamMsgResp) GetPeerUin() uint64 { + if x != nil && x.PeerUin != nil { + return *x.PeerUin + } + return 0 +} + +func (x *PbGetOneDayRoamMsgResp) GetLastMsgTime() uint64 { + if x != nil && x.LastMsgTime != nil { + return *x.LastMsgTime + } + return 0 +} + +func (x *PbGetOneDayRoamMsgResp) GetRandom() uint64 { + if x != nil && x.Random != nil { + return *x.Random + } + return 0 +} + +func (x *PbGetOneDayRoamMsgResp) GetMsg() []*Message { + if x != nil { + return x.Msg + } + return nil +} + +func (x *PbGetOneDayRoamMsgResp) GetIsComplete() uint32 { + if x != nil && x.IsComplete != nil { + return *x.IsComplete + } + return 0 +} + var File_msg_proto protoreflect.FileDescriptor var file_msg_proto_rawDesc = []byte{ @@ -7778,11 +7944,33 @@ var file_msg_proto_rawDesc = []byte{ 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, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x85, 0x01, 0x0a, + 0x15, 0x50, 0x62, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x65, 0x44, 0x61, 0x79, 0x52, 0x6f, 0x61, 0x6d, + 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x55, 0x69, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x70, 0x65, 0x65, 0x72, 0x55, 0x69, 0x6e, + 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, + 0x61, 0x64, 0x43, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x72, 0x65, 0x61, + 0x64, 0x43, 0x6e, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x50, 0x62, 0x47, 0x65, 0x74, 0x4f, 0x6e, + 0x65, 0x44, 0x61, 0x79, 0x52, 0x6f, 0x61, 0x6d, 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, 0x4d, 0x73, + 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x72, 0x72, 0x4d, 0x73, 0x67, 0x12, + 0x18, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x55, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x07, 0x70, 0x65, 0x65, 0x72, 0x55, 0x69, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x61, 0x73, + 0x74, 0x4d, 0x73, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, + 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x72, 0x61, 0x6e, + 0x64, 0x6f, 0x6d, 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, 0x12, + 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 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 ( @@ -7798,76 +7986,78 @@ func file_msg_proto_rawDescGZIP() []byte { } var file_msg_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 67) +var file_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 69) var file_msg_proto_goTypes = []interface{}{ - (SyncFlag)(0), // 0: SyncFlag - (*GetMessageRequest)(nil), // 1: GetMessageRequest - (*SendMessageRequest)(nil), // 2: SendMessageRequest - (*SendMessageResponse)(nil), // 3: SendMessageResponse - (*MsgWithDrawReq)(nil), // 4: MsgWithDrawReq - (*C2CMsgWithDrawReq)(nil), // 5: C2CMsgWithDrawReq - (*GroupMsgWithDrawReq)(nil), // 6: GroupMsgWithDrawReq - (*MsgWithDrawResp)(nil), // 7: MsgWithDrawResp - (*C2CMsgWithDrawResp)(nil), // 8: C2CMsgWithDrawResp - (*GroupMsgWithDrawResp)(nil), // 9: GroupMsgWithDrawResp - (*GroupMsgInfo)(nil), // 10: GroupMsgInfo - (*C2CMsgInfo)(nil), // 11: C2CMsgInfo - (*RoutingHead)(nil), // 12: RoutingHead - (*C2C)(nil), // 13: C2C - (*Grp)(nil), // 14: Grp - (*GrpTmp)(nil), // 15: GrpTmp - (*MsgCtrl)(nil), // 16: MsgCtrl - (*GetMessageResponse)(nil), // 17: GetMessageResponse - (*PushMessagePacket)(nil), // 18: PushMessagePacket - (*UinPairMessage)(nil), // 19: UinPairMessage - (*Message)(nil), // 20: Message - (*MessageBody)(nil), // 21: MessageBody - (*RichText)(nil), // 22: RichText - (*Elem)(nil), // 23: Elem - (*CommonElem)(nil), // 24: CommonElem - (*QQWalletMsg)(nil), // 25: QQWalletMsg - (*QQWalletAioBody)(nil), // 26: QQWalletAioBody - (*QQWalletAioElem)(nil), // 27: QQWalletAioElem - (*RichMsg)(nil), // 28: RichMsg - (*CustomElem)(nil), // 29: CustomElem - (*Text)(nil), // 30: Text - (*Attr)(nil), // 31: Attr - (*Ptt)(nil), // 32: Ptt - (*OnlineImage)(nil), // 33: OnlineImage - (*NotOnlineImage)(nil), // 34: NotOnlineImage - (*NotOnlineFile)(nil), // 35: NotOnlineFile - (*TransElem)(nil), // 36: TransElem - (*ExtraInfo)(nil), // 37: ExtraInfo - (*GroupFile)(nil), // 38: GroupFile - (*AnonymousGroupMessage)(nil), // 39: AnonymousGroupMessage - (*VideoFile)(nil), // 40: VideoFile - (*SourceMsg)(nil), // 41: SourceMsg - (*Face)(nil), // 42: Face - (*LightAppElem)(nil), // 43: LightAppElem - (*CustomFace)(nil), // 44: CustomFace - (*ContentHead)(nil), // 45: ContentHead - (*MessageHead)(nil), // 46: MessageHead - (*GroupInfo)(nil), // 47: GroupInfo - (*DiscussInfo)(nil), // 48: DiscussInfo - (*MutilTransHead)(nil), // 49: MutilTransHead - (*C2CTempMessageHead)(nil), // 50: C2CTempMessageHead - (*InstCtrl)(nil), // 51: InstCtrl - (*InstInfo)(nil), // 52: InstInfo - (*ExtGroupKeyInfo)(nil), // 53: ExtGroupKeyInfo - (*SyncCookie)(nil), // 54: SyncCookie - (*TransMsgInfo)(nil), // 55: TransMsgInfo - (*GeneralFlags)(nil), // 56: GeneralFlags - (*PbMultiMsgItem)(nil), // 57: PbMultiMsgItem - (*PbMultiMsgNew)(nil), // 58: PbMultiMsgNew - (*PbMultiMsgTransmit)(nil), // 59: PbMultiMsgTransmit - (*MsgElemInfoServtype3)(nil), // 60: MsgElemInfo_servtype3 - (*MsgElemInfoServtype33)(nil), // 61: MsgElemInfo_servtype33 - (*SubMsgType0X4Body)(nil), // 62: SubMsgType0x4Body - (*ResvAttr)(nil), // 63: ResvAttr - (*AnimationImageShow)(nil), // 64: AnimationImageShow - (*UinTypeUserDef)(nil), // 65: UinTypeUserDef - (*GetGroupMsgReq)(nil), // 66: GetGroupMsgReq - (*GetGroupMsgResp)(nil), // 67: GetGroupMsgResp + (SyncFlag)(0), // 0: SyncFlag + (*GetMessageRequest)(nil), // 1: GetMessageRequest + (*SendMessageRequest)(nil), // 2: SendMessageRequest + (*SendMessageResponse)(nil), // 3: SendMessageResponse + (*MsgWithDrawReq)(nil), // 4: MsgWithDrawReq + (*C2CMsgWithDrawReq)(nil), // 5: C2CMsgWithDrawReq + (*GroupMsgWithDrawReq)(nil), // 6: GroupMsgWithDrawReq + (*MsgWithDrawResp)(nil), // 7: MsgWithDrawResp + (*C2CMsgWithDrawResp)(nil), // 8: C2CMsgWithDrawResp + (*GroupMsgWithDrawResp)(nil), // 9: GroupMsgWithDrawResp + (*GroupMsgInfo)(nil), // 10: GroupMsgInfo + (*C2CMsgInfo)(nil), // 11: C2CMsgInfo + (*RoutingHead)(nil), // 12: RoutingHead + (*C2C)(nil), // 13: C2C + (*Grp)(nil), // 14: Grp + (*GrpTmp)(nil), // 15: GrpTmp + (*MsgCtrl)(nil), // 16: MsgCtrl + (*GetMessageResponse)(nil), // 17: GetMessageResponse + (*PushMessagePacket)(nil), // 18: PushMessagePacket + (*UinPairMessage)(nil), // 19: UinPairMessage + (*Message)(nil), // 20: Message + (*MessageBody)(nil), // 21: MessageBody + (*RichText)(nil), // 22: RichText + (*Elem)(nil), // 23: Elem + (*CommonElem)(nil), // 24: CommonElem + (*QQWalletMsg)(nil), // 25: QQWalletMsg + (*QQWalletAioBody)(nil), // 26: QQWalletAioBody + (*QQWalletAioElem)(nil), // 27: QQWalletAioElem + (*RichMsg)(nil), // 28: RichMsg + (*CustomElem)(nil), // 29: CustomElem + (*Text)(nil), // 30: Text + (*Attr)(nil), // 31: Attr + (*Ptt)(nil), // 32: Ptt + (*OnlineImage)(nil), // 33: OnlineImage + (*NotOnlineImage)(nil), // 34: NotOnlineImage + (*NotOnlineFile)(nil), // 35: NotOnlineFile + (*TransElem)(nil), // 36: TransElem + (*ExtraInfo)(nil), // 37: ExtraInfo + (*GroupFile)(nil), // 38: GroupFile + (*AnonymousGroupMessage)(nil), // 39: AnonymousGroupMessage + (*VideoFile)(nil), // 40: VideoFile + (*SourceMsg)(nil), // 41: SourceMsg + (*Face)(nil), // 42: Face + (*LightAppElem)(nil), // 43: LightAppElem + (*CustomFace)(nil), // 44: CustomFace + (*ContentHead)(nil), // 45: ContentHead + (*MessageHead)(nil), // 46: MessageHead + (*GroupInfo)(nil), // 47: GroupInfo + (*DiscussInfo)(nil), // 48: DiscussInfo + (*MutilTransHead)(nil), // 49: MutilTransHead + (*C2CTempMessageHead)(nil), // 50: C2CTempMessageHead + (*InstCtrl)(nil), // 51: InstCtrl + (*InstInfo)(nil), // 52: InstInfo + (*ExtGroupKeyInfo)(nil), // 53: ExtGroupKeyInfo + (*SyncCookie)(nil), // 54: SyncCookie + (*TransMsgInfo)(nil), // 55: TransMsgInfo + (*GeneralFlags)(nil), // 56: GeneralFlags + (*PbMultiMsgItem)(nil), // 57: PbMultiMsgItem + (*PbMultiMsgNew)(nil), // 58: PbMultiMsgNew + (*PbMultiMsgTransmit)(nil), // 59: PbMultiMsgTransmit + (*MsgElemInfoServtype3)(nil), // 60: MsgElemInfo_servtype3 + (*MsgElemInfoServtype33)(nil), // 61: MsgElemInfo_servtype33 + (*SubMsgType0X4Body)(nil), // 62: SubMsgType0x4Body + (*ResvAttr)(nil), // 63: ResvAttr + (*AnimationImageShow)(nil), // 64: AnimationImageShow + (*UinTypeUserDef)(nil), // 65: UinTypeUserDef + (*GetGroupMsgReq)(nil), // 66: GetGroupMsgReq + (*GetGroupMsgResp)(nil), // 67: GetGroupMsgResp + (*PbGetOneDayRoamMsgReq)(nil), // 68: PbGetOneDayRoamMsgReq + (*PbGetOneDayRoamMsgResp)(nil), // 69: PbGetOneDayRoamMsgResp } var file_msg_proto_depIdxs = []int32{ 0, // 0: GetMessageRequest.syncFlag:type_name -> SyncFlag @@ -7937,11 +8127,12 @@ var file_msg_proto_depIdxs = []int32{ 35, // 64: SubMsgType0x4Body.notOnlineFile:type_name -> NotOnlineFile 64, // 65: ResvAttr.image_show:type_name -> AnimationImageShow 20, // 66: GetGroupMsgResp.msg:type_name -> Message - 67, // [67:67] is the sub-list for method output_type - 67, // [67:67] is the sub-list for method input_type - 67, // [67:67] is the sub-list for extension type_name - 67, // [67:67] is the sub-list for extension extendee - 0, // [0:67] is the sub-list for field type_name + 20, // 67: PbGetOneDayRoamMsgResp.msg:type_name -> Message + 68, // [68:68] is the sub-list for method output_type + 68, // [68:68] is the sub-list for method input_type + 68, // [68:68] is the sub-list for extension type_name + 68, // [68:68] is the sub-list for extension extendee + 0, // [0:68] is the sub-list for field type_name } func init() { file_msg_proto_init() } @@ -8754,6 +8945,30 @@ func file_msg_proto_init() { return nil } } + file_msg_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PbGetOneDayRoamMsgReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_msg_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PbGetOneDayRoamMsgResp); 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{ @@ -8761,7 +8976,7 @@ func file_msg_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_msg_proto_rawDesc, NumEnums: 1, - NumMessages: 67, + NumMessages: 69, NumExtensions: 0, NumServices: 0, }, diff --git a/client/pb/msg/msg.proto b/client/pb/msg/msg.proto index 9b5a26d0..c7fc7d7a 100644 --- a/client/pb/msg/msg.proto +++ b/client/pb/msg/msg.proto @@ -768,4 +768,21 @@ message GetGroupMsgResp { optional uint64 returnBeginSeq = 4; optional uint64 returnEndSeq = 5; repeated Message msg = 6; +} + +message PbGetOneDayRoamMsgReq { + optional uint64 peerUin = 1; + optional uint64 lastMsgTime = 2; + optional uint64 random = 3; + optional uint32 readCnt = 4; +} + +message PbGetOneDayRoamMsgResp { + optional uint32 result = 1; + optional string errMsg = 2; + optional uint64 peerUin = 3; + optional uint64 lastMsgTime = 4; + optional uint64 random = 5; + repeated Message msg = 6; + optional uint32 isComplete = 7; } \ No newline at end of file diff --git a/client/private_msg.go b/client/private_msg.go new file mode 100644 index 00000000..b14e6188 --- /dev/null +++ b/client/private_msg.go @@ -0,0 +1,165 @@ +package client + +import ( + "github.com/Mrs4s/MiraiGo/client/pb/msg" + "github.com/Mrs4s/MiraiGo/message" + "github.com/Mrs4s/MiraiGo/protocol/packets" + "github.com/golang/protobuf/proto" + "math/rand" + "time" +) + +func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) *message.PrivateMessage { + mr := int32(rand.Uint32()) + seq := c.nextFriendSeq() + t := time.Now().Unix() + imgCount := m.Count(func(e message.IMessageElement) bool { return e.Type() == message.Image }) + msgLen := message.EstimateLength(m.Elements, 703) + if msgLen > 5000 || imgCount > 50 { + return nil + } + if msgLen > 300 || imgCount > 2 { + div := int32(rand.Uint32()) + fragmented := m.ToFragmented() + for i, elems := range fragmented { + _, pkt := c.buildFriendSendingPacket(target, c.nextFriendSeq(), mr, int32(len(fragmented)), int32(i), div, t, elems) + _ = c.send(pkt) + } + } else { + _, pkt := c.buildFriendSendingPacket(target, seq, mr, 1, 0, 0, t, m.Elements) + _ = c.send(pkt) + } + c.stat.MessageSent++ + return &message.PrivateMessage{ + Id: seq, + InternalId: mr, + Target: target, + Time: int32(t), + Sender: &message.Sender{ + Uin: c.Uin, + Nickname: c.Nickname, + IsFriend: true, + }, + Elements: m.Elements, + } +} + +func (c *QQClient) SendTempMessage(groupCode, target int64, m *message.SendingMessage) *message.TempMessage { + group := c.FindGroup(groupCode) + if group == nil { + return nil + } + if c.FindFriend(target) != nil { + pm := c.SendPrivateMessage(target, m) + return &message.TempMessage{ + Id: pm.Id, + GroupCode: group.Code, + GroupName: group.Name, + Sender: pm.Sender, + Elements: m.Elements, + } + } + mr := int32(rand.Uint32()) + seq := c.nextFriendSeq() + t := time.Now().Unix() + _, pkt := c.buildTempSendingPacket(group.Uin, target, seq, mr, t, m) + _ = c.send(pkt) + c.stat.MessageSent++ + return &message.TempMessage{ + Id: seq, + GroupCode: group.Code, + GroupName: group.Name, + Sender: &message.Sender{ + Uin: c.Uin, + Nickname: c.Nickname, + IsFriend: true, + }, + Elements: m.Elements, + } +} + +func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int64, count uint32) (uint16, []byte) { + seq := c.nextSeq() + req := &msg.PbGetOneDayRoamMsgReq{ + PeerUin: proto.Uint64(uint64(target)), + LastMsgTime: proto.Uint64(uint64(lastMsgTime)), + Random: proto.Uint64(uint64(random)), + ReadCnt: &count, + } + payload, _ := proto.Marshal(req) + packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbGetOneDayRoamMsg", 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() + var ptt *msg.Ptt + if len(m) > 0 { + if p, ok := m[0].(*message.PrivateVoiceElement); ok { + ptt = p.Ptt + m = []message.IMessageElement{} + } + } + req := &msg.SendMessageRequest{ + RoutingHead: &msg.RoutingHead{C2C: &msg.C2C{ToUin: &target}}, + ContentHead: &msg.ContentHead{PkgNum: &pkgNum, PkgIndex: &pkgIndex, DivSeq: &pkgDiv}, + MsgBody: &msg.MessageBody{ + RichText: &msg.RichText{ + Elems: message.ToProtoElems(m, false), + Ptt: ptt, + }, + }, + MsgSeq: &msgSeq, + MsgRand: &r, + SyncCookie: func() []byte { + cookie := &msg.SyncCookie{ + Time: &time, + Ran1: proto.Int64(rand.Int63()), + Ran2: proto.Int64(rand.Int63()), + Const1: &syncConst1, + Const2: &syncConst2, + Const3: proto.Int64(0x1d), + } + b, _ := proto.Marshal(cookie) + return b + }(), + } + 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) buildTempSendingPacket(groupUin, target int64, msgSeq, r int32, time int64, m *message.SendingMessage) (uint16, []byte) { + seq := c.nextSeq() + req := &msg.SendMessageRequest{ + RoutingHead: &msg.RoutingHead{GrpTmp: &msg.GrpTmp{ + GroupUin: &groupUin, + ToUin: &target, + }}, + ContentHead: &msg.ContentHead{PkgNum: proto.Int32(1)}, + MsgBody: &msg.MessageBody{ + RichText: &msg.RichText{ + Elems: message.ToProtoElems(m.Elements, false), + }, + }, + MsgSeq: &msgSeq, + MsgRand: &r, + SyncCookie: func() []byte { + cookie := &msg.SyncCookie{ + Time: &time, + Ran1: proto.Int64(rand.Int63()), + Ran2: proto.Int64(rand.Int63()), + Const1: &syncConst1, + Const2: &syncConst2, + Const3: proto.Int64(0x1d), + } + b, _ := proto.Marshal(cookie) + return b + }(), + } + payload, _ := proto.Marshal(req) + packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbSendMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) + return seq, packet +} From e4bd8979bc0c9ffd96b1fcefd7e4f11e04e64231 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 24 Jan 2021 02:30:59 +0800 Subject: [PATCH 2/5] fix group long message result. --- client/group_msg.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/group_msg.go b/client/group_msg.go index 69350bc6..93d2a0a1 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -55,7 +55,14 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage, ), }}, ) - return ret + return &message.GroupMessage{ + Id: ret.Id, + InternalId: ret.InternalId, + GroupCode: ret.GroupCode, + Sender: ret.Sender, + Time: ret.Time, + Elements: m.Elements, + } } return c.sendGroupMessage(groupCode, false, m) } From cb678205d58c452518847b241128c6d4a29db202 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 24 Jan 2021 02:40:12 +0800 Subject: [PATCH 3/5] fix limit. --- client/group_msg.go | 2 +- message/message.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/group_msg.go b/client/group_msg.go index 93d2a0a1..9dc3b83f 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -40,7 +40,7 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage, if msgLen > 5000 || imgCount > 50 { return nil } - if (msgLen > 200 || imgCount > 1) && !useFram { + if (msgLen > 200 || imgCount > 2) && !useFram { ret := c.sendGroupMessage(groupCode, false, &message.SendingMessage{Elements: []message.IMessageElement{ c.uploadGroupLongMessage(groupCode, diff --git a/message/message.go b/message/message.go index c5edc33c..80aefcb1 100644 --- a/message/message.go +++ b/message/message.go @@ -260,7 +260,7 @@ func EstimateLength(elems []IMessageElement, limit int) int { case *ReplyElement: sum += 444 + EstimateLength(e.Elements, left) case *ImageElement, *GroupImageElement, *FriendImageElement: - sum += 260 + sum += 100 default: sum += utils.ChineseLength(ToReadableString([]IMessageElement{elem}), left) } From a401ed3ef104efd0d815791310518cd6b2cac270 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 24 Jan 2021 14:35:08 +0800 Subject: [PATCH 4/5] fix highway encrypt. --- client/highway.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/highway.go b/client/highway.go index c755b8d6..6cff7b6e 100644 --- a/client/highway.go +++ b/client/highway.go @@ -206,7 +206,7 @@ func (c *QQClient) highwayUploadFileMultiThreadingByBDH(path string, cmdId int32 } defer file.Close() if stat.Size() < 1024*1024*3 { - return c.highwayUploadByBDH(file, cmdId, ticket, ext, encrypt) + return c.highwayUploadByBDH(file, cmdId, ticket, ext, false) } type BlockMetaData struct { Id int From 9549a32d954a7674e9fd6fa98500c8d84f78d6c0 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 24 Jan 2021 14:56:45 +0800 Subject: [PATCH 5/5] update GroupInfo. --- client/group_info.go | 10 ++++++---- client/group_msg.go | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/group_info.go b/client/group_info.go index 761ebf62..eac6a534 100644 --- a/client/group_info.go +++ b/client/group_info.go @@ -24,10 +24,12 @@ type ( MemberCount uint16 MaxMemberCount uint16 Members []*GroupMemberInfo + // 最后一条信息的SEQ,只有通过 GetGroupInfo 函数获取的 GroupInfo 才会有 + LastMsgSeq int64 - client *QQClient - lastMsgSeq int64 - lock sync.RWMutex + client *QQClient + + lock sync.RWMutex } GroupMemberInfo struct { @@ -183,7 +185,7 @@ func decodeGroupInfoResponse(c *QQClient, _ uint16, payload []byte) (interface{} MemberCount: uint16(*info.GroupInfo.GroupMemberNum), MaxMemberCount: uint16(*info.GroupInfo.GroupMemberMaxNum), Members: []*GroupMemberInfo{}, - lastMsgSeq: int64(info.GroupInfo.GetGroupCurMsgSeq()), + LastMsgSeq: int64(info.GroupInfo.GetGroupCurMsgSeq()), client: c, }, nil } diff --git a/client/group_msg.go b/client/group_msg.go index 9dc3b83f..e55c4403 100644 --- a/client/group_msg.go +++ b/client/group_msg.go @@ -142,7 +142,7 @@ func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.Se return ret case <-time.After(time.Second * 5): if g, err := c.GetGroupInfo(groupCode); err == nil { - if history, err := c.GetGroupMessages(groupCode, g.lastMsgSeq-10, g.lastMsgSeq+1); err == nil { + if history, err := c.GetGroupMessages(groupCode, g.LastMsgSeq-10, g.LastMsgSeq+1); err == nil { for _, m := range history { if m.InternalId == mr { return m