From 31e21130b91c458dcf4c4defcc15c704e55ca375 Mon Sep 17 00:00:00 2001 From: icarus-ai <82353054+icarus-ai@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:30:02 +0800 Subject: [PATCH] feat: image ocr, proto gen (#121) --- client/operation.go | 16 ++++ client/packets/oidb/group_fs_download.go | 4 +- client/packets/oidb/image_ocr.go | 79 +++++++++++++++++++ client/packets/pb/message/element.pb.go | 2 +- .../pb/service/oidb/OidbSvcTrpcTcp0x6D6.pb.go | 4 +- .../service/oidb/OidbSvcTrpcTcp0xE07_0.pb.go | 68 ++++++++++++++++ .../service/oidb/OidbSvcTrpcTcp0xE07_0.proto | 61 ++++++++++++++ .../service/oidb/OidbSvcTrpcTcp0xFE1_2.pb.go | 2 +- 8 files changed, 230 insertions(+), 6 deletions(-) create mode 100644 client/packets/oidb/image_ocr.go create mode 100644 client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.pb.go create mode 100644 client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.proto diff --git a/client/operation.go b/client/operation.go index 3f03ab4e..82de685a 100644 --- a/client/operation.go +++ b/client/operation.go @@ -1264,3 +1264,19 @@ func (c *QQClient) GetGroupMessages(groupUin, startSeq, endSeq uint32) ([]*messa return ret, nil } + +// ImageOcr 图片识别 有些域名的图可能无法识别,需要重新上传到tx服务器并获取图片下载链接 +func (c *QQClient) ImageOcr(url string) (*oidb2.OcrResponse, error) { + if url != "" { + pkt, err := oidb2.BuildImageOcrRequestPacket(url) + if err != nil { + return nil, err + } + resp, err := c.sendOidbPacketAndWait(pkt) + if err != nil { + return nil, err + } + return oidb2.ParseImageOcrResp(resp) + } + return nil, errors.New("image error") +} diff --git a/client/packets/oidb/group_fs_download.go b/client/packets/oidb/group_fs_download.go index 12708a9d..c319444c 100644 --- a/client/packets/oidb/group_fs_download.go +++ b/client/packets/oidb/group_fs_download.go @@ -12,8 +12,8 @@ func BuildGroupFSDownloadReq(groupUin uint32, fileID string) (*Packet, error) { body := &oidb.OidbSvcTrpcTcp0X6D6{ Download: &oidb.OidbSvcTrpcTcp0X6D6Download{ GroupUin: groupUin, - AppID: 7, - BusID: 102, + AppId: 7, + BusId: 102, FileId: fileID, }, } diff --git a/client/packets/oidb/image_ocr.go b/client/packets/oidb/image_ocr.go new file mode 100644 index 00000000..28779400 --- /dev/null +++ b/client/packets/oidb/image_ocr.go @@ -0,0 +1,79 @@ +package oidb + +import ( + "strings" + + "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" + + "github.com/pkg/errors" +) + +func BuildImageOcrRequestPacket(url string) (*Packet, error) { + body := &oidb.OidbSvcTrpcTcp0XE07_0{ + Version: 1, + Client: 0, + Entrance: 1, + OcrReqBody: &oidb.OcrReqBody{ + ImageUrl: url, + OriginMd5: "", + AfterCompressMd5: "", + AfterCompressFileSize: "", + AfterCompressWeight: "", + AfterCompressHeight: "", + IsCut: false, + }, + } + return BuildOidbPacket(0xE07, 0, body, false, true) +} + +type ( + OcrResponse struct { + Texts []*TextDetection `json:"texts"` + Language string `json:"language"` + } + TextDetection struct { + Text string `json:"text"` + Confidence int32 `json:"confidence"` + Coordinates []*Coordinate `json:"coordinates"` + } + Coordinate struct { + X int32 `json:"x"` + Y int32 `json:"y"` + } +) + +func ParseImageOcrResp(data []byte) (*OcrResponse, error) { + var rsp oidb.OidbSvcTrpcTcp0XE07_0_Response + _, err := ParseOidbPacket(data, &rsp) + if err != nil { + return nil, err + } + if rsp.Wording != "" { + if strings.Contains(rsp.Wording, "服务忙") { + return nil, errors.New("未识别到文本") + } + return nil, errors.New(rsp.Wording) + } + if rsp.RetCode != 0 { + return nil, errors.Errorf("server error, code: %v msg: %v", rsp.RetCode, rsp.ErrMsg) + } + texts := make([]*TextDetection, 0, len(rsp.OcrRspBody.TextDetections)) + for _, text := range rsp.OcrRspBody.TextDetections { + points := make([]*Coordinate, 0, len(text.Polygon.Coordinates)) + for _, c := range text.Polygon.Coordinates { + points = append(points, &Coordinate{ + X: c.X, + Y: c.Y, + }) + } + texts = append(texts, &TextDetection{ + Text: text.DetectedText, + Confidence: text.Confidence, + Coordinates: points, + }) + } + return &OcrResponse{ + Texts: texts, + Language: rsp.OcrRspBody.Language, + }, nil +} diff --git a/client/packets/pb/message/element.pb.go b/client/packets/pb/message/element.pb.go index 3564fd98..7291b675 100644 --- a/client/packets/pb/message/element.pb.go +++ b/client/packets/pb/message/element.pb.go @@ -398,7 +398,7 @@ type QFaceExtra struct { StickerType proto.Option[int32] `protobuf:"varint,5,opt"` ResultId proto.Option[string] `protobuf:"bytes,6,opt"` Text proto.Option[string] `protobuf:"bytes,7,opt"` - // optional bytes surprise_id = 8; + // optional bytes SurpriseId = 8; RandomType proto.Option[int32] `protobuf:"varint,9,opt"` _ [0]func() } diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D6.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D6.pb.go index 8c79afc7..6f6a5c99 100644 --- a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D6.pb.go +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D6.pb.go @@ -30,8 +30,8 @@ type OidbSvcTrpcTcp0X6D6Upload struct { type OidbSvcTrpcTcp0X6D6Download struct { GroupUin uint32 `protobuf:"varint,1,opt"` - AppID uint32 `protobuf:"varint,2,opt"` // 7 - BusID uint32 `protobuf:"varint,3,opt"` // 102 + AppId uint32 `protobuf:"varint,2,opt"` // 7 + BusId uint32 `protobuf:"varint,3,opt"` // 102 FileId string `protobuf:"bytes,4,opt"` _ [0]func() } diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.pb.go new file mode 100644 index 00000000..dd0e0344 --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.pb.go @@ -0,0 +1,68 @@ +// Code generated by protoc-gen-golite. DO NOT EDIT. +// source: pb/service/oidb/OidbSvcTrpcTcp0xE07_0.proto + +package oidb + +type OidbSvcTrpcTcp0XE07_0 struct { + Version uint32 `protobuf:"varint,1,opt"` + Client uint32 `protobuf:"varint,2,opt"` + Entrance uint32 `protobuf:"varint,3,opt"` + OcrReqBody *OcrReqBody `protobuf:"bytes,10,opt"` + _ [0]func() +} + +type OcrReqBody struct { + ImageUrl string `protobuf:"bytes,1,opt"` + LanguageType uint32 `protobuf:"varint,2,opt"` + Scene uint32 `protobuf:"varint,3,opt"` + OriginMd5 string `protobuf:"bytes,10,opt"` + AfterCompressMd5 string `protobuf:"bytes,11,opt"` + AfterCompressFileSize string `protobuf:"bytes,12,opt"` + AfterCompressWeight string `protobuf:"bytes,13,opt"` + AfterCompressHeight string `protobuf:"bytes,14,opt"` + IsCut bool `protobuf:"varint,15,opt"` + _ [0]func() +} + +type OidbSvcTrpcTcp0XE07_0_Response struct { + RetCode int32 `protobuf:"varint,1,opt"` + ErrMsg string `protobuf:"bytes,2,opt"` + Wording string `protobuf:"bytes,3,opt"` + OcrRspBody *OcrRspBody `protobuf:"bytes,10,opt"` + _ [0]func() +} + +type OcrRspBody struct { + TextDetections []*TextDetection `protobuf:"bytes,1,rep"` + Language string `protobuf:"bytes,2,opt"` + RequestId string `protobuf:"bytes,3,opt"` + OcrLanguageList []string `protobuf:"bytes,101,rep"` + DstTranslateLanguageList []string `protobuf:"bytes,102,rep"` + LanguageList []*Language `protobuf:"bytes,103,rep"` + AfterCompressWeight uint32 `protobuf:"varint,111,opt"` + AfterCompressHeight uint32 `protobuf:"varint,112,opt"` +} + +type TextDetection struct { + DetectedText string `protobuf:"bytes,1,opt"` + Confidence int32 `protobuf:"varint,2,opt"` + Polygon *Polygon `protobuf:"bytes,3,opt"` + AdvancedInfo string `protobuf:"bytes,4,opt"` + _ [0]func() +} + +type Polygon struct { + Coordinates []*Coordinate `protobuf:"bytes,1,rep"` +} + +type Coordinate struct { + X int32 `protobuf:"varint,1,opt"` + Y int32 `protobuf:"varint,2,opt"` + _ [0]func() +} + +type Language struct { + LanguageCode string `protobuf:"bytes,1,opt"` + LanguageDesc string `protobuf:"bytes,2,opt"` + _ [0]func() +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.proto b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.proto new file mode 100644 index 00000000..19bc3f17 --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.proto @@ -0,0 +1,61 @@ +syntax = "proto3"; + +option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; + +message OidbSvcTrpcTcp0xE07_0 { + uint32 Version = 1; + uint32 Client = 2; + uint32 Entrance = 3; + OcrReqBody OcrReqBody = 10; +} + +message OcrReqBody { + string ImageUrl = 1; + uint32 LanguageType = 2; + uint32 Scene = 3; + string OriginMd5 = 10; + string AfterCompressMd5 = 11; + string AfterCompressFileSize = 12; + string AfterCompressWeight = 13; + string AfterCompressHeight = 14; + bool IsCut = 15; +} + +message OidbSvcTrpcTcp0xE07_0_Response { + int32 RetCode = 1; + string ErrMsg = 2; + string Wording = 3; + OcrRspBody OcrRspBody = 10; +} + +message OcrRspBody { + repeated TextDetection TextDetections = 1; + string Language = 2; + string RequestId = 3; + repeated string OcrLanguageList = 101; + repeated string DstTranslateLanguageList = 102; + repeated Language LanguageList = 103; + uint32 AfterCompressWeight = 111; + uint32 AfterCompressHeight = 112; +} + +message TextDetection { + string DetectedText = 1; + int32 Confidence = 2; + Polygon Polygon = 3; + string AdvancedInfo = 4; +} + +message Polygon { + repeated Coordinate Coordinates = 1; +} + +message Coordinate { + int32 X = 1; + int32 Y = 2; +} + +message Language { + string LanguageCode = 1; + string LanguageDesc = 2; +} \ No newline at end of file diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE1_2.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE1_2.pb.go index c05ff208..aa40a99d 100644 --- a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE1_2.pb.go +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE1_2.pb.go @@ -31,7 +31,7 @@ type OidbSvcTrpcTcp0XFE1_2Response struct { } type OidbSvcTrpcTcp0XFE1_2ResponseBody struct { - // string UID = 1; + // string Uid = 1; Properties *OidbSvcTrpcTcp0XFE1_2ResponseProperty `protobuf:"bytes,2,opt"` Uin uint32 `protobuf:"varint,3,opt"` _ [0]func()