From 0f7f9708b743764757fa0ece63d1306244b12c22 Mon Sep 17 00:00:00 2001 From: icarus-ai <82353054+icarus-ai@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:12:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=8E=B7=E5=8F=96=E5=89=A9=E4=BD=99@?= =?UTF-8?q?=E5=85=A8=E5=91=98=E6=AC=A1=E6=95=B0=20&=20fix=20(#126)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fmt: import * feat: 获取剩余@全员次数 * feat: 获取剩余@全员次数 & fix & fmt * fix: error类型破坏 --- client/internal/network/response.go | 2 +- client/operation.go | 14 ++++ client/packets/oidb/group_atall_remain.go | 35 +++++++++ client/packets/oidb/security_url.go | 26 ++++--- .../service/oidb/OidbSvcTrpcTcp0x8A7_0.pb.go | 20 +++++ .../service/oidb/OidbSvcTrpcTcp0x8A7_0.proto | 21 +++++ .../service/oidb/OidbSvcTrpcTcp0xBCB_0.pb.go | 68 ++++++++-------- .../service/oidb/OidbSvcTrpcTcp0xBCB_0.proto | 78 +++++++++---------- 8 files changed, 180 insertions(+), 84 deletions(-) create mode 100644 client/packets/oidb/group_atall_remain.go create mode 100644 client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.pb.go create mode 100644 client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto diff --git a/client/internal/network/response.go b/client/internal/network/response.go index 5f9116f..b7db116 100644 --- a/client/internal/network/response.go +++ b/client/internal/network/response.go @@ -80,7 +80,7 @@ func (t *Transport) readSSOFrame(resp *Response, payload []byte) error { err = errors.Errorf("return code unsuccessful: %d", retCode) } if err != nil { - return errors.Errorf("%s %s", err.Error(), resp.Message) + return errors.Wrap(err, resp.Message) } resp.CommandName = head.ReadStringWithLength("u32", true) if resp.CommandName == "Heartbeat.Alive" { diff --git a/client/operation.go b/client/operation.go index 263d7d6..f0f003d 100644 --- a/client/operation.go +++ b/client/operation.go @@ -1349,3 +1349,17 @@ func (c *QQClient) CheckURLSafely(url string) (oidb2.URLSecurityLevel, error) { } return oidb2.ParseURLCheckResponse(resp) } + +// GetAtAllRemain 获取剩余@全员次数 +// ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/group_msg.go#L68 +func (c *QQClient) GetAtAllRemain(uin, groupUin uint32) (*oidb2.AtAllRemainInfo, error) { + pkt, err := oidb2.BuildAtAllRemainRequest(uin, groupUin) + if err != nil { + return nil, err + } + resp, err := c.sendOidbPacketAndWait(pkt) + if err != nil { + return nil, err + } + return oidb2.ParseAtAllRemainResponse(resp) +} diff --git a/client/packets/oidb/group_atall_remain.go b/client/packets/oidb/group_atall_remain.go new file mode 100644 index 0000000..3a7b02b --- /dev/null +++ b/client/packets/oidb/group_atall_remain.go @@ -0,0 +1,35 @@ +package oidb + +import "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" + +// ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/group_msg.go#L213 +func BuildAtAllRemainRequest(uin, gin uint32) (*Packet, error) { + body := &oidb.OidbSvcTrpcTcp0X8A7_0_ReqBody{ + SubCmd: 1, + LimitIntervalTypeForUin: 2, + LimitIntervalTypeForGroup: 1, + Uin: uint64(uin), + GroupUin: uint64(gin), + } + return BuildOidbPacket(0x8A7, 0, body, false, true) +} + +type AtAllRemainInfo struct { + CanAtAll bool + CountForGroup uint32 // 当前群默认可用次数 + CountForUin uint32 // 当前QQ剩余次数 +} + +// ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/group_msg.go#L326 +func ParseAtAllRemainResponse(data []byte) (*AtAllRemainInfo, error) { + var rsp oidb.OidbSvcTrpcTcp0X8A7_0_RspBody + _, err := ParseOidbPacket(data, &rsp) + if err != nil { + return nil, err + } + return &AtAllRemainInfo{ + CanAtAll: rsp.CanAtAll, + CountForGroup: rsp.CountForGroup, + CountForUin: rsp.CountForUin, + }, nil +} diff --git a/client/packets/oidb/security_url.go b/client/packets/oidb/security_url.go index 88d8dd3..1826ac7 100644 --- a/client/packets/oidb/security_url.go +++ b/client/packets/oidb/security_url.go @@ -3,10 +3,12 @@ package oidb import ( "errors" + "github.com/RomiChan/protobuf/proto" + "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" ) -// see https://github.com/Mrs4s/MiraiGo/blob/master/client/security.go +// ref https://github.com/Mrs4s/MiraiGo/blob/master/client/security.go type URLSecurityLevel int @@ -33,16 +35,16 @@ func BuildURLCheckRequest(botuin uint32, url string) (*Packet, error) { body := &oidb.OidbSvcTrpcTcp0XBCB_0_ReqBody{ CheckUrlReq: &oidb.CheckUrlReq{ Url: []string{url}, - QqPfTo: "mqq.group", - Type: 2, - SendUin: uint64(botuin), - ReqType: "webview", - OriginalUrl: url, - IsArk: false, - IsFinish: false, + QqPfTo: proto.String("mqq.group"), + Type: proto.Uint32(2), + SendUin: proto.Uint64(uint64(botuin)), + ReqType: proto.String("webview"), + OriginalUrl: proto.String(url), + IsArk: proto.Bool(false), + IsFinish: proto.Bool(false), SrcUrls: []string{url}, - SrcPlatform: 1, - Qua: "AQQ_2013 4.6/2013 8.4.184945&NA_0/000000&ADR&null18&linux&2017&C2293D02BEE31158&7.1.2&V3", + SrcPlatform: proto.Uint32(1), + Qua: proto.String("AQQ_2013 4.6/2013 8.4.184945&NA_0/000000&ADR&null18&linux&2017&C2293D02BEE31158&7.1.2&V3"), }, } return BuildOidbPacket(0xBCB, 0, body, false, false) @@ -57,10 +59,10 @@ func ParseURLCheckResponse(data []byte) (URLSecurityLevel, error) { if rsp.CheckUrlRsp == nil || len(rsp.CheckUrlRsp.Results) == 0 { return URLSecurityLevelUnknown, errors.New("response is empty") } - if rsp.CheckUrlRsp.Results[0].JumpUrl != "" { + if rsp.CheckUrlRsp.Results[0].JumpUrl.IsSome() { return URLSecurityLevelDanger, nil } - if rsp.CheckUrlRsp.Results[0].Umrtype == 2 { + if rsp.CheckUrlRsp.Results[0].UmrType.Unwrap() == 2 { return URLSecurityLevelSafe, nil } return URLSecurityLevelUnknown, nil diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.pb.go new file mode 100644 index 0000000..fcd2e5e --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.pb.go @@ -0,0 +1,20 @@ +// Code generated by protoc-gen-golite. DO NOT EDIT. +// source: pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto + +package oidb + +type OidbSvcTrpcTcp0X8A7_0_ReqBody struct { + SubCmd uint32 `protobuf:"varint,1,opt"` + LimitIntervalTypeForUin uint32 `protobuf:"varint,2,opt"` + LimitIntervalTypeForGroup uint32 `protobuf:"varint,3,opt"` + Uin uint64 `protobuf:"varint,4,opt"` + GroupUin uint64 `protobuf:"varint,5,opt"` + _ [0]func() +} + +type OidbSvcTrpcTcp0X8A7_0_RspBody struct { + CanAtAll bool `protobuf:"varint,1,opt"` + CountForUin uint32 `protobuf:"varint,2,opt"` + CountForGroup uint32 `protobuf:"varint,3,opt"` + _ [0]func() +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto new file mode 100644 index 0000000..4f4a15d --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +// ref https://github.com/Mrs4s/MiraiGo/blob/master/client/pb/oidb/oidb0x8a7.proto + +option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; + +message OidbSvcTrpcTcp0x8A7_0_ReqBody { + uint32 subCmd = 1; + uint32 limitIntervalTypeForUin = 2; + uint32 limitIntervalTypeForGroup = 3; + uint64 uin = 4; + uint64 groupUin = 5; +} + +message OidbSvcTrpcTcp0x8A7_0_RspBody { + bool canAtAll = 1; + uint32 countForUin = 2; + uint32 countForGroup = 3; + //optional bytes promptMsg1 = 4; + //optional bytes promptMsg2 = 5; +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.pb.go index 409dec1..9d30eb3 100644 --- a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.pb.go +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.pb.go @@ -3,52 +3,56 @@ package oidb +import ( + proto "github.com/RomiChan/protobuf/proto" +) + type OidbSvcTrpcTcp0XBCB_0_ReqBody struct { - NotUseCache int32 `protobuf:"varint,9,opt"` - CheckUrlReq *CheckUrlReq `protobuf:"bytes,10,opt"` + NotUseCache proto.Option[int32] `protobuf:"varint,9,opt"` + CheckUrlReq *CheckUrlReq `protobuf:"bytes,10,opt"` _ [0]func() } type CheckUrlReq struct { - Url []string `protobuf:"bytes,1,rep"` - Refer string `protobuf:"bytes,2,opt"` - Plateform string `protobuf:"bytes,3,opt"` - QqPfTo string `protobuf:"bytes,4,opt"` - Type uint32 `protobuf:"varint,5,opt"` - From uint32 `protobuf:"varint,6,opt"` - Chatid uint64 `protobuf:"varint,7,opt"` - ServiceType uint64 `protobuf:"varint,8,opt"` - SendUin uint64 `protobuf:"varint,9,opt"` - ReqType string `protobuf:"bytes,10,opt"` - OriginalUrl string `protobuf:"bytes,11,opt"` - IsArk bool `protobuf:"varint,12,opt"` - ArkName string `protobuf:"bytes,13,opt"` - IsFinish bool `protobuf:"varint,14,opt"` - SrcUrls []string `protobuf:"bytes,15,rep"` - SrcPlatform uint32 `protobuf:"varint,16,opt"` - Qua string `protobuf:"bytes,17,opt"` + Url []string `protobuf:"bytes,1,rep"` + Refer proto.Option[string] `protobuf:"bytes,2,opt"` + Plateform proto.Option[string] `protobuf:"bytes,3,opt"` + QqPfTo proto.Option[string] `protobuf:"bytes,4,opt"` + Type proto.Option[uint32] `protobuf:"varint,5,opt"` + From proto.Option[uint32] `protobuf:"varint,6,opt"` + ChatId proto.Option[uint64] `protobuf:"varint,7,opt"` + ServiceType proto.Option[uint64] `protobuf:"varint,8,opt"` + SendUin proto.Option[uint64] `protobuf:"varint,9,opt"` + ReqType proto.Option[string] `protobuf:"bytes,10,opt"` + OriginalUrl proto.Option[string] `protobuf:"bytes,11,opt"` + IsArk proto.Option[bool] `protobuf:"varint,12,opt"` + ArkName proto.Option[string] `protobuf:"bytes,13,opt"` + IsFinish proto.Option[bool] `protobuf:"varint,14,opt"` + SrcUrls []string `protobuf:"bytes,15,rep"` + SrcPlatform proto.Option[uint32] `protobuf:"varint,16,opt"` + Qua proto.Option[string] `protobuf:"bytes,17,opt"` } type OidbSvcTrpcTcp0XBCB_0_RspBody struct { - Wording string `protobuf:"bytes,1,opt"` - CheckUrlRsp *CheckUrlRsp `protobuf:"bytes,10,opt"` + Wording proto.Option[string] `protobuf:"bytes,1,opt"` + CheckUrlRsp *CheckUrlRsp `protobuf:"bytes,10,opt"` _ [0]func() } type CheckUrlRsp struct { - Results []*UrlCheckResult `protobuf:"bytes,1,rep"` - NextReqDuration uint32 `protobuf:"varint,2,opt"` + Results []*UrlCheckResult `protobuf:"bytes,1,rep"` + NextReqDuration proto.Option[uint32] `protobuf:"varint,2,opt"` } type UrlCheckResult struct { - Url string `protobuf:"bytes,1,opt"` - Result uint32 `protobuf:"varint,2,opt"` - JumpResult uint32 `protobuf:"varint,3,opt"` - JumpUrl string `protobuf:"bytes,4,opt"` - Level uint32 `protobuf:"varint,5,opt"` - SubLevel uint32 `protobuf:"varint,6,opt"` - Umrtype uint32 `protobuf:"varint,7,opt"` - RetFrom uint32 `protobuf:"varint,8,opt"` - OperationBit uint64 `protobuf:"varint,9,opt"` + Url proto.Option[string] `protobuf:"bytes,1,opt"` + Result proto.Option[uint32] `protobuf:"varint,2,opt"` + JumpResult proto.Option[uint32] `protobuf:"varint,3,opt"` + JumpUrl proto.Option[string] `protobuf:"bytes,4,opt"` + Level proto.Option[uint32] `protobuf:"varint,5,opt"` + SubLevel proto.Option[uint32] `protobuf:"varint,6,opt"` + UmrType proto.Option[uint32] `protobuf:"varint,7,opt"` + RetFrom proto.Option[uint32] `protobuf:"varint,8,opt"` + OperationBit proto.Option[uint64] `protobuf:"varint,9,opt"` _ [0]func() } diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.proto b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.proto index 0a8f691..db939fe 100644 --- a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.proto +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.proto @@ -5,63 +5,63 @@ syntax = "proto3"; option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; message OidbSvcTrpcTcp0xBCB_0_ReqBody { - int32 notUseCache = 9; - CheckUrlReq checkUrlReq = 10; + optional int32 notUseCache = 9; + optional CheckUrlReq checkUrlReq = 10; } message CheckUrlReq { repeated string url = 1; - string refer = 2; - string plateform = 3; - string qqPfTo = 4; - uint32 type = 5; - uint32 from = 6; - uint64 chatid = 7; - uint64 serviceType = 8; - uint64 sendUin = 9; - string reqType = 10; - string originalUrl = 11; - bool isArk = 12; - string arkName = 13; - bool isFinish = 14; + optional string refer = 2; + optional string plateform = 3; + optional string qqPfTo = 4; + optional uint32 type = 5; + optional uint32 from = 6; + optional uint64 chatId = 7; + optional uint64 serviceType = 8; + optional uint64 sendUin = 9; + optional string reqType = 10; + optional string originalUrl = 11; + optional bool isArk = 12; + optional string arkName = 13; + optional bool isFinish = 14; repeated string srcUrls = 15; - uint32 srcPlatform = 16; - string qua = 17; + optional uint32 srcPlatform = 16; + optional string qua = 17; } message OidbSvcTrpcTcp0xBCB_0_RspBody { - string wording = 1; - CheckUrlRsp checkUrlRsp = 10; + optional string wording = 1; + optional CheckUrlRsp checkUrlRsp = 10; } message CheckUrlRsp { repeated UrlCheckResult results = 1; - uint32 nextReqDuration = 2; + optional uint32 nextReqDuration = 2; } message UrlCheckResult { - string url = 1; - uint32 result = 2; - uint32 jumpResult = 3; - string jumpUrl = 4; - uint32 level = 5; - uint32 subLevel = 6; - uint32 umrtype = 7; - uint32 retFrom = 8; - uint64 operationBit = 9; + optional string url = 1; + optional uint32 result = 2; + optional uint32 jumpResult = 3; + optional string jumpUrl = 4; + optional uint32 level = 5; + optional uint32 subLevel = 6; + optional uint32 umrType = 7; + optional uint32 retFrom = 8; + optional uint64 operationBit = 9; } /* message CheckUrlReqItem { - string url = 1; - string refer = 2; - string plateform = 3; - string qqPfTo = 4; - uint32 type = 5; - uint32 from = 6; - uint64 chatid = 7; - uint64 serviceType = 8; - uint64 sendUin = 9; - string reqType = 10; + optional string url = 1; + optional string refer = 2; + optional string plateform = 3; + optional string qqPfTo = 4; + optional uint32 type = 5; + optional uint32 from = 6; + optional uint64 chatId = 7; + optional uint64 serviceType = 8; + optional uint64 sendUin = 9; + optional string reqType = 10; } */