fix: 调整代码层级

This commit is contained in:
fuzhongyun 2026-01-27 14:14:16 +08:00
parent 36db8e7a86
commit 39d2fc1e62
6 changed files with 531 additions and 504 deletions

290
internal/biz/callback.go Normal file
View File

@ -0,0 +1,290 @@
package biz
import (
"ai_scheduler/internal/config"
"ai_scheduler/internal/data/constants"
"ai_scheduler/internal/data/impl"
"ai_scheduler/internal/domain/tools/common/knowledge_base"
"ai_scheduler/internal/pkg/dingtalk"
"ai_scheduler/internal/pkg/util"
"ai_scheduler/internal/pkg/utils_ollama"
"context"
"encoding/json"
"fmt"
"io"
"strings"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
"github.com/alibabacloud-go/dingtalk/card_1_0"
"github.com/alibabacloud-go/tea/tea"
"github.com/gofiber/fiber/v2/log"
"github.com/ollama/ollama/api"
)
type CallbackBiz struct {
cfg *config.Config
ollamaClient *utils_ollama.Client
dingtalkCardClient *dingtalk.CardClient
botConfigImpl *impl.BotConfigImpl
}
func NewCallbackBiz(
cfg *config.Config,
ollamaClient *utils_ollama.Client,
dingtalkCardClient *dingtalk.CardClient,
botConfigImpl *impl.BotConfigImpl,
) *CallbackBiz {
return &CallbackBiz{
cfg: cfg,
ollamaClient: ollamaClient,
dingtalkCardClient: dingtalkCardClient,
botConfigImpl: botConfigImpl,
}
}
// IssueHandlingGroup 问题处理群机器人回调
// 能力1 通过[内容提取] 宏分析用户QA问题调出QA表单卡片
// 能力2 通过[QA收集] 宏,收集用户反馈,写入知识库
// 能力3 通过[知识库查询] 宏,查询知识库,返回答案
func (c *CallbackBiz) IssueHandlingGroup(data chatbot.BotCallbackDataModel) error {
// 能力1、2分析用户QA问题写入知识库
if strings.Contains(data.Text.Content, "[内容提取]") || strings.Contains(data.Text.Content, "[QA收集]") {
c.issueHandlingExtractContent(data)
}
// 能力3查询知识库返回答案
if strings.Contains(data.Text.Content, "[知识库查询]") {
c.issueHandlingQueryKnowledgeBase(data)
}
return nil
}
// 问题处理群机器人内容提取
func (c *CallbackBiz) issueHandlingExtractContent(data chatbot.BotCallbackDataModel) {
// 1.提取用户输入
prompt := fmt.Sprintf(constants.IssueHandlingExtractContentPrompt, data.Text.Content)
log.Infof("问题提取提示词: %s", prompt)
// LLM 提取
generateResp, err := c.ollamaClient.Generation(context.Background(), &api.GenerateRequest{
Model: c.cfg.Ollama.GenerateModel,
Prompt: prompt,
Stream: util.AnyToPoint(false),
})
if err != nil {
log.Errorf("问题提取失败: %v", err)
return
}
// 解析 JSON 响应
var resp struct {
Items []struct {
Question string `json:"question"`
Answer string `json:"answer"`
Confidence string `json:"confidence"`
} `json:"items"`
}
if err := json.Unmarshal([]byte(generateResp.Response), &resp); err != nil {
log.Errorf("解析 JSON 响应失败: %v", err)
return
}
// 2.构建文本域内容
cardContentTpl := "问题:%s \n答案%s"
var cardContentList []string
for _, item := range resp.Items {
cardContentList = append(cardContentList, fmt.Sprintf(cardContentTpl, item.Question, item.Answer))
}
cardContent := strings.Join(cardContentList, "\n\n")
// 3.获取应用AppKey
appKey, err := c.botConfigImpl.GetRobotAppKey(data.RobotCode)
if err != nil {
log.Errorf("获取应用配置失败: %v", err)
return
}
// 4.创建并投放卡片
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) // 构建卡片 OutTrackId
_, err = c.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(c.cfg.Dingtalk.Card.Template.ContentCollect),
OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"),
CallbackRouteKey: tea.String(c.cfg.Dingtalk.Card.CallbackRouteKey),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("QA知识收集"),
"button_display": tea.String("true"),
"QA_details_now": tea.String(cardContent),
"textarea_display": tea.String("normal"),
"action_id": tea.String("collect_qa"),
"tenant_id": tea.String(constants.KnowledgeTenantIdDefault),
"_CARD_DEBUG_TOOL_ENTRY": tea.String(c.cfg.Dingtalk.Card.DebugToolEntryShow), // 调试字段
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + data.ConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(c.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
},
},
)
}
// 问题处理群机器人查询知识库
func (c *CallbackBiz) issueHandlingQueryKnowledgeBase(data chatbot.BotCallbackDataModel) {
// 获取应用配置
appKey, err := c.botConfigImpl.GetRobotAppKey(data.RobotCode)
if err != nil {
log.Errorf("应用机器人配置不存在: %s, err: %v", data.RobotCode, err)
return
}
// 创建卡片
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode)
_, err = c.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(c.cfg.Dingtalk.Card.Template.BaseMsg),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String(data.Text.Content),
"markdown": tea.String("知识库检索中..."),
},
},
OutTrackId: tea.String(outTrackId),
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + data.ConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(data.RobotCode),
},
},
)
// 查询知识库
knowledgeBase := knowledge_base.New(c.cfg.KnowledgeConfig)
knowledgeResp, err := knowledgeBase.Query(&knowledge_base.QueryRequest{
TenantID: constants.KnowledgeTenantIdDefault,
Query: data.Text.Content,
Mode: constants.KnowledgeModeMix,
Stream: false,
Think: false,
OnlyRAG: true,
})
if err != nil {
log.Errorf("查询知识库失败: %v", err)
return
}
knowledgeRespBytes, err := io.ReadAll(knowledgeResp)
if err != nil {
log.Errorf("读取知识库响应失败: %v", err)
return
}
// 卡片更新
message, isRetrieved, err := knowledge_base.ParseOpenAIHTTPData(string(knowledgeRespBytes))
if err != nil {
log.Errorf("读取知识库 SSE 数据失败: %v", err)
return
}
content := message.Content
if !isRetrieved {
content = "知识库未检测到匹配信息,请核查知识库数据是否正确。"
}
// 卡片更新
_, err = c.dingtalkCardClient.UpdateCard(
appKey,
&card_1_0.UpdateCardRequest{
OutTrackId: tea.String(outTrackId),
CardData: &card_1_0.UpdateCardRequestCardData{
CardParamMap: map[string]*string{
"markdown": tea.String(content),
},
},
CardUpdateOptions: &card_1_0.UpdateCardRequestCardUpdateOptions{
UpdateCardDataByKey: tea.Bool(true),
},
},
)
if err != nil {
log.Errorf("更新卡片失败: %v", err)
return
}
}
// IssueHandlingCollectQA 问题处理群机器人 QA 收集回调
func (c *CallbackBiz) IssueHandlingCollectQA(data card.CardRequest) *card.CardResponse {
// 确认提交,文本写入知识库
if data.CardActionData.CardPrivateData.Params["submit"] == "submit" {
content := data.CardActionData.CardPrivateData.Params["QA_details"].(string)
tenantID := data.CardActionData.CardPrivateData.Params["tenant_id"].(string)
// 协程执行耗时操作,防止阻塞
util.SafeGo("inject_knowledge_base", func() {
knowledgeBase := knowledge_base.New(c.cfg.KnowledgeConfig)
err := knowledgeBase.IngestText(&knowledge_base.IngestTextRequest{
TenantID: tenantID,
Text: content,
})
if err != nil {
log.Errorf("注入知识库失败: %v", err)
} else {
log.Infof("注入知识库成功: tenantID=%s", tenantID)
}
// 解析当前卡片的 ConversationId 和 robotCode
conversationId, robotCode := constants.ParseCardOutTrackId(data.OutTrackId)
// 获取应用配置
appKey, err := c.botConfigImpl.GetRobotAppKey(robotCode)
if err != nil {
log.Errorf("获取应用机器人配置失败: %v", err)
return
}
// 发送卡片通知用户注入成功
outTrackId := constants.BuildCardOutTrackId(conversationId, robotCode)
c.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(c.cfg.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("QA知识收集结果"),
"markdown": tea.String("[Get] **成功**"),
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + conversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(robotCode),
},
},
)
})
}
// 取消提交,禁用输入框
resp := &card.CardResponse{
CardUpdateOptions: &card.CardUpdateOptions{
UpdateCardDataByKey: true,
},
CardData: &card.CardDataDto{
CardParamMap: map[string]string{
"textarea_display": "disabled",
},
},
}
return resp
}

