diff --git a/core/models/assets.go b/core/models/assets.go index 2f03c6666..1dadd413d 100644 --- a/core/models/assets.go +++ b/core/models/assets.go @@ -408,9 +408,11 @@ func NewOrgAssets(ctx context.Context, rt *runtime.Runtime, orgID OrgID, prev *O if prev == nil || refresh&RefreshContext > 0 { context := oa.org.ConfigValue("description", "") + hasVtexAds := oa.org.o.Config.Get("vtex_ads", false) c := &OrgContext{} c.c.OrgContext = context c.c.ProjectUUID = oa.org.ProjectUUID() + c.c.HasVtexAds = hasVtexAds.(bool) oa.orgContexts = append(oa.orgContexts, c) if err != nil { return nil, errors.Wrapf(err, "error loading context for org %d", orgID) diff --git a/core/models/org_context.go b/core/models/org_context.go index 07862d734..43b1f903c 100644 --- a/core/models/org_context.go +++ b/core/models/org_context.go @@ -48,12 +48,14 @@ type OrgContext struct { OrgContext string `json:"context"` ChannelUUID assets.ChannelUUID `json:"channel_uuid"` ProjectUUID uuids.UUID `json:"project_uuid"` + HasVtexAds bool `json:"vtex_ads"` } } func (c *OrgContext) Context() string { return c.c.OrgContext } func (c *OrgContext) ChannelUUID() assets.ChannelUUID { return c.c.ChannelUUID } func (c *OrgContext) ProjectUUID() uuids.UUID { return c.c.ProjectUUID } +func (c *OrgContext) HasVtexAds() bool { return c.c.HasVtexAds } type OrgContextService interface { flows.OrgContextService diff --git a/go.mod b/go.mod index ac91067f3..7b228c529 100644 --- a/go.mod +++ b/go.mod @@ -79,4 +79,4 @@ go 1.17 replace github.com/nyaruka/gocommon => github.com/Ilhasoft/gocommon v1.16.2-weni -replace github.com/nyaruka/goflow => github.com/weni-ai/goflow v0.14.3-goflow-0.144.3 +replace github.com/nyaruka/goflow => github.com/weni-ai/goflow v1.0.0 diff --git a/go.sum b/go.sum index 0b6faf2fb..6211f130b 100644 --- a/go.sum +++ b/go.sum @@ -329,12 +329,8 @@ github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLD github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= -github.com/weni-ai/goflow v0.14.1-goflow-0.144.3 h1:VTVwUhcMNWHbLoB8S2BvYFe6sCAO/HtvHt8jliurOVY= -github.com/weni-ai/goflow v0.14.1-goflow-0.144.3/go.mod h1:o0xaVWP9qNcauBSlcNLa79Fm2oCPV+BDpheFRa/D40c= -github.com/weni-ai/goflow v0.14.2-goflow-0.144.3 h1:deCOMSsMpyJaSml1PWpAfWz94r5VKphcc5DPPfHTugs= -github.com/weni-ai/goflow v0.14.2-goflow-0.144.3/go.mod h1:o0xaVWP9qNcauBSlcNLa79Fm2oCPV+BDpheFRa/D40c= -github.com/weni-ai/goflow v0.14.3-goflow-0.144.3 h1:J35Yd0kohBEuR1jJYbq56MZ86oN6MNtdCREYVflKgww= -github.com/weni-ai/goflow v0.14.3-goflow-0.144.3/go.mod h1:o0xaVWP9qNcauBSlcNLa79Fm2oCPV+BDpheFRa/D40c= +github.com/weni-ai/goflow v1.0.0 h1:19Zm8owCQWoFb+fWUxiKpWyB+KysxwJzk7ZwNolSjlo= +github.com/weni-ai/goflow v1.0.0/go.mod h1:o0xaVWP9qNcauBSlcNLa79Fm2oCPV+BDpheFRa/D40c= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/services/external/weni/service.go b/services/external/weni/service.go index 2be78886a..d07e220d4 100644 --- a/services/external/weni/service.go +++ b/services/external/weni/service.go @@ -103,15 +103,18 @@ func (s *service) Call(session flows.Session, params assets.MsgCatalogParam, log return callResult, err } + hasVtexAds := params.HasVtexAds productRetailerIDS := []string{} productRetailerIDMap := make(map[string]struct{}) var productEntries []flows.ProductEntry var productEntry flows.ProductEntry searchResult := []string{} + var searchResultSponsored string var trace *httpx.Trace var traces []*httpx.Trace var sellerID string var allProducts []string + qttProducts := 5 postalCode_ := strings.TrimSpace(params.PostalCode) if params.PostalCode != "" { @@ -125,15 +128,21 @@ func (s *service) Call(session flows.Session, params assets.MsgCatalogParam, log sellerID = "1" } + allProductsSponsored := []flows.ProductEntry{ + { + Product: languages[params.Language], + ProductRetailerIDs: []string{}, + }, + } + + hasSponsored := false + for _, product := range productList { if params.SearchType == "default" { searchResult, trace, err = GetProductListFromSentenX(product, catalog.FacebookCatalogID(), searchThreshold, s.rtConfig) callResult.Traces = append(callResult.Traces, trace) } else if params.SearchType == "vtex" { - searchResult, traces, err = GetProductListFromVtex(product, params.SearchUrl, params.ApiType) - if err != nil { - return callResult, errors.Wrapf(err, "on vtex search products") - } + searchResult, searchResultSponsored, traces, err = GetProductListFromVtex(product, params.SearchUrl, params.ApiType, catalog.FacebookCatalogID(), s.rtConfig, hasVtexAds) callResult.Traces = append(callResult.Traces, traces...) allProducts = append(allProducts, searchResult...) if searchResult == nil { @@ -161,6 +170,12 @@ func (s *service) Call(session flows.Session, params assets.MsgCatalogParam, log productRetailerIDS = nil } productRetailerIDMap = make(map[string]struct{}) + + if len(searchResultSponsored) > 0 { + hasSponsored = true + allProductsSponsored[0].ProductRetailerIDs = append(allProductsSponsored[0].ProductRetailerIDs, searchResultSponsored+"#"+sellerID) + } + } callResult.ProductRetailerIDS = productEntries @@ -180,22 +195,24 @@ func (s *service) Call(session flows.Session, params assets.MsgCatalogParam, log finalResult := &flows.MsgCatalogCall{} finalResult.Traces = callResult.Traces finalResult.ResponseJSON = callResult.ResponseJSON + if hasSponsored { + finalResult.ProductRetailerIDS = allProductsSponsored + } for _, productEntry := range callResult.ProductRetailerIDS { newEntry := productEntry newEntry.ProductRetailerIDs = []string{} - for _, productRetailerID := range productEntry.ProductRetailerIDs { if hasSimulation { for _, existingProductId := range existingProductsIds { if productRetailerID == existingProductId { - if len(newEntry.ProductRetailerIDs) < 5 { + if len(newEntry.ProductRetailerIDs) < qttProducts { newEntry.ProductRetailerIDs = append(newEntry.ProductRetailerIDs, productRetailerID+"#"+sellerID) } } } } else { - if len(newEntry.ProductRetailerIDs) < 5 { + if len(newEntry.ProductRetailerIDs) < qttProducts { newEntry.ProductRetailerIDs = append(newEntry.ProductRetailerIDs, productRetailerID+"#"+sellerID) } } @@ -325,31 +342,67 @@ func GetProductListFromChatGPT(ctx context.Context, rtConfig *runtime.Config, co return products["products"], trace, nil } -func GetProductListFromVtex(productSearch string, searchUrl string, apiType string) ([]string, []*httpx.Trace, error) { +func GetProductListFromVtex(productSearch string, searchUrl string, apiType string, catalog string, rt *runtime.Config, hasVtexAds bool) ([]string, string, []*httpx.Trace, error) { var result []string var traces []*httpx.Trace var err error + var productSponsored string if apiType == "legacy" { result, traces, err = VtexLegacySearch(searchUrl, productSearch) if err != nil { - return nil, traces, err + return nil, productSponsored, traces, err } } else if apiType == "intelligent" { result, traces, err = VtexIntelligentSearch(searchUrl, productSearch) if err != nil { - return nil, traces, err + return nil, productSponsored, traces, err } - } else if apiType == "sponsored" { - result, traces, err = VtexSponsoredSearch(searchUrl, productSearch) + } + if hasVtexAds { + resultSponsored, tracesAds, err := VtexSponsoredSearch(searchUrl, productSearch) + traces = append(traces, tracesAds...) if err != nil { - return nil, traces, err + return nil, productSponsored, traces, err + } + + productRetailerIDS := []string{} + productRetailerIDMap := make(map[string]struct{}) + var productEntries []flows.ProductEntry + var productEntry flows.ProductEntry + + for _, productRetailerID := range resultSponsored { + productRetailerIDS = append(productRetailerIDS, productRetailerID) + productRetailerIDMap[productRetailerID] = struct{}{} + } + + if len(productRetailerIDS) > 0 { + productEntry = flows.ProductEntry{ + Product: searchUrl, + ProductRetailerIDs: productRetailerIDS, + } + productEntries = append(productEntries, productEntry) + productRetailerIDS = nil + + retries := 2 + var newProductRetailerIDS []flows.ProductEntry + var tracesMeta []*httpx.Trace + for i := 0; i < retries; i++ { + newProductRetailerIDS, tracesMeta, err = ProductsSearchMeta(productEntries, fmt.Sprint(catalog), rt.WhatsappSystemUserToken) + if err != nil { + continue + } + break + } + if len(newProductRetailerIDS) > 0 { + productSponsored = newProductRetailerIDS[0].ProductRetailerIDs[0] + traces = append(traces, tracesMeta...) + } } - } else { - return nil, nil, errors.New(fmt.Sprintf("invalid api type for url %s", searchUrl)) + } - return result, traces, nil + return result, productSponsored, traces, nil } type SearchSeller struct { @@ -489,9 +542,14 @@ func VtexSponsoredSearch(searchUrl string, productSearch string) ([]string, []*h query.Add("locale", "pt-BR") query.Add("hideUnavailableItems", "true") - urlAfter := strings.TrimSuffix(searchUrl, "/") + parsedURL, err := url.Parse(searchUrl) + if err != nil { + fmt.Println("Erro ao fazer parse da URL:", err) + return nil, nil, err + } + domain := parsedURL.Host - url_ := fmt.Sprintf("%s?%s", urlAfter, query.Encode()) + url_ := fmt.Sprintf("http://%s/api/io/_v/api/intelligent-search/sponsored_products?%s", domain, query.Encode()) req, err := httpx.NewRequest("GET", url_, nil, nil) if err != nil { @@ -718,3 +776,9 @@ func ProductsSearchMeta(productEntryList []flows.ProductEntry, catalog string, w return newProductEntryList, traces, nil } + +var languages = map[string]string{ + "eng": "You may also like:", + "por": "Você também pode gostar:", + "spa": "También te puede interesar:", +}