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

Merge branch 'master' into Rand

This commit is contained in:
LXY 2021-01-24 22:34:02 +08:00 committed by GitHub
commit 2a17b14c5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 686 additions and 463 deletions

View File

@ -595,79 +595,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()) 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 // LongConn.OffPicUp
func (c *QQClient) buildOffPicUpPacket(target int64, md5 []byte, size int32) (uint16, []byte) { func (c *QQClient) buildOffPicUpPacket(target int64, md5 []byte, size int32) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
@ -826,12 +753,7 @@ func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTi
}, },
} }
b, _ := proto.Marshal(body) b, _ := proto.Marshal(body)
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(2300, 2, b)
Command: 2300,
ServiceType: 2,
Bodybuffer: b,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8fc_2", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8fc_2", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -840,11 +762,7 @@ func (c *QQClient) buildEditSpecialTitlePacket(groupCode, memberUin int64, newTi
func (c *QQClient) buildGroupOperationPacket(body *oidb.D89AReqBody) (uint16, []byte) { func (c *QQClient) buildGroupOperationPacket(body *oidb.D89AReqBody) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
b, _ := proto.Marshal(body) b, _ := proto.Marshal(body)
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(2202, 0, b)
Command: 2202,
Bodybuffer: b,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x89a_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x89a_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -905,11 +823,7 @@ func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg stri
KickMsg: []byte(kickMsg), KickMsg: []byte(kickMsg),
} }
b, _ := proto.Marshal(body) b, _ := proto.Marshal(body)
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(2208, 0, b)
Command: 2208,
Bodybuffer: b,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8a0_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8a0_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -917,18 +831,13 @@ func (c *QQClient) buildGroupKickPacket(groupCode, memberUin int64, kickMsg stri
// OidbSvc.0x570_8 // OidbSvc.0x570_8
func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) (uint16, []byte) { func (c *QQClient) buildGroupMutePacket(groupCode, memberUin int64, time uint32) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(1392, 8, binary.NewWriterF(func(w *binary.Writer) {
Command: 1392, w.WriteUInt32(uint32(groupCode))
ServiceType: 8, w.WriteByte(32)
Bodybuffer: binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(1)
w.WriteUInt32(uint32(groupCode)) w.WriteUInt32(uint32(memberUin))
w.WriteByte(32) w.WriteUInt32(time)
w.WriteUInt16(1) }))
w.WriteUInt32(uint32(memberUin))
w.WriteUInt32(time)
}),
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x570_8", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x570_8", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -941,12 +850,7 @@ func (c *QQClient) buildGroupPokePacket(groupCode, target int64) (uint16, []byte
GroupCode: groupCode, GroupCode: groupCode,
} }
b, _ := proto.Marshal(body) b, _ := proto.Marshal(body)
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(3795, 1, b)
Command: 3795,
ServiceType: 1,
Bodybuffer: b,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xed3", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xed3", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -959,12 +863,7 @@ func (c *QQClient) buildFriendPokePacket(target int64) (uint16, []byte) {
AioUin: target, AioUin: target,
} }
b, _ := proto.Marshal(body) b, _ := proto.Marshal(body)
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(3795, 1, b)
Command: 3795,
ServiceType: 1,
Bodybuffer: b,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xed3", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xed3", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -972,21 +871,16 @@ func (c *QQClient) buildFriendPokePacket(target int64) (uint16, []byte) {
// OidbSvc.0x55c_1 // OidbSvc.0x55c_1
func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) (uint16, []byte) { func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(1372, 1, binary.NewWriterF(func(w *binary.Writer) {
Command: 1372, w.WriteUInt32(uint32(groupCode))
ServiceType: 1, w.WriteUInt32(uint32(member))
Bodybuffer: binary.NewWriterF(func(w *binary.Writer) { w.WriteByte(func() byte {
w.WriteUInt32(uint32(groupCode)) if flag {
w.WriteUInt32(uint32(member)) return 1
w.WriteByte(func() byte { }
if flag { return 0
return 1 }())
} }))
return 0
}())
}),
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x55c_1", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x55c_1", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -1032,11 +926,7 @@ func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, hei
}, },
} }
b, _ := proto.Marshal(body) b, _ := proto.Marshal(body)
req := &oidb.OIDBSSOPkg{ payload := c.packOIDBPackage(3591, 0, b)
Command: 3591,
Bodybuffer: b,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xe07_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xe07_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -1063,18 +953,11 @@ func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) {
func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) { func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
body := &oidb.D79ReqBody{ payload := c.packOIDBPackageProto(3449, 1, &oidb.D79ReqBody{
Uin: uint64(c.Uin), Uin: uint64(c.Uin),
Content: data, Content: data,
Qua: []byte("and_537065262_8.4.5"), 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) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xd79", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -1082,7 +965,7 @@ func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) {
// OidbSvc.0xdad_1 // OidbSvc.0xdad_1
func (c *QQClient) sendGroupGiftPacket(groupCode, uin uint64, productId message.GroupGift) (uint16, []byte) { func (c *QQClient) sendGroupGiftPacket(groupCode, uin uint64, productId message.GroupGift) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
body := &oidb.DADReqBody{ payload := c.packOIDBPackageProto(3501, 1, &oidb.DADReqBody{
Client: 1, Client: 1,
ProductId: uint64(productId), ProductId: uint64(productId),
ToUin: uin, ToUin: uin,
@ -1092,14 +975,7 @@ func (c *QQClient) sendGroupGiftPacket(groupCode, uin uint64, productId message.
Type: 1, Type: 1,
Sig: []byte(c.getSKey()), 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) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xdad_1", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }

View File

@ -426,75 +426,6 @@ func (c *QQClient) GetFriendList() (*FriendListResponse, error) {
return r, nil return r, nil
} }
func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) *message.PrivateMessage {
mr := rand.Int31()
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 := rand.Int31()
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 := rand.Int31()
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 { func (c *QQClient) GetForwardMessage(resId string) *message.ForwardMessage {
m := c.DownloadForwardMessage(resId) m := c.DownloadForwardMessage(resId)
if m == nil { if m == nil {
@ -972,7 +903,7 @@ func (c *QQClient) netLoop() {
// does not need decoder // does not need decoder
f(nil, nil) f(nil, nil)
} else { } 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)
} }
}() }()
} }

View File

@ -3,7 +3,6 @@ package client
import ( import (
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
@ -17,8 +16,8 @@ import (
"github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/binary/jce" "github.com/Mrs4s/MiraiGo/binary/jce"
devinfo "github.com/Mrs4s/MiraiGo/client/pb" devinfo "github.com/Mrs4s/MiraiGo/client/pb"
"github.com/Mrs4s/MiraiGo/client/pb/oidb
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
"github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -382,7 +381,7 @@ func GenIMEI() string {
sum += toAdd sum += toAdd
final.WriteString(fmt.Sprintf("%d", toAdd)) // and even printing them here! 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)) final.WriteString(fmt.Sprintf("%d", ctrlDigit))
return final.String() 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 { func (b *groupMessageBuilder) build() *msg.Message {
sort.Slice(b.MessageSlices, func(i, j int) bool { sort.Slice(b.MessageSlices, func(i, j int) bool {
return b.MessageSlices[i].Content.GetPkgIndex() < b.MessageSlices[j].Content.GetPkgIndex() 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{}) { func (c *QQClient) Error(msg string, args ...interface{}) {
c.dispatchLogEvent(&LogEvent{ c.dispatchLogEvent(&LogEvent{
Type: "ERROR", Type: "ERROR",

View File

@ -24,10 +24,12 @@ type (
MemberCount uint16 MemberCount uint16
MaxMemberCount uint16 MaxMemberCount uint16
Members []*GroupMemberInfo Members []*GroupMemberInfo
// 最后一条信息的SEQ,只有通过 GetGroupInfo 函数获取的 GroupInfo 才会有
LastMsgSeq int64
client *QQClient client *QQClient
lastMsgSeq int64
lock sync.RWMutex lock sync.RWMutex
} }
GroupMemberInfo struct { GroupMemberInfo struct {
@ -183,7 +185,7 @@ func decodeGroupInfoResponse(c *QQClient, _ uint16, payload []byte) (interface{}
MemberCount: uint16(*info.GroupInfo.GroupMemberNum), MemberCount: uint16(*info.GroupInfo.GroupMemberNum),
MaxMemberCount: uint16(*info.GroupInfo.GroupMemberMaxNum), MaxMemberCount: uint16(*info.GroupInfo.GroupMemberMaxNum),
Members: []*GroupMemberInfo{}, Members: []*GroupMemberInfo{},
lastMsgSeq: int64(info.GroupInfo.GetGroupCurMsgSeq()), LastMsgSeq: int64(info.GroupInfo.GetGroupCurMsgSeq()),
client: c, client: c,
}, nil }, nil
} }

View File

@ -1,6 +1,7 @@
package client package client
import ( import (
"encoding/base64"
"fmt" "fmt"
rand "github.com/LXY1226/fastrand" rand "github.com/LXY1226/fastrand"
"github.com/Mrs4s/MiraiGo/client/pb/longmsg" "github.com/Mrs4s/MiraiGo/client/pb/longmsg"
@ -39,7 +40,7 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
if msgLen > 5000 || imgCount > 50 { if msgLen > 5000 || imgCount > 50 {
return nil return nil
} }
if (msgLen > 200 || imgCount > 1) && !useFram { if (msgLen > 200 || imgCount > 2) && !useFram {
ret := c.sendGroupMessage(groupCode, false, ret := c.sendGroupMessage(groupCode, false,
&message.SendingMessage{Elements: []message.IMessageElement{ &message.SendingMessage{Elements: []message.IMessageElement{
c.uploadGroupLongMessage(groupCode, c.uploadGroupLongMessage(groupCode,
@ -54,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) return c.sendGroupMessage(groupCode, false, m)
} }
@ -134,7 +142,7 @@ func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.Se
return ret return ret
case <-time.After(time.Second * 5): case <-time.After(time.Second * 5):
if g, err := c.GetGroupInfo(groupCode); err == nil { 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 { for _, m := range history {
if m.InternalId == mr { if m.InternalId == mr {
return m return m
@ -278,19 +286,13 @@ func (c *QQClient) buildGetGroupMsgRequest(groupCode, beginSeq, endSeq int64) (u
func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) (uint16, []byte) { func (c *QQClient) buildAtAllRemainRequestPacket(groupCode int64) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
body := &oidb.D8A7ReqBody{ payload := c.packOIDBPackageProto(2215, 0, &oidb.D8A7ReqBody{
SubCmd: proto.Uint32(1), SubCmd: proto.Uint32(1),
LimitIntervalTypeForUin: proto.Uint32(2), LimitIntervalTypeForUin: proto.Uint32(2),
LimitIntervalTypeForGroup: proto.Uint32(1), LimitIntervalTypeForGroup: proto.Uint32(1),
Uin: proto.Uint64(uint64(c.Uin)), Uin: proto.Uint64(uint64(c.Uin)),
GroupCode: proto.Uint64(uint64(groupCode)), 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) packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0x8a7_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
@ -377,3 +379,144 @@ func decodeAtAllRemainResponse(_ *QQClient, _ uint16, payload []byte) (interface
RemainAtAllCountForUin: rsp.GetRemainAtAllCountForUin(), RemainAtAllCountForUin: rsp.GetRemainAtAllCountForUin(),
}, nil }, 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
}

View File

@ -206,7 +206,7 @@ func (c *QQClient) highwayUploadFileMultiThreadingByBDH(path string, cmdId int32
} }
defer file.Close() defer file.Close()
if stat.Size() < 1024*1024*3 { 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 { type BlockMetaData struct {
Id int Id int

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.25.0 // protoc-gen-go v1.25.0
// protoc v3.13.0 // protoc v3.11.4
// source: msg.proto // source: msg.proto
package msg package msg
@ -6737,6 +6737,172 @@ func (x *GetGroupMsgResp) GetMsg() []*Message {
return nil 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 protoreflect.FileDescriptor
var file_msg_proto_rawDesc = []byte{ 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, 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, 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, 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, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x85, 0x01, 0x0a,
0x53, 0x79, 0x6e, 0x63, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x15, 0x50, 0x62, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x65, 0x44, 0x61, 0x79, 0x52, 0x6f, 0x61, 0x6d,
0x54, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x4d, 0x45, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x55, 0x69,
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x42, 0x07, 0x5a, 0x05, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x70, 0x65, 0x65, 0x72, 0x55, 0x69, 0x6e,
0x2e, 0x3b, 0x6d, 0x73, 0x67, 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 ( var (
@ -7798,76 +7986,78 @@ func file_msg_proto_rawDescGZIP() []byte {
} }
var file_msg_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 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{}{ var file_msg_proto_goTypes = []interface{}{
(SyncFlag)(0), // 0: SyncFlag (SyncFlag)(0), // 0: SyncFlag
(*GetMessageRequest)(nil), // 1: GetMessageRequest (*GetMessageRequest)(nil), // 1: GetMessageRequest
(*SendMessageRequest)(nil), // 2: SendMessageRequest (*SendMessageRequest)(nil), // 2: SendMessageRequest
(*SendMessageResponse)(nil), // 3: SendMessageResponse (*SendMessageResponse)(nil), // 3: SendMessageResponse
(*MsgWithDrawReq)(nil), // 4: MsgWithDrawReq (*MsgWithDrawReq)(nil), // 4: MsgWithDrawReq
(*C2CMsgWithDrawReq)(nil), // 5: C2CMsgWithDrawReq (*C2CMsgWithDrawReq)(nil), // 5: C2CMsgWithDrawReq
(*GroupMsgWithDrawReq)(nil), // 6: GroupMsgWithDrawReq (*GroupMsgWithDrawReq)(nil), // 6: GroupMsgWithDrawReq
(*MsgWithDrawResp)(nil), // 7: MsgWithDrawResp (*MsgWithDrawResp)(nil), // 7: MsgWithDrawResp
(*C2CMsgWithDrawResp)(nil), // 8: C2CMsgWithDrawResp (*C2CMsgWithDrawResp)(nil), // 8: C2CMsgWithDrawResp
(*GroupMsgWithDrawResp)(nil), // 9: GroupMsgWithDrawResp (*GroupMsgWithDrawResp)(nil), // 9: GroupMsgWithDrawResp
(*GroupMsgInfo)(nil), // 10: GroupMsgInfo (*GroupMsgInfo)(nil), // 10: GroupMsgInfo
(*C2CMsgInfo)(nil), // 11: C2CMsgInfo (*C2CMsgInfo)(nil), // 11: C2CMsgInfo
(*RoutingHead)(nil), // 12: RoutingHead (*RoutingHead)(nil), // 12: RoutingHead
(*C2C)(nil), // 13: C2C (*C2C)(nil), // 13: C2C
(*Grp)(nil), // 14: Grp (*Grp)(nil), // 14: Grp
(*GrpTmp)(nil), // 15: GrpTmp (*GrpTmp)(nil), // 15: GrpTmp
(*MsgCtrl)(nil), // 16: MsgCtrl (*MsgCtrl)(nil), // 16: MsgCtrl
(*GetMessageResponse)(nil), // 17: GetMessageResponse (*GetMessageResponse)(nil), // 17: GetMessageResponse
(*PushMessagePacket)(nil), // 18: PushMessagePacket (*PushMessagePacket)(nil), // 18: PushMessagePacket
(*UinPairMessage)(nil), // 19: UinPairMessage (*UinPairMessage)(nil), // 19: UinPairMessage
(*Message)(nil), // 20: Message (*Message)(nil), // 20: Message
(*MessageBody)(nil), // 21: MessageBody (*MessageBody)(nil), // 21: MessageBody
(*RichText)(nil), // 22: RichText (*RichText)(nil), // 22: RichText
(*Elem)(nil), // 23: Elem (*Elem)(nil), // 23: Elem
(*CommonElem)(nil), // 24: CommonElem (*CommonElem)(nil), // 24: CommonElem
(*QQWalletMsg)(nil), // 25: QQWalletMsg (*QQWalletMsg)(nil), // 25: QQWalletMsg
(*QQWalletAioBody)(nil), // 26: QQWalletAioBody (*QQWalletAioBody)(nil), // 26: QQWalletAioBody
(*QQWalletAioElem)(nil), // 27: QQWalletAioElem (*QQWalletAioElem)(nil), // 27: QQWalletAioElem
(*RichMsg)(nil), // 28: RichMsg (*RichMsg)(nil), // 28: RichMsg
(*CustomElem)(nil), // 29: CustomElem (*CustomElem)(nil), // 29: CustomElem
(*Text)(nil), // 30: Text (*Text)(nil), // 30: Text
(*Attr)(nil), // 31: Attr (*Attr)(nil), // 31: Attr
(*Ptt)(nil), // 32: Ptt (*Ptt)(nil), // 32: Ptt
(*OnlineImage)(nil), // 33: OnlineImage (*OnlineImage)(nil), // 33: OnlineImage
(*NotOnlineImage)(nil), // 34: NotOnlineImage (*NotOnlineImage)(nil), // 34: NotOnlineImage
(*NotOnlineFile)(nil), // 35: NotOnlineFile (*NotOnlineFile)(nil), // 35: NotOnlineFile
(*TransElem)(nil), // 36: TransElem (*TransElem)(nil), // 36: TransElem
(*ExtraInfo)(nil), // 37: ExtraInfo (*ExtraInfo)(nil), // 37: ExtraInfo
(*GroupFile)(nil), // 38: GroupFile (*GroupFile)(nil), // 38: GroupFile
(*AnonymousGroupMessage)(nil), // 39: AnonymousGroupMessage (*AnonymousGroupMessage)(nil), // 39: AnonymousGroupMessage
(*VideoFile)(nil), // 40: VideoFile (*VideoFile)(nil), // 40: VideoFile
(*SourceMsg)(nil), // 41: SourceMsg (*SourceMsg)(nil), // 41: SourceMsg
(*Face)(nil), // 42: Face (*Face)(nil), // 42: Face
(*LightAppElem)(nil), // 43: LightAppElem (*LightAppElem)(nil), // 43: LightAppElem
(*CustomFace)(nil), // 44: CustomFace (*CustomFace)(nil), // 44: CustomFace
(*ContentHead)(nil), // 45: ContentHead (*ContentHead)(nil), // 45: ContentHead
(*MessageHead)(nil), // 46: MessageHead (*MessageHead)(nil), // 46: MessageHead
(*GroupInfo)(nil), // 47: GroupInfo (*GroupInfo)(nil), // 47: GroupInfo
(*DiscussInfo)(nil), // 48: DiscussInfo (*DiscussInfo)(nil), // 48: DiscussInfo
(*MutilTransHead)(nil), // 49: MutilTransHead (*MutilTransHead)(nil), // 49: MutilTransHead
(*C2CTempMessageHead)(nil), // 50: C2CTempMessageHead (*C2CTempMessageHead)(nil), // 50: C2CTempMessageHead
(*InstCtrl)(nil), // 51: InstCtrl (*InstCtrl)(nil), // 51: InstCtrl
(*InstInfo)(nil), // 52: InstInfo (*InstInfo)(nil), // 52: InstInfo
(*ExtGroupKeyInfo)(nil), // 53: ExtGroupKeyInfo (*ExtGroupKeyInfo)(nil), // 53: ExtGroupKeyInfo
(*SyncCookie)(nil), // 54: SyncCookie (*SyncCookie)(nil), // 54: SyncCookie
(*TransMsgInfo)(nil), // 55: TransMsgInfo (*TransMsgInfo)(nil), // 55: TransMsgInfo
(*GeneralFlags)(nil), // 56: GeneralFlags (*GeneralFlags)(nil), // 56: GeneralFlags
(*PbMultiMsgItem)(nil), // 57: PbMultiMsgItem (*PbMultiMsgItem)(nil), // 57: PbMultiMsgItem
(*PbMultiMsgNew)(nil), // 58: PbMultiMsgNew (*PbMultiMsgNew)(nil), // 58: PbMultiMsgNew
(*PbMultiMsgTransmit)(nil), // 59: PbMultiMsgTransmit (*PbMultiMsgTransmit)(nil), // 59: PbMultiMsgTransmit
(*MsgElemInfoServtype3)(nil), // 60: MsgElemInfo_servtype3 (*MsgElemInfoServtype3)(nil), // 60: MsgElemInfo_servtype3
(*MsgElemInfoServtype33)(nil), // 61: MsgElemInfo_servtype33 (*MsgElemInfoServtype33)(nil), // 61: MsgElemInfo_servtype33
(*SubMsgType0X4Body)(nil), // 62: SubMsgType0x4Body (*SubMsgType0X4Body)(nil), // 62: SubMsgType0x4Body
(*ResvAttr)(nil), // 63: ResvAttr (*ResvAttr)(nil), // 63: ResvAttr
(*AnimationImageShow)(nil), // 64: AnimationImageShow (*AnimationImageShow)(nil), // 64: AnimationImageShow
(*UinTypeUserDef)(nil), // 65: UinTypeUserDef (*UinTypeUserDef)(nil), // 65: UinTypeUserDef
(*GetGroupMsgReq)(nil), // 66: GetGroupMsgReq (*GetGroupMsgReq)(nil), // 66: GetGroupMsgReq
(*GetGroupMsgResp)(nil), // 67: GetGroupMsgResp (*GetGroupMsgResp)(nil), // 67: GetGroupMsgResp
(*PbGetOneDayRoamMsgReq)(nil), // 68: PbGetOneDayRoamMsgReq
(*PbGetOneDayRoamMsgResp)(nil), // 69: PbGetOneDayRoamMsgResp
} }
var file_msg_proto_depIdxs = []int32{ var file_msg_proto_depIdxs = []int32{
0, // 0: GetMessageRequest.syncFlag:type_name -> SyncFlag 0, // 0: GetMessageRequest.syncFlag:type_name -> SyncFlag
@ -7937,11 +8127,12 @@ var file_msg_proto_depIdxs = []int32{
35, // 64: SubMsgType0x4Body.notOnlineFile:type_name -> NotOnlineFile 35, // 64: SubMsgType0x4Body.notOnlineFile:type_name -> NotOnlineFile
64, // 65: ResvAttr.image_show:type_name -> AnimationImageShow 64, // 65: ResvAttr.image_show:type_name -> AnimationImageShow
20, // 66: GetGroupMsgResp.msg:type_name -> Message 20, // 66: GetGroupMsgResp.msg:type_name -> Message
67, // [67:67] is the sub-list for method output_type 20, // 67: PbGetOneDayRoamMsgResp.msg:type_name -> Message
67, // [67:67] is the sub-list for method input_type 68, // [68:68] is the sub-list for method output_type
67, // [67:67] is the sub-list for extension type_name 68, // [68:68] is the sub-list for method input_type
67, // [67:67] is the sub-list for extension extendee 68, // [68:68] is the sub-list for extension type_name
0, // [0:67] is the sub-list for field 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() } func init() { file_msg_proto_init() }
@ -8754,6 +8945,30 @@ func file_msg_proto_init() {
return nil 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{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
@ -8761,7 +8976,7 @@ func file_msg_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_msg_proto_rawDesc, RawDescriptor: file_msg_proto_rawDesc,
NumEnums: 1, NumEnums: 1,
NumMessages: 67, NumMessages: 69,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@ -769,3 +769,20 @@ message GetGroupMsgResp {
optional uint64 returnEndSeq = 5; optional uint64 returnEndSeq = 5;
repeated Message msg = 6; 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;
}

165
client/private_msg.go Normal file
View File

@ -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
}

View File

@ -260,7 +260,7 @@ func EstimateLength(elems []IMessageElement, limit int) int {
case *ReplyElement: case *ReplyElement:
sum += 444 + EstimateLength(e.Elements, left) sum += 444 + EstimateLength(e.Elements, left)
case *ImageElement, *GroupImageElement, *FriendImageElement: case *ImageElement, *GroupImageElement, *FriendImageElement:
sum += 260 sum += 100
default: default:
sum += utils.ChineseLength(ToReadableString([]IMessageElement{elem}), left) sum += utils.ChineseLength(ToReadableString([]IMessageElement{elem}), left)
} }