View File

@ -20,8 +20,13 @@ import (
"strings" "strings"
"time" "time"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
dingtalkPkg "ai_scheduler/internal/pkg/dingtalk"
"github.com/alibabacloud-go/dingtalk/card_1_0"
"github.com/alibabacloud-go/tea/tea"
"github.com/gofiber/fiber/v2/log" "github.com/gofiber/fiber/v2/log"
"xorm.io/builder" "xorm.io/builder"
) )
@ -45,6 +50,9 @@ type DingTalkBotBiz struct {
groupConfigBiz *GroupConfigBiz groupConfigBiz *GroupConfigBiz
reportDailyCacheImpl *impl.ReportDailyCacheImpl reportDailyCacheImpl *impl.ReportDailyCacheImpl
macro *do.Macro macro *do.Macro
dingtalkOauth2Client *dingtalkPkg.Oauth2Client
dingTalkOld *dingtalkPkg.OldClient
dingtalkCardClient *dingtalkPkg.CardClient
} }
// NewDingTalkBotBiz // NewDingTalkBotBiz
@ -61,6 +69,9 @@ func NewDingTalkBotBiz(
cardSend *dingtalk.SendCardClient, cardSend *dingtalk.SendCardClient,
groupConfigBiz *GroupConfigBiz, groupConfigBiz *GroupConfigBiz,
macro *do.Macro, macro *do.Macro,
dingtalkOauth2Client *dingtalkPkg.Oauth2Client,
dingTalkOld *dingtalkPkg.OldClient,
dingtalkCardClient *dingtalkPkg.CardClient,
) *DingTalkBotBiz { ) *DingTalkBotBiz {
return &DingTalkBotBiz{ return &DingTalkBotBiz{
do: do, do: do,
@ -76,6 +87,9 @@ func NewDingTalkBotBiz(
cardSend: cardSend, cardSend: cardSend,
reportDailyCacheImpl: reportDailyCacheImpl, reportDailyCacheImpl: reportDailyCacheImpl,
macro: macro, macro: macro,
dingtalkOauth2Client: dingtalkOauth2Client,
dingTalkOld: dingTalkOld,
dingtalkCardClient: dingtalkCardClient,
} }
} }
@ -408,3 +422,209 @@ func (d *DingTalkBotBiz) defaultPrompt() string {
-parameters 必须是 **转义后的 JSON 字符串** "{\"product_name\": \"京东月卡\"}" -parameters 必须是 **转义后的 JSON 字符串** "{\"product_name\": \"京东月卡\"}"
当前时间` + now + `所有的时间识别精确到秒` 当前时间` + now + `所有的时间识别精确到秒`
} }
// CreateIssueHandlingGroupAndInit 创建问题处理群聊并初始化
func (d *DingTalkBotBiz) CreateIssueHandlingGroupAndInit(ctx context.Context, data *card.CardRequest) (resp *card.CardResponse, err error) {
// 解析 OutTrackId 以获取 SpaceId 和 BotId
spaceId, botId := constants.ParseCardOutTrackId(data.OutTrackId)
// 获取新群聊人员
var userIds []string
userIds, err = d.buildNewGroupUserIds(spaceId, botId, data.UserId)
if err != nil {
return nil, err
}
// 创建群聊及群初始化(异步响应)
if data.CardActionData.CardPrivateData.Params["status"] == "confirm" {
go func() {
err := d.createIssueHandlingGroupAndInit(ctx, data.CardActionData.CardPrivateData.Params, spaceId, botId, userIds)
if err != nil {
log.Errorf("创建群聊及群初始化失败: %v", err)
}
}()
}
// 构建关闭创建群组卡片按钮的响应
return d.buildCreateGroupCardResp(), nil
}
// buildNewGroupUserIds 构建新群聊人员列表
func (d *DingTalkBotBiz) buildNewGroupUserIds(spaceId, botId, groupOwner string) ([]string, error) {
// 群id+机器人id确认一个群配置
botGroup, err := d.botGroupImpl.GetByConversationIdAndRobotCode(spaceId, botId)
if err != nil {
return nil, err
}
// 获取群配置
var groupConfig model.AiBotGroupConfig
cond := builder.NewCond().And(builder.Eq{"config_id": botGroup.ConfigID})
err = d.botGroupConfigImpl.GetOneBySearchToStrut(&cond, &groupConfig)
if err != nil {
return nil, err
}
// 获取处理人列表
issueOwnerJson := groupConfig.IssueOwner
type issueOwnerType struct {
UserId string `json:"userid"`
Name string `json:"name"`
}
var issueOwner []issueOwnerType
if err = json.Unmarshal([]byte(issueOwnerJson), &issueOwner); err != nil {
return nil, err
}
// 合并所有userid
userIds := []string{groupOwner} // 当前用户为群主
for _, owner := range issueOwner {
userIds = append(userIds, owner.UserId)
}
return userIds, nil
}
// createIssueHandlingGroupAndInit 创建问题处理群聊及群初始化
func (d *DingTalkBotBiz) createIssueHandlingGroupAndInit(ctx context.Context, callbackParams map[string]any, spaceId, botId string, userIds []string) error {
// 获取应用配置
appKey, err := d.botConfigImpl.GetRobotAppKey(botId)
if err != nil {
return err
}
// 获取 access_token
accessToken, err := d.dingtalkOauth2Client.GetAccessToken(appKey)
if err != nil {
return err
}
appKey.AccessToken = accessToken
// 创建群聊
_, openConversationId, err := d.createIssueHandlingGroup(ctx, accessToken, userIds)
if err != nil {
return err
}
// 添加当前机器人到新群 - SDK 有问题,后续再考虑使用
// _, err = d.dingtalkImClient.AddRobotToConversation(
// appKey,
// &im_1_0.AddRobotToConversationRequest{
// OpenConversationId: tea.String(openConversationId),
// RobotCode: tea.String(botId),
// })
// if err != nil {
// fmt.Printf("添加机器人到会话失败: %v", err)
// }
// 返回新群分享链接,直接进群 - SDK 有问题,后续再考虑使用
// newGroupShareLink, err = d.dingTalkOld.GetJoinGroupQrcode(ctx, chatId, data.UserId)
// if err != nil {
// fmt.Printf("获取入群二维码失败: %v", err)
// }
// 初始化群聊
groupScope := callbackParams["group_scope"].(string) // 群主题
d.initIssueHandlingGroup(appKey, openConversationId, groupScope)
return nil
}
// createIssueHandlingGroup 创建问题处理群聊会话
func (d *DingTalkBotBiz) createIssueHandlingGroup(ctx context.Context, accessToken string, userIds []string) (chatId, openConversationId string, err error) {
// 是否使用模板群开关
var useTemplateGroup bool = true
// 创建内部群会话
if !useTemplateGroup {
return d.dingTalkOld.CreateInternalGroupConversation(ctx, accessToken, "问题处理群", userIds)
}
// 根据群模板ID创建群
if useTemplateGroup {
return d.dingTalkOld.CreateSceneGroupConversation(ctx, accessToken, "问题处理群", userIds, d.conf.Dingtalk.SceneGroup.GroupTemplateIDIssueHandling)
}
return
}
// initIssueHandlingGroup 初始化问题处理群聊
func (d *DingTalkBotBiz) initIssueHandlingGroup(appKey dingtalkPkg.AppKey, openConversationId, groupScope string) error {
// 1.开场白
outTrackId := constants.BuildCardOutTrackId(openConversationId, d.conf.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling)
_, err := d.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(d.conf.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("当前会话主题"),
"markdown": tea.String("问题:" + groupScope),
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(d.conf.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
AtUserIds: map[string]*string{
"@ALL": tea.String("@ALL"),
},
},
},
)
if err != nil {
return err
}
// 2. 机器人能力
// 构建卡片 OutTrackId
outTrackId = constants.BuildCardOutTrackId(openConversationId, d.conf.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling)
_, err = d.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(d.conf.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("当前机器人能力"),
"markdown": tea.String("- 聊天内容提取(@机器人 [内容提取]{聊天记录/问答描述} \n - QA知识收集卡片信息收集 \n - QA知识问答@机器人 [知识库查询]{问题描述}"),
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(d.conf.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
AtUserIds: map[string]*string{
"@ALL": tea.String("@ALL"),
},
},
},
)
if err != nil {
return err
}
return nil
}
// buildCreateGroupCardResp 构建关闭创建群组卡片按钮
func (d *DingTalkBotBiz) buildCreateGroupCardResp() *card.CardResponse {
return &card.CardResponse{
CardData: &card.CardDataDto{
CardParamMap: map[string]string{
"button_display": "false",
},
},
CardUpdateOptions: &card.CardUpdateOptions{
UpdateCardDataByKey: true,
},
}
}

