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

feat: GetUnidirectionalFriendList.

This commit is contained in:
Mrs4s 2021-09-16 15:32:39 +08:00
parent 59288fc4dc
commit 3b6d4a6671
No known key found for this signature in database
GPG Key ID: 3186E98FA19CE3A7
7 changed files with 684 additions and 19 deletions

View File

@ -142,8 +142,9 @@ type QiDianAccountInfo struct {
} }
type handlerInfo struct { type handlerInfo struct {
fun func(i interface{}, err error) fun func(i interface{}, err error)
params requestParams dynamic bool
params requestParams
} }
var decoders = map[string]func(*QQClient, *incomingPacketInfo, []byte) (interface{}, error){ var decoders = map[string]func(*QQClient, *incomingPacketInfo, []byte) (interface{}, error){

View File

@ -92,7 +92,7 @@ func (c *QQClient) sendAndWait(seq uint16, pkt []byte, params ...requestParams)
Response: i, Response: i,
Error: err, Error: err,
} }
}, params: p}) }, params: p, dynamic: false})
err := c.sendPacket(pkt) err := c.sendPacket(pkt)
if err != nil { if err != nil {
@ -138,6 +138,25 @@ func (c *QQClient) waitPacket(cmd string, f func(interface{}, error)) func() {
} }
} }
// sendAndWaitDynamic
// 发送数据包并返回需要解析的 response
func (c *QQClient) sendAndWaitDynamic(seq uint16, pkt []byte) ([]byte, error) {
ch := make(chan []byte, 1)
c.handlers.Store(seq, &handlerInfo{fun: func(i interface{}, err error) { ch <- i.([]byte) }, dynamic: true})
err := c.sendPacket(pkt)
if err != nil {
c.handlers.Delete(seq)
return nil, err
}
select {
case rsp := <-ch:
return rsp, nil
case <-time.After(time.Second * 15):
c.handlers.Delete(seq)
return nil, errors.New("Packet timed out")
}
}
// plannedDisconnect 计划中断线事件 // plannedDisconnect 计划中断线事件
func (c *QQClient) plannedDisconnect(_ *utils.TCPListener) { func (c *QQClient) plannedDisconnect(_ *utils.TCPListener) {
c.Debug("planned disconnect.") c.Debug("planned disconnect.")
@ -208,27 +227,31 @@ func (c *QQClient) netLoop() {
if decoder, ok := decoders[pkt.CommandName]; ok { if decoder, ok := decoders[pkt.CommandName]; ok {
// found predefined decoder // found predefined decoder
info, ok := c.handlers.LoadAndDelete(pkt.SequenceId) info, ok := c.handlers.LoadAndDelete(pkt.SequenceId)
rsp, err := decoder(c, &incomingPacketInfo{ var decoded interface{}
SequenceId: pkt.SequenceId, decoded = pkt.Payload
CommandName: pkt.CommandName, if info != nil && !info.dynamic {
Params: func() requestParams { decoded, err = decoder(c, &incomingPacketInfo{
if !ok { SequenceId: pkt.SequenceId,
return nil CommandName: pkt.CommandName,
} Params: func() requestParams {
return info.params if !ok {
}(), return nil
}, pkt.Payload) }
if err != nil { return info.params
c.Debug("decode pkt %v error: %+v", pkt.CommandName, err) }(),
}, pkt.Payload)
if err != nil {
c.Debug("decode pkt %v error: %+v", pkt.CommandName, err)
}
} }
if ok { if ok {
info.fun(rsp, err) info.fun(decoded, err)
} else if f, ok := c.waiters.Load(pkt.CommandName); ok { // 在不存在handler的情况下触发wait } else if f, ok := c.waiters.Load(pkt.CommandName); ok { // 在不存在handler的情况下触发wait
f.(func(interface{}, error))(rsp, err) f.(func(interface{}, error))(decoded, err)
} }
} else if f, ok := c.handlers.LoadAndDelete(pkt.SequenceId); ok { } else if f, ok := c.handlers.LoadAndDelete(pkt.SequenceId); ok {
// does not need decoder // does not need decoder
f.fun(nil, nil) f.fun(pkt.Payload, nil)
} else { } else {
c.Debug("Unhandled Command: %s\nSeq: %d\nThis message can be ignored.", pkt.CommandName, pkt.SequenceId) c.Debug("Unhandled Command: %s\nSeq: %d\nThis message can be ignored.", pkt.CommandName, pkt.SequenceId)
} }

View File

@ -0,0 +1,510 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.14.0
// source: WebSsoBody.proto
package web
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type STServiceMonitItem struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Cmd *string `protobuf:"bytes,1,opt,name=cmd" json:"cmd,omitempty"`
Url *string `protobuf:"bytes,2,opt,name=url" json:"url,omitempty"`
Errcode *int32 `protobuf:"varint,3,opt,name=errcode" json:"errcode,omitempty"`
Cost *uint32 `protobuf:"varint,4,opt,name=cost" json:"cost,omitempty"`
Src *uint32 `protobuf:"varint,5,opt,name=src" json:"src,omitempty"`
}
func (x *STServiceMonitItem) Reset() {
*x = STServiceMonitItem{}
if protoimpl.UnsafeEnabled {
mi := &file_WebSsoBody_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *STServiceMonitItem) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*STServiceMonitItem) ProtoMessage() {}
func (x *STServiceMonitItem) ProtoReflect() protoreflect.Message {
mi := &file_WebSsoBody_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use STServiceMonitItem.ProtoReflect.Descriptor instead.
func (*STServiceMonitItem) Descriptor() ([]byte, []int) {
return file_WebSsoBody_proto_rawDescGZIP(), []int{0}
}
func (x *STServiceMonitItem) GetCmd() string {
if x != nil && x.Cmd != nil {
return *x.Cmd
}
return ""
}
func (x *STServiceMonitItem) GetUrl() string {
if x != nil && x.Url != nil {
return *x.Url
}
return ""
}
func (x *STServiceMonitItem) GetErrcode() int32 {
if x != nil && x.Errcode != nil {
return *x.Errcode
}
return 0
}
func (x *STServiceMonitItem) GetCost() uint32 {
if x != nil && x.Cost != nil {
return *x.Cost
}
return 0
}
func (x *STServiceMonitItem) GetSrc() uint32 {
if x != nil && x.Src != nil {
return *x.Src
}
return 0
}
type STServiceMonitReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
List []*STServiceMonitItem `protobuf:"bytes,1,rep,name=list" json:"list,omitempty"`
}
func (x *STServiceMonitReq) Reset() {
*x = STServiceMonitReq{}
if protoimpl.UnsafeEnabled {
mi := &file_WebSsoBody_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *STServiceMonitReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*STServiceMonitReq) ProtoMessage() {}
func (x *STServiceMonitReq) ProtoReflect() protoreflect.Message {
mi := &file_WebSsoBody_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use STServiceMonitReq.ProtoReflect.Descriptor instead.
func (*STServiceMonitReq) Descriptor() ([]byte, []int) {
return file_WebSsoBody_proto_rawDescGZIP(), []int{1}
}
func (x *STServiceMonitReq) GetList() []*STServiceMonitItem {
if x != nil {
return x.List
}
return nil
}
type WebSsoControlData struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Frequency *uint32 `protobuf:"varint,1,opt,name=frequency" json:"frequency,omitempty"`
PackageSize *uint32 `protobuf:"varint,2,opt,name=packageSize" json:"packageSize,omitempty"`
}
func (x *WebSsoControlData) Reset() {
*x = WebSsoControlData{}
if protoimpl.UnsafeEnabled {
mi := &file_WebSsoBody_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WebSsoControlData) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebSsoControlData) ProtoMessage() {}
func (x *WebSsoControlData) ProtoReflect() protoreflect.Message {
mi := &file_WebSsoBody_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WebSsoControlData.ProtoReflect.Descriptor instead.
func (*WebSsoControlData) Descriptor() ([]byte, []int) {
return file_WebSsoBody_proto_rawDescGZIP(), []int{2}
}
func (x *WebSsoControlData) GetFrequency() uint32 {
if x != nil && x.Frequency != nil {
return *x.Frequency
}
return 0
}
func (x *WebSsoControlData) GetPackageSize() uint32 {
if x != nil && x.PackageSize != nil {
return *x.PackageSize
}
return 0
}
type WebSsoRequestBody struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Version *uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
Type *uint32 `protobuf:"varint,2,opt,name=type" json:"type,omitempty"`
Data *string `protobuf:"bytes,3,opt,name=data" json:"data,omitempty"`
WebData *string `protobuf:"bytes,4,opt,name=webData" json:"webData,omitempty"`
}
func (x *WebSsoRequestBody) Reset() {
*x = WebSsoRequestBody{}
if protoimpl.UnsafeEnabled {
mi := &file_WebSsoBody_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WebSsoRequestBody) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebSsoRequestBody) ProtoMessage() {}
func (x *WebSsoRequestBody) ProtoReflect() protoreflect.Message {
mi := &file_WebSsoBody_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WebSsoRequestBody.ProtoReflect.Descriptor instead.
func (*WebSsoRequestBody) Descriptor() ([]byte, []int) {
return file_WebSsoBody_proto_rawDescGZIP(), []int{3}
}
func (x *WebSsoRequestBody) GetVersion() uint32 {
if x != nil && x.Version != nil {
return *x.Version
}
return 0
}
func (x *WebSsoRequestBody) GetType() uint32 {
if x != nil && x.Type != nil {
return *x.Type
}
return 0
}
func (x *WebSsoRequestBody) GetData() string {
if x != nil && x.Data != nil {
return *x.Data
}
return ""
}
func (x *WebSsoRequestBody) GetWebData() string {
if x != nil && x.WebData != nil {
return *x.WebData
}
return ""
}
type WebSsoResponseBody struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Version *uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
Type *uint32 `protobuf:"varint,2,opt,name=type" json:"type,omitempty"`
Ret *uint32 `protobuf:"varint,3,opt,name=ret" json:"ret,omitempty"`
Data *string `protobuf:"bytes,4,opt,name=data" json:"data,omitempty"`
ControlData *WebSsoControlData `protobuf:"bytes,5,opt,name=controlData" json:"controlData,omitempty"`
}
func (x *WebSsoResponseBody) Reset() {
*x = WebSsoResponseBody{}
if protoimpl.UnsafeEnabled {
mi := &file_WebSsoBody_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WebSsoResponseBody) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebSsoResponseBody) ProtoMessage() {}
func (x *WebSsoResponseBody) ProtoReflect() protoreflect.Message {
mi := &file_WebSsoBody_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WebSsoResponseBody.ProtoReflect.Descriptor instead.
func (*WebSsoResponseBody) Descriptor() ([]byte, []int) {
return file_WebSsoBody_proto_rawDescGZIP(), []int{4}
}
func (x *WebSsoResponseBody) GetVersion() uint32 {
if x != nil && x.Version != nil {
return *x.Version
}
return 0
}
func (x *WebSsoResponseBody) GetType() uint32 {
if x != nil && x.Type != nil {
return *x.Type
}
return 0
}
func (x *WebSsoResponseBody) GetRet() uint32 {
if x != nil && x.Ret != nil {
return *x.Ret
}
return 0
}
func (x *WebSsoResponseBody) GetData() string {
if x != nil && x.Data != nil {
return *x.Data
}
return ""
}
func (x *WebSsoResponseBody) GetControlData() *WebSsoControlData {
if x != nil {
return x.ControlData
}
return nil
}
var File_WebSsoBody_proto protoreflect.FileDescriptor
var file_WebSsoBody_proto_rawDesc = []byte{
0x0a, 0x10, 0x57, 0x65, 0x62, 0x53, 0x73, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0x78, 0x0a, 0x12, 0x53, 0x54, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d,
0x6f, 0x6e, 0x69, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72,
0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07,
0x65, 0x72, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65,
0x72, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x72,
0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x73, 0x72, 0x63, 0x22, 0x3c, 0x0a, 0x11,
0x53, 0x54, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x52, 0x65,
0x71, 0x12, 0x27, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x13, 0x2e, 0x53, 0x54, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x53, 0x0a, 0x11, 0x57, 0x65,
0x62, 0x53, 0x73, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12,
0x1c, 0x0a, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x20, 0x0a,
0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22,
0x6f, 0x0a, 0x11, 0x57, 0x65, 0x62, 0x53, 0x73, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79,
0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x44, 0x61, 0x74,
0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x44, 0x61, 0x74, 0x61,
0x22, 0x9e, 0x01, 0x0a, 0x12, 0x57, 0x65, 0x62, 0x53, 0x73, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x0b, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x12, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x73, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x44, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x44, 0x61, 0x74,
0x61, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x3b, 0x77, 0x65, 0x62,
}
var (
file_WebSsoBody_proto_rawDescOnce sync.Once
file_WebSsoBody_proto_rawDescData = file_WebSsoBody_proto_rawDesc
)
func file_WebSsoBody_proto_rawDescGZIP() []byte {
file_WebSsoBody_proto_rawDescOnce.Do(func() {
file_WebSsoBody_proto_rawDescData = protoimpl.X.CompressGZIP(file_WebSsoBody_proto_rawDescData)
})
return file_WebSsoBody_proto_rawDescData
}
var file_WebSsoBody_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_WebSsoBody_proto_goTypes = []interface{}{
(*STServiceMonitItem)(nil), // 0: STServiceMonitItem
(*STServiceMonitReq)(nil), // 1: STServiceMonitReq
(*WebSsoControlData)(nil), // 2: WebSsoControlData
(*WebSsoRequestBody)(nil), // 3: WebSsoRequestBody
(*WebSsoResponseBody)(nil), // 4: WebSsoResponseBody
}
var file_WebSsoBody_proto_depIdxs = []int32{
0, // 0: STServiceMonitReq.list:type_name -> STServiceMonitItem
2, // 1: WebSsoResponseBody.controlData:type_name -> WebSsoControlData
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_WebSsoBody_proto_init() }
func file_WebSsoBody_proto_init() {
if File_WebSsoBody_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_WebSsoBody_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*STServiceMonitItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_WebSsoBody_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*STServiceMonitReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_WebSsoBody_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WebSsoControlData); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_WebSsoBody_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WebSsoRequestBody); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_WebSsoBody_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WebSsoResponseBody); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_WebSsoBody_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_WebSsoBody_proto_goTypes,
DependencyIndexes: file_WebSsoBody_proto_depIdxs,
MessageInfos: file_WebSsoBody_proto_msgTypes,
}.Build()
File_WebSsoBody_proto = out.File
file_WebSsoBody_proto_rawDesc = nil
file_WebSsoBody_proto_goTypes = nil
file_WebSsoBody_proto_depIdxs = nil
}

