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

use uploaded image to ocr request.

This commit is contained in:
Mrs4s 2021-04-04 16:18:45 +08:00
parent 741de4e6e8
commit 0a81b76d23
7 changed files with 1685 additions and 66 deletions

View File

@ -79,10 +79,6 @@ func AppendUUID(dst []byte, uuid []byte) []byte {
return dst return dst
} }
func genUUID(uuid []byte, dst []byte) {
}
func ToIPV4Address(arr []byte) string { func ToIPV4Address(arr []byte) string {
ip := (net.IP)(arr) ip := (net.IP)(arr)
return ip.String() return ip.String()

View File

@ -1009,28 +1009,6 @@ func (c *QQClient) buildQuitGroupPacket(groupCode int64) (uint16, []byte) {
return seq, packet 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)
payload := c.packOIDBPackage(3591, 0, b)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xe07_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
// LightAppSvc.mini_app_info.GetAppInfoById // LightAppSvc.mini_app_info.GetAppInfoById
func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()

View File

@ -148,7 +148,6 @@ var decoders = map[string]func(*QQClient, *incomingPacketInfo, []byte) (interfac
"LongConn.OffPicUp": decodeOffPicUpResponse, "LongConn.OffPicUp": decodeOffPicUpResponse,
"ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket, "ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket,
"ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket, "ProfileService.Pb.ReqSystemMsgNew.Friend": decodeSystemMsgFriendPacket,
"OidbSvc.0xe07_0": decodeImageOcrResponse,
"OidbSvc.0xd79": decodeWordSegmentation, "OidbSvc.0xd79": decodeWordSegmentation,
"OidbSvc.0x990": decodeTranslateResponse, "OidbSvc.0x990": decodeTranslateResponse,
"SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse,

View File

@ -767,43 +767,6 @@ func decodeWordSegmentation(_ *QQClient, _ *incomingPacketInfo, payload []byte)
return nil, errors.New("no word received") return nil, errors.New("no word received")
} }
// OidbSvc.0xe07_0
func decodeImageOcrResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) {
pkg := oidb.OIDBSSOPkg{}
rsp := oidb.DE07RspBody{}
if err := proto.Unmarshal(payload, &pkg); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if err := proto.Unmarshal(pkg.Bodybuffer, &rsp); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if rsp.Wording != "" {
return nil, errors.New(rsp.Wording)
}
if rsp.RetCode != 0 {
return nil, errors.Errorf("server error, code: %v msg: %v", rsp.RetCode, rsp.ErrMsg)
}
var texts = make([]*TextDetection, 0, len(rsp.OcrRspBody.TextDetections))
for _, text := range rsp.OcrRspBody.TextDetections {
var 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
}
// LightAppSvc.mini_app_info.GetAppInfoById // LightAppSvc.mini_app_info.GetAppInfoById
func decodeAppInfoResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { func decodeAppInfoResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) {
pkg := qweb.QWebRsp{} pkg := qweb.QWebRsp{}

View File

@ -4,8 +4,11 @@ import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/Mrs4s/MiraiGo/client/pb/highway"
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
"image" "image"
"io" "io"
"math/rand"
"os" "os"
"strings" "strings"
@ -20,6 +23,7 @@ import (
func init() { func init() {
decoders["ImgStore.GroupPicUp"] = decodeGroupImageStoreResponse decoders["ImgStore.GroupPicUp"] = decodeGroupImageStoreResponse
decoders["OidbSvc.0xe07_0"] = decodeImageOcrResponse
} }
func (c *QQClient) UploadGroupImage(groupCode int64, img io.ReadSeeker) (*message.GroupImageElement, error) { func (c *QQClient) UploadGroupImage(groupCode int64, img io.ReadSeeker) (*message.GroupImageElement, error) {
@ -128,15 +132,28 @@ func (c *QQClient) uploadPrivateImage(target int64, img io.ReadSeeker, count int
} }
func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) { func (c *QQClient) ImageOcr(img interface{}) (*OcrResponse, error) {
url := ""
switch e := img.(type) { switch e := img.(type) {
case *message.GroupImageElement: case *message.GroupImageElement:
rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(e.Url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height)) url = e.Url
if b, err := utils.HttpGetBytes(e.Url, ""); err == nil {
if url, err = c.uploadOcrImage(bytes.NewReader(b)); err != nil {
url = e.Url
}
}
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 {
return nil, err return nil, err
} }
return rsp.(*OcrResponse), nil return rsp.(*OcrResponse), nil
case *message.ImageElement: case *message.ImageElement:
rsp, err := c.sendAndWait(c.buildImageOcrRequestPacket(e.Url, strings.ToUpper(hex.EncodeToString(e.Md5)), e.Size, e.Width, e.Height)) url = e.Url
if b, err := utils.HttpGetBytes(e.Url, ""); err == nil {
if url, err = c.uploadOcrImage(bytes.NewReader(b)); err != nil {
url = e.Url
}
}
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 {
return nil, err return nil, err
} }
@ -214,6 +231,46 @@ func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 []byte, size
return seq, packet return seq, packet
} }
func (c *QQClient) uploadOcrImage(img io.ReadSeeker) (string, error) {
r := make([]byte, 16)
rand.Read(r)
ext, _ := proto.Marshal(&highway.CommFileExtReq{
ActionType: proto.Uint32(0),
Uuid: binary.GenUUID(r),
})
rsp, err := c.highwayUploadByBDH(img, 76, c.highwaySession.SigSession, ext, false)
if err != nil {
return "", errors.Wrap(err, "upload ocr image error")
}
rspExt := highway.CommFileExtRsp{}
if err = proto.Unmarshal(rsp, &rspExt); err != nil {
return "", errors.Wrap(err, "error unmarshal highway resp")
}
return string(rspExt.GetDownloadUrl()), nil
}
// 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)
payload := c.packOIDBPackage(3591, 0, b)
packet := packets.BuildUniPacket(c.Uin, seq, "OidbSvc.0xe07_0", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}
// ImgStore.GroupPicUp // ImgStore.GroupPicUp
func decodeGroupImageStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { func decodeGroupImageStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) {
pkt := pb.D388RespBody{} pkt := pb.D388RespBody{}
@ -241,3 +298,40 @@ func decodeGroupImageStoreResponse(_ *QQClient, _ *incomingPacketInfo, payload [
UploadPort: rsp.Uint32UpPort, UploadPort: rsp.Uint32UpPort,
}, nil }, nil
} }
// OidbSvc.0xe07_0
func decodeImageOcrResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) {
pkg := oidb.OIDBSSOPkg{}
rsp := oidb.DE07RspBody{}
if err := proto.Unmarshal(payload, &pkg); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if err := proto.Unmarshal(pkg.Bodybuffer, &rsp); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if rsp.Wording != "" {
return nil, errors.New(rsp.Wording)
}
if rsp.RetCode != 0 {
return nil, errors.Errorf("server error, code: %v msg: %v", rsp.RetCode, rsp.ErrMsg)
}
var texts = make([]*TextDetection, 0, len(rsp.OcrRspBody.TextDetections))
for _, text := range rsp.OcrRspBody.TextDetections {
var 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
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
syntax = "proto2";
option go_package = ".;highway";
message CommFileExtReq {
optional uint32 actionType = 1;
optional bytes uuid = 2;
}
message CommFileExtRsp {
optional int32 retcode = 1;
optional bytes downloadUrl = 2;
}
message PicInfo {
optional uint32 idx = 1;
optional uint32 size = 2;
optional bytes binMd5 = 3;
optional uint32 type = 4;
}
message QQVoiceExtReq {
optional bytes qid = 1;
optional uint32 fmt = 2;
optional uint32 rate = 3;
optional uint32 bits = 4;
optional uint32 channel = 5;
optional uint32 pinyin = 6;
}
message QQVoiceExtRsp {
optional bytes qid = 1;
optional int32 retcode = 2;
repeated QQVoiceResult result = 3;
}
message QQVoiceResult {
optional bytes text = 1;
optional bytes pinyin = 2;
optional uint32 source = 3;
}
message ShortVideoReqExtInfo {
optional uint32 cmd = 1;
optional uint64 sessionId = 2;
optional PicInfo thumbinfo = 3;
optional VideoInfo videoinfo = 4;
optional ShortVideoSureReqInfo shortvideoSureReq = 5;
optional bool isMergeCmdBeforeData = 6;
}
message ShortVideoRspExtInfo {
optional uint32 cmd = 1;
optional uint64 sessionId = 2;
optional int32 retcode = 3;
optional bytes errinfo = 4;
optional PicInfo thumbinfo = 5;
optional VideoInfo videoinfo = 6;
optional ShortVideoSureRspInfo shortvideoSureRsp = 7;
optional uint32 retryFlag = 8;
}
message ShortVideoSureReqInfo {
optional uint64 fromuin = 1;
optional uint32 chatType = 2;
optional uint64 touin = 3;
optional uint64 groupCode = 4;
optional uint32 clientType = 5;
optional PicInfo thumbinfo = 6;
repeated VideoInfo mergeVideoinfo = 7;
repeated VideoInfo dropVideoinfo = 8;
optional uint32 businessType = 9;
optional uint32 subBusinessType = 10;
}
message ShortVideoSureRspInfo {
optional bytes fileid = 1;
optional bytes ukey = 2;
optional VideoInfo videoinfo = 3;
optional uint32 mergeCost = 4;
}
message StoryVideoExtReq {
}
message StoryVideoExtRsp {
optional int32 retcode = 1;
optional bytes msg = 2;
optional bytes cdnUrl = 3;
optional bytes fileKey = 4;
optional bytes fileId = 5;
}
message UploadPicExtInfo {
optional bytes fileResid = 1;
optional bytes downloadUrl = 2;
optional bytes thumbDownloadUrl = 3;
}
message VideoInfo {
optional uint32 idx = 1;
optional uint32 size = 2;
optional bytes binMd5 = 3;
optional uint32 format = 4;
optional uint32 resLen = 5;
optional uint32 resWidth = 6;
optional uint32 time = 7;
optional uint64 starttime = 8;
optional uint32 isAudio = 9;
}