chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/bizpkg/config"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/app/bot_common"
|
||||
productCommon "github.com/coze-dev/coze-studio/backend/api/model/marketplace/product_common"
|
||||
productAPI "github.com/coze-dev/coze-studio/backend/api/model/marketplace/product_public_api"
|
||||
pluginAPI "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop"
|
||||
common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop/common"
|
||||
"github.com/coze-dev/coze-studio/backend/application/base/ctxutil"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/plugin/consts"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/plugin/convert/api"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/dto"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/repository"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/service"
|
||||
search "github.com/coze-dev/coze-studio/backend/domain/search/service"
|
||||
userEntity "github.com/coze-dev/coze-studio/backend/domain/user/entity"
|
||||
user "github.com/coze-dev/coze-studio/backend/domain/user/service"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/storage"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/logs"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
var PluginApplicationSVC = &PluginApplicationService{}
|
||||
|
||||
type PluginApplicationService struct {
|
||||
DomainSVC service.PluginService
|
||||
eventbus search.ResourceEventBus
|
||||
oss storage.Storage
|
||||
userSVC user.User
|
||||
|
||||
toolRepo repository.ToolRepository
|
||||
pluginRepo repository.PluginRepository
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) CheckAndLockPluginEdit(ctx context.Context, req *pluginAPI.CheckAndLockPluginEditRequest) (resp *pluginAPI.CheckAndLockPluginEditResponse, err error) {
|
||||
resp = &pluginAPI.CheckAndLockPluginEditResponse{
|
||||
Data: &common.CheckAndLockPluginEditData{
|
||||
Seized: true,
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) GetBotDefaultParams(ctx context.Context, req *pluginAPI.GetBotDefaultParamsRequest) (resp *pluginAPI.GetBotDefaultParamsResponse, err error) {
|
||||
|
||||
draftAgentTool, err := p.DomainSVC.GetDraftAgentToolByName(ctx, req.BotID, req.PluginID, req.APIName)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetDraftAgentToolByName failed, agentID=%d, toolName=%s", req.BotID, req.APIName)
|
||||
}
|
||||
reqAPIParams, err := draftAgentTool.ToReqAPIParameter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
respAPIParams, err := draftAgentTool.ToRespAPIParameter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp = &pluginAPI.GetBotDefaultParamsResponse{
|
||||
RequestParams: reqAPIParams,
|
||||
ResponseParams: respAPIParams,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) UpdateBotDefaultParams(ctx context.Context, req *pluginAPI.UpdateBotDefaultParamsRequest) (resp *pluginAPI.UpdateBotDefaultParamsResponse, err error) {
|
||||
op, err := api.APIParamsToOpenapiOperation(req.RequestParams, req.ResponseParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = p.DomainSVC.UpdateBotDefaultParams(ctx, &dto.UpdateBotDefaultParamsRequest{
|
||||
PluginID: req.PluginID,
|
||||
ToolName: req.APIName,
|
||||
AgentID: req.BotID,
|
||||
Parameters: op.Parameters,
|
||||
RequestBody: op.RequestBody,
|
||||
Responses: op.Responses,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "UpdateBotDefaultParams failed, agentID=%d, toolName=%s", req.BotID, req.APIName)
|
||||
}
|
||||
|
||||
resp = &pluginAPI.UpdateBotDefaultParamsResponse{}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) UnlockPluginEdit(ctx context.Context, req *pluginAPI.UnlockPluginEditRequest) (resp *pluginAPI.UnlockPluginEditResponse, err error) {
|
||||
resp = &pluginAPI.UnlockPluginEditResponse{
|
||||
Released: true,
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) PublicGetProductList(ctx context.Context, req *productAPI.GetProductListRequest) (resp *productAPI.GetProductListResponse, err error) {
|
||||
res, err := p.DomainSVC.ListPluginProducts(ctx, &dto.ListPluginProductsRequest{})
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "ListPluginProducts failed")
|
||||
}
|
||||
|
||||
products := make([]*productAPI.ProductInfo, 0, len(res.Plugins))
|
||||
for _, pl := range res.Plugins {
|
||||
tls, err := p.toolRepo.GetPluginAllOnlineTools(ctx, pl.ID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetPluginAllOnlineTools failed, pluginID=%d", pl.ID)
|
||||
}
|
||||
|
||||
pi, err := p.buildProductInfo(ctx, pl, tls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
products = append(products, pi)
|
||||
}
|
||||
|
||||
if req.GetKeyword() != "" {
|
||||
filterProducts := make([]*productAPI.ProductInfo, 0, len(products))
|
||||
for _, _p := range products {
|
||||
if strings.Contains(strings.ToLower(_p.MetaInfo.Name), strings.ToLower(req.GetKeyword())) {
|
||||
filterProducts = append(filterProducts, _p)
|
||||
}
|
||||
}
|
||||
products = filterProducts
|
||||
}
|
||||
|
||||
resp = &productAPI.GetProductListResponse{
|
||||
Data: &productAPI.GetProductListData{
|
||||
Products: products,
|
||||
HasMore: false, // Finish at one time
|
||||
Total: int32(res.Total),
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) buildProductInfo(ctx context.Context, plugin *entity.PluginInfo, tools []*entity.ToolInfo) (*productAPI.ProductInfo, error) {
|
||||
metaInfo, err := p.buildProductMetaInfo(ctx, plugin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extraInfo, err := p.buildPluginProductExtraInfo(ctx, plugin, tools)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pi := &productAPI.ProductInfo{
|
||||
CommercialSetting: &productCommon.CommercialSetting{
|
||||
CommercialType: productCommon.ProductPaidType_Free,
|
||||
},
|
||||
MetaInfo: metaInfo,
|
||||
PluginExtra: extraInfo,
|
||||
}
|
||||
|
||||
return pi, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) buildProductMetaInfo(ctx context.Context, plugin *entity.PluginInfo) (*productAPI.ProductMetaInfo, error) {
|
||||
iconURL, err := p.oss.GetObjectUrl(ctx, plugin.GetIconURI())
|
||||
if err != nil {
|
||||
logs.CtxWarnf(ctx, "get icon url failed with '%s', err=%v", plugin.GetIconURI(), err)
|
||||
}
|
||||
|
||||
return &productAPI.ProductMetaInfo{
|
||||
ID: plugin.GetRefProductID(),
|
||||
EntityID: plugin.ID,
|
||||
EntityType: productCommon.ProductEntityType_Plugin,
|
||||
IconURL: iconURL,
|
||||
Name: plugin.GetName(),
|
||||
Description: plugin.GetDesc(),
|
||||
IsFree: true,
|
||||
IsOfficial: true,
|
||||
Status: productCommon.ProductStatus_Listed,
|
||||
ListedAt: time.Now().Unix(),
|
||||
UserInfo: &productCommon.UserInfo{
|
||||
Name: "Coze Official",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) buildPluginProductExtraInfo(ctx context.Context, plugin *entity.PluginInfo, tools []*entity.ToolInfo) (*productAPI.PluginExtraInfo, error) {
|
||||
ei := &productAPI.PluginExtraInfo{
|
||||
IsOfficial: true,
|
||||
PluginType: func() *productCommon.PluginType {
|
||||
if plugin.PluginType == common.PluginType_LOCAL {
|
||||
return ptr.Of(productCommon.PluginType_LocalPlugin)
|
||||
}
|
||||
return ptr.Of(productCommon.PluginType_CLoudPlugin)
|
||||
}(),
|
||||
JumpSaasURL: func() *string {
|
||||
if plugin.SaasPluginExtra != nil && plugin.SaasPluginExtra.JumpSaasURL != nil {
|
||||
return plugin.SaasPluginExtra.JumpSaasURL
|
||||
}
|
||||
return nil
|
||||
}(),
|
||||
}
|
||||
|
||||
toolInfos := make([]*productAPI.PluginToolInfo, 0, len(tools))
|
||||
for _, tl := range tools {
|
||||
params, err := tl.ToToolParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
toolInfo := &productAPI.PluginToolInfo{
|
||||
ID: tl.ID,
|
||||
Name: tl.GetName(),
|
||||
Description: tl.GetDesc(),
|
||||
Parameters: params,
|
||||
}
|
||||
|
||||
example := plugin.GetToolExample(ctx, tl.GetName())
|
||||
if example != nil {
|
||||
toolInfo.Example = &productAPI.PluginToolExample{
|
||||
ReqExample: example.RequestExample,
|
||||
RespExample: example.ResponseExample,
|
||||
}
|
||||
}
|
||||
|
||||
toolInfos = append(toolInfos, toolInfo)
|
||||
}
|
||||
|
||||
ei.Tools = toolInfos
|
||||
|
||||
authInfo := plugin.GetAuthInfo()
|
||||
|
||||
authMode := ptr.Of(productAPI.PluginAuthMode_NoAuth)
|
||||
if authInfo != nil {
|
||||
if authInfo.Type == consts.AuthzTypeOfService || authInfo.Type == consts.AuthzTypeOfOAuth {
|
||||
authMode = ptr.Of(productAPI.PluginAuthMode_Required)
|
||||
err := plugin.Manifest.Validate(false)
|
||||
if err != nil {
|
||||
logs.CtxWarnf(ctx, "validate plugin manifest failed, err=%v", err)
|
||||
} else {
|
||||
authMode = ptr.Of(productAPI.PluginAuthMode_Configured)
|
||||
}
|
||||
} else if authInfo.Type == consts.AuthTypeOfSaasInstalled {
|
||||
authMode = ptr.Of(productAPI.PluginAuthMode_NeedInstalled)
|
||||
}
|
||||
}
|
||||
|
||||
ei.AuthMode = authMode
|
||||
|
||||
return ei, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) PublicGetProductDetail(ctx context.Context, req *productAPI.GetProductDetailRequest) (resp *productAPI.GetProductDetailResponse, err error) {
|
||||
plugin, exist, err := p.pluginRepo.GetOnlinePlugin(ctx, req.GetEntityID())
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetOnlinePlugin failed, pluginID=%d", req.GetEntityID())
|
||||
}
|
||||
if !exist {
|
||||
return nil, errorx.New(errno.ErrPluginRecordNotFound)
|
||||
}
|
||||
|
||||
tools, err := p.toolRepo.GetPluginAllOnlineTools(ctx, plugin.ID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetPluginAllOnlineTools failed, pluginID=%d", plugin.ID)
|
||||
}
|
||||
pi, err := p.buildProductInfo(ctx, plugin, tools)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp = &productAPI.GetProductDetailResponse{
|
||||
Data: &productAPI.GetProductDetailData{
|
||||
MetaInfo: pi.MetaInfo,
|
||||
PluginExtra: pi.PluginExtra,
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) validateDraftPluginAccess(ctx context.Context, pluginID int64) (plugin *entity.PluginInfo, err error) {
|
||||
uid := ctxutil.GetUIDFromCtx(ctx)
|
||||
if uid == nil {
|
||||
return nil, errorx.New(errno.ErrPluginPermissionCode, errorx.KV(errno.PluginMsgKey, "session is required"))
|
||||
}
|
||||
|
||||
plugin, err = p.DomainSVC.GetDraftPlugin(ctx, pluginID)
|
||||
if err != nil {
|
||||
return nil, errorx.Wrapf(err, "GetDraftPlugin failed, pluginID=%d", pluginID)
|
||||
}
|
||||
|
||||
if plugin.DeveloperID != *uid {
|
||||
return nil, errorx.New(errno.ErrPluginPermissionCode, errorx.KV(errno.PluginMsgKey, "you are not the plugin owner"))
|
||||
}
|
||||
|
||||
return plugin, nil
|
||||
}
|
||||
|
||||
// convertPluginToProductInfo converts a plugin entity to ProductInfo
|
||||
func convertPluginToProductInfo(plugin *entity.PluginInfo) *productAPI.ProductInfo {
|
||||
|
||||
isOfficial := func() bool {
|
||||
if plugin.SaasPluginExtra == nil {
|
||||
return true
|
||||
}
|
||||
return plugin.SaasPluginExtra.IsOfficial
|
||||
}()
|
||||
return &productAPI.ProductInfo{
|
||||
MetaInfo: &productAPI.ProductMetaInfo{
|
||||
ID: plugin.GetRefProductID(),
|
||||
Name: plugin.GetName(),
|
||||
EntityID: plugin.ID,
|
||||
Description: plugin.GetDesc(),
|
||||
IconURL: plugin.GetIconURI(),
|
||||
ListedAt: plugin.CreatedAt,
|
||||
EntityType: func() productCommon.ProductEntityType {
|
||||
if ptr.From(plugin.Source) == bot_common.PluginFrom_FromSaas {
|
||||
return productCommon.ProductEntityType_SaasPlugin
|
||||
}
|
||||
return productCommon.ProductEntityType_Plugin
|
||||
}(),
|
||||
IsOfficial: isOfficial,
|
||||
Status: productCommon.ProductStatus_Listed,
|
||||
UserInfo: &productCommon.UserInfo{
|
||||
Name: func() string {
|
||||
if isOfficial {
|
||||
return "Coze Official"
|
||||
}
|
||||
return "Coze Community"
|
||||
}(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) convertPluginsToProductInfos(ctx context.Context, plugins []*entity.PluginInfo, tools map[int64][]*entity.ToolInfo) []*productAPI.ProductInfo {
|
||||
products := make([]*productAPI.ProductInfo, 0, len(plugins))
|
||||
for _, plugin := range plugins {
|
||||
var pExtra *productAPI.PluginExtraInfo
|
||||
if tool, exist := tools[plugin.ID]; exist {
|
||||
pluginExtra, err := p.buildPluginProductExtraInfo(ctx, plugin, tool)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "buildPluginProductExtraInfo failed: %v", err)
|
||||
} else {
|
||||
pExtra = pluginExtra
|
||||
}
|
||||
}
|
||||
pi := convertPluginToProductInfo(plugin)
|
||||
pi.PluginExtra = pExtra
|
||||
products = append(products, pi)
|
||||
}
|
||||
return products
|
||||
}
|
||||
func (p *PluginApplicationService) convertPluginsToMetaInfos(ctx context.Context, plugins []*entity.PluginInfo, tools map[int64][]*entity.ToolInfo) []*productAPI.ProductMetaInfo {
|
||||
products := make([]*productAPI.ProductMetaInfo, 0, len(plugins))
|
||||
for _, plugin := range plugins {
|
||||
pi := &productAPI.ProductMetaInfo{
|
||||
ID: plugin.ID,
|
||||
Name: plugin.GetName(),
|
||||
Description: plugin.GetDesc(),
|
||||
IconURL: plugin.GetIconURI(),
|
||||
ListedAt: plugin.CreatedAt,
|
||||
EntityID: plugin.ID,
|
||||
}
|
||||
products = append(products, pi)
|
||||
}
|
||||
return products
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) getSaasPluginList(ctx context.Context, domainReq *dto.ListSaasPluginProductsRequest) (*dto.ListPluginProductsResponse, error) {
|
||||
return p.DomainSVC.ListSaasPluginProducts(ctx, domainReq)
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) getSaasPluginToolsList(ctx context.Context, pluginIDs []int64) (map[int64][]*entity.ToolInfo, error) {
|
||||
tools, _, err := p.DomainSVC.BatchGetSaasPluginToolsInfo(ctx, pluginIDs)
|
||||
return tools, err
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) GetCozeSaasPluginList(ctx context.Context, req *productAPI.GetProductListRequest) (resp *productAPI.GetProductListResponse, err error) {
|
||||
domainResp, err := p.getSaasPluginList(ctx, &dto.ListSaasPluginProductsRequest{
|
||||
PageNum: ptr.Of(req.PageNum),
|
||||
PageSize: ptr.Of(req.PageSize),
|
||||
Keyword: req.Keyword,
|
||||
EntityTypes: req.EntityTypes,
|
||||
})
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "ListSaasPluginProducts failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// tools
|
||||
pluginIDs := make([]int64, 0, len(domainResp.Plugins))
|
||||
for _, product := range domainResp.Plugins {
|
||||
pluginIDs = append(pluginIDs, product.ID)
|
||||
}
|
||||
|
||||
tools, err := p.getSaasPluginToolsList(ctx, pluginIDs)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "BatchGetSaasPluginToolsInfo failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
products := p.convertPluginsToProductInfos(ctx, domainResp.Plugins, tools)
|
||||
|
||||
return &productAPI.GetProductListResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: &productAPI.GetProductListData{
|
||||
Products: products,
|
||||
Total: int32(domainResp.Total),
|
||||
HasMore: domainResp.HasMore,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) PublicSearchProduct(ctx context.Context, req *productAPI.SearchProductRequest) (resp *productAPI.SearchProductResponse, err error) {
|
||||
domainResp, err := p.getSaasPluginList(ctx, &dto.ListSaasPluginProductsRequest{
|
||||
PageNum: ptr.Of(req.PageNum),
|
||||
PageSize: ptr.Of(req.PageSize),
|
||||
Keyword: ptr.Of(req.Keyword),
|
||||
EntityTypes: func() []productCommon.ProductEntityType {
|
||||
if req.EntityTypes == nil {
|
||||
return nil
|
||||
}
|
||||
return p.convertEntityTypesStrToSlice(*req.EntityTypes)
|
||||
}(),
|
||||
CategoryIDs: req.CategoryIDs,
|
||||
IsOfficial: req.IsOfficial,
|
||||
PluginType: req.PluginType,
|
||||
ProductPaidType: req.ProductPaidType,
|
||||
SortType: req.SortType,
|
||||
})
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "ListSaasPluginProducts failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
// tools
|
||||
pluginIDs := make([]int64, 0, len(domainResp.Plugins))
|
||||
for _, product := range domainResp.Plugins {
|
||||
pluginIDs = append(pluginIDs, product.ID)
|
||||
}
|
||||
|
||||
tools, err := p.getSaasPluginToolsList(ctx, pluginIDs)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "BatchGetSaasPluginToolsInfo failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
products := p.convertPluginsToProductInfos(ctx, domainResp.Plugins, tools)
|
||||
|
||||
return &productAPI.SearchProductResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: &productAPI.SearchProductResponseData{
|
||||
Products: products,
|
||||
Total: ptr.Of(int32(domainResp.Total)),
|
||||
HasMore: ptr.Of(domainResp.HasMore),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) convertEntityTypesStrToSlice(entityTypesStr string) []productCommon.ProductEntityType {
|
||||
var entityTypes []productCommon.ProductEntityType
|
||||
if entityTypesStr != "" {
|
||||
typeStrs := strings.Split(entityTypesStr, ",")
|
||||
for _, typeStr := range typeStrs {
|
||||
typeStr = strings.TrimSpace(typeStr)
|
||||
if typeStr != "" {
|
||||
if entityType, err := productCommon.ProductEntityTypeFromString(typeStr); err == nil {
|
||||
entityTypes = append(entityTypes, entityType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return entityTypes
|
||||
}
|
||||
func (p *PluginApplicationService) PublicSearchSuggest(ctx context.Context, req *productAPI.SearchSuggestRequest) (resp *productAPI.SearchSuggestResponse, err error) {
|
||||
domainResp, err := p.getSaasPluginList(ctx, &dto.ListSaasPluginProductsRequest{
|
||||
PageNum: req.PageNum,
|
||||
PageSize: req.PageSize,
|
||||
Keyword: req.Keyword,
|
||||
EntityTypes: func() []productCommon.ProductEntityType {
|
||||
if req.EntityTypes == nil {
|
||||
return nil
|
||||
}
|
||||
return p.convertEntityTypesStrToSlice(*req.EntityTypes)
|
||||
}(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "ListSaasPluginProducts for suggestions failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// tools
|
||||
pluginIDs := make([]int64, 0, len(domainResp.Plugins))
|
||||
for _, product := range domainResp.Plugins {
|
||||
pluginIDs = append(pluginIDs, product.ID)
|
||||
}
|
||||
|
||||
tools, err := p.getSaasPluginToolsList(ctx, pluginIDs)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "BatchGetSaasPluginToolsInfo failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
suggestionProducts := p.convertPluginsToProductInfos(ctx, domainResp.Plugins, tools)
|
||||
|
||||
return &productAPI.SearchSuggestResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: &productAPI.SearchSuggestResponseData{
|
||||
SuggestionV2: suggestionProducts,
|
||||
Suggestions: p.convertPluginsToMetaInfos(ctx, domainResp.Plugins, tools),
|
||||
HasMore: ptr.Of(domainResp.HasMore),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) GetSaasProductCategoryList(ctx context.Context, req *productAPI.GetProductCategoryListRequest) (resp *productAPI.GetProductCategoryListResponse, err error) {
|
||||
|
||||
domainReq := &dto.ListPluginCategoriesRequest{}
|
||||
|
||||
if req.GetEntityType() == productCommon.ProductEntityType_SaasPlugin {
|
||||
domainReq.EntityType = ptr.Of("plugin")
|
||||
}
|
||||
|
||||
domainResp, err := p.DomainSVC.ListSaasPluginCategories(ctx, domainReq)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "ListSaasPluginCategories failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换响应数据
|
||||
categories := make([]*productAPI.ProductCategory, 0)
|
||||
if domainResp.Data != nil && domainResp.Data.Items != nil {
|
||||
for _, item := range domainResp.Data.Items {
|
||||
// 将字符串 ID 转换为 int64
|
||||
categoryID, _ := strconv.ParseInt(item.ID, 10, 64)
|
||||
categories = append(categories, &productAPI.ProductCategory{
|
||||
ID: categoryID,
|
||||
Name: item.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &productAPI.GetProductCategoryListResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: &productAPI.GetProductCategoryListData{
|
||||
EntityType: req.GetEntityType(),
|
||||
Categories: categories,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) GetProductCallInfo(ctx context.Context, req *productAPI.GetProductCallInfoRequest) (resp *productAPI.GetProductCallInfoResponse, err error) {
|
||||
userInfo, err := p.userSVC.GetSaasUserInfo(ctx)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetSaasUserInfo failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
benefit, err := p.userSVC.GetUserBenefit(ctx)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetUserBenefit failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build response data
|
||||
data := &productAPI.GetProductCallInfoData{
|
||||
UserInfo: &productAPI.UserInfo{
|
||||
UserName: ptr.Of(userInfo.UserName),
|
||||
NickName: ptr.Of(userInfo.NickName),
|
||||
AvatarURL: ptr.Of(userInfo.AvatarURL),
|
||||
},
|
||||
}
|
||||
|
||||
if benefit != nil {
|
||||
data.UserLevel = func() productAPI.UserLevel {
|
||||
switch benefit.UserLevel {
|
||||
case userEntity.UserLevelPro:
|
||||
return productAPI.UserLevel_ProPersonal
|
||||
case userEntity.UserLevelEnterprise:
|
||||
return productAPI.UserLevel_Enterprise
|
||||
default:
|
||||
return productAPI.UserLevel_Free
|
||||
}
|
||||
}()
|
||||
data.CallCountLimit = &productAPI.ProductCallCountLimit{
|
||||
IsUnlimited: benefit.IsUnlimited,
|
||||
UsedCount: benefit.UsedCount,
|
||||
TotalCount: benefit.TotalCount,
|
||||
ResetDatetime: benefit.ResetDatetime,
|
||||
}
|
||||
data.CallRateLimit = &productAPI.ProductCallRateLimit{
|
||||
QPS: benefit.CallQPS,
|
||||
}
|
||||
}
|
||||
|
||||
return &productAPI.GetProductCallInfoResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *PluginApplicationService) GetMarketPluginConfig(ctx context.Context, req *productAPI.GetMarketPluginConfigRequest) (resp *productAPI.GetMarketPluginConfigResponse, err error) {
|
||||
|
||||
baseConfig, err := config.Base().GetBaseConfig(ctx)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetBaseConfig failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cozeSaasPluginEnabled := baseConfig.PluginConfiguration.CozeSaasPluginEnabled
|
||||
saasAPIKey := baseConfig.PluginConfiguration.CozeAPIToken
|
||||
|
||||
enableSaasPlugin := cozeSaasPluginEnabled && len(saasAPIKey) > 0
|
||||
|
||||
resp = &productAPI.GetMarketPluginConfigResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: &productAPI.Configuration{
|
||||
EnableSaasPlugin: &enableSaasPlugin,
|
||||
},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
Reference in New Issue
Block a user