View File

@ -0,0 +1,36 @@
syntax = "proto2";
option go_package = "./;web";
message STServiceMonitItem {
optional string cmd = 1;
optional string url = 2;
optional int32 errcode = 3;
optional uint32 cost = 4;
optional uint32 src = 5;
}
message STServiceMonitReq {
repeated STServiceMonitItem list = 1;
}
message WebSsoControlData {
optional uint32 frequency = 1;
optional uint32 packageSize = 2;
}
message WebSsoRequestBody {
optional uint32 version = 1;
optional uint32 type = 2;
optional string data = 3;
optional string webData = 4;
}
message WebSsoResponseBody {
optional uint32 version = 1;
optional uint32 type = 2;
optional uint32 ret = 3;
optional string data = 4;
optional WebSsoControlData controlData = 5;
}

85
client/web.go Normal file
View File

@ -0,0 +1,85 @@
package client
import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/Mrs4s/MiraiGo/client/pb/web"
"github.com/Mrs4s/MiraiGo/protocol/packets"
"github.com/Mrs4s/MiraiGo/utils"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
"strings"
)
type UnidirectionalFriendInfo struct {
Uin int64
Nickname string
Age int32
Source string
}
func (c *QQClient) GetUnidirectionalFriendList() (ret []*UnidirectionalFriendInfo, err error) {
webRsp := &struct {
BlockList []struct {
Uin int64 `json:"uint64_uin"`
NickBytes string `json:"bytes_nick"`
Age int32 `json:"uint32_age"`
Sex int32 `json:"uint32_sex"`
SourceBytes string `json:"bytes_source"`
} `json:"rpt_block_list"`
ErrorCode int32 `json:"ErrorCode"`
}{}
rsp, err := c.webSsoRequest("ti.qq.com", "OidbSvc.0xe17_0", fmt.Sprintf(`{"uint64_uin":%v,"uint64_top":0,"uint32_req_num":99,"bytes_cookies":""}`, c.Uin))
if err != nil {
return nil, err
}
if err = json.Unmarshal(utils.S2B(rsp), webRsp); err != nil {
return nil, errors.Wrap(err, "unmarshal json error")
}
if webRsp.ErrorCode != 0 {
return nil, errors.Errorf("web sso request error: %v", webRsp.ErrorCode)
}
for _, block := range webRsp.BlockList {
decodeBase64String := func(str string) string {
b, err := base64.StdEncoding.DecodeString(str)
if err != nil {
return ""
}
return utils.B2S(b)
}
ret = append(ret, &UnidirectionalFriendInfo{
Uin: block.Uin,
Nickname: decodeBase64String(block.NickBytes),
Age: block.Age,
Source: decodeBase64String(block.SourceBytes),
})
}
return
}
func (c *QQClient) webSsoRequest(host, webCmd, data string) (string, error) {
s := strings.Split(host, `.`)
sub := ""
for i := len(s) - 1; i >= 0; i-- {
sub += s[i]
if i != 0 {
sub += "_"
}
}
cmd := "MQUpdateSvc_" + sub + ".web." + webCmd
req, _ := proto.Marshal(&web.WebSsoRequestBody{
Type: proto.Uint32(0),
Data: &data,
})
seq := c.nextSeq()
rspData, err := c.sendAndWaitDynamic(seq, packets.BuildUniPacket(c.Uin, seq, cmd, 1, c.OutGoingPacketSessionId, []byte{}, c.sigInfo.d2Key, req))
if err != nil {
return "", errors.Wrap(err, "send web sso request error")
}
rsp := &web.WebSsoResponseBody{}
if err = proto.Unmarshal(rspData, rsp); err != nil {
return "", errors.Wrap(err, "unmarshal response error")
}
return rsp.GetData(), nil
}

4
go.mod
View File

@ -3,9 +3,11 @@ module github.com/Mrs4s/MiraiGo
go 1.16 go 1.16
require ( require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/tidwall/gjson v1.8.1 github.com/tidwall/gjson v1.8.1
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/protobuf v1.25.0 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/protobuf v1.27.1
) )

8
go.sum
View File

@ -16,12 +16,16 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -77,5 +81,9 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=