mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 11:07:40 +08:00
Merge
sync
This commit is contained in:
commit
375490e386
@ -36,17 +36,21 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
req := packets.BuildOicqRequestPacket(c.Uin, 0x0810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) {
|
||||
w.WriteUInt16(9)
|
||||
w.WriteUInt16(17)
|
||||
if c.AllowSlider {
|
||||
w.WriteUInt16(0x17)
|
||||
} else {
|
||||
w.WriteUInt16(0x16)
|
||||
}
|
||||
|
||||
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, 0))
|
||||
w.Write(tlv.T116(184024956, 0x10400))
|
||||
w.Write(tlv.T100(uint32(SystemDeviceInfo.Protocol), 34869472))
|
||||
w.Write(tlv.T106(uint32(c.Uin), 0, c.version.AppId, c.version.SSOVersion, c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 0))
|
||||
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
|
||||
w.Write(tlv.T100(c.version.SSOVersion, c.version.AppId, c.version.MainSigMap))
|
||||
w.Write(tlv.T107(0))
|
||||
w.Write(tlv.T142("com.tencent.mobileqq"))
|
||||
w.Write(tlv.T142(c.version.ApkId))
|
||||
w.Write(tlv.T144(
|
||||
SystemDeviceInfo.AndroidId,
|
||||
[]byte(SystemDeviceInfo.IMEI),
|
||||
SystemDeviceInfo.GenDeviceInfoData(),
|
||||
SystemDeviceInfo.OSType,
|
||||
SystemDeviceInfo.Version.Release,
|
||||
@ -60,7 +64,7 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) {
|
||||
))
|
||||
|
||||
w.Write(tlv.T145(SystemDeviceInfo.Guid))
|
||||
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.T147(16, []byte(c.version.SortVersionName), c.version.ApkSign))
|
||||
/*
|
||||
if (miscBitMap & 0x80) != 0{
|
||||
w.Write(tlv.T166(1))
|
||||
@ -80,16 +84,18 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) {
|
||||
if len(SystemDeviceInfo.IMSIMd5) != 0 {
|
||||
w.Write(tlv.T194(SystemDeviceInfo.IMSIMd5))
|
||||
}
|
||||
w.Write(tlv.T191(0x82))
|
||||
if c.AllowSlider {
|
||||
w.Write(tlv.T191(0x82))
|
||||
}
|
||||
if len(SystemDeviceInfo.WifiBSSID) != 0 && len(SystemDeviceInfo.WifiSSID) != 0 {
|
||||
w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID))
|
||||
}
|
||||
w.Write(tlv.T177())
|
||||
w.Write(tlv.T177(c.version.BuildTime, c.version.SdkVersion))
|
||||
w.Write(tlv.T516())
|
||||
w.Write(tlv.T521())
|
||||
w.Write(tlv.T525(tlv.T536([]byte{0x01, 0x00})))
|
||||
})
|
||||
sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
||||
return seq, packet
|
||||
}
|
||||
@ -102,11 +108,11 @@ func (c *QQClient) buildDeviceLockLoginPacket(t402 []byte) (uint16, []byte) {
|
||||
|
||||
w.Write(tlv.T8(2052))
|
||||
w.Write(tlv.T104(c.t104))
|
||||
w.Write(tlv.T116(150470524, 66560))
|
||||
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
|
||||
h := md5.Sum(append(append(SystemDeviceInfo.Guid, []byte("stMNokHgxZUGhsYp")...), t402...))
|
||||
w.Write(tlv.T401(h[:]))
|
||||
})
|
||||
sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
||||
return seq, packet
|
||||
}
|
||||
@ -122,7 +128,45 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt
|
||||
w.Write(tlv.T104(c.t104))
|
||||
w.Write(tlv.T116(150470524, 66560))
|
||||
})
|
||||
sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
||||
return seq, packet
|
||||
}
|
||||
|
||||
func (c *QQClient) buildSNSRequestPacket() (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
req := packets.BuildOicqRequestPacket(c.Uin, 0x810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) {
|
||||
w.WriteUInt16(8)
|
||||
w.WriteUInt16(6)
|
||||
|
||||
w.Write(tlv.T8(2052))
|
||||
w.Write(tlv.T104(c.t104))
|
||||
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
|
||||
w.Write(tlv.T174(c.t174))
|
||||
w.Write(tlv.T17A(9))
|
||||
w.Write(tlv.T197())
|
||||
})
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
||||
return seq, packet
|
||||
}
|
||||
|
||||
func (c *QQClient) buildSNSCodeSubmitPacket(code string) (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
req := packets.BuildOicqRequestPacket(c.Uin, 0x810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) {
|
||||
w.WriteUInt16(7)
|
||||
w.WriteUInt16(7)
|
||||
|
||||
w.Write(tlv.T8(2052))
|
||||
w.Write(tlv.T104(c.t104))
|
||||
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
|
||||
w.Write(tlv.T174(c.t174))
|
||||
w.Write(tlv.T17C(code))
|
||||
h := md5.Sum(append(append(SystemDeviceInfo.Guid, []byte("12 34567890123456")...), c.t402...))
|
||||
w.Write(tlv.T401(h[:]))
|
||||
w.Write(tlv.T198())
|
||||
})
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
||||
return seq, packet
|
||||
}
|
||||
@ -135,9 +179,9 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||
|
||||
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.T106(uint32(c.Uin), 0, c.version.AppId, c.version.SSOVersion, c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 1))
|
||||
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
|
||||
w.Write(tlv.T100(c.version.SSOVersion, 2, c.version.MainSigMap))
|
||||
w.Write(tlv.T107(0))
|
||||
w.Write(tlv.T144(
|
||||
SystemDeviceInfo.AndroidId,
|
||||
@ -152,7 +196,7 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||
SystemDeviceInfo.Brand,
|
||||
SystemDeviceInfo.TgtgtKey,
|
||||
))
|
||||
w.Write(tlv.T142("com.tencent.mobileqq"))
|
||||
w.Write(tlv.T142(c.version.ApkId))
|
||||
w.Write(tlv.T145(SystemDeviceInfo.Guid))
|
||||
w.Write(tlv.T16A(c.sigInfo.srmToken))
|
||||
w.Write(tlv.T154(seq))
|
||||
@ -163,8 +207,8 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||
"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.T147(16, []byte(c.version.SortVersionName), c.version.ApkSign))
|
||||
w.Write(tlv.T177(c.version.BuildTime, c.version.SdkVersion))
|
||||
w.Write(tlv.T187(SystemDeviceInfo.MacAddress))
|
||||
w.Write(tlv.T188(SystemDeviceInfo.AndroidId))
|
||||
w.Write(tlv.T194(SystemDeviceInfo.IMSIMd5))
|
||||
@ -218,7 +262,7 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
|
||||
Context: make(map[string]string),
|
||||
Status: make(map[string]string),
|
||||
}
|
||||
sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "StatSvc.register", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, pkt.ToBytes(), c.ksid)
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "StatSvc.register", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, pkt.ToBytes(), c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 1, c.sigInfo.d2Key, sso, c.sigInfo.d2)
|
||||
return seq, packet
|
||||
}
|
||||
@ -691,7 +735,7 @@ func (c *QQClient) buildImageUploadPacket(data, updKey []byte, commandId int32,
|
||||
}
|
||||
return c.nextGroupDataTransSeq()
|
||||
}(),
|
||||
Appid: int32(SystemDeviceInfo.Protocol),
|
||||
Appid: int32(c.version.AppId),
|
||||
Dataflag: 4096,
|
||||
CommandId: commandId,
|
||||
LocaleId: 2052,
|
||||
@ -1081,7 +1125,7 @@ func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool)
|
||||
func (c *QQClient) buildGroupInfoRequestPacket(groupCode int64) (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
body := &oidb.D88DReqBody{
|
||||
AppId: proto.Uint32(uint32(SystemDeviceInfo.Protocol)),
|
||||
AppId: proto.Uint32(c.version.AppId),
|
||||
ReqGroupInfo: []*oidb.ReqGroupInfo{
|
||||
{
|
||||
GroupCode: proto.Uint64(uint64(groupCode)),
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
type QQClient struct {
|
||||
Uin int64
|
||||
PasswordMd5 [16]byte
|
||||
AllowSlider bool
|
||||
|
||||
Nickname string
|
||||
Age uint16
|
||||
@ -50,12 +51,15 @@ type QQClient struct {
|
||||
servers []*net.TCPAddr
|
||||
currServerIndex int
|
||||
retryTimes int
|
||||
version *versionInfo
|
||||
|
||||
syncCookie []byte
|
||||
pubAccountCookie []byte
|
||||
msgCtrlBuf []byte
|
||||
ksid []byte
|
||||
t104 []byte
|
||||
t174 []byte
|
||||
t402 []byte // only for sms
|
||||
t150 []byte
|
||||
t149 []byte
|
||||
t528 []byte
|
||||
@ -159,10 +163,11 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
|
||||
groupSeq: int32(rand.Intn(20000)),
|
||||
friendSeq: 22911,
|
||||
highwayApplyUpSeq: 77918,
|
||||
ksid: []byte("|454001228437590|A8.2.7.27f6ea96"),
|
||||
ksid: []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", SystemDeviceInfo.IMEI)),
|
||||
eventHandlers: &eventHandlers{},
|
||||
msgSvcCache: utils.NewCache(time.Second * 15),
|
||||
transCache: utils.NewCache(time.Second * 15),
|
||||
version: genVersionInfo(SystemDeviceInfo.Protocol),
|
||||
servers: []*net.TCPAddr{ // default servers
|
||||
{IP: net.IP{42, 81, 169, 46}, Port: 8080},
|
||||
{IP: net.IP{42, 81, 172, 81}, Port: 80},
|
||||
@ -212,6 +217,47 @@ func (c *QQClient) Login() (*LoginResponse, error) {
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
// SubmitCaptcha send captcha to server
|
||||
func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, error) {
|
||||
seq, packet := c.buildCaptchaPacket(result, sign)
|
||||
rsp, err := c.sendAndWait(seq, packet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := rsp.(LoginResponse)
|
||||
if l.Success {
|
||||
c.registerClient()
|
||||
if !c.heartbeatEnabled {
|
||||
c.startHeartbeat()
|
||||
}
|
||||
}
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
func (c *QQClient) SubmitSNS(code string) (*LoginResponse, error) {
|
||||
rsp, err := c.sendAndWait(c.buildSNSCodeSubmitPacket(code))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := rsp.(LoginResponse)
|
||||
if l.Success {
|
||||
c.registerClient()
|
||||
if !c.heartbeatEnabled {
|
||||
c.startHeartbeat()
|
||||
}
|
||||
}
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
func (c *QQClient) RequestSNS() bool {
|
||||
rsp, err := c.sendAndWait(c.buildSNSRequestPacket())
|
||||
if err != nil {
|
||||
c.Error("request sms error: %v", err)
|
||||
return false
|
||||
}
|
||||
return rsp.(LoginResponse).Error == SNSNeededError
|
||||
}
|
||||
|
||||
func (c *QQClient) GetVipInfo(target int64) (*VipInfo, error) {
|
||||
b, err := utils.HttpGetBytes(fmt.Sprintf("https://h5.vip.qq.com/p/mc/cardv2/other?platform=1&qq=%d&adtag=geren&aid=mvip.pingtai.mobileqq.androidziliaoka.fromqita", target), c.getCookiesWithDomain("h5.vip.qq.com"))
|
||||
if err != nil {
|
||||
@ -283,23 +329,6 @@ func (c *QQClient) GetSummaryInfo(target int64) (*SummaryCardInfo, error) {
|
||||
return rsp.(*SummaryCardInfo), nil
|
||||
}
|
||||
|
||||
// SubmitCaptcha send captcha to server
|
||||
func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, error) {
|
||||
seq, packet := c.buildCaptchaPacket(result, sign)
|
||||
rsp, err := c.sendAndWait(seq, packet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := rsp.(LoginResponse)
|
||||
if l.Success {
|
||||
c.registerClient()
|
||||
if !c.heartbeatEnabled {
|
||||
c.startHeartbeat()
|
||||
}
|
||||
}
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
// ReloadFriendList refresh QQClient.FriendList field via GetFriendList()
|
||||
func (c *QQClient) ReloadFriendList() error {
|
||||
rsp, err := c.GetFriendList()
|
||||
@ -957,6 +986,13 @@ func (c *QQClient) connect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *QQClient) Disconnect() {
|
||||
if c.Online {
|
||||
c.Online = false
|
||||
c.Conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *QQClient) SetCustomServer(servers []*net.TCPAddr) {
|
||||
c.servers = append(servers, c.servers...)
|
||||
}
|
||||
@ -1118,7 +1154,7 @@ func (c *QQClient) startHeartbeat() {
|
||||
func (c *QQClient) doHeartbeat() {
|
||||
if c.Online {
|
||||
seq := c.nextSeq()
|
||||
sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "Heartbeat.Alive", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, []byte{}, c.ksid)
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "Heartbeat.Alive", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, []byte{}, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 0, []byte{}, sso, []byte{})
|
||||
_, err := c.sendAndWait(seq, packet)
|
||||
if err != nil {
|
||||
|
@ -56,8 +56,9 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er
|
||||
c.t104, _ = m[0x104]
|
||||
if m.Exists(0x192) { // slider, not supported yet
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: UnknownLoginError,
|
||||
Success: false,
|
||||
VerifyUrl: string(m[0x192]),
|
||||
Error: SliderNeededError,
|
||||
}, nil
|
||||
}
|
||||
if m.Exists(0x165) { // image
|
||||
@ -80,11 +81,54 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er
|
||||
} // need captcha
|
||||
|
||||
if t == 160 {
|
||||
|
||||
if t174, ok := m[0x174]; ok { // 短信验证
|
||||
c.t104 = m[0x104]
|
||||
c.t174 = t174
|
||||
c.t402 = m[0x402]
|
||||
phone := func() string {
|
||||
r := binary.NewReader(m[0x178])
|
||||
return r.ReadStringLimit(int(r.ReadInt32()))
|
||||
}()
|
||||
if t204, ok := m[0x204]; ok { // 同时支持扫码验证 ?
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: SNSOrVerifyNeededError,
|
||||
VerifyUrl: string(t204),
|
||||
SMSPhone: phone,
|
||||
ErrorMessage: string(m[0x17e]),
|
||||
}, nil
|
||||
}
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: SNSNeededError,
|
||||
SMSPhone: phone,
|
||||
ErrorMessage: string(m[0x17e]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
if _, ok := m[0x17b]; ok { // 二次验证
|
||||
c.t104 = m[0x104]
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: SNSNeededError,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if t204, ok := m[0x204]; ok { // 扫码验证
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: UnsafeDeviceError,
|
||||
VerifyUrl: string(t204),
|
||||
ErrorMessage: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if t == 162 {
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: UnsafeDeviceError,
|
||||
VerifyUrl: string(m[0x204]),
|
||||
ErrorMessage: "",
|
||||
Error: TooManySNSRequestError,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -139,7 +183,7 @@ func decodeExchangeEmpResponse(c *QQClient, _ uint16, payload []byte) (interface
|
||||
return nil, nil
|
||||
}
|
||||
if cmd == 15 { // TODO: 免密登录
|
||||
c.decodeT119(m[0x119])
|
||||
c.decodeT119R(m[0x119])
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ type (
|
||||
// Unsafe device
|
||||
VerifyUrl string
|
||||
|
||||
// SMS needed
|
||||
SMSPhone string
|
||||
|
||||
// other error
|
||||
ErrorMessage string
|
||||
}
|
||||
@ -119,6 +122,12 @@ type (
|
||||
Member *GroupMemberInfo
|
||||
}
|
||||
|
||||
MemberCardUpdatedEvent struct {
|
||||
Group *GroupInfo
|
||||
OldCard string
|
||||
Member *GroupMemberInfo
|
||||
}
|
||||
|
||||
IGroupNotifyEvent interface {
|
||||
From() int64
|
||||
Content() string
|
||||
@ -240,18 +249,22 @@ type (
|
||||
)
|
||||
|
||||
const (
|
||||
NeedCaptcha LoginError = 1
|
||||
OtherLoginError LoginError = 3
|
||||
UnsafeDeviceError LoginError = 4
|
||||
UnknownLoginError LoginError = -1
|
||||
NeedCaptcha LoginError = 1
|
||||
OtherLoginError LoginError = 3
|
||||
UnsafeDeviceError LoginError = 4
|
||||
SNSNeededError LoginError = 5
|
||||
TooManySNSRequestError LoginError = 6
|
||||
SNSOrVerifyNeededError LoginError = 7
|
||||
SliderNeededError LoginError = 8
|
||||
UnknownLoginError LoginError = -1
|
||||
|
||||
Owner MemberPermission = iota
|
||||
Administrator
|
||||
Member
|
||||
|
||||
AndroidPhone ClientProtocol = 537062845
|
||||
AndroidPad ClientProtocol = 537062409
|
||||
AndroidWatch ClientProtocol = 537061176
|
||||
AndroidPhone ClientProtocol = 1
|
||||
AndroidPad ClientProtocol = 2
|
||||
AndroidWatch ClientProtocol = 3
|
||||
)
|
||||
|
||||
func (g *GroupInfo) UpdateName(newName string) {
|
||||
|
@ -17,6 +17,7 @@ type eventHandlers struct {
|
||||
leaveGroupHandlers []func(*QQClient, *GroupLeaveEvent)
|
||||
memberJoinedHandlers []func(*QQClient, *MemberJoinGroupEvent)
|
||||
memberLeavedHandlers []func(*QQClient, *MemberLeaveGroupEvent)
|
||||
memberCardUpdatedHandlers []func(*QQClient, *MemberCardUpdatedEvent)
|
||||
permissionChangedHandlers []func(*QQClient, *MemberPermissionChangedEvent)
|
||||
groupInvitedHandlers []func(*QQClient, *GroupInvitedRequest)
|
||||
joinRequestHandlers []func(*QQClient, *UserJoinGroupRequest)
|
||||
@ -69,6 +70,10 @@ func (c *QQClient) OnGroupMemberLeaved(f func(*QQClient, *MemberLeaveGroupEvent)
|
||||
c.eventHandlers.memberLeavedHandlers = append(c.eventHandlers.memberLeavedHandlers, f)
|
||||
}
|
||||
|
||||
func (c *QQClient) OnGroupMemberCardUpdated(f func(*QQClient, *MemberCardUpdatedEvent)) {
|
||||
c.eventHandlers.memberCardUpdatedHandlers = append(c.eventHandlers.memberCardUpdatedHandlers, f)
|
||||
}
|
||||
|
||||
func (c *QQClient) OnGroupMemberPermissionChanged(f func(*QQClient, *MemberPermissionChangedEvent)) {
|
||||
c.eventHandlers.permissionChangedHandlers = append(c.eventHandlers.permissionChangedHandlers, f)
|
||||
}
|
||||
@ -237,6 +242,17 @@ func (c *QQClient) dispatchMemberLeaveEvent(e *MemberLeaveGroupEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *QQClient) dispatchMemberCardUpdatedEvent(e *MemberCardUpdatedEvent) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
for _, f := range c.eventHandlers.memberCardUpdatedHandlers {
|
||||
cover(func() {
|
||||
f(c, e)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *QQClient) dispatchPermissionChanged(e *MemberPermissionChangedEvent) {
|
||||
if e == nil {
|
||||
return
|
||||
|
@ -66,6 +66,19 @@ type groupMessageBuilder struct {
|
||||
MessageSlices []*msg.Message
|
||||
}
|
||||
|
||||
type versionInfo struct {
|
||||
ApkId string
|
||||
AppId uint32
|
||||
SortVersionName string
|
||||
BuildTime uint32
|
||||
ApkSign []byte
|
||||
SdkVersion string
|
||||
SSOVersion uint32
|
||||
MiscBitmap uint32
|
||||
SubSigmap uint32
|
||||
MainSigMap uint32
|
||||
}
|
||||
|
||||
// default
|
||||
var SystemDeviceInfo = &DeviceInfo{
|
||||
Display: []byte("MIRAI.123456.001"),
|
||||
@ -125,6 +138,51 @@ func GenRandomDevice() {
|
||||
SystemDeviceInfo.GenNewTgtgtKey()
|
||||
}
|
||||
|
||||
func genVersionInfo(p ClientProtocol) *versionInfo {
|
||||
switch p {
|
||||
case AndroidPhone: // Dumped by mirai from qq android v8.2.7
|
||||
return &versionInfo{
|
||||
ApkId: "com.tencent.mobileqq",
|
||||
AppId: 537062845,
|
||||
SortVersionName: "8.2.7",
|
||||
BuildTime: 1571193922,
|
||||
ApkSign: []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D},
|
||||
SdkVersion: "6.0.0.2413",
|
||||
SSOVersion: 5,
|
||||
MiscBitmap: 184024956,
|
||||
SubSigmap: 0x10400,
|
||||
MainSigMap: 34869472,
|
||||
}
|
||||
case AndroidWatch:
|
||||
return &versionInfo{
|
||||
ApkId: "com.tencent.mobileqq",
|
||||
AppId: 537061176,
|
||||
SortVersionName: "8.2.7",
|
||||
BuildTime: 1571193922,
|
||||
ApkSign: []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D},
|
||||
SdkVersion: "6.0.0.2413",
|
||||
SSOVersion: 5,
|
||||
MiscBitmap: 184024956,
|
||||
SubSigmap: 0x10400,
|
||||
MainSigMap: 34869472,
|
||||
}
|
||||
case AndroidPad: // Dumped from qq-hd v5.8.9
|
||||
return &versionInfo{
|
||||
ApkId: "com.tencent.minihd.qq",
|
||||
AppId: 537065549,
|
||||
SortVersionName: "5.8.9",
|
||||
BuildTime: 1595836208,
|
||||
ApkSign: []byte{170, 57, 120, 244, 31, 217, 111, 249, 145, 74, 102, 158, 24, 100, 116, 199},
|
||||
SdkVersion: "6.0.0.2433",
|
||||
SSOVersion: 12,
|
||||
MiscBitmap: 150470524,
|
||||
SubSigmap: 66560,
|
||||
MainSigMap: 1970400,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (info *DeviceInfo) ToJson() []byte {
|
||||
f := &DeviceInfoFile{
|
||||
Display: string(info.Display),
|
||||
@ -309,6 +367,21 @@ func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage {
|
||||
Member: info,
|
||||
})
|
||||
}
|
||||
if m.Head.GroupInfo != nil && m.Head.GroupInfo.GroupCard != "" && mem.CardName != m.Head.GroupInfo.GroupCard {
|
||||
old := mem.CardName
|
||||
if mem.Nickname == m.Head.GroupInfo.GroupCard {
|
||||
mem.CardName = ""
|
||||
} else {
|
||||
mem.CardName = m.Head.GroupInfo.GroupCard
|
||||
}
|
||||
if old != mem.CardName {
|
||||
go c.dispatchMemberCardUpdatedEvent(&MemberCardUpdatedEvent{
|
||||
Group: group,
|
||||
OldCard: old,
|
||||
Member: mem,
|
||||
})
|
||||
}
|
||||
}
|
||||
sender = &message.Sender{
|
||||
Uin: mem.Uin,
|
||||
Nickname: mem.Nickname,
|
||||
|
@ -23,18 +23,6 @@ func (c *QQClient) decodeT119(data []byte) {
|
||||
reader := binary.NewReader(tea.Decrypt(data))
|
||||
reader.ReadBytes(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 {
|
||||
c.decodeT130(t130)
|
||||
}
|
||||
@ -117,6 +105,23 @@ func (c *QQClient) decodeT119(data []byte) {
|
||||
c.Gender = gender
|
||||
}
|
||||
|
||||
// wtlogin.exchange_emp
|
||||
func (c *QQClient) decodeT119R(data []byte) {
|
||||
tea := binary.NewTeaCipher(SystemDeviceInfo.TgtgtKey)
|
||||
reader := binary.NewReader(tea.Decrypt(data))
|
||||
reader.ReadBytes(2)
|
||||
m := reader.ReadTlvMap(2)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *QQClient) decodeT130(data []byte) {
|
||||
reader := binary.NewReader(data)
|
||||
reader.ReadBytes(2)
|
||||
|
@ -24,11 +24,11 @@ func BuildLoginPacket(uin int64, bodyType byte, key, body, extraData []byte) []b
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func BuildUniPacket(uin int64, seq uint16, commandName string, bodyType byte, sessionId, extraData, key, body []byte) []byte {
|
||||
func BuildUniPacket(uin int64, seq uint16, commandName string, encryptType byte, sessionId, extraData, key, body []byte) []byte {
|
||||
w := binary.NewWriter()
|
||||
w.WriteIntLvPacket(4, func(w *binary.Writer) {
|
||||
w.WriteUInt32(0x0B)
|
||||
w.WriteByte(bodyType)
|
||||
w.WriteByte(encryptType)
|
||||
w.WriteUInt32(uint32(seq))
|
||||
w.WriteByte(0)
|
||||
w.WriteString(strconv.FormatInt(uin, 10))
|
||||
|
@ -52,12 +52,12 @@ func BuildOicqRequestPacket(uin int64, commandId uint16, encrypt IEncryptMethod,
|
||||
return p.Bytes()
|
||||
}
|
||||
|
||||
func BuildSsoPacket(seq uint16, protocol uint32, commandName, imei string, extData, outPacketSessionId, body, ksid []byte) []byte {
|
||||
func BuildSsoPacket(seq uint16, appId uint32, commandName, imei string, extData, outPacketSessionId, body, ksid []byte) []byte {
|
||||
p := binary.NewWriter()
|
||||
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
|
||||
writer.WriteUInt32(uint32(seq))
|
||||
writer.WriteUInt32(protocol)
|
||||
writer.WriteUInt32(protocol)
|
||||
writer.WriteUInt32(appId)
|
||||
writer.WriteUInt32(appId)
|
||||
writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
|
||||
if len(extData) == 0 || len(extData) == 4 {
|
||||
writer.WriteUInt32(0x04)
|
||||
@ -66,8 +66,9 @@ func BuildSsoPacket(seq uint16, protocol uint32, commandName, imei string, extDa
|
||||
writer.Write(extData)
|
||||
}
|
||||
writer.WriteString(commandName)
|
||||
writer.WriteUInt32(0x08)
|
||||
writer.Write(outPacketSessionId)
|
||||
writer.WriteIntLvPacket(4, func(w *binary.Writer) {
|
||||
w.Write(outPacketSessionId)
|
||||
})
|
||||
writer.WriteString(imei)
|
||||
writer.WriteUInt32(0x04)
|
||||
{
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"github.com/Mrs4s/MiraiGo/binary"
|
||||
)
|
||||
|
||||
func T100(protocol, mainSigMap uint32) []byte {
|
||||
func T100(ssoVersion, protocol, mainSigMap uint32) []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x100)
|
||||
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(1)
|
||||
w.WriteUInt32(5)
|
||||
w.WriteUInt32(ssoVersion)
|
||||
w.WriteUInt32(16)
|
||||
w.WriteUInt32(protocol)
|
||||
w.WriteUInt32(0) // App client version
|
||||
|
@ -8,13 +8,13 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte {
|
||||
func T106(uin, salt, appId, ssoVer uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x106)
|
||||
body := binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(4)
|
||||
w.WriteUInt32(rand.Uint32())
|
||||
w.WriteUInt32(5)
|
||||
w.WriteUInt32(ssoVer)
|
||||
w.WriteUInt32(16) // appId
|
||||
w.WriteUInt32(0) // app client version
|
||||
if uin == 0 {
|
||||
@ -36,7 +36,7 @@ func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool,
|
||||
} else {
|
||||
w.Write(guid)
|
||||
}
|
||||
w.WriteUInt32(protocol)
|
||||
w.WriteUInt32(appId)
|
||||
w.WriteUInt32(1) // password login
|
||||
b := make([]byte, 8)
|
||||
binary2.BigEndian.PutUint64(b, uint64(uin))
|
||||
|
@ -1,9 +1,11 @@
|
||||
package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
import (
|
||||
"github.com/Mrs4s/MiraiGo/binary"
|
||||
)
|
||||
|
||||
func T144(
|
||||
androidId, devInfo, osType, osVersion, simInfo, apn []byte,
|
||||
imei, devInfo, osType, osVersion, simInfo, apn []byte,
|
||||
isGuidFromFileNull, isGuidAvailable, isGuidChanged bool,
|
||||
guidFlag uint32,
|
||||
buildModel, guid, buildBrand, tgtgtKey []byte,
|
||||
@ -13,7 +15,7 @@ func T144(
|
||||
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.EncryptAndWrite(tgtgtKey, binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(5)
|
||||
w.Write(T109(androidId))
|
||||
w.Write(T109(imei))
|
||||
w.Write(T52D(devInfo))
|
||||
w.Write(T124(osType, osVersion, simInfo, apn))
|
||||
w.Write(T128(isGuidFromFileNull, isGuidAvailable, isGuidChanged, guidFlag, buildModel, guid, buildBrand))
|
||||
|
10
protocol/tlv/t174.go
Normal file
10
protocol/tlv/t174.go
Normal file
@ -0,0 +1,10 @@
|
||||
package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
|
||||
func T174(data []byte) []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x174)
|
||||
w.WriteTlv(data)
|
||||
})
|
||||
}
|
@ -2,13 +2,13 @@ package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
|
||||
func T177() []byte {
|
||||
func T177(buildTime uint32, sdkVersion string) []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x177)
|
||||
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteByte(0x01)
|
||||
w.WriteUInt32(1571193922)
|
||||
w.WriteTlv([]byte("6.0.0.2413"))
|
||||
w.WriteUInt32(buildTime)
|
||||
w.WriteTlv([]byte(sdkVersion))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
12
protocol/tlv/t17a.go
Normal file
12
protocol/tlv/t17a.go
Normal file
@ -0,0 +1,12 @@
|
||||
package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
|
||||
func T17A(value int32) []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x17a)
|
||||
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt32(uint32(value))
|
||||
}))
|
||||
})
|
||||
}
|
12
protocol/tlv/t17c.go
Normal file
12
protocol/tlv/t17c.go
Normal file
@ -0,0 +1,12 @@
|
||||
package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
|
||||
func T17C(code string) []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x17c)
|
||||
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteStringShort(code)
|
||||
}))
|
||||
})
|
||||
}
|
10
protocol/tlv/t197.go
Normal file
10
protocol/tlv/t197.go
Normal file
@ -0,0 +1,10 @@
|
||||
package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
|
||||
func T197() []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x197)
|
||||
w.WriteTlv([]byte{0})
|
||||
})
|
||||
}
|
10
protocol/tlv/t198.go
Normal file
10
protocol/tlv/t198.go
Normal file
@ -0,0 +1,10 @@
|
||||
package tlv
|
||||
|
||||
import "github.com/Mrs4s/MiraiGo/binary"
|
||||
|
||||
func T198() []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt16(0x198)
|
||||
w.WriteTlv([]byte{0})
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user