diff --git a/client/builders.go b/client/builders.go index 2a864f51..7bad83b0 100644 --- a/client/builders.go +++ b/client/builders.go @@ -1146,6 +1146,32 @@ func (c *QQClient) buildGroupFileDownloadReqPacket(groupCode int64, fileId strin return seq, packet } +// OidbSvc.0xe07_0 +func (c *QQClient) buildImageOcrRequestPacket(url, md5 string, size, weight, height int32) (uint16, []byte) { + seq := c.nextSeq() + body := &oidb.DE07ReqBody{ + Version: 1, + Entrance: 3, + OcrReqBody: &oidb.OCRReqBody{ + ImageUrl: url, + OriginMd5: md5, + AfterCompressMd5: md5, + AfterCompressFileSize: size, + AfterCompressWeight: weight, + AfterCompressHeight: height, + IsCut: false, + }, + } + b, _ := proto.Marshal(body) + req := &oidb.OIDBSSOPkg{ + Command: 3591, + Bodybuffer: b, + } + payload, _ := proto.Marshal(req) + packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xe07_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) + return seq, packet +} + // PttCenterSvr.ShortVideoDownReq func (c *QQClient) buildPttShortVideoDownReqPacket(uuid, md5 []byte) (uint16, []byte) { seq := c.nextSeq() diff --git a/client/client.go b/client/client.go index cc566063..0ed9ce9c 100644 --- a/client/client.go +++ b/client/client.go @@ -142,6 +142,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { "MultiMsg.ApplyDown": decodeMultiApplyDownResponse, // 长消息/合并转发请求下载包 "OidbSvc.0x6d6_2": decodeOIDB6d6Response, // 群文件操作包 "OidbSvc.0x88d_0": decodeGroupInfoResponse, // 获取群资料包 + "OidbSvc.0xe07_0": decodeImageOcrResponse, // 图片OCR请求包 "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, // 获取用户卡片资料包 "PttCenterSvr.ShortVideoDownReq": decodePttShortVideoDownResponse, // 短视频下载请求包 "LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse, // 获取小程序资料包 @@ -624,6 +625,24 @@ func (c *QQClient) uploadPrivateImage(target int64, img []byte, count int) (*mes return e, nil } +func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) { + switch e := img.(type) { + case *message.GroupImageElement: + rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(e.Url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height)) + if err != nil { + return nil, err + } + return rsp.(*OcrResponse), nil + case *message.ImageElement: + rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(e.Url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height)) + if err != nil { + return nil, err + } + return rsp.(*OcrResponse), nil + } + return nil, errors.New("image error") +} + func (c *QQClient) UploadGroupPtt(groupCode int64, voice []byte) (*message.GroupVoiceElement, error) { h := md5.Sum(voice) seq, pkt := c.buildGroupPttStorePacket(groupCode, h[:], int32(len(voice)), 0, int32(len(voice))) diff --git a/client/decoders.go b/client/decoders.go index 4149e688..3458c177 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -1009,6 +1009,39 @@ func decodeOIDB6d6Response(c *QQClient, _ uint16, payload []byte) (interface{}, return fmt.Sprintf("http://%s/ftn_handler/%s/", ip, url), nil } +func decodeImageOcrResponse(_ *QQClient, _ uint16, payload []byte) (interface{}, error) { + pkg := oidb.OIDBSSOPkg{} + rsp := oidb.DE07RspBody{} + if err := proto.Unmarshal(payload, &pkg); err != nil { + return nil, err + } + if err := proto.Unmarshal(pkg.Bodybuffer, &rsp); err != nil { + return nil, err + } + if rsp.Wording != "" { + return nil, errors.New(rsp.Wording) + } + var texts []*TextDetection + for _, text := range rsp.OcrRspBody.TextDetections { + var points []*Coordinate + 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 +} + func decodePttShortVideoDownResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) { rsp := pttcenter.ShortVideoRspBody{} if err := proto.Unmarshal(payload, &rsp); err != nil { diff --git a/client/entities.go b/client/entities.go index 7e137f32..6dcc4142 100644 --- a/client/entities.go +++ b/client/entities.go @@ -183,6 +183,22 @@ type ( Friend *FriendInfo } + 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"` + } + groupMemberListResponse struct { NextUin int64 list []*GroupMemberInfo