package repositories import ( "context" "encoding/json" "errors" "fmt" "fusenapi/constants" "fusenapi/model/gmodel" "fusenapi/utils/auth" "fusenapi/utils/curl" "fusenapi/utils/file" "fusenapi/utils/hash" "fusenapi/utils/s3url_to_s3id" "strconv" "time" "github.com/aws/aws-sdk-go/aws/session" "github.com/zeromicro/go-zero/core/logc" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" ) var globalBLMServiceIndex int func NewImageHandle(gormDB *gorm.DB, bLMServiceUrls []string, awsSession *session.Session) ImageHandle { return &defaultImageHandle{ MysqlConn: gormDB, BLMServiceUrls: bLMServiceUrls, AwsSession: awsSession, } } type ( defaultImageHandle struct { MysqlConn *gorm.DB BLMServiceUrls []string AwsSession *session.Session } ImageHandle = interface { // logo信息 LogoInfoSet(ctx context.Context, in *LogoInfoSetReq) (*LogoInfoSetRes, error) // logo合图 LogoCombine(ctx context.Context, in *LogoCombineReq) (*LogoCombineRes, error) // logo裁剪 LogoStandard(ctx context.Context, in *LogoStandardReq) (*LogoStandardRes, error) } ) /* 获取logo最新信息 */ type ( LogoInfoReq struct { UserId int64 `json:"user_id"` GuestId int64 `json:"guest_id"` } LogoInfoRes struct { Metadata *string `json:"metadata"` LogoUrl *string `json:"logo_url"` UserInfoMetadata *string `json:"user_info_metadata"` } ) /* 获取logo最新信息 */ /* logo信息 */ type ( LogoInfoSetReq struct { LogoUrl string `json:"logo_url"` Version string `json:"version"` Debug *auth.Debug `json:"debug"` } LogoInfoSetRes struct { Res string `json:"res"` } ) func (l *defaultImageHandle) LogoInfoSet(ctx context.Context, in *LogoInfoSetReq) (*LogoInfoSetRes, error) { var bLMServicePort = l.BLMServiceUrls[globalBLMServiceIndex] if len(l.BLMServiceUrls) == (globalBLMServiceIndex + 1) { globalBLMServiceIndex = 0 } else { globalBLMServiceIndex = globalBLMServiceIndex + 1 } var resultBLM constants.BLMServiceUrlResult postMap := make(map[string]string, 3) postMap["logo_url"] = in.LogoUrl postMap["version"] = in.Version if in.Debug != nil && in.Debug.IsAllTemplateTag == 1 { postMap["is_all_template"] = "1" } else { postMap["is_all_template"] = "0" } // logc.Infof(ctx, "算法请求--LOGO基础信息--开始时间:%v", time.Now().UTC()) err := curl.NewClient(ctx, &curl.Config{ BaseUrl: bLMServicePort, Url: constants.BLMServiceUrlLogoFeatureExtraction, }).PostJson(postMap, &resultBLM) // logc.Infof(ctx, "算法请求--LOGO基础信息--结束时间:%v", time.Now().UTC()) if err != nil { logx.Error(err) return nil, err } if resultBLM.Code != "200" { err = errors.New(resultBLM.Msg) logx.Error(err) return nil, err } return &LogoInfoSetRes{ Res: resultBLM.Data.(string), }, nil } /* logo信息 */ /* logo合图 */ type ( LogoCombineReq struct { UserId int64 `json:"user_id"` GuestId int64 `json:"guest_id"` ProductTemplateV2Info *gmodel.FsProductTemplateV2 `json:"product_template_v2_info"` ProductTemplateTagGroups interface{} `json:"product_template_tag_groups"` TemplateTag string `json:"template_tag"` LogoUrl string `json:"logo_url"` // 合图参数 Resolution string `json:"resolution"` // 合图参数 TemplateTagColor TemplateTagColor `json:"template_tag_color"` // 合图颜色 Debug *auth.Debug `json:"debug"` Website *string `json:"website"` // 合图参数 Slogan *string `json:"slogan"` // 合图参数 Address *string `json:"address"` // 合图参数 Phone *string `json:"phone"` // 合图参数 Qrcode *string `json:"qrcode"` // 合图参数 } LogoCombineRes struct { ResourceId string `json:"resource_id"` ResourceUrl *string `json:"resource_url"` Metadata *string `json:"metadata"` DebugData *auth.DebugData `json:"debug_data"` } ) type TemplateTagColor struct { Color [][]string `json:"color"` Index int `json:"index"` } func (l *defaultImageHandle) LogoCombine(ctx context.Context, in *LogoCombineReq) (*LogoCombineRes, error) { var resp = &LogoCombineRes{} logoResourceId := s3url_to_s3id.GetS3ResourceIdFormUrl(in.LogoUrl) if logoResourceId == "" { return nil, errors.New("invalid logo url") } userMaterialModel := gmodel.NewFsUserMaterialModel(l.MysqlConn.Debug()) resLogoInfo, err := userMaterialModel.FindOneByLogoResourceId(ctx, logoResourceId) if err != nil { logx.Error(err) return nil, fmt.Errorf("logo find fial logoResourceId: %v, err: %v", logoResourceId, err) } // 根据hash 查询数据资源 var hashKeyData = *in hashKeyData.GuestId = 0 hashKeyData.UserId = 0 hashKeyData.LogoUrl = in.LogoUrl var hashKeyDataMap map[string]interface{} hashKeyDataB, _ := json.Marshal(hashKeyData) json.Unmarshal(hashKeyDataB, &hashKeyDataMap) var resourceId string = hash.JsonHashKey(hashKeyDataMap) resourceModel := gmodel.NewFsResourceModel(l.MysqlConn) resourceInfo, err := resourceModel.FindOneById(ctx, resourceId) if err == nil && resourceInfo.ResourceId != "" { if in.Debug == nil || (in.Debug != nil && in.Debug.IsCache == 1) { return &LogoCombineRes{ ResourceId: resourceId, ResourceUrl: resourceInfo.ResourceUrl, }, nil } } else { if err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { logx.Error(err) return nil, err } } } var groupOptions map[string]interface{} var materialList []interface{} if in.ProductTemplateV2Info.TemplateInfo != nil { var templateInfo map[string]interface{} err = json.Unmarshal([]byte(*in.ProductTemplateV2Info.TemplateInfo), &templateInfo) if err != nil { logx.Error(err) return nil, err } mapMaterialList, existMaterialList := templateInfo["materialList"] if !existMaterialList { err = errors.New("materialList is null") logc.Errorf(ctx, "materialList err:%v", err) return nil, err } materialList = mapMaterialList.([]interface{}) mapGroupOptions, existGroupOptions := templateInfo["groupOptions"] if !existGroupOptions { err = errors.New("groupOptions is null") logc.Errorf(ctx, "groupOptions err:%v", err) return nil, err } groupOptions = mapGroupOptions.(map[string]interface{}) } var moduleDataMap = make(map[string]interface{}, 4) moduleDataMap["id"] = in.ProductTemplateV2Info.Id moduleDataMap["material"] = in.ProductTemplateV2Info.MaterialImg moduleDataMap["groupOptions"] = groupOptions moduleDataMap["materialList"] = materialList var combineParam = make(map[string]interface{}, 8) json.Unmarshal(*resLogoInfo.Metadata, &combineParam) combineParam["resolution"] = in.Resolution combineParam["template_tagid"] = in.TemplateTag if in.Website != nil { combineParam["website"] = *in.Website } if in.Slogan != nil { combineParam["slogan"] = *in.Slogan } if in.Phone != nil { combineParam["phone"] = *in.Phone } if in.Address != nil { combineParam["address"] = *in.Address } if in.Qrcode != nil { combineParam["qrcode"] = *in.Qrcode } combineParam["template_tag_selected"] = map[string]interface{}{ "template_tag": in.TemplateTag, "color": in.TemplateTagColor.Color, "index": in.TemplateTagColor.Index, } var postMap = make(map[string]interface{}, 3) postMap["module_data"] = moduleDataMap postMap["tag_data"] = in.ProductTemplateTagGroups postMap["param_data"] = combineParam var bLMServicePort = l.BLMServiceUrls[globalBLMServiceIndex] if len(l.BLMServiceUrls) == (globalBLMServiceIndex + 1) { globalBLMServiceIndex = 0 } else { globalBLMServiceIndex = globalBLMServiceIndex + 1 } // logc.Infof(ctx, "合图--算法请求--合图--开始时间:%v", time.Now().UTC()) // var startTimeLogoCombine = time.Now().UnixMilli() //合图--处理--开始时间 // postMapB, _ := json.Marshal(postMap) // logc.Info(ctx, "合图参数--%v", string(postMapB)) var resultBLM constants.BLMServiceUrlResult err = curl.NewClient(ctx, &curl.Config{ BaseUrl: bLMServicePort, Url: constants.BLMServiceUrlLogoCombine, RequireTimeout: time.Second * 15, }).PostJson(postMap, &resultBLM) //logc.Infof(ctx, "合图--算法请求--合图--结束时间:%v", time.Now().UTC()) // endTimeLogoCombine := time.Now().UnixMilli() //合图--处理--开始时间 // diffTimeLogoCombine := endTimeLogoCombine - startTimeLogoCombine //合图--处理--中间差 // logc.Infof(ctx, "合图--算法请求--合图--业务耗时:%d", diffTimeLogoCombine) if err != nil { logx.Error(err) return nil, err } if resultBLM.Code != "200" { err = errors.New(resultBLM.Msg) logx.Error(err) return nil, err } var resultStr string = resultBLM.Data.(string) var resultData map[string]interface{} err = json.Unmarshal([]byte(resultStr), &resultData) if err != nil || resultData == nil { logx.Error(err) return nil, err } var fileBase = resultData["result"].(string) var spendTime = resultData["spend_time"].(string) spendTimeInt, _ := strconv.Atoi(spendTime) diffTimeLogoCombine := int64(spendTimeInt) // logc.Infof(ctx, "合图--算法请求--合图--业务耗时(自身):%d", diffTimeLogoCombine) // 上传文件 var upload = file.Upload{ Ctx: ctx, MysqlConn: l.MysqlConn, AwsSession: l.AwsSession, } // logc.Infof(ctx, "合图--上传文件--开始时间:%v", time.Now().UTC()) var startTimeUploadFile = time.Now().UnixMilli() //合图--上传--开始时间 uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{ Source: "combine-image", FileHash: resourceId, FileData: fileBase, UploadBucket: 1, ApiType: 2, UserId: in.UserId, GuestId: in.GuestId, ResourceId: resourceId, Refresh: 1, }) // logc.Infof(ctx, "合图--上传文件--结束时间:%v", time.Now().UTC()) endTimeUploadFile := time.Now().UnixMilli() //合图--处理--开始时间 diffTimeUploadFile := endTimeUploadFile - startTimeUploadFile //合图--处理--中间差 // logc.Infof(ctx, "合图--上传文件--业务耗时:%d", diffTimeUploadFile) if err != nil { logx.Error(err) return nil, err } resp.ResourceId = uploadRes.ResourceId resp.ResourceUrl = &uploadRes.ResourceUrl if in.Debug != nil { resp.DebugData = &auth.DebugData{ DiffTimeLogoCombine: diffTimeLogoCombine, DiffTimeUploadFile: diffTimeUploadFile, } } return resp, nil } /* logo合图 */ type ( LogoStandardReq struct { IsRemoveBg string `json:"is_remove_bg"` LogoFile string `json:"logo_file"` Width string `json:"width"` Height string `json:"height"` Proportion string `json:"proportion"` } LogoStandardRes struct { ResourceId string `json:"resource_id"` ResourceUrl string `json:"resource_url"` IsmaxProportion bool `json:"ismax_proportion"` ImgColor []string `json:"img_color"` } LogoStandardMetaData struct { Param LogoStandardReq `json:"param"` Result LogoStandardRes `json:"result"` } ) /* 图片裁剪 */ func (l *defaultImageHandle) LogoStandard(ctx context.Context, in *LogoStandardReq) (*LogoStandardRes, error) { var ismaxProportion bool var imgColor []string var logoStandardMetaData LogoStandardMetaData var hashKeyDataMap map[string]interface{} hashKeyDataB, _ := json.Marshal(in) json.Unmarshal(hashKeyDataB, &hashKeyDataMap) var resourceId string = hash.JsonHashKey(hashKeyDataMap) resourceModel := gmodel.NewFsResourceModel(l.MysqlConn) resourceInfo, err := resourceModel.FindOneById(ctx, resourceId) if err == nil && resourceInfo.ResourceId != "" { if resourceInfo.Metadata != nil { json.Unmarshal([]byte(*resourceInfo.Metadata), &logoStandardMetaData) } // 取出参数 ismaxProportion = logoStandardMetaData.Result.IsmaxProportion imgColor = logoStandardMetaData.Result.ImgColor return &LogoStandardRes{ ResourceId: resourceInfo.ResourceId, ResourceUrl: *resourceInfo.ResourceUrl, IsmaxProportion: ismaxProportion, ImgColor: imgColor, }, nil } else { if err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { logx.Error(err) return nil, err } } } var resultBLM constants.BLMServiceUrlResult var postMap = make(map[string]interface{}, 5) postMap["is_remove_bg"] = in.IsRemoveBg postMap["logo_file"] = in.LogoFile postMap["width"] = in.Width postMap["height"] = in.Height postMap["proportion"] = in.Proportion var bLMServicePort = l.BLMServiceUrls[globalBLMServiceIndex] if len(l.BLMServiceUrls) == (globalBLMServiceIndex + 1) { globalBLMServiceIndex = 0 } else { globalBLMServiceIndex = globalBLMServiceIndex + 1 } // logc.Infof(ctx, "算法请求--去背景--开始时间:%v", time.Now().UTC()) err = curl.NewClient(ctx, &curl.Config{ BaseUrl: bLMServicePort, Url: constants.BLMServiceUrlLogoRemovebg, }).PostJson(postMap, &resultBLM) // logc.Infof(ctx, "算法请求--去背景--结束时间:%v", time.Now().UTC()) if err != nil { logx.Error(err) return nil, err } if resultBLM.Code != "200" { err = errors.New(resultBLM.Msg) logx.Error(err) return nil, err } var resultStr string = resultBLM.Data.(string) var resultData map[string]interface{} err = json.Unmarshal([]byte(resultStr), &resultData) if err != nil || resultData == nil { logx.Error(err) return nil, err } var fileBase = resultData["nobg_url"].(string) ismaxProportion = resultData["ismax_proportion"].(bool) for _, v := range resultData["img_color"].([]interface{}) { imgColor = append(imgColor, v.(string)) } var logoStandardRes LogoStandardRes logoStandardRes.IsmaxProportion = ismaxProportion logoStandardRes.ImgColor = imgColor logoStandardMetaData.Param = *in logoStandardMetaData.Result = logoStandardRes metadataB, err := json.Marshal(logoStandardMetaData) if err != nil { logx.Error(err) return nil, err } var metadata = string(metadataB) // 上传文件 var upload = file.Upload{ Ctx: ctx, MysqlConn: l.MysqlConn, AwsSession: l.AwsSession, } uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{ Source: "combine-removebg", FileHash: resourceId, FileData: fileBase, UploadBucket: 1, ApiType: 2, Metadata: metadata, }) if err != nil { logx.Error(err) return nil, err } return &LogoStandardRes{ ResourceId: uploadRes.ResourceId, ResourceUrl: uploadRes.ResourceUrl, IsmaxProportion: ismaxProportion, ImgColor: imgColor, }, nil } /* 图片裁剪 */