package aiService import ( "91porn-server/common" "91porn-server/common/httputil" "91porn-server/common/log" "91porn-server/common/redis" "encoding/json" "errors" "reflect" "strings" "time" "github.com/fatih/structs" "go.mongodb.org/mongo-driver/bson/primitive" ) type AiService struct { c *Conf } type Conf struct { AppId int Url string Redis *redis.Client } type Option func(c *Conf) func NewAiService(opts ...Option) *AiService { c := &Conf{} for _, opt := range opts { opt(c) } return &AiService{ c: c, } } func Redis(r *redis.Client) Option { return func(c *Conf) { c.Redis = r } } func AppId(appId int) Option { return func(c *Conf) { c.AppId = appId } } func Url(url string) Option { return func(c *Conf) { c.Url = url } } type msg struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } func (m *AiService) getParams(p interface{}) (params map[string]interface{}) { req := structs.New(p) fields := req.Fields() params = make(map[string]interface{}) for _, field := range fields { jsonTag := field.Tag("json") tagList := strings.Split(jsonTag, ",") key := field.Name() omitempty := "" if len(tagList) > 0 { key = tagList[0] } if len(tagList) > 1 { omitempty = tagList[1] } kind := reflect.TypeOf(field.Value()).Kind() // 如果是0值忽略或者空指针,不需要传 if field.IsZero() && (kind == reflect.Ptr || omitempty == "omitempty") { continue } if kind == reflect.Ptr { // 通过指针取值 params[key] = reflect.ValueOf(field.Value()).Elem().Interface() } else { params[key] = field.Value() } } params["appId"] = m.c.AppId return } func (s *AiService) getTemplateList(p *TemplateListReq) (result TemplateListResp, err error) { var retMsg msg path := "/api/ai/template/all" params := s.getParams(p) code, err := httputil.DefaultClientGetWithResp(&retMsg, common.BindUrl(s.c.Url, path), nil, params) if err != nil { log.Error("AiService GetTemplateList fail", log.Any("params", params), log.E(err)) err = errors.New("AiService GetTemplateList fail") return } if code != 200 { log.Error("AiService GetTemplateList fail", log.Any("params", params), log.Any("code", code)) err = errors.New("AiService GetTemplateList fail") return } if retMsg.Code != 200 { log.Error("AiService GetTemplateList fail", log.Any("params", params), log.Any("retMsg", retMsg)) err = errors.New("AiService GetTemplateList fail") return } b, err := json.Marshal(retMsg.Data) if err != nil { log.Error("AiService GetTemplateList json.Marshal fail", log.Any("params", params), log.E(err)) err = errors.New("AiService GetTemplateList json.Marshal fail") return } if err = json.Unmarshal(b, &result); err != nil { log.Error("AiService GetTemplateList json.Unmarshal fail", log.Any("params", params), log.Any("data", string(b)), log.E(err)) err = errors.New("AiService GetTemplateList json.Unmarshal fail") return } return } type TemplateDetailReq struct { Ids []primitive.ObjectID `json:"ids" binding:"required"` } func (s *AiService) getTemplateDetail(p *TemplateDetailReq) (result TemplateDetailResp, err error) { var retMsg msg path := "/api/ai/template/detail" params := s.getParams(p) code, err := httputil.DefaultClientPostJsonWithResp(&retMsg, common.BindUrl(s.c.Url, path), nil, params) if err != nil { log.Error("AiService GetTemplateDetail fail", log.Any("params", params), log.E(err)) err = errors.New("AiService GetTemplateDetail fail") return } if code != 200 { log.Error("AiService GetTemplateDetail fail", log.Any("params", params), log.Any("code", code)) err = errors.New("AiService GetTemplateDetail fail") return } if retMsg.Code != 200 { log.Error("AiService GetTemplateDetail fail", log.Any("params", params), log.Any("retMsg", retMsg)) err = errors.New("AiService GetTemplateDetail fail") return } b, err := json.Marshal(retMsg.Data) if err != nil { log.Error("AiService GetTemplateDetail json.Marshal fail", log.Any("params", params), log.E(err)) err = errors.New("AiService GetTemplateDetail json.Marshal fail") return } if err = json.Unmarshal(b, &result); err != nil { log.Error("AiService GetTemplateDetail json.Unmarshal fail", log.Any("params", params), log.Any("data", string(b)), log.E(err)) err = errors.New("AiService GetTemplateDetail json.Unmarshal fail") return } return } func (s *AiService) Sync() (err error) { if s.c.Redis == nil { return errors.New("redis is nil") } resp, err := s.getTemplateList(&TemplateListReq{}) if err != nil { log.Error("AI Template sync fail", log.E(err)) return } for _, template := range resp.TemplateList { b, err := json.Marshal(template) if err != nil { continue } // 将模版数据写入redis s.c.Redis.Set(AiTemplateKey(template.ID), string(b), time.Hour*24*7) } var imageCategoryList []Category var videoCategoryList []Category for _, v := range resp.CategoryList { if v.Type == 0 { imageCategoryList = append(imageCategoryList, v) } else { videoCategoryList = append(videoCategoryList, v) } } // 将数据写入写入redis b0, err := json.Marshal(imageCategoryList) if err != nil { log.Error("AI Template json.Marshal(imageCategoryList) fail", log.E(err)) return } b1, err := json.Marshal(videoCategoryList) if err != nil { log.Error("AI Template json.Marshal(videoCategoryList) fail", log.E(err)) return } err = s.c.Redis.Set(AiCategoryKey(0), string(b0), time.Hour*24*7) if err != nil { log.Error("AI Template Redis.Set(AiCategoryKey(0) fail", log.E(err)) return } err = s.c.Redis.Set(AiCategoryKey(1), string(b1), time.Hour*24*7) if err != nil { log.Error("AI Template Redis.Set(AiCategoryKey(1) fail", log.E(err)) return } return nil } func (s *AiService) GetTemplateList(types int, categoryId string) (categoryList []*Category, queryCategoryId string, templateList []*Template, err error) { if s.c.Redis == nil { err = errors.New("redis nil") return } // 获取分类列表 val, err := s.c.Redis.Get(AiCategoryKey(types)) if err != nil { return } if val == nil { return } err = json.Unmarshal([]byte(*val), &categoryList) if err != nil { return } if len(categoryList) == 0 { return } if categoryId == "" { queryCategoryId = categoryList[0].ID.Hex() } else { queryCategoryId = categoryId } templateIds := []primitive.ObjectID{} for _, v := range categoryList { if v.ID.Hex() == queryCategoryId { templateIds = v.TemplateIds break } } keys := []string{} for _, templateId := range templateIds { keys = append(keys, AiTemplateKey(templateId)) } if len(keys) == 0 { return } // 通过id查找这个模版 res, err := s.c.Redis.MGet(keys...) if err != nil { return } for _, v := range res { templateVal, ok := v.(string) if !ok || templateVal == "" { continue } item := Template{} err = json.Unmarshal([]byte(templateVal), &item) if err != nil { continue } if item.ModuleType != types { continue } templateList = append(templateList, &item) } return categoryList, queryCategoryId, templateList, nil } func (s *AiService) GetTemplate(id primitive.ObjectID) (template Template, err error) { if id.IsZero() { return } if s.c.Redis == nil { err = errors.New("redis nil") return } // 从缓存中获取数据 val, err := s.c.Redis.Get(AiTemplateKey(id)) if err != nil { return } if val != nil && *val != "" { err = json.Unmarshal([]byte(*val), &template) if err == nil { return template, nil } } // 如果获取不到,尝试从ai服务获取 res, err := s.getTemplateDetail(&TemplateDetailReq{ Ids: []primitive.ObjectID{id}, }) if err != nil { return } if len(res.List) == 0 { return } template = res.List[0] common.Go(func() { b, err := json.Marshal(template) if err != nil { return } // 将模版数据写入redis s.c.Redis.Set(AiTemplateKey(template.ID), string(b), time.Hour*48) }) return template, nil } func (s *AiService) GetTemplateByIds(ids []primitive.ObjectID) (templateList []Template, err error) { if len(ids) == 0 { return } if s.c.Redis == nil { err = errors.New("redis nil") return } keys := []string{} for _, id := range ids { keys = append(keys, AiTemplateKey(id)) } // 从缓存中获取数据 list, err := s.c.Redis.MGet(keys...) if err != nil { return } noFoundKey := []int{} for k, v := range list { if v == nil { noFoundKey = append(noFoundKey, k) continue } val, ok := v.(string) if !ok || val == "" { noFoundKey = append(noFoundKey, k) continue } item := Template{} err = json.Unmarshal([]byte(val), &item) if err != nil { noFoundKey = append(noFoundKey, k) continue } templateList = append(templateList, item) } noFoundIds := []primitive.ObjectID{} for _, k := range noFoundKey { noFoundIds = append(noFoundIds, ids[k]) } if len(noFoundIds) == 0 { return } // 如果获取不到,尝试从ai服务获取 res, err := s.getTemplateDetail(&TemplateDetailReq{ Ids: noFoundIds, }) if err != nil { return } if len(res.List) == 0 { return } templateList = append(templateList, res.List...) common.Go(func() { // 将查到的写入redis for _, template := range res.List { b, err := json.Marshal(template) if err != nil { return } // 将模版数据写入redis s.c.Redis.Set(AiTemplateKey(template.ID), string(b), time.Hour*48) } }) return templateList, nil }