mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 11:07:40 +08:00
fix issue of repeatedly trigger for OnlinePush events.
This commit is contained in:
parent
d795ee54ce
commit
0e4b1c602b
@ -348,7 +348,7 @@ func (r *JceReader) readObject(t reflect.Type, tag int) reflect.Value {
|
||||
r.ReadObject(&s, tag)
|
||||
return reflect.ValueOf(s)
|
||||
case reflect.Slice:
|
||||
s := reflect.New(t.Elem()).Interface().(IJecStruct)
|
||||
s := reflect.New(t.Elem()).Interface().(IJceStruct)
|
||||
r.readHead()
|
||||
s.ReadFrom(r)
|
||||
r.skipToStructEnd()
|
||||
@ -410,7 +410,7 @@ func (r *JceReader) ReadObject(i interface{}, tag int) {
|
||||
*o = r.ReadFloat64(tag)
|
||||
case *string:
|
||||
*o = r.ReadString(tag)
|
||||
case IJecStruct:
|
||||
case IJceStruct:
|
||||
o.ReadFrom(r)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package jce
|
||||
|
||||
type IJecStruct interface {
|
||||
ToBytes() []byte
|
||||
type IJceStruct interface {
|
||||
//ToBytes() []byte
|
||||
ReadFrom(*JceReader)
|
||||
}
|
||||
|
||||
@ -86,6 +86,25 @@ type (
|
||||
}
|
||||
|
||||
SvcRespPushMsg struct {
|
||||
Uin int64 `jceId:"0"`
|
||||
DelInfos []IJceStruct `jceId:"1"`
|
||||
Svrip int32 `jceId:"2"`
|
||||
PushToken []byte `jceId:"3"`
|
||||
ServiceType int32 `jceId:"4"`
|
||||
}
|
||||
|
||||
DelMsgInfo struct {
|
||||
FromUin int64 `jceId:"0"`
|
||||
MsgTime int64 `jceId:"1"`
|
||||
MsgSeq int16 `jceId:"2"`
|
||||
MsgCookies []byte `jceId:"3"`
|
||||
Cmd int16 `jceId:"4"`
|
||||
MsgType int64 `jceId:"5"`
|
||||
AppId int64 `jceId:"6"`
|
||||
SendTime int64 `jceId:"7"`
|
||||
SsoSeq int32 `jceId:"8"`
|
||||
SsoIp int32 `jceId:"9"`
|
||||
ClientIp int32 `jceId:"10"`
|
||||
}
|
||||
|
||||
FriendListRequest struct {
|
||||
@ -304,12 +323,6 @@ func (pkt *RequestDataVersion3) ReadFrom(r *JceReader) {
|
||||
})
|
||||
}
|
||||
|
||||
func (pkt *RequestDataVersion2) ToBytes() []byte {
|
||||
w := NewJceWriter()
|
||||
w.WriteJceStructRaw(pkt)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (pkt *RequestDataVersion2) ReadFrom(r *JceReader) {
|
||||
pkt.Map = make(map[string]map[string][]byte)
|
||||
r.ReadMapF(0, func(k interface{}, v interface{}) {
|
||||
@ -340,12 +353,6 @@ func (pkt *FriendListRequest) ReadFrom(r *JceReader) {
|
||||
|
||||
}
|
||||
|
||||
func (pkt *FriendInfo) ToBytes() []byte {
|
||||
w := NewJceWriter()
|
||||
w.WriteJceStructRaw(pkt)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (pkt *FriendInfo) ReadFrom(r *JceReader) {
|
||||
pkt.FriendUin = r.ReadInt64(0)
|
||||
pkt.GroupId = r.ReadByte(1)
|
||||
@ -370,12 +377,6 @@ func (pkt *TroopListRequest) ReadFrom(r *JceReader) {
|
||||
|
||||
}
|
||||
|
||||
func (pkt *TroopNumber) ToBytes() []byte {
|
||||
w := NewJceWriter()
|
||||
w.WriteJceStructRaw(pkt)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (pkt *TroopNumber) ReadFrom(r *JceReader) {
|
||||
pkt.GroupUin = r.ReadInt64(0)
|
||||
pkt.GroupCode = r.ReadInt64(1)
|
||||
@ -396,12 +397,6 @@ func (pkt *TroopMemberListRequest) ReadFrom(r *JceReader) {
|
||||
|
||||
}
|
||||
|
||||
func (pkt *TroopMemberInfo) ToBytes() []byte {
|
||||
w := NewJceWriter()
|
||||
w.WriteJceStructRaw(pkt)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (pkt *TroopMemberInfo) ReadFrom(r *JceReader) {
|
||||
pkt.MemberUin = r.ReadInt64(0)
|
||||
pkt.FaceId = r.ReadInt16(1)
|
||||
@ -417,12 +412,6 @@ func (pkt *TroopMemberInfo) ReadFrom(r *JceReader) {
|
||||
pkt.Job = r.ReadString(25)
|
||||
}
|
||||
|
||||
func (pkt *PushMessageInfo) ToBytes() []byte {
|
||||
w := NewJceWriter()
|
||||
w.WriteJceStructRaw(pkt)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (pkt *PushMessageInfo) ReadFrom(r *JceReader) {
|
||||
pkt.FromUin = r.ReadInt64(0)
|
||||
pkt.MsgTime = r.ReadInt64(1)
|
||||
@ -430,6 +419,20 @@ func (pkt *PushMessageInfo) ReadFrom(r *JceReader) {
|
||||
pkt.MsgSeq = r.ReadInt16(3)
|
||||
pkt.Msg = r.ReadString(4)
|
||||
pkt.VMsg = r.ReadAny(6).([]byte)
|
||||
pkt.MsgCookies = r.ReadAny(8).([]byte)
|
||||
pkt.MsgUid = r.ReadInt64(10)
|
||||
pkt.FromMobile = r.ReadString(16)
|
||||
pkt.FromName = r.ReadString(17)
|
||||
}
|
||||
|
||||
func (pkt *SvcRespPushMsg) ToBytes() []byte {
|
||||
w := NewJceWriter()
|
||||
w.WriteJceStructRaw(pkt)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (pkt *SvcRespPushMsg) ReadFrom(r *JceReader) {
|
||||
}
|
||||
|
||||
func (pkt *DelMsgInfo) ReadFrom(r *JceReader) {
|
||||
}
|
||||
|
@ -112,6 +112,18 @@ func (w *JceWriter) WriteInt64Slice(l []int64, tag int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, tag int) {
|
||||
w.writeHead(9, tag)
|
||||
if len(l) == 0 {
|
||||
w.WriteInt32(0, 0)
|
||||
return
|
||||
}
|
||||
w.WriteInt32(int32(len(l)), 0)
|
||||
for _, v := range l {
|
||||
w.WriteJceStruct(v, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *JceWriter) WriteMap(m interface{}, tag int) {
|
||||
if m == nil {
|
||||
w.writeHead(8, tag)
|
||||
@ -158,12 +170,14 @@ func (w *JceWriter) WriteObject(i interface{}, tag int) {
|
||||
w.WriteBytes(o, tag)
|
||||
case []int64:
|
||||
w.WriteInt64Slice(o, tag)
|
||||
case IJecStruct:
|
||||
case IJceStruct:
|
||||
w.WriteJceStruct(o, tag)
|
||||
case []IJceStruct:
|
||||
w.WriteJceStructSlice(o, tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *JceWriter) WriteJceStructRaw(s IJecStruct) {
|
||||
func (w *JceWriter) WriteJceStructRaw(s IJceStruct) {
|
||||
var (
|
||||
t = reflect.TypeOf(s).Elem()
|
||||
v = reflect.ValueOf(s).Elem()
|
||||
@ -181,7 +195,7 @@ func (w *JceWriter) WriteJceStructRaw(s IJecStruct) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *JceWriter) WriteJceStruct(s IJecStruct, tag int) {
|
||||
func (w *JceWriter) WriteJceStruct(s IJceStruct, tag int) {
|
||||
w.writeHead(10, tag)
|
||||
w.WriteJceStructRaw(s)
|
||||
w.writeHead(11, 0)
|
||||
|
@ -3,12 +3,10 @@ package binary
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"crypto/rand"
|
||||
binary2 "encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -20,19 +18,6 @@ func ZlibUncompress(src []byte) []byte {
|
||||
return out.Bytes()
|
||||
}
|
||||
|
||||
func RandomString(len int) string {
|
||||
var res string
|
||||
var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||
b := bytes.NewBufferString(str)
|
||||
length := b.Len()
|
||||
bigInt := big.NewInt(int64(length))
|
||||
for i := 0; i < len; i++ {
|
||||
randomInt, _ := rand.Int(rand.Reader, bigInt)
|
||||
res += string(str[randomInt.Int64()])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func CalculateImageResourceId(md5 []byte) string {
|
||||
return strings.ToUpper(fmt.Sprintf(
|
||||
"{%s-%s-%s-%s-%s}.png",
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/Mrs4s/MiraiGo/protocol/crypto"
|
||||
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
||||
"github.com/Mrs4s/MiraiGo/protocol/tlv"
|
||||
"github.com/Mrs4s/MiraiGo/utils"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
@ -327,6 +328,33 @@ func (c *QQClient) buildDeleteMessageRequestPacket(msg []*pb.MessageItem) (uint1
|
||||
return seq, packet
|
||||
}
|
||||
|
||||
func (c *QQClient) buildDeleteOnlinePushPacket(uin int64, seq uint16, delMsg []jce.PushMessageInfo) []byte {
|
||||
req := &jce.SvcRespPushMsg{Uin: uin}
|
||||
for _, m := range delMsg {
|
||||
req.DelInfos = append(req.DelInfos, &jce.DelMsgInfo{
|
||||
FromUin: m.FromUin,
|
||||
MsgSeq: m.MsgSeq,
|
||||
MsgCookies: m.MsgCookies,
|
||||
MsgTime: m.MsgTime,
|
||||
})
|
||||
}
|
||||
b := append([]byte{0x0A}, req.ToBytes()...)
|
||||
b = append(b, 0x0B)
|
||||
buf := &jce.RequestDataVersion3{
|
||||
Map: map[string][]byte{"resp": b},
|
||||
}
|
||||
pkt := &jce.RequestPacket{
|
||||
IVersion: 3,
|
||||
IRequestId: int32(seq),
|
||||
SServantName: "OnlinePush",
|
||||
SFuncName: "SvcRespPushMsg",
|
||||
SBuffer: buf.ToBytes(),
|
||||
Context: make(map[string]string),
|
||||
Status: make(map[string]string),
|
||||
}
|
||||
return packets.BuildUniPacket(c.Uin, seq, "OnlinePush.RespPush", 1, c.OutGoingPacketSessionId, []byte{}, c.sigInfo.d2Key, pkt.ToBytes())
|
||||
}
|
||||
|
||||
func (c *QQClient) buildGroupSendingPacket(groupCode int64, m *message.SendingMessage) (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
req := &msg.SendMessageRequest{
|
||||
@ -350,7 +378,7 @@ func (c *QQClient) buildGroupSendingPacket(groupCode int64, m *message.SendingMe
|
||||
|
||||
func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 [16]byte, size int32) (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
name := binary.RandomString(16) + ".gif"
|
||||
name := utils.RandomString(16) + ".gif"
|
||||
req := &pb.D388ReqBody{
|
||||
NetType: 3,
|
||||
Subcmd: 1,
|
||||
|
@ -33,7 +33,7 @@ type QQClient struct {
|
||||
RandomKey []byte
|
||||
Conn net.Conn
|
||||
|
||||
decoders map[string]func(*QQClient, []byte) (interface{}, error)
|
||||
decoders map[string]func(*QQClient, uint16, []byte) (interface{}, error)
|
||||
handlers map[uint16]func(interface{}, error)
|
||||
|
||||
syncCookie []byte
|
||||
@ -52,6 +52,7 @@ type QQClient struct {
|
||||
running bool
|
||||
|
||||
lastMessageSeq int32
|
||||
onlinePushCache []int16 // reset on reconnect
|
||||
requestPacketRequestId int32
|
||||
messageSeq int32
|
||||
groupDataTransSeq int32
|
||||
@ -84,7 +85,7 @@ func NewClient(uin int64, password string) *QQClient {
|
||||
SequenceId: 0x3635,
|
||||
RandomKey: make([]byte, 16),
|
||||
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
|
||||
decoders: map[string]func(*QQClient, []byte) (interface{}, error){
|
||||
decoders: map[string]func(*QQClient, uint16, []byte) (interface{}, error){
|
||||
"wtlogin.login": decodeLoginResponse,
|
||||
"StatSvc.register": decodeClientRegisterResponse,
|
||||
"MessageSvc.PushNotify": decodeSvcNotify,
|
||||
@ -312,6 +313,7 @@ func (c *QQClient) connect() error {
|
||||
return err
|
||||
}
|
||||
c.Conn = conn
|
||||
c.onlinePushCache = []int16{}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -411,7 +413,7 @@ func (c *QQClient) loop() {
|
||||
}
|
||||
return
|
||||
}
|
||||
rsp, err := decoder(c, payload)
|
||||
rsp, err := decoder(c, pkt.SequenceId, payload)
|
||||
if err != nil {
|
||||
log.Println("decode", pkt.CommandName, "error:", err)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func decodeLoginResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeLoginResponse(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
reader := binary.NewReader(payload)
|
||||
reader.ReadUInt16() // sub command
|
||||
t := reader.ReadByte()
|
||||
@ -91,7 +91,7 @@ func decodeLoginResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
return nil, nil // ?
|
||||
}
|
||||
|
||||
func decodeClientRegisterResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeClientRegisterResponse(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
request := &jce.RequestPacket{}
|
||||
request.ReadFrom(jce.NewJceReader(payload))
|
||||
data := &jce.RequestDataVersion2{}
|
||||
@ -99,7 +99,7 @@ func decodeClientRegisterResponse(c *QQClient, payload []byte) (interface{}, err
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func decodePushReqPacket(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodePushReqPacket(c *QQClient, s uint16, payload []byte) (interface{}, error) {
|
||||
request := &jce.RequestPacket{}
|
||||
request.ReadFrom(jce.NewJceReader(payload))
|
||||
data := &jce.RequestDataVersion2{}
|
||||
@ -113,7 +113,7 @@ func decodePushReqPacket(c *QQClient, payload []byte) (interface{}, error) {
|
||||
return nil, c.send(pkt)
|
||||
}
|
||||
|
||||
func decodeMessageSvcPacket(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeMessageSvcPacket(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
rsp := msg.GetMessageResponse{}
|
||||
err := proto.Unmarshal(payload, &rsp)
|
||||
if err != nil {
|
||||
@ -163,7 +163,7 @@ func decodeMessageSvcPacket(c *QQClient, payload []byte) (interface{}, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func decodeGroupMessagePacket(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeGroupMessagePacket(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
pkt := msg.PushMessagePacket{}
|
||||
err := proto.Unmarshal(payload, &pkt)
|
||||
if err != nil {
|
||||
@ -176,12 +176,12 @@ func decodeGroupMessagePacket(c *QQClient, payload []byte) (interface{}, error)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func decodeSvcNotify(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeSvcNotify(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
_, pkt := c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix())
|
||||
return nil, c.send(pkt)
|
||||
}
|
||||
|
||||
func decodeFriendGroupListResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeFriendGroupListResponse(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
request := &jce.RequestPacket{}
|
||||
request.ReadFrom(jce.NewJceReader(payload))
|
||||
data := &jce.RequestDataVersion3{}
|
||||
@ -206,7 +206,7 @@ func decodeFriendGroupListResponse(c *QQClient, payload []byte) (interface{}, er
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
func decodeGroupListResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeGroupListResponse(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
request := &jce.RequestPacket{}
|
||||
request.ReadFrom(jce.NewJceReader(payload))
|
||||
data := &jce.RequestDataVersion3{}
|
||||
@ -229,7 +229,7 @@ func decodeGroupListResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func decodeGroupMemberListResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeGroupMemberListResponse(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
request := &jce.RequestPacket{}
|
||||
request.ReadFrom(jce.NewJceReader(payload))
|
||||
data := &jce.RequestDataVersion3{}
|
||||
@ -258,7 +258,7 @@ func decodeGroupMemberListResponse(c *QQClient, payload []byte) (interface{}, er
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeGroupImageStoreResponse(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeGroupImageStoreResponse(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
pkt := pb.D388RespBody{}
|
||||
err := proto.Unmarshal(payload, &pkt)
|
||||
if err != nil {
|
||||
@ -281,15 +281,29 @@ func decodeGroupImageStoreResponse(c *QQClient, payload []byte) (interface{}, er
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeOnlinePushReqPacket(c *QQClient, payload []byte) (interface{}, error) {
|
||||
func decodeOnlinePushReqPacket(c *QQClient, seq uint16, payload []byte) (interface{}, error) {
|
||||
request := &jce.RequestPacket{}
|
||||
request.ReadFrom(jce.NewJceReader(payload))
|
||||
data := &jce.RequestDataVersion2{}
|
||||
data.ReadFrom(jce.NewJceReader(request.SBuffer))
|
||||
jr := jce.NewJceReader(data.Map["req"]["OnlinePushPack.SvcReqPushMsg"][1:])
|
||||
msgInfos := []jce.PushMessageInfo{}
|
||||
uin := jr.ReadInt64(0)
|
||||
jr.ReadSlice(&msgInfos, 2)
|
||||
_ = c.send(c.buildDeleteOnlinePushPacket(uin, seq, msgInfos))
|
||||
seqExists := func(ms int16) bool {
|
||||
for _, s := range c.onlinePushCache {
|
||||
if ms == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
for _, m := range msgInfos {
|
||||
if seqExists(m.MsgSeq) {
|
||||
continue
|
||||
}
|
||||
c.onlinePushCache = append(c.onlinePushCache, m.MsgSeq)
|
||||
if m.MsgType == 732 {
|
||||
r := binary.NewReader(m.VMsg)
|
||||
groupId := int64(uint32(r.ReadInt32()))
|
||||
@ -329,5 +343,6 @@ func decodeOnlinePushReqPacket(c *QQClient, payload []byte) (interface{}, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
20
utils/string.go
Normal file
20
utils/string.go
Normal file
@ -0,0 +1,20 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func RandomString(len int) string {
|
||||
var res string
|
||||
var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||
b := bytes.NewBufferString(str)
|
||||
length := b.Len()
|
||||
bigInt := big.NewInt(int64(length))
|
||||
for i := 0; i < len; i++ {
|
||||
randomInt, _ := rand.Int(rand.Reader, bigInt)
|
||||
res += string(str[randomInt.Int64()])
|
||||
}
|
||||
return res
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user