mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 19:17:38 +08:00
zap: reuse some []byte
优化单线程上传内存使用
This commit is contained in:
parent
86e0f3327a
commit
2e64a6913d
@ -1,7 +1,7 @@
|
|||||||
package jce
|
package jce
|
||||||
|
|
||||||
type IJceStruct interface {
|
type IJceStruct interface {
|
||||||
//ToBytes() []byte
|
// ToBytes() []byte
|
||||||
ReadFrom(*JceReader)
|
ReadFrom(*JceReader)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,8 +42,8 @@ type (
|
|||||||
BigDataChannel *BigDataChannel `jceId:"5"`
|
BigDataChannel *BigDataChannel `jceId:"5"`
|
||||||
VipEmotionList []FileStorageServerInfo `jceId:"6"`
|
VipEmotionList []FileStorageServerInfo `jceId:"6"`
|
||||||
C2CPicDownList []FileStorageServerInfo `jceId:"7"`
|
C2CPicDownList []FileStorageServerInfo `jceId:"7"`
|
||||||
//FmtIPInfo *FmtIPInfo `jceId:"8"`
|
// FmtIPInfo *FmtIPInfo `jceId:"8"`
|
||||||
//DomainIPChannel *DomainIPChannel `jceId:"9"`
|
// DomainIPChannel *DomainIPChannel `jceId:"9"`
|
||||||
PttList []byte `jceId:"10"`
|
PttList []byte `jceId:"10"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,8 +496,8 @@ type (
|
|||||||
IsFriend byte `jceId:"3"`
|
IsFriend byte `jceId:"3"`
|
||||||
GroupCode int64 `jceId:"4"`
|
GroupCode int64 `jceId:"4"`
|
||||||
GroupUin int64 `jceId:"5"`
|
GroupUin int64 `jceId:"5"`
|
||||||
//Seed []byte`jceId:"6"`
|
// Seed []byte`jceId:"6"`
|
||||||
//SearchName string`jceId:"7"`
|
// SearchName string`jceId:"7"`
|
||||||
GetControl int64 `jceId:"8"`
|
GetControl int64 `jceId:"8"`
|
||||||
AddFriendSource int32 `jceId:"9"`
|
AddFriendSource int32 `jceId:"9"`
|
||||||
SecureSig []byte `jceId:"10"`
|
SecureSig []byte `jceId:"10"`
|
||||||
|
@ -243,7 +243,7 @@ func (w *JceWriter) WriteJceStructRaw(s IJceStruct) {
|
|||||||
decoderCache.Store(ty2, jceDec) // 存入缓存
|
decoderCache.Store(ty2, jceDec) // 存入缓存
|
||||||
}
|
}
|
||||||
for _, dec := range jceDec {
|
for _, dec := range jceDec {
|
||||||
var obj = dec.ty.UnsafeIndirect(unsafe.Pointer(uintptr(reflect2.PtrOf(s)) + dec.offset)) // MAGIC!
|
obj := dec.ty.UnsafeIndirect(unsafe.Pointer(uintptr(reflect2.PtrOf(s)) + dec.offset)) // MAGIC!
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
w.WriteObject(obj, dec.id)
|
w.WriteObject(obj, dec.id)
|
||||||
}
|
}
|
||||||
|
97
binary/pool.go
Normal file
97
binary/pool.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package binary
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"compress/zlib"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var bufferPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return new(Writer)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWriter 从池中取出一个 Writer
|
||||||
|
func NewWriter() *Writer {
|
||||||
|
w := bufferPool.Get().(*Writer)
|
||||||
|
if w == nil {
|
||||||
|
return new(Writer)
|
||||||
|
}
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutBuffer 将 Writer 放回池中
|
||||||
|
func PutBuffer(w *Writer) {
|
||||||
|
// See https://golang.org/issue/23199
|
||||||
|
const maxSize = 1 << 16
|
||||||
|
if w.Cap() < maxSize { // 对于大Buffer直接丢弃
|
||||||
|
w.Reset()
|
||||||
|
bufferPool.Put(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type gzipWriter struct {
|
||||||
|
w *gzip.Writer
|
||||||
|
buf *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
var gzipPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w := gzip.NewWriter(buf)
|
||||||
|
return &gzipWriter{
|
||||||
|
w: w,
|
||||||
|
buf: buf,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func acquireGzipWriter() *gzipWriter {
|
||||||
|
ret := gzipPool.Get().(*gzipWriter)
|
||||||
|
ret.buf.Reset()
|
||||||
|
ret.w.Reset(ret.buf)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func releaseGzipWriter(w *gzipWriter) {
|
||||||
|
// See https://golang.org/issue/23199
|
||||||
|
const maxSize = 1 << 16
|
||||||
|
if w.buf.Cap() < maxSize {
|
||||||
|
w.buf.Reset()
|
||||||
|
gzipPool.Put(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type zlibWriter struct {
|
||||||
|
w *zlib.Writer
|
||||||
|
buf *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
var zlibPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w := zlib.NewWriter(buf)
|
||||||
|
return &zlibWriter{
|
||||||
|
w: w,
|
||||||
|
buf: buf,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func acquireZlibWriter() *zlibWriter {
|
||||||
|
ret := zlibPool.Get().(*zlibWriter)
|
||||||
|
ret.buf.Reset()
|
||||||
|
ret.w.Reset(ret.buf)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func releaseZlibWriter(w *zlibWriter) {
|
||||||
|
// See https://golang.org/issue/23199
|
||||||
|
const maxSize = 1 << 16
|
||||||
|
if w.buf.Cap() < maxSize {
|
||||||
|
w.buf.Reset()
|
||||||
|
zlibPool.Put(w)
|
||||||
|
}
|
||||||
|
}
|
@ -13,12 +13,9 @@ func xorQ(a, b []byte, c []byte) { // MAGIC
|
|||||||
*(*uint64)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data))
|
*(*uint64)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func isZero(a []byte) bool { // MAGIC
|
|
||||||
return *(*uint64)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&a)).Data)) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type TEA [4]uint32
|
type TEA [4]uint32
|
||||||
|
|
||||||
|
// Encrypt tea 加密
|
||||||
// http://bbs.chinaunix.net/thread-583468-1-1.html
|
// http://bbs.chinaunix.net/thread-583468-1-1.html
|
||||||
// 感谢xichen大佬对TEA的解释
|
// 感谢xichen大佬对TEA的解释
|
||||||
func (t *TEA) Encrypt(src []byte) (dst []byte) {
|
func (t *TEA) Encrypt(src []byte) (dst []byte) {
|
||||||
@ -27,9 +24,9 @@ func (t *TEA) Encrypt(src []byte) (dst []byte) {
|
|||||||
tmp1 := make([]byte, 8) // 非纯src的数据
|
tmp1 := make([]byte, 8) // 非纯src的数据
|
||||||
tmp2 := make([]byte, 8)
|
tmp2 := make([]byte, 8)
|
||||||
dst = make([]byte, fill+lens+7)
|
dst = make([]byte, fill+lens+7)
|
||||||
//for i := 0; i < fill; i++ {
|
// for i := 0; i < fill; i++ {
|
||||||
// dst[i] = ' '
|
// dst[i] = ' '
|
||||||
//} // For test purpose
|
// } // For test purpose
|
||||||
_, _ = rand.Read(dst[0:fill])
|
_, _ = rand.Read(dst[0:fill])
|
||||||
dst[0] = byte(fill-3) | 0xF8 // 存储pad长度
|
dst[0] = byte(fill-3) | 0xF8 // 存储pad长度
|
||||||
in := 0 // 位置
|
in := 0 // 位置
|
||||||
@ -86,9 +83,6 @@ func (t *TEA) Decrypt(data []byte) []byte {
|
|||||||
xorQ(dst[in:in+8], data[in-8:in], dst[in:in+8])
|
xorQ(dst[in:in+8], data[in-8:in], dst[in:in+8])
|
||||||
xorQ(dst[in:in+8], data[in-8:in], tmp)
|
xorQ(dst[in:in+8], data[in-8:in], tmp)
|
||||||
}
|
}
|
||||||
//if !isZero(dst[len(data)-7:]) {
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
return dst[dst[0]&7+3 : len(data)-7]
|
return dst[dst[0]&7+3 : len(data)-7]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ var sampleData = func() [][3]string {
|
|||||||
|
|
||||||
{"LXY1226 Mrs4s", "LXY Testing~", "ab20caa63f3a6503a84f3cb28f9e26b6c18c051e995d1721"},
|
{"LXY1226 Mrs4s", "LXY Testing~", "ab20caa63f3a6503a84f3cb28f9e26b6c18c051e995d1721"},
|
||||||
}
|
}
|
||||||
for i, _ := range out {
|
for i := range out {
|
||||||
c, _ := hex.DecodeString(out[i][ENC])
|
c, _ := hex.DecodeString(out[i][ENC])
|
||||||
out[i][ENC] = utils.B2S(c)
|
out[i][ENC] = utils.B2S(c)
|
||||||
}
|
}
|
||||||
|
@ -8,43 +8,10 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gzipWriter struct {
|
|
||||||
w *gzip.Writer
|
|
||||||
buf *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
var gzipPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
w := gzip.NewWriter(buf)
|
|
||||||
return &gzipWriter{
|
|
||||||
w: w,
|
|
||||||
buf: buf,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func acquireGzipWriter() *gzipWriter {
|
|
||||||
ret := gzipPool.Get().(*gzipWriter)
|
|
||||||
ret.buf.Reset()
|
|
||||||
ret.w.Reset(ret.buf)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func releaseGzipWriter(w *gzipWriter) {
|
|
||||||
// See https://golang.org/issue/23199
|
|
||||||
const maxSize = 1 << 15
|
|
||||||
if w.buf.Cap() < maxSize {
|
|
||||||
w.buf.Reset()
|
|
||||||
gzipPool.Put(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ZlibUncompress(src []byte) []byte {
|
func ZlibUncompress(src []byte) []byte {
|
||||||
b := bytes.NewReader(src)
|
b := bytes.NewReader(src)
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
@ -55,11 +22,12 @@ func ZlibUncompress(src []byte) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ZlibCompress(data []byte) []byte {
|
func ZlibCompress(data []byte) []byte {
|
||||||
buf := new(bytes.Buffer)
|
zw := acquireZlibWriter()
|
||||||
w := zlib.NewWriter(buf)
|
_, _ = zw.w.Write(data)
|
||||||
_, _ = w.Write(data)
|
_ = zw.w.Close()
|
||||||
w.Close()
|
ret := append([]byte(nil), zw.buf.Bytes()...)
|
||||||
return buf.Bytes()
|
releaseZlibWriter(zw)
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func GZipCompress(data []byte) []byte {
|
func GZipCompress(data []byte) []byte {
|
||||||
@ -87,7 +55,6 @@ func CalculateImageResourceId(md5 []byte) string {
|
|||||||
id = id[:37]
|
id = id[:37]
|
||||||
id = append(id, "}.png"...)
|
id = append(id, "}.png"...)
|
||||||
return utils.B2S(bytes.ToUpper(id))
|
return utils.B2S(bytes.ToUpper(id))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenUUID(uuid []byte) []byte {
|
func GenUUID(uuid []byte) []byte {
|
||||||
|
@ -1,33 +1,13 @@
|
|||||||
package binary
|
package binary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Writer struct {
|
// Writer 写入
|
||||||
b []byte
|
type Writer bytes.Buffer
|
||||||
}
|
|
||||||
|
|
||||||
var bufferPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return new(Writer)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWriter() *Writer {
|
|
||||||
return bufferPool.Get().(*Writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutBuffer(w *Writer) {
|
|
||||||
// See https://golang.org/issue/23199
|
|
||||||
const maxSize = 1 << 16
|
|
||||||
if cap(w.b) < maxSize { // 对于大Buffer直接丢弃
|
|
||||||
w.b = w.b[:0]
|
|
||||||
bufferPool.Put(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWriterF(f func(writer *Writer)) []byte {
|
func NewWriterF(f func(writer *Writer)) []byte {
|
||||||
w := NewWriter()
|
w := NewWriter()
|
||||||
@ -38,7 +18,7 @@ func NewWriterF(f func(writer *Writer)) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Write(b []byte) {
|
func (w *Writer) Write(b []byte) {
|
||||||
w.b = append(w.b, b...)
|
(*bytes.Buffer)(w).Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) WriteHex(h string) {
|
func (w *Writer) WriteHex(h string) {
|
||||||
@ -47,7 +27,7 @@ func (w *Writer) WriteHex(h string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) WriteByte(b byte) {
|
func (w *Writer) WriteByte(b byte) {
|
||||||
w.b = append(w.b, b)
|
(*bytes.Buffer)(w).WriteByte(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) WriteUInt16(v uint16) {
|
func (w *Writer) WriteUInt16(v uint16) {
|
||||||
@ -129,5 +109,17 @@ func (w *Writer) WriteTlvLimitedSize(data []byte, limit int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Bytes() []byte {
|
func (w *Writer) Bytes() []byte {
|
||||||
return w.b
|
return (*bytes.Buffer)(w).Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Cap() int {
|
||||||
|
return (*bytes.Buffer)(w).Cap()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Reset() {
|
||||||
|
(*bytes.Buffer)(w).Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Grow(n int) {
|
||||||
|
(*bytes.Buffer)(w).Grow(n)
|
||||||
}
|
}
|
||||||
|
@ -393,7 +393,7 @@ func (c *QQClient) buildRequestChangeSigPacket() (uint16, []byte) {
|
|||||||
"qzone.qq.com", "vip.qq.com", "qun.qq.com", "game.qq.com", "qqweb.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",
|
"office.qq.com", "ti.qq.com", "mail.qq.com", "qzone.com", "mma.qq.com",
|
||||||
}))
|
}))
|
||||||
//w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID))
|
// w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID))
|
||||||
})
|
})
|
||||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.exchange_emp", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, req, c.ksid)
|
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.exchange_emp", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, req, c.ksid)
|
||||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
|
||||||
|
@ -15,6 +15,9 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/binary/jce"
|
"github.com/Mrs4s/MiraiGo/binary/jce"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
||||||
@ -22,8 +25,6 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/protocol/crypto"
|
"github.com/Mrs4s/MiraiGo/protocol/crypto"
|
||||||
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var json = jsoniter.ConfigFastest
|
var json = jsoniter.ConfigFastest
|
||||||
@ -536,7 +537,7 @@ func (c *QQClient) ReloadFriendList() error {
|
|||||||
|
|
||||||
// GetFriendList request friend list
|
// GetFriendList request friend list
|
||||||
func (c *QQClient) GetFriendList() (*FriendListResponse, error) {
|
func (c *QQClient) GetFriendList() (*FriendListResponse, error) {
|
||||||
var curFriendCount = 0
|
curFriendCount := 0
|
||||||
r := &FriendListResponse{}
|
r := &FriendListResponse{}
|
||||||
for {
|
for {
|
||||||
rsp, err := c.sendAndWait(c.buildFriendGroupListRequestPacket(int16(curFriendCount), 150, 0, 0))
|
rsp, err := c.sendAndWait(c.buildFriendGroupListRequestPacket(int16(curFriendCount), 150, 0, 0))
|
||||||
|
@ -447,7 +447,7 @@ func decodeFriendGroupListResponse(_ *QQClient, _ *incomingPacketInfo, payload [
|
|||||||
totalFriendCount := r.ReadInt16(5)
|
totalFriendCount := r.ReadInt16(5)
|
||||||
friends := []jce.FriendInfo{}
|
friends := []jce.FriendInfo{}
|
||||||
r.ReadSlice(&friends, 7)
|
r.ReadSlice(&friends, 7)
|
||||||
var l = make([]*FriendInfo, 0, len(friends))
|
l := make([]*FriendInfo, 0, len(friends))
|
||||||
for _, f := range friends {
|
for _, f := range friends {
|
||||||
l = append(l, &FriendInfo{
|
l = append(l, &FriendInfo{
|
||||||
Uin: f.FriendUin,
|
Uin: f.FriendUin,
|
||||||
@ -474,7 +474,7 @@ func decodeGroupListResponse(c *QQClient, _ *incomingPacketInfo, payload []byte)
|
|||||||
groups := []jce.TroopNumber{}
|
groups := []jce.TroopNumber{}
|
||||||
r.ReadSlice(&vecCookie, 4)
|
r.ReadSlice(&vecCookie, 4)
|
||||||
r.ReadSlice(&groups, 5)
|
r.ReadSlice(&groups, 5)
|
||||||
var l = make([]*GroupInfo, 0, len(groups))
|
l := make([]*GroupInfo, 0, len(groups))
|
||||||
for _, g := range groups {
|
for _, g := range groups {
|
||||||
l = append(l, &GroupInfo{
|
l = append(l, &GroupInfo{
|
||||||
Uin: g.GroupUin,
|
Uin: g.GroupUin,
|
||||||
@ -507,7 +507,7 @@ func decodeGroupMemberListResponse(_ *QQClient, _ *incomingPacketInfo, payload [
|
|||||||
members := []jce.TroopMemberInfo{}
|
members := []jce.TroopMemberInfo{}
|
||||||
r.ReadSlice(&members, 3)
|
r.ReadSlice(&members, 3)
|
||||||
next := r.ReadInt64(4)
|
next := r.ReadInt64(4)
|
||||||
var l = make([]*GroupMemberInfo, 0, len(members))
|
l := make([]*GroupMemberInfo, 0, len(members))
|
||||||
for _, m := range members {
|
for _, m := range members {
|
||||||
l = append(l, &GroupMemberInfo{
|
l = append(l, &GroupMemberInfo{
|
||||||
Uin: m.MemberUin,
|
Uin: m.MemberUin,
|
||||||
@ -677,7 +677,7 @@ func decodeOnlinePushTransPacket(c *QQClient, _ *incomingPacketInfo, payload []b
|
|||||||
if info.GetMsgType() == 44 {
|
if info.GetMsgType() == 44 {
|
||||||
data.ReadBytes(5)
|
data.ReadBytes(5)
|
||||||
var4 := int32(data.ReadByte())
|
var4 := int32(data.ReadByte())
|
||||||
var var5 = int64(0)
|
var5 := int64(0)
|
||||||
target := int64(uint32(data.ReadInt32()))
|
target := int64(uint32(data.ReadInt32()))
|
||||||
if var4 != 0 && var4 != 1 {
|
if var4 != 0 && var4 != 1 {
|
||||||
var5 = int64(uint32(data.ReadInt32()))
|
var5 = int64(uint32(data.ReadInt32()))
|
||||||
|
@ -3,10 +3,11 @@ package client
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/faceroam"
|
|
||||||
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/MiraiGo/client/pb/faceroam"
|
||||||
|
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CustomFace struct {
|
type CustomFace struct {
|
||||||
|
@ -156,8 +156,10 @@ var SystemDeviceInfo = &DeviceInfo{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var EmptyBytes = []byte{}
|
var (
|
||||||
var NumberRange = "0123456789"
|
EmptyBytes = []byte{}
|
||||||
|
NumberRange = "0123456789"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
r := make([]byte, 16)
|
r := make([]byte, 16)
|
||||||
@ -404,7 +406,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 = (sum * 9) % 10 // calculating the control digit
|
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()
|
||||||
}
|
}
|
||||||
@ -443,7 +445,7 @@ func getSSOAddress() ([]*net.TCPAddr, error) {
|
|||||||
reader := jce.NewJceReader(data.Map["HttpServerListRes"][1:])
|
reader := jce.NewJceReader(data.Map["HttpServerListRes"][1:])
|
||||||
servers := []jce.SsoServerInfo{}
|
servers := []jce.SsoServerInfo{}
|
||||||
reader.ReadSlice(&servers, 2)
|
reader.ReadSlice(&servers, 2)
|
||||||
var adds = make([]*net.TCPAddr, 0, len(servers))
|
adds := make([]*net.TCPAddr, 0, len(servers))
|
||||||
for _, s := range servers {
|
for _, s := range servers {
|
||||||
if strings.Contains(s.Server, "com") {
|
if strings.Contains(s.Server, "com") {
|
||||||
continue
|
continue
|
||||||
|
@ -12,11 +12,12 @@ import (
|
|||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/exciting"
|
"github.com/Mrs4s/MiraiGo/client/pb/exciting"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
||||||
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -173,7 +174,7 @@ func (fs *GroupFileSystem) UploadFile(p, name, folderId string) error {
|
|||||||
defer fileSingleFlight.Delete(p)
|
defer fileSingleFlight.Delete(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(p, os.O_RDONLY, 0666)
|
file, err := os.OpenFile(p, os.O_RDONLY, 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "open file error")
|
return errors.Wrap(err, "open file error")
|
||||||
}
|
}
|
||||||
|
@ -631,7 +631,7 @@ func (c *QQClient) GetGroupEssenceMsgList(groupCode int64) ([]GroupDigest, error
|
|||||||
}
|
}
|
||||||
rsp = rsp[bytes.Index(rsp, []byte("window.__INITIAL_STATE__={"))+25:]
|
rsp = rsp[bytes.Index(rsp, []byte("window.__INITIAL_STATE__={"))+25:]
|
||||||
rsp = rsp[:bytes.Index(rsp, []byte("</script>"))]
|
rsp = rsp[:bytes.Index(rsp, []byte("</script>"))]
|
||||||
var data = &struct {
|
data := &struct {
|
||||||
List []GroupDigest `json:"msgList"`
|
List []GroupDigest `json:"msgList"`
|
||||||
}{}
|
}{}
|
||||||
err = json.Unmarshal(rsp, data)
|
err = json.Unmarshal(rsp, data)
|
||||||
|
@ -11,8 +11,9 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type noticePicUpResponse struct {
|
type noticePicUpResponse struct {
|
||||||
@ -29,7 +30,7 @@ type noticeImage struct {
|
|||||||
|
|
||||||
func (c *QQClient) uploadGroupNoticePic(img []byte) (*noticeImage, error) {
|
func (c *QQClient) uploadGroupNoticePic(img []byte) (*noticeImage, error) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
var w = multipart.NewWriter(buf)
|
w := multipart.NewWriter(buf)
|
||||||
err := w.WriteField("bkn", strconv.Itoa(c.getCSRFToken()))
|
err := w.WriteField("bkn", strconv.Itoa(c.getCSRFToken()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "write multipart<bkn> failed")
|
return nil, errors.Wrap(err, "write multipart<bkn> failed")
|
||||||
|
@ -37,7 +37,7 @@ func (c *QQClient) highwayUploadStream(ip uint32, port int, updKey []byte, strea
|
|||||||
h := md5.New()
|
h := md5.New()
|
||||||
length, _ := io.Copy(h, stream)
|
length, _ := io.Copy(h, stream)
|
||||||
fh := h.Sum(nil)
|
fh := h.Sum(nil)
|
||||||
chunkSize := 8192 * 8
|
const chunkSize = 8192 * 8
|
||||||
_, _ = stream.Seek(0, io.SeekStart)
|
_, _ = stream.Seek(0, io.SeekStart)
|
||||||
conn, err := net.DialTCP("tcp", nil, &addr)
|
conn, err := net.DialTCP("tcp", nil, &addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -46,8 +46,11 @@ func (c *QQClient) highwayUploadStream(ip uint32, port int, updKey []byte, strea
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
offset := 0
|
offset := 0
|
||||||
reader := binary.NewNetworkReader(conn)
|
reader := binary.NewNetworkReader(conn)
|
||||||
for {
|
|
||||||
chunk := make([]byte, chunkSize)
|
chunk := make([]byte, chunkSize)
|
||||||
|
w := binary.NewWriter()
|
||||||
|
defer binary.PutBuffer(w)
|
||||||
|
for {
|
||||||
|
chunk = chunk[:chunkSize]
|
||||||
rl, err := io.ReadFull(stream, chunk)
|
rl, err := io.ReadFull(stream, chunk)
|
||||||
if errors.Is(err, io.EOF) {
|
if errors.Is(err, io.EOF) {
|
||||||
break
|
break
|
||||||
@ -78,14 +81,14 @@ func (c *QQClient) highwayUploadStream(ip uint32, port int, updKey []byte, strea
|
|||||||
ReqExtendinfo: EmptyBytes,
|
ReqExtendinfo: EmptyBytes,
|
||||||
})
|
})
|
||||||
offset += rl
|
offset += rl
|
||||||
_, err = conn.Write(binary.NewWriterF(func(w *binary.Writer) {
|
w.Reset()
|
||||||
w.WriteByte(40)
|
w.WriteByte(40)
|
||||||
w.WriteUInt32(uint32(len(head)))
|
w.WriteUInt32(uint32(len(head)))
|
||||||
w.WriteUInt32(uint32(len(chunk)))
|
w.WriteUInt32(uint32(len(chunk)))
|
||||||
w.Write(head)
|
w.Write(head)
|
||||||
w.Write(chunk)
|
w.Write(chunk)
|
||||||
w.WriteByte(41)
|
w.WriteByte(41)
|
||||||
}))
|
_, err = conn.Write(w.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "write conn error")
|
return errors.Wrap(err, "write conn error")
|
||||||
}
|
}
|
||||||
@ -100,7 +103,7 @@ func (c *QQClient) highwayUploadStream(ip uint32, port int, updKey []byte, strea
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) highwayUploadByBDH(stream io.ReadSeeker, cmdId int32, ticket, ext []byte, encrypt bool) ([]byte, error) {
|
func (c *QQClient) highwayUploadByBDH(stream io.Reader, length int64, cmdId int32, ticket, sum, ext []byte, encrypt bool) ([]byte, error) {
|
||||||
if len(c.srvSsoAddrs) == 0 {
|
if len(c.srvSsoAddrs) == 0 {
|
||||||
return nil, errors.New("srv addrs not found. maybe miss some packet?")
|
return nil, errors.New("srv addrs not found. maybe miss some packet?")
|
||||||
}
|
}
|
||||||
@ -110,11 +113,7 @@ func (c *QQClient) highwayUploadByBDH(stream io.ReadSeeker, cmdId int32, ticket,
|
|||||||
}
|
}
|
||||||
ext = binary.NewTeaCipher(c.highwaySession.SessionKey).Encrypt(ext)
|
ext = binary.NewTeaCipher(c.highwaySession.SessionKey).Encrypt(ext)
|
||||||
}
|
}
|
||||||
h := md5.New()
|
const chunkSize = 8192 * 16
|
||||||
length, _ := io.Copy(h, stream)
|
|
||||||
fh := h.Sum(nil)
|
|
||||||
chunkSize := 8192 * 16
|
|
||||||
_, _ = stream.Seek(0, io.SeekStart)
|
|
||||||
conn, err := net.DialTimeout("tcp", c.srvSsoAddrs[0], time.Second*20)
|
conn, err := net.DialTimeout("tcp", c.srvSsoAddrs[0], time.Second*20)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "connect error")
|
return nil, errors.Wrap(err, "connect error")
|
||||||
@ -129,8 +128,11 @@ func (c *QQClient) highwayUploadByBDH(stream io.ReadSeeker, cmdId int32, ticket,
|
|||||||
return nil, errors.Wrap(err, "echo error")
|
return nil, errors.Wrap(err, "echo error")
|
||||||
}
|
}
|
||||||
var rspExt []byte
|
var rspExt []byte
|
||||||
for {
|
|
||||||
chunk := make([]byte, chunkSize)
|
chunk := make([]byte, chunkSize)
|
||||||
|
w := binary.NewWriter()
|
||||||
|
defer binary.PutBuffer(w)
|
||||||
|
for {
|
||||||
|
chunk = chunk[:chunkSize]
|
||||||
rl, err := io.ReadFull(stream, chunk)
|
rl, err := io.ReadFull(stream, chunk)
|
||||||
if errors.Is(err, io.EOF) {
|
if errors.Is(err, io.EOF) {
|
||||||
break
|
break
|
||||||
@ -156,19 +158,19 @@ func (c *QQClient) highwayUploadByBDH(stream io.ReadSeeker, cmdId int32, ticket,
|
|||||||
Datalength: int32(rl),
|
Datalength: int32(rl),
|
||||||
Serviceticket: ticket,
|
Serviceticket: ticket,
|
||||||
Md5: ch[:],
|
Md5: ch[:],
|
||||||
FileMd5: fh[:],
|
FileMd5: sum,
|
||||||
},
|
},
|
||||||
ReqExtendinfo: ext,
|
ReqExtendinfo: ext,
|
||||||
})
|
})
|
||||||
offset += rl
|
offset += rl
|
||||||
_, err = conn.Write(binary.NewWriterF(func(w *binary.Writer) {
|
w.Reset()
|
||||||
w.WriteByte(40)
|
w.WriteByte(40)
|
||||||
w.WriteUInt32(uint32(len(head)))
|
w.WriteUInt32(uint32(len(head)))
|
||||||
w.WriteUInt32(uint32(len(chunk)))
|
w.WriteUInt32(uint32(len(chunk)))
|
||||||
w.Write(head)
|
w.Write(head)
|
||||||
w.Write(chunk)
|
w.Write(chunk)
|
||||||
w.WriteByte(41)
|
w.WriteByte(41)
|
||||||
}))
|
_, err = conn.Write(w.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "write conn error")
|
return nil, errors.Wrap(err, "write conn error")
|
||||||
}
|
}
|
||||||
@ -203,22 +205,23 @@ func (c *QQClient) highwayUploadFileMultiThreadingByBDH(path string, cmdId int32
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "get stat error")
|
return nil, errors.Wrap(err, "get stat error")
|
||||||
}
|
}
|
||||||
file, err := os.OpenFile(path, os.O_RDONLY, 0666)
|
file, err := os.OpenFile(path, os.O_RDONLY, 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "open file error")
|
return nil, errors.Wrap(err, "open file error")
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
h := md5.New()
|
||||||
|
length, _ := io.Copy(h, file)
|
||||||
|
fh := h.Sum(nil)
|
||||||
|
_, _ = file.Seek(0, io.SeekStart)
|
||||||
if stat.Size() < 1024*1024*3 {
|
if stat.Size() < 1024*1024*3 {
|
||||||
return c.highwayUploadByBDH(file, cmdId, ticket, ext, false)
|
return c.highwayUploadByBDH(file, length, cmdId, ticket, fh, ext, false)
|
||||||
}
|
}
|
||||||
type BlockMetaData struct {
|
type BlockMetaData struct {
|
||||||
Id int
|
Id int
|
||||||
BeginOffset int64
|
BeginOffset int64
|
||||||
EndOffset int64
|
EndOffset int64
|
||||||
}
|
}
|
||||||
h := md5.New()
|
|
||||||
_, _ = io.Copy(h, file)
|
|
||||||
fh := h.Sum(nil)
|
|
||||||
const blockSize int64 = 1024 * 512
|
const blockSize int64 = 1024 * 512
|
||||||
var (
|
var (
|
||||||
blocks []*BlockMetaData
|
blocks []*BlockMetaData
|
||||||
@ -251,7 +254,7 @@ func (c *QQClient) highwayUploadFileMultiThreadingByBDH(path string, cmdId int32
|
|||||||
return errors.Wrap(err, "connect error")
|
return errors.Wrap(err, "connect error")
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
chunk, _ := os.OpenFile(path, os.O_RDONLY, 0666)
|
chunk, _ := os.OpenFile(path, os.O_RDONLY, 0o666)
|
||||||
defer chunk.Close()
|
defer chunk.Close()
|
||||||
reader := binary.NewNetworkReader(conn)
|
reader := binary.NewNetworkReader(conn)
|
||||||
if err = c.highwaySendHeartbreak(conn); err != nil {
|
if err = c.highwaySendHeartbreak(conn); err != nil {
|
||||||
@ -278,7 +281,7 @@ func (c *QQClient) highwayUploadFileMultiThreadingByBDH(path string, cmdId int32
|
|||||||
}
|
}
|
||||||
buffer := make([]byte, blockSize)
|
buffer := make([]byte, blockSize)
|
||||||
_, _ = chunk.Seek(block.BeginOffset, io.SeekStart)
|
_, _ = chunk.Seek(block.BeginOffset, io.SeekStart)
|
||||||
ri, err := io.ReadFull(chunk, buffer)
|
ri, err := io.ReadFull(chunk, buffer) // todo: reuse buffer
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
@ -311,14 +314,15 @@ func (c *QQClient) highwayUploadFileMultiThreadingByBDH(path string, cmdId int32
|
|||||||
},
|
},
|
||||||
ReqExtendinfo: ext,
|
ReqExtendinfo: ext,
|
||||||
})
|
})
|
||||||
_, err = conn.Write(binary.NewWriterF(func(w *binary.Writer) {
|
w := binary.NewWriter()
|
||||||
w.WriteByte(40)
|
w.WriteByte(40)
|
||||||
w.WriteUInt32(uint32(len(head)))
|
w.WriteUInt32(uint32(len(head)))
|
||||||
w.WriteUInt32(uint32(len(buffer)))
|
w.WriteUInt32(uint32(len(buffer)))
|
||||||
w.Write(head)
|
w.Write(head)
|
||||||
w.Write(buffer)
|
w.Write(buffer)
|
||||||
w.WriteByte(41)
|
w.WriteByte(41)
|
||||||
}))
|
_, err = conn.Write(w.Bytes())
|
||||||
|
binary.PutBuffer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "write conn error")
|
return errors.Wrap(err, "write conn error")
|
||||||
}
|
}
|
||||||
@ -364,13 +368,14 @@ func (c *QQClient) highwaySendHeartbreak(conn net.Conn) error {
|
|||||||
LocaleId: 2052,
|
LocaleId: 2052,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
_, err := conn.Write(binary.NewWriterF(func(w *binary.Writer) {
|
w := binary.NewWriter()
|
||||||
w.WriteByte(40)
|
w.WriteByte(40)
|
||||||
w.WriteUInt32(uint32(len(head)))
|
w.WriteUInt32(uint32(len(head)))
|
||||||
w.WriteUInt32(0)
|
w.WriteUInt32(0)
|
||||||
w.Write(head)
|
w.Write(head)
|
||||||
w.WriteByte(41)
|
w.WriteByte(41)
|
||||||
}))
|
_, err := conn.Write(w.Bytes())
|
||||||
|
binary.PutBuffer(w)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,8 +405,12 @@ func (c *QQClient) excitingUploadStream(stream io.ReadSeeker, cmdId int32, ticke
|
|||||||
offset int64 = 0
|
offset int64 = 0
|
||||||
chunkSize = 524288
|
chunkSize = 524288
|
||||||
)
|
)
|
||||||
for {
|
|
||||||
chunk := make([]byte, chunkSize)
|
chunk := make([]byte, chunkSize)
|
||||||
|
w := binary.NewWriter()
|
||||||
|
w.Reset()
|
||||||
|
w.Grow(600 * 1024) // 复用,600k 不要放回池中
|
||||||
|
for {
|
||||||
|
chunk = chunk[:chunkSize]
|
||||||
rl, err := io.ReadFull(stream, chunk)
|
rl, err := io.ReadFull(stream, chunk)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
@ -432,15 +441,14 @@ func (c *QQClient) excitingUploadStream(stream io.ReadSeeker, cmdId int32, ticke
|
|||||||
ReqExtendinfo: ext,
|
ReqExtendinfo: ext,
|
||||||
})
|
})
|
||||||
offset += int64(rl)
|
offset += int64(rl)
|
||||||
io.Pipe()
|
w.Reset()
|
||||||
req, _ := http.NewRequest("POST", url, bytes.NewReader(binary.NewWriterF(func(w *binary.Writer) {
|
|
||||||
w.WriteByte(40)
|
w.WriteByte(40)
|
||||||
w.WriteUInt32(uint32(len(head)))
|
w.WriteUInt32(uint32(len(head)))
|
||||||
w.WriteUInt32(uint32(len(chunk)))
|
w.WriteUInt32(uint32(len(chunk)))
|
||||||
w.Write(head)
|
w.Write(head)
|
||||||
w.Write(chunk)
|
w.Write(chunk)
|
||||||
w.WriteByte(41)
|
w.WriteByte(41)
|
||||||
})))
|
req, _ := http.NewRequest("POST", url, bytes.NewReader(w.Bytes()))
|
||||||
req.Header.Set("Accept", "*/*")
|
req.Header.Set("Accept", "*/*")
|
||||||
req.Header.Set("Connection", "Keep-Alive")
|
req.Header.Set("Connection", "Keep-Alive")
|
||||||
req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")
|
req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")
|
||||||
@ -504,7 +512,7 @@ func (c *QQClient) uploadGroupHeadPortrait(groupCode int64, img []byte) error {
|
|||||||
groupCode,
|
groupCode,
|
||||||
len(img),
|
len(img),
|
||||||
)
|
)
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewReader(img))
|
req, _ := http.NewRequest("POST", url, bytes.NewReader(img))
|
||||||
req.Header["User-Agent"] = []string{"Dalvik/2.1.0 (Linux; U; Android 7.1.2; PCRT00 Build/N2G48H)"}
|
req.Header["User-Agent"] = []string{"Dalvik/2.1.0 (Linux; U; Android 7.1.2; PCRT00 Build/N2G48H)"}
|
||||||
req.Header["Content-Type"] = []string{"multipart/form-data;boundary=****"}
|
req.Header["Content-Type"] = []string{"multipart/form-data;boundary=****"}
|
||||||
rsp, err := http.DefaultClient.Do(req)
|
rsp, err := http.DefaultClient.Do(req)
|
||||||
|
@ -31,9 +31,9 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Talkative HonorType = 1 //龙王
|
Talkative HonorType = 1 // 龙王
|
||||||
Performer HonorType = 2 //群聊之火
|
Performer HonorType = 2 // 群聊之火
|
||||||
Legend HonorType = 3 //群聊炙焰
|
Legend HonorType = 3 // 群聊炙焰
|
||||||
StrongNewbie HonorType = 5 //冒尖小春笋
|
StrongNewbie HonorType = 5 // 冒尖小春笋
|
||||||
Emotion HonorType = 6 //快乐源泉
|
Emotion HonorType = 6 // 快乐源泉
|
||||||
)
|
)
|
||||||
|
@ -13,13 +13,14 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/client/pb/highway"
|
"github.com/Mrs4s/MiraiGo/client/pb/highway"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb"
|
"github.com/Mrs4s/MiraiGo/client/pb"
|
||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -48,7 +49,7 @@ func (c *QQClient) UploadGroupImage(groupCode int64, img io.ReadSeeker) (*messag
|
|||||||
c.srvSsoAddrs = append(c.srvSsoAddrs, fmt.Sprintf("%v:%v", binary.UInt32ToIPV4Address(uint32(addr)), rsp.UploadPort[i]))
|
c.srvSsoAddrs = append(c.srvSsoAddrs, fmt.Sprintf("%v:%v", binary.UInt32ToIPV4Address(uint32(addr)), rsp.UploadPort[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err = c.highwayUploadByBDH(img, 2, rsp.UploadKey, EmptyBytes, false); err == nil {
|
if _, err = c.highwayUploadByBDH(img, length, 2, rsp.UploadKey, EmptyBytes, fh, false); err == nil {
|
||||||
goto ok
|
goto ok
|
||||||
}
|
}
|
||||||
return nil, errors.New("upload failed")
|
return nil, errors.New("upload failed")
|
||||||
@ -66,7 +67,7 @@ ok:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) UploadGroupImageByFile(groupCode int64, path string) (*message.GroupImageElement, error) {
|
func (c *QQClient) UploadGroupImageByFile(groupCode int64, path string) (*message.GroupImageElement, error) {
|
||||||
img, err := os.OpenFile(path, os.O_RDONLY, 0666)
|
img, err := os.OpenFile(path, os.O_RDONLY, 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -137,10 +138,11 @@ func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) {
|
|||||||
switch e := img.(type) {
|
switch e := img.(type) {
|
||||||
case *message.GroupImageElement:
|
case *message.GroupImageElement:
|
||||||
url = e.Url
|
url = e.Url
|
||||||
if b, err := utils.HttpGetBytes(e.Url, ""); err == nil {
|
if b, err := utils.HTTPGetReadCloser(e.Url, ""); err == nil {
|
||||||
if url, err = c.uploadOcrImage(bytes.NewReader(b)); err != nil {
|
if url, err = c.uploadOcrImage(b, int64(e.Size), e.Md5); err != nil {
|
||||||
url = e.Url
|
url = e.Url
|
||||||
}
|
}
|
||||||
|
_ = b.Close()
|
||||||
}
|
}
|
||||||
rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height))
|
rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -149,10 +151,11 @@ func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) {
|
|||||||
return rsp.(*OcrResponse), nil
|
return rsp.(*OcrResponse), nil
|
||||||
case *message.ImageElement:
|
case *message.ImageElement:
|
||||||
url = e.Url
|
url = e.Url
|
||||||
if b, err := utils.HttpGetBytes(e.Url, ""); err == nil {
|
if b, err := utils.HTTPGetReadCloser(e.Url, ""); err == nil {
|
||||||
if url, err = c.uploadOcrImage(bytes.NewReader(b)); err != nil {
|
if url, err = c.uploadOcrImage(b, int64(e.Size), e.Md5); err != nil {
|
||||||
url = e.Url
|
url = e.Url
|
||||||
}
|
}
|
||||||
|
_ = b.Close()
|
||||||
}
|
}
|
||||||
rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height))
|
rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -232,14 +235,14 @@ func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 []byte, size
|
|||||||
return seq, packet
|
return seq, packet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) uploadOcrImage(img io.ReadSeeker) (string, error) {
|
func (c *QQClient) uploadOcrImage(img io.Reader, length int64, sum []byte) (string, error) {
|
||||||
r := make([]byte, 16)
|
r := make([]byte, 16)
|
||||||
rand.Read(r)
|
rand.Read(r)
|
||||||
ext, _ := proto.Marshal(&highway.CommFileExtReq{
|
ext, _ := proto.Marshal(&highway.CommFileExtReq{
|
||||||
ActionType: proto.Uint32(0),
|
ActionType: proto.Uint32(0),
|
||||||
Uuid: binary.GenUUID(r),
|
Uuid: binary.GenUUID(r),
|
||||||
})
|
})
|
||||||
rsp, err := c.highwayUploadByBDH(img, 76, c.highwaySession.SigSession, ext, false)
|
rsp, err := c.highwayUploadByBDH(img, length, 76, c.highwaySession.SigSession, sum, ext, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "upload ocr image error")
|
return "", errors.Wrap(err, "upload ocr image error")
|
||||||
}
|
}
|
||||||
@ -316,9 +319,9 @@ func decodeImageOcrResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte)
|
|||||||
if rsp.RetCode != 0 {
|
if rsp.RetCode != 0 {
|
||||||
return nil, errors.Errorf("server error, code: %v msg: %v", rsp.RetCode, rsp.ErrMsg)
|
return nil, errors.Errorf("server error, code: %v msg: %v", rsp.RetCode, rsp.ErrMsg)
|
||||||
}
|
}
|
||||||
var texts = make([]*TextDetection, 0, len(rsp.OcrRspBody.TextDetections))
|
texts := make([]*TextDetection, 0, len(rsp.OcrRspBody.TextDetections))
|
||||||
for _, text := range rsp.OcrRspBody.TextDetections {
|
for _, text := range rsp.OcrRspBody.TextDetections {
|
||||||
var points = make([]*Coordinate, 0, len(text.Polygon.Coordinates))
|
points := make([]*Coordinate, 0, len(text.Polygon.Coordinates))
|
||||||
for _, c := range text.Polygon.Coordinates {
|
for _, c := range text.Polygon.Coordinates {
|
||||||
points = append(points, &Coordinate{
|
points = append(points, &Coordinate{
|
||||||
X: c.X,
|
X: c.X,
|
||||||
|
@ -40,7 +40,7 @@ type (
|
|||||||
// grayTipProcessor 提取出来专门用于处理群内 notify tips
|
// grayTipProcessor 提取出来专门用于处理群内 notify tips
|
||||||
func (c *QQClient) grayTipProcessor(groupID int64, tipInfo *notify.GeneralGrayTipInfo) {
|
func (c *QQClient) grayTipProcessor(groupID int64, tipInfo *notify.GeneralGrayTipInfo) {
|
||||||
if tipInfo.BusiType == 12 && tipInfo.BusiId == 1061 {
|
if tipInfo.BusiType == 12 && tipInfo.BusiId == 1061 {
|
||||||
var sender = int64(0)
|
sender := int64(0)
|
||||||
receiver := c.Uin
|
receiver := c.Uin
|
||||||
for _, templ := range tipInfo.MsgTemplParam {
|
for _, templ := range tipInfo.MsgTemplParam {
|
||||||
if templ.Name == "uin_str1" {
|
if templ.Name == "uin_str1" {
|
||||||
|
@ -7,12 +7,13 @@ import (
|
|||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/msgtype0x210"
|
"github.com/Mrs4s/MiraiGo/client/pb/msgtype0x210"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/binary/jce"
|
"github.com/Mrs4s/MiraiGo/binary/jce"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb"
|
"github.com/Mrs4s/MiraiGo/client/pb"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/notify"
|
"github.com/Mrs4s/MiraiGo/client/pb/notify"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var msg0x210Decoders = map[int64]func(*QQClient, []byte) error{
|
var msg0x210Decoders = map[int64]func(*QQClient, []byte) error{
|
||||||
@ -90,7 +91,7 @@ func decodeOnlinePushReqPacket(c *QQClient, info *incomingPacketInfo, payload []
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if b.QqGroupDigestMsg != nil {
|
if b.QqGroupDigestMsg != nil {
|
||||||
var digest = b.QqGroupDigestMsg
|
digest := b.QqGroupDigestMsg
|
||||||
c.dispatchGroupDigestEvent(&GroupDigestEvent{
|
c.dispatchGroupDigestEvent(&GroupDigestEvent{
|
||||||
GroupCode: int64(digest.GroupCode),
|
GroupCode: int64(digest.GroupCode),
|
||||||
MessageID: int32(digest.Seq),
|
MessageID: int32(digest.Seq),
|
||||||
|
@ -6,10 +6,11 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
"github.com/Mrs4s/MiraiGo/protocol/packets"
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) *message.PrivateMessage {
|
func (c *QQClient) SendPrivateMessage(target int64, m *message.SendingMessage) *message.PrivateMessage {
|
||||||
|
@ -31,7 +31,7 @@ func (c *QQClient) UploadGroupPtt(groupCode int64, voice io.ReadSeeker) (*messag
|
|||||||
fh := h.Sum(nil)
|
fh := h.Sum(nil)
|
||||||
_, _ = voice.Seek(0, io.SeekStart)
|
_, _ = voice.Seek(0, io.SeekStart)
|
||||||
ext := c.buildGroupPttStoreBDHExt(groupCode, fh[:], int32(length), 0, int32(length))
|
ext := c.buildGroupPttStoreBDHExt(groupCode, fh[:], int32(length), 0, int32(length))
|
||||||
rsp, err := c.highwayUploadByBDH(voice, 29, c.highwaySession.SigSession, ext, false)
|
rsp, err := c.highwayUploadByBDH(voice, length, 29, c.highwaySession.SigSession, fh, ext, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -55,7 +55,8 @@ func (c *QQClient) UploadGroupPtt(groupCode int64, voice io.ReadSeeker) (*messag
|
|||||||
GroupFileKey: pkt.MsgTryUpPttRsp[0].FileKey,
|
GroupFileKey: pkt.MsgTryUpPttRsp[0].FileKey,
|
||||||
BoolValid: proto.Bool(true),
|
BoolValid: proto.Bool(true),
|
||||||
PbReserve: []byte{8, 0, 40, 0, 56, 0},
|
PbReserve: []byte{8, 0, 40, 0, 56, 0},
|
||||||
}}, nil
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadPrivatePtt 将语音数据使用好友语音通道上传到服务器, 返回 message.PrivateVoiceElement 可直接发送
|
// UploadPrivatePtt 将语音数据使用好友语音通道上传到服务器, 返回 message.PrivateVoiceElement 可直接发送
|
||||||
@ -65,7 +66,7 @@ func (c *QQClient) UploadPrivatePtt(target int64, voice io.ReadSeeker) (*message
|
|||||||
fh := h.Sum(nil)
|
fh := h.Sum(nil)
|
||||||
_, _ = voice.Seek(0, io.SeekStart)
|
_, _ = voice.Seek(0, io.SeekStart)
|
||||||
ext := c.buildC2CPttStoreBDHExt(target, fh[:], int32(length), int32(length))
|
ext := c.buildC2CPttStoreBDHExt(target, fh[:], int32(length), int32(length))
|
||||||
rsp, err := c.highwayUploadByBDH(voice, 26, c.highwaySession.SigSession, ext, false)
|
rsp, err := c.highwayUploadByBDH(voice, length, 26, c.highwaySession.SigSession, fh, ext, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -89,7 +90,8 @@ func (c *QQClient) UploadPrivatePtt(target int64, voice io.ReadSeeker) (*message
|
|||||||
FileSize: proto.Int32(int32(length)),
|
FileSize: proto.Int32(int32(length)),
|
||||||
// Reserve: constructPTTExtraInfo(1, int32(len(voice))), // todo length
|
// Reserve: constructPTTExtraInfo(1, int32(len(voice))), // todo length
|
||||||
BoolValid: proto.Bool(true),
|
BoolValid: proto.Bool(true),
|
||||||
}}, nil
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadGroupShortVideo 将视频和封面上传到服务器, 返回 message.ShortVideoElement 可直接发送
|
// UploadGroupShortVideo 将视频和封面上传到服务器, 返回 message.ShortVideoElement 可直接发送
|
||||||
@ -117,22 +119,27 @@ func (c *QQClient) UploadGroupShortVideo(groupCode int64, video, thumb io.ReadSe
|
|||||||
}
|
}
|
||||||
ext, _ := proto.Marshal(c.buildPttGroupShortVideoProto(videoHash, thumbHash, groupCode, videoLen, thumbLen).PttShortVideoUploadReq)
|
ext, _ := proto.Marshal(c.buildPttGroupShortVideoProto(videoHash, thumbHash, groupCode, videoLen, thumbLen).PttShortVideoUploadReq)
|
||||||
var hwRsp []byte
|
var hwRsp []byte
|
||||||
|
multi := utils.MultiReadSeeker(thumb, video)
|
||||||
|
h := md5.New()
|
||||||
|
length, _ := io.Copy(h, multi)
|
||||||
|
fh := h.Sum(nil)
|
||||||
|
_, _ = multi.Seek(0, io.SeekStart)
|
||||||
if cache != "" {
|
if cache != "" {
|
||||||
var file *os.File
|
var file *os.File
|
||||||
file, err = os.OpenFile(cache, os.O_WRONLY|os.O_CREATE, 0666)
|
file, err = os.OpenFile(cache, os.O_WRONLY|os.O_CREATE, 0o666)
|
||||||
cp := func() error {
|
cp := func() error {
|
||||||
_, err := io.Copy(file, utils.MultiReadSeeker(thumb, video))
|
_, err := io.Copy(file, utils.MultiReadSeeker(thumb, video))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err != nil || cp() != nil {
|
if err != nil || cp() != nil {
|
||||||
hwRsp, err = c.highwayUploadByBDH(utils.MultiReadSeeker(thumb, video), 25, c.highwaySession.SigSession, ext, true)
|
hwRsp, err = c.highwayUploadByBDH(multi, length, 25, c.highwaySession.SigSession, fh, ext, true)
|
||||||
} else {
|
} else {
|
||||||
_ = file.Close()
|
_ = file.Close()
|
||||||
hwRsp, err = c.highwayUploadFileMultiThreadingByBDH(cache, 25, 8, c.highwaySession.SigSession, ext, true)
|
hwRsp, err = c.highwayUploadFileMultiThreadingByBDH(cache, 25, 8, c.highwaySession.SigSession, ext, true)
|
||||||
_ = os.Remove(cache)
|
_ = os.Remove(cache)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hwRsp, err = c.highwayUploadByBDH(utils.MultiReadSeeker(thumb, video), 25, c.highwaySession.SigSession, ext, true)
|
hwRsp, err = c.highwayUploadByBDH(multi, length, 25, c.highwaySession.SigSession, fh, ext, true)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "upload video file error")
|
return nil, errors.Wrap(err, "upload video file error")
|
||||||
@ -279,7 +286,7 @@ func decodeGroupPttStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload []b
|
|||||||
if rsp.BoolFileExit {
|
if rsp.BoolFileExit {
|
||||||
return pttUploadResponse{IsExists: true}, nil
|
return pttUploadResponse{IsExists: true}, nil
|
||||||
}
|
}
|
||||||
var ip = make([]string, 0, len(rsp.Uint32UpIp))
|
ip := make([]string, 0, len(rsp.Uint32UpIp))
|
||||||
for _, i := range rsp.Uint32UpIp {
|
for _, i := range rsp.Uint32UpIp {
|
||||||
ip = append(ip, binary.UInt32ToIPV4Address(uint32(i)))
|
ip = append(ip, binary.UInt32ToIPV4Address(uint32(i)))
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ func (c *QQClient) GetAllowedClients() ([]*OtherClientInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
list := i.([]jce.SvcDevLoginInfo)
|
list := i.([]jce.SvcDevLoginInfo)
|
||||||
var ret = make([]*OtherClientInfo, 0, len(list))
|
ret := make([]*OtherClientInfo, 0, len(list))
|
||||||
for _, l := range list {
|
for _, l := range list {
|
||||||
ret = append(ret, &OtherClientInfo{
|
ret = append(ret, &OtherClientInfo{
|
||||||
AppId: l.AppId,
|
AppId: l.AppId,
|
||||||
@ -208,7 +208,8 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
|
|||||||
Type: proto.Uint32(283),
|
Type: proto.Uint32(283),
|
||||||
Version: proto.Uint32(0),
|
Version: proto.Uint32(0),
|
||||||
},
|
},
|
||||||
}})
|
},
|
||||||
|
})
|
||||||
regReq := &jce.SvcReqRegisterNew{
|
regReq := &jce.SvcReqRegisterNew{
|
||||||
RequestOptional: 128 | 64 | 256 | 2 | 8192 | 16384 | 65536,
|
RequestOptional: 128 | 64 | 256 | 2 | 8192 | 16384 | 65536,
|
||||||
DisGroupMsgFilter: 1,
|
DisGroupMsgFilter: 1,
|
||||||
|
@ -43,24 +43,24 @@ func (c *QQClient) decodeT119(data, ek []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//openId []byte
|
// openId []byte
|
||||||
//openKey []byte
|
// openKey []byte
|
||||||
//payToken []byte
|
// payToken []byte
|
||||||
//pf []byte
|
// pf []byte
|
||||||
//pfkey []byte
|
// pfkey []byte
|
||||||
gender uint16 = 0
|
gender uint16 = 0
|
||||||
age uint16 = 0
|
age uint16 = 0
|
||||||
nick = ""
|
nick = ""
|
||||||
//a1 []byte
|
// a1 []byte
|
||||||
//noPicSig []byte
|
// noPicSig []byte
|
||||||
//ctime = time.Now().Unix()
|
// ctime = time.Now().Unix()
|
||||||
//etime = ctime + 2160000
|
// etime = ctime + 2160000
|
||||||
psKeyMap map[string][]byte
|
psKeyMap map[string][]byte
|
||||||
pt4TokenMap map[string][]byte
|
pt4TokenMap map[string][]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
if _, ok := m[0x125]; ok {
|
if _, ok := m[0x125]; ok {
|
||||||
//openId, openKey = readT125(t125)
|
// openId, openKey = readT125(t125)
|
||||||
}
|
}
|
||||||
if t186, ok := m[0x186]; ok {
|
if t186, ok := m[0x186]; ok {
|
||||||
c.decodeT186(t186)
|
c.decodeT186(t186)
|
||||||
@ -69,20 +69,20 @@ func (c *QQClient) decodeT119(data, ek []byte) {
|
|||||||
nick, age, gender = readT11A(t11a)
|
nick, age, gender = readT11A(t11a)
|
||||||
}
|
}
|
||||||
if _, ok := m[0x199]; ok {
|
if _, ok := m[0x199]; ok {
|
||||||
//openId, payToken = readT199(t199)
|
// openId, payToken = readT199(t199)
|
||||||
}
|
}
|
||||||
if _, ok := m[0x200]; ok {
|
if _, ok := m[0x200]; ok {
|
||||||
//pf, pfkey = readT200(t200)
|
// pf, pfkey = readT200(t200)
|
||||||
}
|
}
|
||||||
if t512, ok := m[0x512]; ok {
|
if t512, ok := m[0x512]; ok {
|
||||||
psKeyMap, pt4TokenMap = readT512(t512)
|
psKeyMap, pt4TokenMap = readT512(t512)
|
||||||
}
|
}
|
||||||
if _, ok := m[0x531]; ok {
|
if _, ok := m[0x531]; ok {
|
||||||
//a1, noPicSig = readT531(t531)
|
// a1, noPicSig = readT531(t531)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := m[0x138]; ok {
|
if _, ok := m[0x138]; ok {
|
||||||
//readT138(t138) // chg time
|
// readT138(t138) // chg time
|
||||||
}
|
}
|
||||||
|
|
||||||
c.sigInfo = &loginSigInfo{
|
c.sigInfo = &loginSigInfo{
|
||||||
|
@ -86,7 +86,7 @@ type ReplyElement struct {
|
|||||||
Time int32
|
Time int32
|
||||||
Elements []IMessageElement
|
Elements []IMessageElement
|
||||||
|
|
||||||
//original []*msg.Elem
|
// original []*msg.Elem
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShortVideoElement struct {
|
type ShortVideoElement struct {
|
||||||
@ -241,7 +241,7 @@ func NewReply(m *GroupMessage) *ReplyElement {
|
|||||||
ReplySeq: m.Id,
|
ReplySeq: m.Id,
|
||||||
Sender: m.Sender.Uin,
|
Sender: m.Sender.Uin,
|
||||||
Time: m.Time,
|
Time: m.Time,
|
||||||
//original: m.OriginalElements,
|
// original: m.OriginalElements,
|
||||||
Elements: m.Elements,
|
Elements: m.Elements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,9 +271,10 @@ func NewUrlShare(url, title, content, image string) *ServiceElement {
|
|||||||
SubType: "UrlShare",
|
SubType: "UrlShare",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRichXml(template string, ResId int64) *ServiceElement {
|
func NewRichXml(template string, ResId int64) *ServiceElement {
|
||||||
if ResId == 0 {
|
if ResId == 0 {
|
||||||
ResId = 60 //默认值60
|
ResId = 60 // 默认值60
|
||||||
}
|
}
|
||||||
return &ServiceElement{
|
return &ServiceElement{
|
||||||
Id: int32(ResId),
|
Id: int32(ResId),
|
||||||
|
@ -36,7 +36,7 @@ var faceMap = map[int]string{
|
|||||||
`
|
`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
f, _ := os.OpenFile("face.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0755)
|
f, _ := os.OpenFile("face.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o755)
|
||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
resp, err := http.Get(faceDownloadUrl)
|
resp, err := http.Get(faceDownloadUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -46,7 +46,7 @@ type (
|
|||||||
Time int32
|
Time int32
|
||||||
Elements []IMessageElement
|
Elements []IMessageElement
|
||||||
OriginalObject *msg.Message
|
OriginalObject *msg.Message
|
||||||
//OriginalElements []*msg.Elem
|
// OriginalElements []*msg.Elem
|
||||||
}
|
}
|
||||||
|
|
||||||
SendingMessage struct {
|
SendingMessage struct {
|
||||||
@ -327,7 +327,7 @@ func ToProtoElems(elems []IMessageElement, generalFlags bool) (r []*msg.Elem) {
|
|||||||
})
|
})
|
||||||
break L
|
break L
|
||||||
}
|
}
|
||||||
//d, _ := hex.DecodeString("08097800C80100F00100F80100900200C80200980300A00320B00300C00300D00300E803008A04020803900480808010B80400C00400")
|
// d, _ := hex.DecodeString("08097800C80100F00100F80100900200C80200980300A00320B00300C00300D00300E803008A04020803900480808010B80400C00400")
|
||||||
r = append(r, &msg.Elem{
|
r = append(r, &msg.Elem{
|
||||||
GeneralFlags: &msg.GeneralFlags{
|
GeneralFlags: &msg.GeneralFlags{
|
||||||
PbReserve: []byte{
|
PbReserve: []byte{
|
||||||
@ -590,7 +590,7 @@ func (forMsg *ForwardMessage) CalculateValidationDataForward(seq, random int32,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (forMsg *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64) []*msg.Message {
|
func (forMsg *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64) []*msg.Message {
|
||||||
var msgs = make([]*msg.Message, 0, len(forMsg.Nodes))
|
msgs := make([]*msg.Message, 0, len(forMsg.Nodes))
|
||||||
for _, node := range forMsg.Nodes {
|
for _, node := range forMsg.Nodes {
|
||||||
msgs = append(msgs, &msg.Message{
|
msgs = append(msgs, &msg.Message{
|
||||||
Head: &msg.MessageHead{
|
Head: &msg.MessageHead{
|
||||||
|
@ -8,9 +8,11 @@ import (
|
|||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var imgOld = []byte{0x15, 0x36, 0x20, 0x39, 0x32, 0x6B, 0x41, 0x31, 0x00, 0x38, 0x37, 0x32, 0x66, 0x30, 0x36, 0x36, 0x30, 0x33, 0x61, 0x65, 0x31, 0x30, 0x33, 0x62, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20,
|
var imgOld = []byte{
|
||||||
|
0x15, 0x36, 0x20, 0x39, 0x32, 0x6B, 0x41, 0x31, 0x00, 0x38, 0x37, 0x32, 0x66, 0x30, 0x36, 0x36, 0x30, 0x33, 0x61, 0x65, 0x31, 0x30, 0x33, 0x62, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x35, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x30, 0x31, 0x45, 0x39, 0x34, 0x35, 0x31, 0x42, 0x2D, 0x37, 0x30, 0x45, 0x44,
|
0x20, 0x35, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x30, 0x31, 0x45, 0x39, 0x34, 0x35, 0x31, 0x42, 0x2D, 0x37, 0x30, 0x45, 0x44,
|
||||||
0x2D, 0x45, 0x41, 0x45, 0x33, 0x2D, 0x42, 0x33, 0x37, 0x43, 0x2D, 0x31, 0x30, 0x31, 0x46, 0x31, 0x45, 0x45, 0x42, 0x46, 0x35, 0x42, 0x35, 0x7D, 0x2E, 0x70, 0x6E, 0x67, 0x41}
|
0x2D, 0x45, 0x41, 0x45, 0x33, 0x2D, 0x42, 0x33, 0x37, 0x43, 0x2D, 0x31, 0x30, 0x31, 0x46, 0x31, 0x45, 0x45, 0x42, 0x46, 0x35, 0x42, 0x35, 0x7D, 0x2E, 0x70, 0x6E, 0x67, 0x41,
|
||||||
|
}
|
||||||
|
|
||||||
func (e *TextElement) Pack() (r []*msg.Elem) {
|
func (e *TextElement) Pack() (r []*msg.Elem) {
|
||||||
r = append(r, &msg.Elem{
|
r = append(r, &msg.Elem{
|
||||||
@ -93,7 +95,7 @@ func (e *GroupImageElement) Pack() (r []*msg.Elem) {
|
|||||||
CustomFace: &msg.CustomFace{
|
CustomFace: &msg.CustomFace{
|
||||||
FileType: proto.Int32(66),
|
FileType: proto.Int32(66),
|
||||||
Useful: proto.Int32(1),
|
Useful: proto.Int32(1),
|
||||||
//Origin: 1,
|
// Origin: 1,
|
||||||
BizType: proto.Int32(5),
|
BizType: proto.Int32(5),
|
||||||
Width: &e.Width,
|
Width: &e.Width,
|
||||||
Height: &e.Height,
|
Height: &e.Height,
|
||||||
@ -103,7 +105,7 @@ func (e *GroupImageElement) Pack() (r []*msg.Elem) {
|
|||||||
Size: &e.Size,
|
Size: &e.Size,
|
||||||
Md5: e.Md5,
|
Md5: e.Md5,
|
||||||
Flag: make([]byte, 4),
|
Flag: make([]byte, 4),
|
||||||
//OldData: imgOld,
|
// OldData: imgOld,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -252,7 +254,7 @@ func (e *GroupShowPicElement) Pack() (r []*msg.Elem) {
|
|||||||
Size: &e.Size,
|
Size: &e.Size,
|
||||||
Md5: e.Md5,
|
Md5: e.Md5,
|
||||||
Flag: []byte{0x11, 0x00, 0x00, 0x00},
|
Flag: []byte{0x11, 0x00, 0x00, 0x00},
|
||||||
//OldData: imgOld,
|
// OldData: imgOld,
|
||||||
PbReserve: reserve,
|
PbReserve: reserve,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -96,7 +96,7 @@ func (e *EncryptECDH) FetchPubKey(uin int64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var pubKey = pubKeyResp{}
|
pubKey := pubKeyResp{}
|
||||||
err = jsoniter.NewDecoder(resp.Body).Decode(&pubKey)
|
err = jsoniter.NewDecoder(resp.Body).Decode(&pubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -8,11 +8,13 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrUnknownFlag = errors.New("unknown flag")
|
var (
|
||||||
var ErrInvalidPayload = errors.New("invalid payload")
|
ErrUnknownFlag = errors.New("unknown flag")
|
||||||
var ErrDecryptFailed = errors.New("decrypt failed")
|
ErrInvalidPayload = errors.New("invalid payload")
|
||||||
var ErrSessionExpired = errors.New("session expired")
|
ErrDecryptFailed = errors.New("decrypt failed")
|
||||||
var ErrPacketDropped = errors.New("packet dropped")
|
ErrSessionExpired = errors.New("session expired")
|
||||||
|
ErrPacketDropped = errors.New("packet dropped")
|
||||||
|
)
|
||||||
|
|
||||||
type ISendingPacket interface {
|
type ISendingPacket interface {
|
||||||
CommandId() uint16
|
CommandId() uint16
|
||||||
@ -109,7 +111,7 @@ func ParseIncomingPacket(payload, d2key []byte) (*IncomingPacket, error) {
|
|||||||
flag1 := reader.ReadInt32()
|
flag1 := reader.ReadInt32()
|
||||||
flag2 := reader.ReadByte()
|
flag2 := reader.ReadByte()
|
||||||
if reader.ReadByte() != 0 { // flag3
|
if reader.ReadByte() != 0 { // flag3
|
||||||
//return nil, errors.WithStack(ErrUnknownFlag)
|
// return nil, errors.WithStack(ErrUnknownFlag)
|
||||||
}
|
}
|
||||||
reader.ReadString() // uin string
|
reader.ReadString() // uin string
|
||||||
decrypted := func() (data []byte) {
|
decrypted := func() (data []byte) {
|
||||||
|
@ -3,6 +3,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -19,32 +20,12 @@ var client = &http.Client{
|
|||||||
|
|
||||||
// HttpGetBytes 带 cookie 的 GET 请求
|
// HttpGetBytes 带 cookie 的 GET 请求
|
||||||
func HttpGetBytes(url, cookie string) ([]byte, error) {
|
func HttpGetBytes(url, cookie string) ([]byte, error) {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
body, err := HTTPGetReadCloser(url, cookie)
|
||||||
|
defer func() { _ = body.Close() }()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header["User-Agent"] = []string{"QQ/8.2.0.1296 CFNetwork/1126"}
|
return io.ReadAll(body)
|
||||||
req.Header["Net-Type"] = []string{"Wifi"}
|
|
||||||
if cookie != "" {
|
|
||||||
req.Header["Cookie"] = []string{cookie}
|
|
||||||
}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if strings.Contains(resp.Header.Get("Content-Encoding"), "gzip") {
|
|
||||||
buffer := bytes.NewBuffer(body)
|
|
||||||
r, _ := gzip.NewReader(buffer)
|
|
||||||
defer r.Close()
|
|
||||||
unCom, err := ioutil.ReadAll(r)
|
|
||||||
return unCom, err
|
|
||||||
}
|
|
||||||
return body, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpPostBytes(url string, data []byte) ([]byte, error) {
|
func HttpPostBytes(url string, data []byte) ([]byte, error) {
|
||||||
@ -105,3 +86,52 @@ func HttpPostBytesWithCookie(url string, data []byte, cookie string, contentType
|
|||||||
}
|
}
|
||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type gzipCloser struct {
|
||||||
|
f io.Closer
|
||||||
|
r *gzip.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGzipReadCloser 从 io.ReadCloser 创建 gunzip io.ReadCloser
|
||||||
|
func NewGzipReadCloser(reader io.ReadCloser) (io.ReadCloser, error) {
|
||||||
|
gzipReader, err := gzip.NewReader(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &gzipCloser{
|
||||||
|
f: reader,
|
||||||
|
r: gzipReader,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read impls io.Reader
|
||||||
|
func (g *gzipCloser) Read(p []byte) (n int, err error) {
|
||||||
|
return g.r.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close impls io.Closer
|
||||||
|
func (g *gzipCloser) Close() error {
|
||||||
|
_ = g.f.Close()
|
||||||
|
return g.r.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPGetReadCloser 从 Http url 获取 io.ReadCloser
|
||||||
|
func HTTPGetReadCloser(url string, cookie string) (io.ReadCloser, error) {
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header["User-Agent"] = []string{"QQ/8.2.0.1296 CFNetwork/1126"}
|
||||||
|
req.Header["Net-Type"] = []string{"Wifi"}
|
||||||
|
if cookie != "" {
|
||||||
|
req.Header["Cookie"] = []string{cookie}
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if strings.Contains(resp.Header.Get("Content-Encoding"), "gzip") {
|
||||||
|
return NewGzipReadCloser(resp.Body)
|
||||||
|
}
|
||||||
|
return resp.Body, err
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user