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:
parent
741de4e6e8
commit
0a81b76d23
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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,
|
||||||
|
@ -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{}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
1479
client/pb/highway/bdhExtInfo.pb.go
Normal file
1479
client/pb/highway/bdhExtInfo.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
110
client/pb/highway/bdhExtInfo.proto
Normal file
110
client/pb/highway/bdhExtInfo.proto
Normal 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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user