View File

@ -476,7 +476,7 @@ func (g *GroupConfigBiz) GetReportCache(ctx context.Context, day time.Time, tota
return nil return nil
} }
// handleKnowledgeV2 处理知识库V2版本 // handleKnowledge 处理知识库V2版本
func (g *GroupConfigBiz) handleKnowledge(ctx context.Context, rec *entitys.Recognize, groupConfig *model.AiBotGroupConfig, callback *chatbot.BotCallbackDataModel) (err error) { func (g *GroupConfigBiz) handleKnowledge(ctx context.Context, rec *entitys.Recognize, groupConfig *model.AiBotGroupConfig, callback *chatbot.BotCallbackDataModel) (err error) {
// 请求知识库工具 // 请求知识库工具
knowledgeBase := knowledge_base.New(g.conf.KnowledgeConfig) knowledgeBase := knowledge_base.New(g.conf.KnowledgeConfig)

View File

@ -6,31 +6,24 @@ import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/data/constants" "ai_scheduler/internal/data/constants"
errorcode "ai_scheduler/internal/data/error" errorcode "ai_scheduler/internal/data/error"
"ai_scheduler/internal/data/impl"
"ai_scheduler/internal/domain/component/callback" "ai_scheduler/internal/domain/component/callback"
"ai_scheduler/internal/domain/tools/common/knowledge_base"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/gateway" "ai_scheduler/internal/gateway"
"ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg"
"ai_scheduler/internal/pkg/dingtalk" "ai_scheduler/internal/pkg/dingtalk"
"ai_scheduler/internal/pkg/util" "ai_scheduler/internal/pkg/util"
"ai_scheduler/internal/pkg/utils_ollama"
"ai_scheduler/internal/tool_callback" "ai_scheduler/internal/tool_callback"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/url" "net/url"
"strings" "strings"
"time" "time"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
"github.com/alibabacloud-go/dingtalk/card_1_0"
"github.com/alibabacloud-go/tea/tea"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/log" "github.com/gofiber/fiber/v2/log"
"github.com/ollama/ollama/api"
) )
// CallbackService 统一回调入口 // CallbackService 统一回调入口
@ -43,8 +36,9 @@ type CallbackService struct {
dingtalkCardClient *dingtalk.CardClient dingtalkCardClient *dingtalk.CardClient
callbackManager callback.Manager callbackManager callback.Manager
dingTalkBotBiz *biz.DingTalkBotBiz dingTalkBotBiz *biz.DingTalkBotBiz
ollamaClient *utils_ollama.Client callbackBiz *biz.CallbackBiz
botConfigImpl *impl.BotConfigImpl // ollamaClient *utils_ollama.Client
// botConfigImpl *impl.BotConfigImpl
} }
func NewCallbackService( func NewCallbackService(
@ -56,8 +50,9 @@ func NewCallbackService(
dingtalkCardClient *dingtalk.CardClient, dingtalkCardClient *dingtalk.CardClient,
callbackManager callback.Manager, callbackManager callback.Manager,
dingTalkBotBiz *biz.DingTalkBotBiz, dingTalkBotBiz *biz.DingTalkBotBiz,
ollamaClient *utils_ollama.Client, callbackBiz *biz.CallbackBiz,
botConfigImpl *impl.BotConfigImpl, // ollamaClient *utils_ollama.Client,
// botConfigImpl *impl.BotConfigImpl,
) *CallbackService { ) *CallbackService {
return &CallbackService{ return &CallbackService{
cfg: cfg, cfg: cfg,
@ -68,8 +63,9 @@ func NewCallbackService(
dingtalkCardClient: dingtalkCardClient, dingtalkCardClient: dingtalkCardClient,
callbackManager: callbackManager, callbackManager: callbackManager,
dingTalkBotBiz: dingTalkBotBiz, dingTalkBotBiz: dingTalkBotBiz,
ollamaClient: ollamaClient, callbackBiz: callbackBiz,
botConfigImpl: botConfigImpl, // ollamaClient: ollamaClient,
// botConfigImpl: botConfigImpl,
} }
} }
@ -411,9 +407,10 @@ func (s *CallbackService) CallbackDingtalkRobot(c *fiber.Ctx) (err error) {
switch data.RobotCode { switch data.RobotCode {
case s.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling: case s.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling:
// 问题处理群机器人 // 问题处理群机器人
err := s.issueHandling(c, data) // err := s.issueHandling(data)
err := s.callbackBiz.IssueHandlingGroup(data)
if err != nil { if err != nil {
return fmt.Errorf("issueHandling failed: %v", err) return fmt.Errorf("IssueHandlingGroup failed: %v", err)
} }
default: default:
// 其他机器人 // 其他机器人
@ -423,190 +420,6 @@ func (s *CallbackService) CallbackDingtalkRobot(c *fiber.Ctx) (err error) {
return nil return nil
} }
// issueHandling 问题处理群机器人回调
// 能力1 通过[内容提取] 宏分析用户QA问题调出QA表单卡片
// 能力2 通过[QA收集] 宏,收集用户反馈,写入知识库
// 能力3 通过[知识库查询] 宏,查询知识库,返回答案
func (s *CallbackService) issueHandling(c *fiber.Ctx, data chatbot.BotCallbackDataModel) error {
// 能力1、2分析用户QA问题写入知识库
if strings.Contains(data.Text.Content, "[内容提取]") || strings.Contains(data.Text.Content, "[QA收集]") {
s.issueHandlingExtractContent(data)
}
// 能力3查询知识库返回答案
if strings.Contains(data.Text.Content, "[知识库查询]") {
s.issueHandlingQueryKnowledgeBase(data)
}
return nil
}
// 问题处理群机器人内容提取
func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDataModel) {
// 1.提取用户输入
prompt := fmt.Sprintf(constants.IssueHandlingExtractContentPrompt, data.Text.Content)
log.Infof("问题提取提示词: %s", prompt)
// LLM 提取
generateResp, err := s.ollamaClient.Generation(context.Background(), &api.GenerateRequest{
Model: s.cfg.Ollama.GenerateModel,
Prompt: prompt,
Stream: util.AnyToPoint(false),
})
if err != nil {
log.Errorf("问题提取失败: %v", err)
return
}
// 解析 JSON 响应
var resp struct {
Items []struct {
Question string `json:"question"`
Answer string `json:"answer"`
Confidence string `json:"confidence"`
} `json:"items"`
}
if err := json.Unmarshal([]byte(generateResp.Response), &resp); err != nil {
log.Errorf("解析 JSON 响应失败: %v", err)
return
}
// 2.构建文本域内容
cardContentTpl := "问题:%s \n答案%s"
var cardContentList []string
for _, item := range resp.Items {
cardContentList = append(cardContentList, fmt.Sprintf(cardContentTpl, item.Question, item.Answer))
}
cardContent := strings.Join(cardContentList, "\n\n")
// 3.获取应用AppKey
appKey, err := s.botConfigImpl.GetRobotAppKey(data.RobotCode)
if err != nil {
log.Errorf("获取应用配置失败: %v", err)
return
}
// 4.创建并投放卡片
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) // 构建卡片 OutTrackId
_, err = s.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.ContentCollect),
OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"),
CallbackRouteKey: tea.String(s.cfg.Dingtalk.Card.CallbackRouteKey),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("QA知识收集"),
"button_display": tea.String("true"),
"QA_details_now": tea.String(cardContent),
"textarea_display": tea.String("normal"),
"action_id": tea.String("collect_qa"),
"tenant_id": tea.String(constants.KnowledgeTenantIdDefault),
"_CARD_DEBUG_TOOL_ENTRY": tea.String(s.cfg.Dingtalk.Card.DebugToolEntryShow), // 调试字段
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + data.ConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(s.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
},
},
)
}
// 问题处理群机器人查询知识库
func (s *CallbackService) issueHandlingQueryKnowledgeBase(data chatbot.BotCallbackDataModel) {
// // 获取应用主机器人
// mainRobotCode := data.RobotCode
// if robotCode, ok := constants.GroupTemplateRobotIdMap[data.RobotCode]; ok {
// mainRobotCode = robotCode
// }
// 获取应用配置
appKey, err := s.botConfigImpl.GetRobotAppKey(data.RobotCode)
if err != nil {
log.Errorf("应用机器人配置不存在: %s, err: %v", data.RobotCode, err)
return
}
// 创建卡片
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode)
_, err = s.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.BaseMsg),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String(data.Text.Content),
"markdown": tea.String("知识库检索中..."),
},
},
OutTrackId: tea.String(outTrackId),
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + data.ConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(data.RobotCode),
},
},
)
// 查询知识库
knowledgeBase := knowledge_base.New(s.cfg.KnowledgeConfig)
knowledgeResp, err := knowledgeBase.Query(&knowledge_base.QueryRequest{
TenantID: constants.KnowledgeTenantIdDefault,
Query: data.Text.Content,
Mode: constants.KnowledgeModeMix,
Stream: false,
Think: false,
OnlyRAG: true,
})
if err != nil {
log.Errorf("查询知识库失败: %v", err)
return
}
knowledgeRespBytes, err := io.ReadAll(knowledgeResp)
if err != nil {
log.Errorf("读取知识库响应失败: %v", err)
return
}
// 卡片更新
message, isRetrieved, err := knowledge_base.ParseOpenAIHTTPData(string(knowledgeRespBytes))
if err != nil {
log.Errorf("读取知识库 SSE 数据失败: %v", err)
return
}
content := message.Content
if !isRetrieved {
content = "知识库未检测到匹配信息,请核查知识库数据是否正确。"
}
// 卡片更新
_, err = s.dingtalkCardClient.UpdateCard(
appKey,
&card_1_0.UpdateCardRequest{
OutTrackId: tea.String(outTrackId),
CardData: &card_1_0.UpdateCardRequestCardData{
CardParamMap: map[string]*string{
"markdown": tea.String(content),
},
},
CardUpdateOptions: &card_1_0.UpdateCardRequestCardUpdateOptions{
UpdateCardDataByKey: tea.Bool(true),
},
},
)
if err != nil {
log.Errorf("更新卡片失败: %v", err)
return
}
return
}
// CallbackDingtalkCard 处理钉钉卡片回调 // CallbackDingtalkCard 处理钉钉卡片回调
// 钉钉 callbackRouteKey: gateway.dev.cdlsxd.cn-dingtalk-card // 钉钉 callbackRouteKey: gateway.dev.cdlsxd.cn-dingtalk-card
// 钉钉 apiSecret: aB3dE7fG9hI2jK4L5M6N7O8P9Q0R1S2T // 钉钉 apiSecret: aB3dE7fG9hI2jK4L5M6N7O8P9Q0R1S2T
@ -640,7 +453,7 @@ func (s *CallbackService) CallbackDingtalkCard(c *fiber.Ctx) error {
switch actionId { switch actionId {
case "collect_qa": case "collect_qa":
// 问题处理群机器人 QA 收集 // 问题处理群机器人 QA 收集
resp = s.issueHandlingCollectQA(data) resp = s.callbackBiz.IssueHandlingCollectQA(data)
} }
} }
@ -648,79 +461,3 @@ func (s *CallbackService) CallbackDingtalkCard(c *fiber.Ctx) error {
c.Locals("skip_response_wrap", true) c.Locals("skip_response_wrap", true)
return c.JSON(resp) return c.JSON(resp)
} }
// 问题处理群机器人 QA 收集
func (s *CallbackService) issueHandlingCollectQA(data card.CardRequest) *card.CardResponse {
// 确认提交,文本写入知识库
if data.CardActionData.CardPrivateData.Params["submit"] == "submit" {
content := data.CardActionData.CardPrivateData.Params["QA_details"].(string)
tenantID := data.CardActionData.CardPrivateData.Params["tenant_id"].(string)
// 协程执行耗时操作,防止阻塞
util.SafeGo("inject_knowledge_base", func() {
knowledgeBase := knowledge_base.New(s.cfg.KnowledgeConfig)
err := knowledgeBase.IngestText(&knowledge_base.IngestTextRequest{
TenantID: tenantID,
Text: content,
})
if err != nil {
log.Errorf("注入知识库失败: %v", err)
} else {
log.Infof("注入知识库成功: tenantID=%s", tenantID)
}
// 解析当前卡片的 ConversationId 和 robotCode
conversationId, robotCode := constants.ParseCardOutTrackId(data.OutTrackId)
// 获取主应用机器人(这里可能是群模板机器人)
// mainRobotId := robotCode
// if robotCode, ok := constants.GroupTemplateRobotIdMap[robotCode]; ok {
// mainRobotId = robotCode
// }
// 获取应用配置
appKey, err := s.botConfigImpl.GetRobotAppKey(robotCode)
if err != nil {
log.Errorf("获取应用机器人配置失败: %v", err)
return
}
// 发送卡片通知用户注入成功
outTrackId := constants.BuildCardOutTrackId(conversationId, robotCode)
s.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("QA知识收集结果"),
"markdown": tea.String("[Get] **成功**"),
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + conversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(robotCode),
},
},
)
})
}
// 取消提交,禁用输入框
resp := &card.CardResponse{
CardUpdateOptions: &card.CardUpdateOptions{
UpdateCardDataByKey: true,
},
CardData: &card.CardDataDto{
CardParamMap: map[string]string{
"textarea_display": "disabled",
},
},
}
return resp
}

