fix: 1.增加回调 OutTrackId 模板处理 2.群组查询增加状态判断 3.群组配置表增加群组问题处理人字段 4.增加卡片更新方法,调整回调执行逻辑
This commit is contained in:
parent
17d7b01fdf
commit
a0b76f1581
|
|
@ -32,7 +32,6 @@ import (
|
|||
"github.com/alibabacloud-go/tea/tea"
|
||||
"github.com/coze-dev/coze-go"
|
||||
"github.com/gofiber/fiber/v2/log"
|
||||
"github.com/google/uuid"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
|
|
@ -506,14 +505,16 @@ func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Rec
|
|||
|
||||
// 未检索到匹配信息,询问是否拉群
|
||||
if !isRetrieved {
|
||||
// 构建卡片 OutTrackId
|
||||
outTrackId := constants.BuildCardOutTrackId("cidwP24PLZhLVOS2dVIkEawLw==", "ding5wwvnf9hxeyjau7t")
|
||||
|
||||
// 发送钉钉卡片
|
||||
uuid := uuid.New().String()
|
||||
_, err = g.dingtalkCardClient.CreateAndDeliver(dingtalk.AppKey{
|
||||
AppKey: "ding5wwvnf9hxeyjau7t",
|
||||
AppSecret: "FxXVlTzxrKXvJ8h-9uK0s5TjaBfOJSXumpmrHal-NmQAtku9wOPxcss0Af6WHoAK",
|
||||
}, &card_1_0.CreateAndDeliverRequest{
|
||||
CardTemplateId: tea.String("faad6d5d-726d-467f-a6ba-28c1930aa5f3.schema"),
|
||||
OutTrackId: tea.String(uuid),
|
||||
OutTrackId: tea.String(outTrackId),
|
||||
CallbackType: tea.String("STREAM"),
|
||||
CardData: &card_1_0.CreateAndDeliverRequestCardData{
|
||||
CardParamMap: map[string]*string{
|
||||
|
|
@ -525,6 +526,7 @@ func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Rec
|
|||
"button_right": tea.String("忽略"),
|
||||
"button_right_link": tea.String(""),
|
||||
"action_id": tea.String("create_group"),
|
||||
"button_display": tea.String("true"),
|
||||
"_CARD_DEBUG_TOOL_ENTRY": tea.String("show"),
|
||||
},
|
||||
},
|
||||
|
|
@ -534,9 +536,9 @@ func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Rec
|
|||
OpenSpaceId: tea.String("dtv1.card//im_group.cidwP24PLZhLVOS2dVIkEawLw=="),
|
||||
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
|
||||
RobotCode: tea.String("ding5wwvnf9hxeyjau7t"),
|
||||
// Recipients: []*string{
|
||||
// tea.String("17415698414368678"),
|
||||
// },
|
||||
Recipients: []*string{
|
||||
tea.String("17415698414368678"),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
package constants
|
||||
|
||||
import "net/url"
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const DingTalkBseUrl = "https://oapi.dingtalk.com"
|
||||
|
||||
|
|
@ -79,7 +84,35 @@ const (
|
|||
}`
|
||||
)
|
||||
|
||||
// 交互卡片回调类型
|
||||
const (
|
||||
CardActionCallbackTypeAction string = "actionCallback" // 交互卡片回调事件类型
|
||||
)
|
||||
|
||||
// 交互卡片回调事件类型
|
||||
const (
|
||||
CardActionTypeCreateGroup string = "create_group" // 创建群聊
|
||||
)
|
||||
|
||||
// dingtalk 卡片 OutTrackId 模板
|
||||
const CardOutTrackIdTemplate string = "{space_id}:{bot_id}:{uuid}"
|
||||
|
||||
func BuildCardOutTrackId(spaceId string, botId string) (outTrackId string) {
|
||||
uuid := uuid.New().String()
|
||||
|
||||
outTrackId = strings.ReplaceAll(CardOutTrackIdTemplate, "{space_id}", spaceId)
|
||||
outTrackId = strings.ReplaceAll(outTrackId, "{bot_id}", botId)
|
||||
outTrackId = strings.ReplaceAll(outTrackId, "{uuid}", uuid)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func ParseCardOutTrackId(outTrackId string) (spaceId string, botId string) {
|
||||
parts := strings.Split(outTrackId, ":")
|
||||
if len(parts) != 3 {
|
||||
return
|
||||
}
|
||||
spaceId, botId, _ = parts[0], parts[1], parts[2]
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ func NewBotGroupImpl(db *utils.Db) *BotGroupImpl {
|
|||
|
||||
func (k BotGroupImpl) GetByConversationIdAndRobotCode(staffId string, robotCode string) (*model.AiBotGroup, error) {
|
||||
var data model.AiBotGroup
|
||||
err := k.Db.Model(k.Model).Where("conversation_id = ? and robot_code = ?", staffId, robotCode).Find(&data).Error
|
||||
err := k.Db.Model(k.Model).Where("conversation_id = ? and robot_code = ? and status = 1", staffId, robotCode).Find(&data).Error
|
||||
if data.GroupID == 0 {
|
||||
err = sql.ErrNoRows
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type AiBotGroupConfig struct {
|
|||
ConfigID int32 `gorm:"column:config_id;primaryKey;autoIncrement:true" json:"config_id"`
|
||||
ToolList string `gorm:"column:tool_list;not null" json:"tool_list"`
|
||||
ProductName string `gorm:"column:product_name;not null" json:"product_name"`
|
||||
IssueOwner string `gorm:"column:issue_owner;comment:群组问题处理人" json:"issue_owner"` // 群组问题处理人
|
||||
}
|
||||
|
||||
// TableName AiBotGroupConfig's table name
|
||||
|
|
|
|||
|
|
@ -58,3 +58,28 @@ func (c *CardClient) CreateAndDeliver(req AppKey, cardData *card.CreateAndDelive
|
|||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 更新卡片
|
||||
func (c *CardClient) UpdateCard(req AppKey, cardData *card.UpdateCardRequest) (bool, error) {
|
||||
// 获取token
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 调用API
|
||||
resp, err := c.cli.UpdateCardWithOptions(
|
||||
cardData,
|
||||
&card.UpdateCardHeaders{XAcsDingtalkAccessToken: tea.String(accessToken)},
|
||||
&util.RuntimeOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if resp.Body == nil {
|
||||
return false, errorcode.ParamErrf("empty response body")
|
||||
}
|
||||
|
||||
return *resp.Body.Success, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import (
|
|||
"ai_scheduler/internal/biz"
|
||||
"ai_scheduler/internal/config"
|
||||
"ai_scheduler/internal/data/constants"
|
||||
"ai_scheduler/internal/data/impl"
|
||||
"ai_scheduler/internal/data/model"
|
||||
"ai_scheduler/internal/entitys"
|
||||
"ai_scheduler/internal/pkg/dingtalk"
|
||||
"context"
|
||||
|
|
@ -15,19 +17,33 @@ import (
|
|||
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/card"
|
||||
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
type DingBotService struct {
|
||||
config *config.Config
|
||||
dingTalkBotBiz *biz.DingTalkBotBiz
|
||||
dingTalkOld *dingtalk.OldClient
|
||||
config *config.Config
|
||||
dingTalkBotBiz *biz.DingTalkBotBiz
|
||||
dingTalkOld *dingtalk.OldClient
|
||||
dingtalkCardClient *dingtalk.CardClient
|
||||
botGroupConfigImpl *impl.BotGroupConfigImpl
|
||||
botGroupImpl *impl.BotGroupImpl
|
||||
}
|
||||
|
||||
func NewDingBotService(config *config.Config, dingTalkBotBiz *biz.DingTalkBotBiz, dingTalkOld *dingtalk.OldClient) *DingBotService {
|
||||
func NewDingBotService(
|
||||
config *config.Config,
|
||||
dingTalkBotBiz *biz.DingTalkBotBiz,
|
||||
dingTalkOld *dingtalk.OldClient,
|
||||
dingtalkCardClient *dingtalk.CardClient,
|
||||
botGroupConfigImpl *impl.BotGroupConfigImpl,
|
||||
botGroupImpl *impl.BotGroupImpl,
|
||||
) *DingBotService {
|
||||
return &DingBotService{
|
||||
config: config,
|
||||
dingTalkBotBiz: dingTalkBotBiz,
|
||||
dingTalkOld: dingTalkOld,
|
||||
config: config,
|
||||
dingTalkBotBiz: dingTalkBotBiz,
|
||||
dingTalkOld: dingTalkOld,
|
||||
dingtalkCardClient: dingtalkCardClient,
|
||||
botGroupConfigImpl: botGroupConfigImpl,
|
||||
botGroupImpl: botGroupImpl,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,26 +163,75 @@ func (d *DingBotService) runBackgroundTasks(ctx context.Context, data *chatbot.B
|
|||
return nil
|
||||
}
|
||||
|
||||
// **一把梭先搞,后续规范化**
|
||||
func (d *DingBotService) OnCardMessageReceived(ctx context.Context, data *card.CardRequest) (resp *card.CardResponse, err error) {
|
||||
// 解content
|
||||
var cardActionData card.PrivateCardActionData
|
||||
if err = json.Unmarshal([]byte(data.Content), &cardActionData); err != nil {
|
||||
return nil, err
|
||||
// 非回调类型暂不接受
|
||||
if data.Type != constants.CardActionCallbackTypeAction {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// action 处理
|
||||
for _, actionId := range cardActionData.CardPrivateData.ActionIdList {
|
||||
// action 处理 - 这里先只处理第一个匹配的actionId
|
||||
for _, actionId := range data.CardActionData.CardPrivateData.ActionIdList {
|
||||
switch actionId {
|
||||
case constants.CardActionTypeCreateGroup:
|
||||
if cardActionData.CardPrivateData.Params["status"] != "confirm" {
|
||||
continue
|
||||
}
|
||||
// 创建群聊
|
||||
if _, err = d.dingTalkOld.CreateInternalGroupConversation(ctx, "问题处理群", []string{"17415698414368678", "17101201090101570"}); err != nil {
|
||||
// 解析 OutTrackId 以获取 SpaceId 和 BotId
|
||||
spaceId, botId := constants.ParseCardOutTrackId(data.OutTrackId)
|
||||
// 群id+机器人id确认一个群配置
|
||||
var botGroup *model.AiBotGroup
|
||||
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{data.UserId} // 当前用户为群主
|
||||
for _, owner := range issueOwner {
|
||||
userIds = append(userIds, owner.UserId)
|
||||
}
|
||||
|
||||
if data.CardActionData.CardPrivateData.Params["status"] == "confirm" {
|
||||
// 创建群聊 - 这里用的是“统一登录平台”这个应用的接口
|
||||
// 不是很关心成功失败,ws中,后续考虑协程去创建
|
||||
if _, err = d.dingTalkOld.CreateInternalGroupConversation(ctx, "问题处理群", userIds); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 构建关闭创建群组卡片按钮的响应
|
||||
resp = d.buildCreateGroupCardResp()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return &card.CardResponse{}, nil
|
||||
}
|
||||
|
||||
// 关闭创建群组卡片按钮
|
||||
func (d *DingBotService) buildCreateGroupCardResp() *card.CardResponse {
|
||||
return &card.CardResponse{
|
||||
CardData: &card.CardDataDto{
|
||||
CardParamMap: map[string]string{
|
||||
"button_display": "false",
|
||||
},
|
||||
},
|
||||
CardUpdateOptions: &card.CardUpdateOptions{
|
||||
UpdateCardDataByKey: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue