mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-05 03:23:50 +08:00
Merge
merge
This commit is contained in:
commit
ebdcad5168
@ -6,6 +6,8 @@ qq-android协议的golang实现 移植于mirai
|
|||||||
|
|
||||||
建议基于 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 使用框架开发。
|
建议基于 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 使用框架开发。
|
||||||
|
|
||||||
|
同时提供不基于 CQHTTP 的原生框架 [MiraiGo-Template](https://github.com/Logiase/MiraiGo-Template) 进行开发。
|
||||||
|
|
||||||
# 已完成功能/开发计划
|
# 已完成功能/开发计划
|
||||||
#### 登录
|
#### 登录
|
||||||
- [x] 账号密码登录
|
- [x] 账号密码登录
|
||||||
|
@ -40,9 +40,9 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) {
|
|||||||
|
|
||||||
w.Write(tlv.T18(16, uint32(c.Uin)))
|
w.Write(tlv.T18(16, uint32(c.Uin)))
|
||||||
w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress))
|
w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress))
|
||||||
w.Write(tlv.T106(uint32(c.Uin), 0, uint32(SystemDeviceInfo.Protocol), c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey))
|
w.Write(tlv.T106(uint32(c.Uin), 0, uint32(SystemDeviceInfo.Protocol), c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 0))
|
||||||
w.Write(tlv.T116(184024956, 0x10400))
|
w.Write(tlv.T116(184024956, 0x10400))
|
||||||
w.Write(tlv.T100(uint32(SystemDeviceInfo.Protocol)))
|
w.Write(tlv.T100(uint32(SystemDeviceInfo.Protocol), 34869472))
|
||||||
w.Write(tlv.T107(0))
|
w.Write(tlv.T107(0))
|
||||||
w.Write(tlv.T142("com.tencent.mobileqq"))
|
w.Write(tlv.T142("com.tencent.mobileqq"))
|
||||||
w.Write(tlv.T144(
|
w.Write(tlv.T144(
|
||||||
@ -127,6 +127,54 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt
|
|||||||
return seq, packet
|
return seq, packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||||
|
seq := c.nextSeq()
|
||||||
|
req := packets.BuildOicqRequestPacket(c.Uin, 0x0810, crypto.NewEncryptSession(c.sigInfo.t133), c.sigInfo.wtSessionTicketKey, func(w *binary.Writer) {
|
||||||
|
w.WriteUInt16(15)
|
||||||
|
w.WriteUInt16(21)
|
||||||
|
|
||||||
|
w.Write(tlv.T18(16, uint32(c.Uin)))
|
||||||
|
w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress))
|
||||||
|
w.Write(tlv.T106(uint32(c.Uin), 0, uint32(SystemDeviceInfo.Protocol), c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 1))
|
||||||
|
w.Write(tlv.T116(150470524, 66560))
|
||||||
|
w.Write(tlv.T100(2, 34869472))
|
||||||
|
w.Write(tlv.T107(0))
|
||||||
|
w.Write(tlv.T144(
|
||||||
|
SystemDeviceInfo.AndroidId,
|
||||||
|
SystemDeviceInfo.GenDeviceInfoData(),
|
||||||
|
SystemDeviceInfo.OSType,
|
||||||
|
SystemDeviceInfo.Version.Release,
|
||||||
|
SystemDeviceInfo.SimInfo,
|
||||||
|
SystemDeviceInfo.APN,
|
||||||
|
false, true, false, tlv.GuidFlag(),
|
||||||
|
SystemDeviceInfo.Model,
|
||||||
|
SystemDeviceInfo.Guid,
|
||||||
|
SystemDeviceInfo.Brand,
|
||||||
|
SystemDeviceInfo.TgtgtKey,
|
||||||
|
))
|
||||||
|
w.Write(tlv.T142("com.tencent.mobileqq"))
|
||||||
|
w.Write(tlv.T145(SystemDeviceInfo.Guid))
|
||||||
|
w.Write(tlv.T16A(c.sigInfo.srmToken))
|
||||||
|
w.Write(tlv.T154(seq))
|
||||||
|
w.Write(tlv.T141(SystemDeviceInfo.SimInfo, SystemDeviceInfo.APN))
|
||||||
|
w.Write(tlv.T8(2052))
|
||||||
|
w.Write(tlv.T511([]string{
|
||||||
|
"tenpay.com", "openmobile.qq.com", "docs.qq.com", "connect.qq.com",
|
||||||
|
"qzone.qq.com", "vip.qq.com", "qun.qq.com", "game.qq.com", "qqweb.qq.com",
|
||||||
|
"office.qq.com", "ti.qq.com", "mail.qq.com", "qzone.com", "mma.qq.com",
|
||||||
|
}))
|
||||||
|
w.Write(tlv.T147(16, []byte("8.2.7"), []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D}))
|
||||||
|
w.Write(tlv.T177())
|
||||||
|
w.Write(tlv.T187(SystemDeviceInfo.MacAddress))
|
||||||
|
w.Write(tlv.T188(SystemDeviceInfo.AndroidId))
|
||||||
|
w.Write(tlv.T194(SystemDeviceInfo.IMSIMd5))
|
||||||
|
w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID))
|
||||||
|
w.Write(tlv.T516())
|
||||||
|
})
|
||||||
|
packet := packets.BuildUniPacket(c.Uin, seq, "wtlogin.exchange_emp", 2, c.OutGoingPacketSessionId, []byte{}, make([]byte, 16), req)
|
||||||
|
return seq, packet
|
||||||
|
}
|
||||||
|
|
||||||
// StatSvc.register
|
// StatSvc.register
|
||||||
func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
|
func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
|
||||||
seq := c.nextSeq()
|
seq := c.nextSeq()
|
||||||
|
@ -94,6 +94,7 @@ type loginSigInfo struct {
|
|||||||
userStKey []byte
|
userStKey []byte
|
||||||
userStWebSig []byte
|
userStWebSig []byte
|
||||||
sKey []byte
|
sKey []byte
|
||||||
|
sKeyExpiredTime int64
|
||||||
d2 []byte
|
d2 []byte
|
||||||
d2Key []byte
|
d2Key []byte
|
||||||
wtSessionTicketKey []byte
|
wtSessionTicketKey []byte
|
||||||
@ -121,6 +122,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
|
|||||||
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
|
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
|
||||||
decoders: map[string]func(*QQClient, uint16, []byte) (interface{}, error){
|
decoders: map[string]func(*QQClient, uint16, []byte) (interface{}, error){
|
||||||
"wtlogin.login": decodeLoginResponse,
|
"wtlogin.login": decodeLoginResponse,
|
||||||
|
"wtlogin.exchange_emp": decodeExchangeEmpResponse,
|
||||||
"StatSvc.register": decodeClientRegisterResponse,
|
"StatSvc.register": decodeClientRegisterResponse,
|
||||||
"StatSvc.ReqMSFOffline": decodeMSFOfflinePacket,
|
"StatSvc.ReqMSFOffline": decodeMSFOfflinePacket,
|
||||||
"StatSvc.GetDevLoginInfo": decodeDevListResponse,
|
"StatSvc.GetDevLoginInfo": decodeDevListResponse,
|
||||||
@ -849,6 +851,10 @@ func (c *QQClient) SolveFriendRequest(req *NewFriendRequest, accept bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) getCookies() string {
|
func (c *QQClient) getCookies() string {
|
||||||
|
if c.sigInfo.sKeyExpiredTime < time.Now().Unix() {
|
||||||
|
c.Debug("skey expired. refresh...")
|
||||||
|
_, _ = c.sendAndWait(c.buildRequestTgtgtNopicsigPacket())
|
||||||
|
}
|
||||||
return fmt.Sprintf("uin=o%d; skey=%s;", c.Uin, c.sigInfo.sKey)
|
return fmt.Sprintf("uin=o%d; skey=%s;", c.Uin, c.sigInfo.sKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,23 @@ func decodeClientRegisterResponse(_ *QQClient, _ uint16, payload []byte) (interf
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wtlogin.exchange_emp
|
||||||
|
func decodeExchangeEmpResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
|
||||||
|
reader := binary.NewReader(payload)
|
||||||
|
cmd := reader.ReadUInt16()
|
||||||
|
t := reader.ReadByte()
|
||||||
|
reader.ReadUInt16()
|
||||||
|
m := reader.ReadTlvMap(2)
|
||||||
|
if t != 0 {
|
||||||
|
c.Error("exchange_emp error: %v", t)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if cmd == 15 { // TODO: 免密登录
|
||||||
|
c.decodeT119(m[0x119])
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ConfigPushSvc.PushReq
|
// ConfigPushSvc.PushReq
|
||||||
func decodePushReqPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
|
func decodePushReqPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
|
||||||
request := &jce.RequestPacket{}
|
request := &jce.RequestPacket{}
|
||||||
|
@ -23,7 +23,18 @@ func (c *QQClient) decodeT119(data []byte) {
|
|||||||
reader := binary.NewReader(tea.Decrypt(data))
|
reader := binary.NewReader(tea.Decrypt(data))
|
||||||
reader.ReadBytes(2)
|
reader.ReadBytes(2)
|
||||||
m := reader.ReadTlvMap(2)
|
m := reader.ReadTlvMap(2)
|
||||||
|
if len(c.sigInfo.sKey) > 0 { // refresh
|
||||||
|
if t120, ok := m[0x120]; ok {
|
||||||
|
c.sigInfo.sKey = t120
|
||||||
|
c.sigInfo.sKeyExpiredTime = time.Now().Unix() + 43200 // 86400 / 2
|
||||||
|
c.Debug("skey updated: %v", c.sigInfo.sKey)
|
||||||
|
}
|
||||||
|
if t11a, ok := m[0x11a]; ok {
|
||||||
|
c.Nickname, c.Age, c.Gender = readT11A(t11a)
|
||||||
|
c.Debug("account info updated: " + c.Nickname)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
if t130, ok := m[0x130]; ok {
|
if t130, ok := m[0x130]; ok {
|
||||||
c.decodeT130(t130)
|
c.decodeT130(t130)
|
||||||
}
|
}
|
||||||
@ -79,6 +90,10 @@ func (c *QQClient) decodeT119(data []byte) {
|
|||||||
//a1, noPicSig = readT531(t531)
|
//a1, noPicSig = readT531(t531)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := m[0x138]; ok {
|
||||||
|
//readT138(t138) // chg time
|
||||||
|
}
|
||||||
|
|
||||||
c.sigInfo = &loginSigInfo{
|
c.sigInfo = &loginSigInfo{
|
||||||
loginBitmap: 0,
|
loginBitmap: 0,
|
||||||
srmToken: m[0x16a],
|
srmToken: m[0x16a],
|
||||||
@ -88,6 +103,7 @@ func (c *QQClient) decodeT119(data []byte) {
|
|||||||
userStKey: m[0x10e],
|
userStKey: m[0x10e],
|
||||||
userStWebSig: m[0x103],
|
userStWebSig: m[0x103],
|
||||||
sKey: m[0x120],
|
sKey: m[0x120],
|
||||||
|
sKeyExpiredTime: time.Now().Unix() + 43200, // 86400 / 2
|
||||||
d2: m[0x143],
|
d2: m[0x143],
|
||||||
d2Key: m[0x305],
|
d2Key: m[0x305],
|
||||||
wtSessionTicketKey: m[0x134],
|
wtSessionTicketKey: m[0x134],
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
func T100(protocol uint32) []byte {
|
func T100(protocol, mainSigMap uint32) []byte {
|
||||||
return binary.NewWriterF(func(w *binary.Writer) {
|
return binary.NewWriterF(func(w *binary.Writer) {
|
||||||
w.WriteUInt16(0x100)
|
w.WriteUInt16(0x100)
|
||||||
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
||||||
@ -12,8 +12,8 @@ func T100(protocol uint32) []byte {
|
|||||||
w.WriteUInt32(5)
|
w.WriteUInt32(5)
|
||||||
w.WriteUInt32(16)
|
w.WriteUInt32(16)
|
||||||
w.WriteUInt32(protocol)
|
w.WriteUInt32(protocol)
|
||||||
w.WriteUInt32(0) // App client version
|
w.WriteUInt32(0) // App client version
|
||||||
w.WriteUInt32(34869472)
|
w.WriteUInt32(mainSigMap) // 34869472
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte) []byte {
|
func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte {
|
||||||
return binary.NewWriterF(func(w *binary.Writer) {
|
return binary.NewWriterF(func(w *binary.Writer) {
|
||||||
w.WriteUInt16(0x106)
|
w.WriteUInt16(0x106)
|
||||||
body := binary.NewWriterF(func(w *binary.Writer) {
|
body := binary.NewWriterF(func(w *binary.Writer) {
|
||||||
@ -27,7 +27,7 @@ func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool,
|
|||||||
w.WriteByte(0x01)
|
w.WriteByte(0x01)
|
||||||
w.Write(passwordMd5[:])
|
w.Write(passwordMd5[:])
|
||||||
w.Write(tgtgtKey)
|
w.Write(tgtgtKey)
|
||||||
w.WriteUInt32(0)
|
w.WriteUInt32(wtf)
|
||||||
w.WriteBool(guidAvailable)
|
w.WriteBool(guidAvailable)
|
||||||
if len(guid) == 0 {
|
if len(guid) == 0 {
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user