View File

@ -4,57 +4,29 @@ import (
"ai_scheduler/internal/biz" "ai_scheduler/internal/biz"
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/data/constants" "ai_scheduler/internal/data/constants"
"ai_scheduler/internal/data/impl"
"ai_scheduler/internal/data/model"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg/dingtalk"
"context" "context"
"encoding/json"
"log" "log"
"sync" "sync"
"time" "time"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
"github.com/alibabacloud-go/dingtalk/card_1_0"
"github.com/alibabacloud-go/tea/tea"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"xorm.io/builder"
) )
type DingBotService struct { type DingBotService struct {
config *config.Config config *config.Config
dingTalkBotBiz *biz.DingTalkBotBiz dingTalkBotBiz *biz.DingTalkBotBiz
dingTalkOld *dingtalk.OldClient
dingtalkCardClient *dingtalk.CardClient
dingtalkImClient *dingtalk.ImClient
dingtalkOauth2Client *dingtalk.Oauth2Client
botGroupConfigImpl *impl.BotGroupConfigImpl
botGroupImpl *impl.BotGroupImpl
botConfigImpl *impl.BotConfigImpl
} }
func NewDingBotService( func NewDingBotService(
config *config.Config, config *config.Config,
dingTalkBotBiz *biz.DingTalkBotBiz, dingTalkBotBiz *biz.DingTalkBotBiz,
dingTalkOld *dingtalk.OldClient,
dingtalkCardClient *dingtalk.CardClient,
dingtalkImClient *dingtalk.ImClient,
dingtalkOauth2Client *dingtalk.Oauth2Client,
botGroupConfigImpl *impl.BotGroupConfigImpl,
botGroupImpl *impl.BotGroupImpl,
botConfigImpl *impl.BotConfigImpl,
) *DingBotService { ) *DingBotService {
return &DingBotService{ return &DingBotService{
config: config, config: config,
dingTalkBotBiz: dingTalkBotBiz, dingTalkBotBiz: dingTalkBotBiz,
dingTalkOld: dingTalkOld,
dingtalkCardClient: dingtalkCardClient,
dingtalkImClient: dingtalkImClient,
dingtalkOauth2Client: dingtalkOauth2Client,
botGroupConfigImpl: botGroupConfigImpl,
botGroupImpl: botGroupImpl,
botConfigImpl: botConfigImpl,
} }
} }
@ -174,7 +146,7 @@ func (d *DingBotService) runBackgroundTasks(ctx context.Context, data *chatbot.B
return nil return nil
} }
// **一把梭先搞,后续规范化** // OnCardMessageReceived 处理卡片回调
func (d *DingBotService) OnCardMessageReceived(ctx context.Context, data *card.CardRequest) (resp *card.CardResponse, err error) { func (d *DingBotService) OnCardMessageReceived(ctx context.Context, data *card.CardRequest) (resp *card.CardResponse, err error) {
// 非回调类型暂不接受 // 非回调类型暂不接受
if data.Type != constants.CardActionCallbackTypeAction { if data.Type != constants.CardActionCallbackTypeAction {
@ -185,206 +157,14 @@ func (d *DingBotService) OnCardMessageReceived(ctx context.Context, data *card.C
for _, actionId := range data.CardActionData.CardPrivateData.ActionIdList { for _, actionId := range data.CardActionData.CardPrivateData.ActionIdList {
switch actionId { switch actionId {
case constants.CardActionTypeCreateGroup: case constants.CardActionTypeCreateGroup:
// 解析 OutTrackId 以获取 SpaceId 和 BotId resp, err = d.dingTalkBotBiz.CreateIssueHandlingGroupAndInit(ctx, data)
spaceId, botId := constants.ParseCardOutTrackId(data.OutTrackId)
// 获取新群聊人员
var userIds []string
userIds, err = d.buildNewGroupUserIds(ctx, spaceId, botId, data.UserId)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// 创建群聊及群初始化ws中直接协程
if data.CardActionData.CardPrivateData.Params["status"] == "confirm" {
go func() {
err := d.createIssueHandlingGroupAndInit(ctx, data.CardActionData.CardPrivateData.Params, spaceId, botId, userIds)
if err != nil {
log.Printf("创建群聊及群初始化失败: %v", err)
}
}()
}
// 构建关闭创建群组卡片按钮的响应
resp = d.buildCreateGroupCardResp()
return return
} }
} }
return &card.CardResponse{}, nil return &card.CardResponse{}, nil
} }
// buildNewGroupUserIds 构建新群聊人员列表
func (d *DingBotService) buildNewGroupUserIds(ctx context.Context, spaceId, botId, groupOwner string) ([]string, error) {
// 群id+机器人id确认一个群配置
botGroup, err := d.botGroupImpl.GetByConversationIdAndRobotCode(spaceId, botId)
if err != nil {
return nil, err
}
// 获取群配置
var groupConfig model.AiBotGroupConfig
cond := builder.NewCond().And(builder.Eq{"config_id": botGroup.ConfigID})
err = d.botGroupConfigImpl.GetOneBySearchToStrut(&cond, &groupConfig)
if err != nil {
return nil, err
}
// 获取处理人列表
issueOwnerJson := groupConfig.IssueOwner
type issueOwnerType struct {
UserId string `json:"userid"`
Name string `json:"name"`
}
var issueOwner []issueOwnerType
if err = json.Unmarshal([]byte(issueOwnerJson), &issueOwner); err != nil {
return nil, err
}
// 合并所有userid
userIds := []string{groupOwner} // 当前用户为群主
for _, owner := range issueOwner {
userIds = append(userIds, owner.UserId)
}
return userIds, nil
}
// createIssueHandlingGroupAndInit 创建问题处理群聊及群初始化
func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, callbackParams map[string]any, spaceId, botId string, userIds []string) error {
// 获取机器人配置
botConfig, err := d.botConfigImpl.GetRobotConfig(botId)
if err != nil {
return err
}
appKey := dingtalk.AppKey{
AppKey: botConfig.ClientId,
AppSecret: botConfig.ClientSecret,
}
// 获取 access_token
accessToken, err := d.dingtalkOauth2Client.GetAccessToken(appKey)
if err != nil {
return err
}
appKey.AccessToken = accessToken
// 创建群聊
_, openConversationId, err := d.createIssueHandlingGroup(ctx, accessToken, spaceId, botId, userIds)
if err != nil {
return err
}
// 添加当前机器人到新群 - SDK 有问题,后续再考虑使用
// _, err = d.dingtalkImClient.AddRobotToConversation(
// appKey,
// &im_1_0.AddRobotToConversationRequest{
// OpenConversationId: tea.String(openConversationId),
// RobotCode: tea.String(botId),
// })
// if err != nil {
// fmt.Printf("添加机器人到会话失败: %v", err)
// }
// 返回新群分享链接,直接进群 - SDK 有问题,后续再考虑使用
// newGroupShareLink, err = d.dingTalkOld.GetJoinGroupQrcode(ctx, chatId, data.UserId)
// if err != nil {
// fmt.Printf("获取入群二维码失败: %v", err)
// }
// 初始化群聊
// 1.开场白
// 群主题
groupScope := callbackParams["group_scope"].(string)
// 构建卡片 OutTrackId
outTrackId := constants.BuildCardOutTrackId(openConversationId, d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling)
_, err = d.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(d.config.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("当前会话主题"),
"markdown": tea.String("问题:" + groupScope),
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
AtUserIds: map[string]*string{
"@ALL": tea.String("@ALL"),
},
},
},
)
// 2. 机器人能力
// 构建卡片 OutTrackId
outTrackId = constants.BuildCardOutTrackId(openConversationId, d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling)
_, err = d.dingtalkCardClient.CreateAndDeliver(
appKey,
&card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(d.config.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{
"title": tea.String("当前机器人能力"),
"markdown": tea.String("- 聊天内容提取(@机器人 [内容提取]{聊天记录/问答描述} \n - QA知识收集卡片信息收集 \n - QA知识问答@机器人 [知识库查询]{问题描述}"),
},
},
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
SupportForward: tea.Bool(false),
},
OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
AtUserIds: map[string]*string{
"@ALL": tea.String("@ALL"),
},
},
},
)
return nil
}
// createGroupV1 创建普通内部群会话
// 这里用的是“统一登录平台”这个应用的接口加入群聊 - 这里用的是“统一登录平台”这个应用的接口
func (d *DingBotService) createIssueHandlingGroup(ctx context.Context, accessToken, spaceId, botId string, userIds []string) (chatId, openConversationId string, err error) {
// 是否使用模板群开关
var useTemplateGroup bool = true
// 创建内部群会话
if !useTemplateGroup {
return d.dingTalkOld.CreateInternalGroupConversation(ctx, accessToken, "问题处理群", userIds)
}
// 根据群模板ID创建群
if useTemplateGroup {
return d.dingTalkOld.CreateSceneGroupConversation(ctx, accessToken, "问题处理群", userIds, d.config.Dingtalk.SceneGroup.GroupTemplateIDIssueHandling)
}
return
}
// buildCreateGroupCardResp 构建关闭创建群组卡片按钮
func (d *DingBotService) buildCreateGroupCardResp() *card.CardResponse {
return &card.CardResponse{
CardData: &card.CardDataDto{
CardParamMap: map[string]string{
"button_display": "false",
},
},
CardUpdateOptions: &card.CardUpdateOptions{
UpdateCardDataByKey: true,
},
}
}

View File

@ -126,7 +126,7 @@ func run() {
qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other) qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other)
groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, botConfigImpl, registry, configConfig, impl.NewReportDailyCacheImpl(db), rdb, manager, cardClient) groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, botConfigImpl, registry, configConfig, impl.NewReportDailyCacheImpl(db), rdb, manager, cardClient)
macro := do.NewMacro(botGroupImpl, impl.NewReportDailyCacheImpl(db)) macro := do.NewMacro(botGroupImpl, impl.NewReportDailyCacheImpl(db))
dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl, botGroupImpl, user, botChatHisImpl, impl.NewReportDailyCacheImpl(db), manager, configConfig, sendCardClient, groupConfigBiz, macro) dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl, botGroupImpl, user, botChatHisImpl, impl.NewReportDailyCacheImpl(db), manager, configConfig, sendCardClient, groupConfigBiz, macro, oauth2Client, oldClient, cardClient)
// 初始化钉钉机器人服务 // 初始化钉钉机器人服务
cronService = NewCronService(configConfig, dingTalkBotBiz, qywxAppBiz, groupConfigBiz) cronService = NewCronService(configConfig, dingTalkBotBiz, qywxAppBiz, groupConfigBiz)
} }