1. 增加钉钉IM客户端,增加创建并投放卡片方法 2.规范化多处配置获取代码 3.增加获取入群二维码链接方法 4.调整加群流程为 确认加群-创建群聊-将机器人添加到新群-获取新群分享链接-点击跳转至新群
This commit is contained in:
parent
a0b76f1581
commit
534da15898
|
|
@ -309,7 +309,7 @@ func (r *Handle) getUserDingtalkUnionId(ctx context.Context, accessToken, sessio
|
|||
creatorName := session.UserName
|
||||
|
||||
// 获取创建者uid 用户名 -> dingtalk uid
|
||||
creatorId, err := r.dingtalkContactClient.SearchUserOne(accessToken, creatorName)
|
||||
creatorId, err := r.dingtalkContactClient.SearchUserOne(dingtalk.AppKey{AccessToken: accessToken}, creatorName)
|
||||
if err != nil {
|
||||
log.Warnf("search dingtalk user one failed: %v", err)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ func (g *GroupConfigBiz) handleMatch(ctx context.Context, rec *entitys.Recognize
|
|||
case constants.TaskTypeCozeWorkflow:
|
||||
return g.handleCozeWorkflow(ctx, rec, pointTask)
|
||||
case constants.TaskTypeKnowle: // 知识库V2版本
|
||||
return g.handleKnowledgeV2(ctx, rec, pointTask)
|
||||
return g.handleKnowledgeV2(ctx, rec, groupConfig)
|
||||
// return g.handleKnowledgeV3(ctx, rec, pointTask)
|
||||
default:
|
||||
return g.otherTask(ctx, rec)
|
||||
|
|
@ -473,7 +473,7 @@ func (g *GroupConfigBiz) GetReportCache(ctx context.Context, day time.Time, tota
|
|||
}
|
||||
|
||||
// handleKnowledgeV2 处理知识库V2版本
|
||||
func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Recognize, pointTask *model.AiBotTool) (err error) {
|
||||
func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Recognize, groupConfig *model.AiBotGroupConfig) (err error) {
|
||||
req := l_request.Request{
|
||||
Method: "POST",
|
||||
Url: "http://127.0.0.1:9600/query",
|
||||
|
|
@ -499,12 +499,24 @@ func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Rec
|
|||
return
|
||||
}
|
||||
|
||||
// var DingtalkGroupCaseOwner = map[string][]string{
|
||||
// "cidwP24PLZhLVOS2dVIkEawLw==": {"付仲云", "贺泽琨", "任志远"},
|
||||
// }
|
||||
|
||||
// 未检索到匹配信息,询问是否拉群
|
||||
if !isRetrieved {
|
||||
// 获取群问题处理人
|
||||
type issueOwnerType struct {
|
||||
UserId string `json:"userid"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
var issueOwner []issueOwnerType
|
||||
if err = json.Unmarshal([]byte(groupConfig.IssueOwner), &issueOwner); err != nil {
|
||||
return fmt.Errorf("解析群问题处理人失败,err: %v", err)
|
||||
}
|
||||
// 合并所有name
|
||||
var userNames []string
|
||||
for _, owner := range issueOwner {
|
||||
userNames = append(userNames, "@"+owner.Name)
|
||||
}
|
||||
issueOwnerStr := strings.Join(userNames, "、")
|
||||
|
||||
// 构建卡片 OutTrackId
|
||||
outTrackId := constants.BuildCardOutTrackId("cidwP24PLZhLVOS2dVIkEawLw==", "ding5wwvnf9hxeyjau7t")
|
||||
|
||||
|
|
@ -519,7 +531,7 @@ func (g *GroupConfigBiz) handleKnowledgeV2(ctx context.Context, rec *entitys.Rec
|
|||
CardData: &card_1_0.CreateAndDeliverRequestCardData{
|
||||
CardParamMap: map[string]*string{
|
||||
"title": tea.String("群创建提醒"),
|
||||
"content": tea.String("**确认创建群聊?**\n\n将邀请以下成员加入群聊:\n\n@张三、@李四"),
|
||||
"content": tea.String(fmt.Sprintf("**确认创建群聊?**\n\n将邀请以下成员加入群聊:\n\n%s", issueOwnerStr)),
|
||||
"remark": tea.String("注:如若无需,忽略即可"),
|
||||
"button_left": tea.String("点击进群"),
|
||||
"button_left_link": tea.String(""),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package dingtalk
|
||||
|
||||
import (
|
||||
"ai_scheduler/internal/config"
|
||||
errorcode "ai_scheduler/internal/data/error"
|
||||
|
||||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
|
|
@ -11,30 +10,27 @@ import (
|
|||
)
|
||||
|
||||
type CardClient struct {
|
||||
config *config.Config
|
||||
cli *card.Client
|
||||
oauth2Client *Oauth2Client
|
||||
}
|
||||
|
||||
func NewCardClient(config *config.Config, oauth2Client *Oauth2Client) (*CardClient, error) {
|
||||
func NewCardClient(oauth2Client *Oauth2Client) (*CardClient, error) {
|
||||
cfg := &openapi.Config{
|
||||
AccessKeyId: tea.String(config.Tools.DingTalkBot.APIKey),
|
||||
AccessKeySecret: tea.String(config.Tools.DingTalkBot.APISecret),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
}
|
||||
c, err := card.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CardClient{config: config, cli: c, oauth2Client: oauth2Client}, nil
|
||||
return &CardClient{cli: c, oauth2Client: oauth2Client}, nil
|
||||
}
|
||||
|
||||
// 创建并投放卡片
|
||||
func (c *CardClient) CreateAndDeliver(req AppKey, cardData *card.CreateAndDeliverRequest) (bool, error) {
|
||||
func (c *CardClient) CreateAndDeliver(appKey AppKey, cardData *card.CreateAndDeliverRequest) (bool, error) {
|
||||
// 获取token
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(req)
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(appKey)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -60,9 +56,9 @@ func (c *CardClient) CreateAndDeliver(req AppKey, cardData *card.CreateAndDelive
|
|||
}
|
||||
|
||||
// 更新卡片
|
||||
func (c *CardClient) UpdateCard(req AppKey, cardData *card.UpdateCardRequest) (bool, error) {
|
||||
func (c *CardClient) UpdateCard(appKey AppKey, cardData *card.UpdateCardRequest) (bool, error) {
|
||||
// 获取token
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(req)
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(appKey)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package dingtalk
|
||||
|
||||
import (
|
||||
"ai_scheduler/internal/config"
|
||||
errorcode "ai_scheduler/internal/data/error"
|
||||
|
||||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
|
|
@ -11,22 +10,20 @@ import (
|
|||
)
|
||||
|
||||
type ContactClient struct {
|
||||
config *config.Config
|
||||
cli *contact.Client
|
||||
cli *contact.Client
|
||||
oauth2Client *Oauth2Client
|
||||
}
|
||||
|
||||
func NewContactClient(config *config.Config) (*ContactClient, error) {
|
||||
func NewContactClient(oauth2Client *Oauth2Client) (*ContactClient, error) {
|
||||
cfg := &openapi.Config{
|
||||
AccessKeyId: tea.String(config.Tools.DingTalkBot.APIKey),
|
||||
AccessKeySecret: tea.String(config.Tools.DingTalkBot.APISecret),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
}
|
||||
c, err := contact.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ContactClient{config: config, cli: c}, nil
|
||||
return &ContactClient{cli: c, oauth2Client: oauth2Client}, nil
|
||||
}
|
||||
|
||||
type SearchUserReq struct {
|
||||
|
|
@ -40,15 +37,23 @@ type SearchUserResp struct {
|
|||
Body interface{}
|
||||
}
|
||||
|
||||
func (c *ContactClient) SearchUserOne(accessToken string, name string) (string, error) {
|
||||
headers := &contact.SearchUserHeaders{}
|
||||
headers.XAcsDingtalkAccessToken = tea.String(accessToken)
|
||||
resp, err := c.cli.SearchUserWithOptions(&contact.SearchUserRequest{
|
||||
FullMatchField: tea.Int32(1),
|
||||
QueryWord: tea.String(name),
|
||||
Offset: tea.Int32(0),
|
||||
Size: tea.Int32(1),
|
||||
}, headers, &util.RuntimeOptions{})
|
||||
func (c *ContactClient) SearchUserOne(appKey AppKey, name string) (string, error) {
|
||||
// 获取token
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(appKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := c.cli.SearchUserWithOptions(
|
||||
&contact.SearchUserRequest{
|
||||
FullMatchField: tea.Int32(1),
|
||||
QueryWord: tea.String(name),
|
||||
Offset: tea.Int32(0),
|
||||
Size: tea.Int32(1),
|
||||
},
|
||||
&contact.SearchUserHeaders{XAcsDingtalkAccessToken: tea.String(accessToken)},
|
||||
&util.RuntimeOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
package dingtalk
|
||||
|
||||
import (
|
||||
errorcode "ai_scheduler/internal/data/error"
|
||||
|
||||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
im "github.com/alibabacloud-go/dingtalk/im_1_0"
|
||||
util "github.com/alibabacloud-go/tea-utils/v2/service"
|
||||
"github.com/alibabacloud-go/tea/tea"
|
||||
)
|
||||
|
||||
type ImClient struct {
|
||||
cli *im.Client
|
||||
oauth2Client *Oauth2Client
|
||||
}
|
||||
|
||||
func NewImClient(oauth2Client *Oauth2Client) (*ImClient, error) {
|
||||
cfg := &openapi.Config{
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
}
|
||||
c, err := im.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ImClient{cli: c, oauth2Client: oauth2Client}, nil
|
||||
}
|
||||
|
||||
// 创建并投放卡片
|
||||
func (c *ImClient) AddRobotToConversation(appKey AppKey, imData *im.AddRobotToConversationRequest) (string, error) {
|
||||
// 获取token
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(appKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 调用API
|
||||
resp, err := c.cli.AddRobotToConversationWithOptions(
|
||||
imData,
|
||||
&im.AddRobotToConversationHeaders{XAcsDingtalkAccessToken: tea.String(accessToken)},
|
||||
&util.RuntimeOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.Body == nil {
|
||||
return "", errorcode.ParamErrf("empty response body")
|
||||
}
|
||||
|
||||
return *resp.Body.ChatBotUserId, nil
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package dingtalk
|
||||
|
||||
import (
|
||||
"ai_scheduler/internal/config"
|
||||
errorcode "ai_scheduler/internal/data/error"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
|
@ -13,22 +12,20 @@ import (
|
|||
)
|
||||
|
||||
type NotableClient struct {
|
||||
config *config.Config
|
||||
cli *notable.Client
|
||||
cli *notable.Client
|
||||
oauth2Client *Oauth2Client
|
||||
}
|
||||
|
||||
func NewNotableClient(config *config.Config) (*NotableClient, error) {
|
||||
func NewNotableClient(oauth2Client *Oauth2Client) (*NotableClient, error) {
|
||||
cfg := &openapi.Config{
|
||||
AccessKeyId: tea.String(config.Tools.DingTalkBot.APIKey),
|
||||
AccessKeySecret: tea.String(config.Tools.DingTalkBot.APISecret),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
}
|
||||
c, err := notable.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NotableClient{config: config, cli: c}, nil
|
||||
return &NotableClient{cli: c, oauth2Client: oauth2Client}, nil
|
||||
}
|
||||
|
||||
type UpdateRecordReq struct {
|
||||
|
|
@ -43,9 +40,13 @@ type UpdateRecordsserResp struct {
|
|||
Body interface{}
|
||||
}
|
||||
|
||||
func (c *NotableClient) UpdateRecord(accessToken string, req *UpdateRecordReq) (bool, error) {
|
||||
headers := ¬able.UpdateRecordsHeaders{}
|
||||
headers.XAcsDingtalkAccessToken = tea.String(accessToken)
|
||||
func (c *NotableClient) UpdateRecord(appKey AppKey, req *UpdateRecordReq) (bool, error) {
|
||||
// 获取token
|
||||
accessToken, err := c.oauth2Client.GetAccessToken(appKey)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := c.cli.UpdateRecordsWithOptions(
|
||||
tea.String(req.BaseId),
|
||||
tea.String(req.SheetId),
|
||||
|
|
@ -63,7 +64,10 @@ func (c *NotableClient) UpdateRecord(accessToken string, req *UpdateRecordReq) (
|
|||
Id: tea.String(req.RecordId),
|
||||
},
|
||||
},
|
||||
}, headers, &util.RuntimeOptions{})
|
||||
},
|
||||
¬able.UpdateRecordsHeaders{XAcsDingtalkAccessToken: tea.String(accessToken)},
|
||||
&util.RuntimeOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package dingtalk
|
||||
|
||||
import (
|
||||
"ai_scheduler/internal/config"
|
||||
errorcode "ai_scheduler/internal/data/error"
|
||||
"ai_scheduler/utils"
|
||||
"context"
|
||||
|
|
@ -15,32 +14,35 @@ import (
|
|||
)
|
||||
|
||||
type Oauth2Client struct {
|
||||
config *config.Config
|
||||
cli *oauth2.Client
|
||||
redisCli *redis.Client
|
||||
}
|
||||
|
||||
func NewOauth2Client(config *config.Config, rds *utils.Rdb) (*Oauth2Client, error) {
|
||||
func NewOauth2Client(rds *utils.Rdb) (*Oauth2Client, error) {
|
||||
cfg := &openapi.Config{
|
||||
AccessKeyId: tea.String(config.Tools.DingTalkBot.APIKey),
|
||||
AccessKeySecret: tea.String(config.Tools.DingTalkBot.APISecret),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
}
|
||||
c, err := oauth2.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Oauth2Client{config: config, cli: c, redisCli: rds.Rdb}, nil
|
||||
return &Oauth2Client{cli: c, redisCli: rds.Rdb}, nil
|
||||
}
|
||||
|
||||
type AppKey struct {
|
||||
AppKey string `json:"appKey"`
|
||||
AppSecret string `json:"appSecret"`
|
||||
AppKey string `json:"appKey"`
|
||||
AppSecret string `json:"appSecret"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
|
||||
// GetAccessToken 获取access token
|
||||
func (c *Oauth2Client) GetAccessToken(req AppKey) (string, error) {
|
||||
// 兼容直接传入 access token 场景
|
||||
if req.AccessToken != "" {
|
||||
return req.AccessToken, nil
|
||||
}
|
||||
|
||||
// 取cache
|
||||
ctx := context.Background()
|
||||
accessToken, err := c.redisCli.Get(ctx, fmt.Sprintf("dingtalk:oauth2:%s:access_token", req.AppKey)).Result()
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ func (c *OldClient) GetAccessToken() (string, error) {
|
|||
}
|
||||
|
||||
// CreateInternalGroupConversation 创建企业内部群聊
|
||||
func (c *OldClient) CreateInternalGroupConversation(ctx context.Context, groupName string, userIds []string) (string, error) {
|
||||
func (c *OldClient) CreateInternalGroupConversation(ctx context.Context, groupName string, userIds []string) (chatId, openConversationId string, err error) {
|
||||
body := struct {
|
||||
Name string `json:"name"`
|
||||
Owner string `json:"owner"`
|
||||
|
|
@ -130,9 +130,10 @@ func (c *OldClient) CreateInternalGroupConversation(ctx context.Context, groupNa
|
|||
UserIds: userIds,
|
||||
}
|
||||
b, _ := json.Marshal(body)
|
||||
res, err := c.do(ctx, http.MethodPost, "/chat/create", b)
|
||||
var res []byte
|
||||
res, err = c.do(ctx, http.MethodPost, "/chat/create", b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return
|
||||
}
|
||||
var resp struct {
|
||||
Code int `json:"errcode"`
|
||||
|
|
@ -141,11 +142,37 @@ func (c *OldClient) CreateInternalGroupConversation(ctx context.Context, groupNa
|
|||
OpenConversationId string `json:"openConversationId"`
|
||||
ConversationTag int `json:"conversationTag"`
|
||||
}
|
||||
if err = json.Unmarshal(res, &resp); err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Code != 0 {
|
||||
return "", "", errors.New(resp.Msg)
|
||||
}
|
||||
|
||||
return resp.ChatId, resp.OpenConversationId, nil
|
||||
}
|
||||
|
||||
// 获取入群二维码链接
|
||||
func (c *OldClient) GetJoinGroupQrcode(ctx context.Context, chatId, userId string) (string, error) {
|
||||
body := struct {
|
||||
ChatId string `json:"chatid"`
|
||||
UserId string `json:"userid"`
|
||||
}{ChatId: chatId, UserId: userId}
|
||||
b, _ := json.Marshal(body)
|
||||
res, err := c.do(ctx, http.MethodPost, "/topapi/chat/qrcode/get", b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var resp struct {
|
||||
Code int `json:"errcode"`
|
||||
Msg string `json:"errmsg"`
|
||||
Result string `json:"result"`
|
||||
}
|
||||
if err := json.Unmarshal(res, &resp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resp.Code != 0 {
|
||||
return "", errors.New(resp.Msg)
|
||||
}
|
||||
return resp.OpenConversationId, nil
|
||||
return resp.Result, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package dingtalk
|
||||
|
||||
import (
|
||||
"ai_scheduler/internal/config"
|
||||
errorcode "ai_scheduler/internal/data/error"
|
||||
"encoding/json"
|
||||
|
||||
|
|
@ -12,22 +11,19 @@ import (
|
|||
)
|
||||
|
||||
type RobotClient struct {
|
||||
config *config.Config
|
||||
cli *robot.Client
|
||||
cli *robot.Client
|
||||
}
|
||||
|
||||
func NewRobotClient(config *config.Config) (*RobotClient, error) {
|
||||
func NewRobotClient() (*RobotClient, error) {
|
||||
cfg := &openapi.Config{
|
||||
AccessKeyId: tea.String(config.Tools.DingTalkBot.APIKey),
|
||||
AccessKeySecret: tea.String(config.Tools.DingTalkBot.APISecret),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
Protocol: tea.String("https"),
|
||||
RegionId: tea.String("central"),
|
||||
}
|
||||
c, err := robot.NewClient(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RobotClient{config: config, cli: c}, nil
|
||||
return &RobotClient{cli: c}, nil
|
||||
}
|
||||
|
||||
type SendGroupMessagesReq struct {
|
||||
|
|
@ -37,17 +33,19 @@ type SendGroupMessagesReq struct {
|
|||
RobotCode string
|
||||
}
|
||||
|
||||
func (c *RobotClient) SendGroupMessages(accessToken string, req *SendGroupMessagesReq) (string, error) {
|
||||
headers := &robot.OrgGroupSendHeaders{}
|
||||
headers.XAcsDingtalkAccessToken = tea.String(accessToken)
|
||||
func (c *RobotClient) SendGroupMessages(appKey AppKey, req *SendGroupMessagesReq) (string, error) {
|
||||
msgParamBytes, _ := json.Marshal(req.MsgParam)
|
||||
msgParamJson := string(msgParamBytes)
|
||||
resp, err := c.cli.OrgGroupSendWithOptions(&robot.OrgGroupSendRequest{
|
||||
MsgKey: tea.String(req.MsgKey),
|
||||
MsgParam: tea.String(msgParamJson),
|
||||
OpenConversationId: tea.String(req.OpenConversationId),
|
||||
RobotCode: tea.String(req.RobotCode),
|
||||
}, headers, &util.RuntimeOptions{})
|
||||
resp, err := c.cli.OrgGroupSendWithOptions(
|
||||
&robot.OrgGroupSendRequest{
|
||||
MsgKey: tea.String(req.MsgKey),
|
||||
MsgParam: tea.String(msgParamJson),
|
||||
OpenConversationId: tea.String(req.OpenConversationId),
|
||||
RobotCode: tea.String(req.RobotCode),
|
||||
},
|
||||
&robot.OrgGroupSendHeaders{XAcsDingtalkAccessToken: tea.String(appKey.AccessToken)},
|
||||
&util.RuntimeOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ var ProviderSetClient = wire.NewSet(
|
|||
// dingtalk.NewRobotClient,
|
||||
dingtalk.NewOauth2Client,
|
||||
dingtalk.NewCardClient,
|
||||
dingtalk.NewImClient,
|
||||
|
||||
utils_oss.NewClient,
|
||||
lsxd.NewLogin,
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ func (s *CallbackService) handleBugOptimizationSubmitUpdate(ctx context.Context,
|
|||
|
||||
// 获取创建者uid
|
||||
accessToken, _ := s.dingtalkOldClient.GetAccessToken()
|
||||
creatorId, err := s.dingtalkContactClient.SearchUserOne(accessToken, data.Creator)
|
||||
creatorId, err := s.dingtalkContactClient.SearchUserOne(dingtalk.AppKey{AccessToken: accessToken}, data.Creator)
|
||||
if err != nil {
|
||||
return "", errorcode.ParamErrf("invalid data type: %v", err)
|
||||
}
|
||||
|
|
@ -286,7 +286,7 @@ func (s *CallbackService) handleBugOptimizationSubmitUpdate(ctx context.Context,
|
|||
unionId := userDetails.UnionID
|
||||
|
||||
// 更新记录
|
||||
ok, err := s.dingtalkNotableClient.UpdateRecord(accessToken, &dingtalk.UpdateRecordReq{
|
||||
ok, err := s.dingtalkNotableClient.UpdateRecord(dingtalk.AppKey{AccessToken: accessToken}, &dingtalk.UpdateRecordReq{
|
||||
BaseId: data.BaseId,
|
||||
SheetId: data.SheetId,
|
||||
RecordId: data.RecordId,
|
||||
|
|
|
|||
|
|
@ -10,12 +10,16 @@ import (
|
|||
"ai_scheduler/internal/pkg/dingtalk"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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/dingtalk/im_1_0"
|
||||
"github.com/alibabacloud-go/tea/tea"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
|
@ -25,8 +29,10 @@ type DingBotService struct {
|
|||
dingTalkBotBiz *biz.DingTalkBotBiz
|
||||
dingTalkOld *dingtalk.OldClient
|
||||
dingtalkCardClient *dingtalk.CardClient
|
||||
dingtalkImClient *dingtalk.ImClient
|
||||
botGroupConfigImpl *impl.BotGroupConfigImpl
|
||||
botGroupImpl *impl.BotGroupImpl
|
||||
botConfigImpl *impl.BotConfigImpl
|
||||
}
|
||||
|
||||
func NewDingBotService(
|
||||
|
|
@ -34,16 +40,20 @@ func NewDingBotService(
|
|||
dingTalkBotBiz *biz.DingTalkBotBiz,
|
||||
dingTalkOld *dingtalk.OldClient,
|
||||
dingtalkCardClient *dingtalk.CardClient,
|
||||
dingtalkImClient *dingtalk.ImClient,
|
||||
botGroupConfigImpl *impl.BotGroupConfigImpl,
|
||||
botGroupImpl *impl.BotGroupImpl,
|
||||
botConfigImpl *impl.BotConfigImpl,
|
||||
) *DingBotService {
|
||||
return &DingBotService{
|
||||
config: config,
|
||||
dingTalkBotBiz: dingTalkBotBiz,
|
||||
dingTalkOld: dingTalkOld,
|
||||
dingtalkCardClient: dingtalkCardClient,
|
||||
dingtalkImClient: dingtalkImClient,
|
||||
botGroupConfigImpl: botGroupConfigImpl,
|
||||
botGroupImpl: botGroupImpl,
|
||||
botConfigImpl: botConfigImpl,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,51 +180,95 @@ func (d *DingBotService) OnCardMessageReceived(ctx context.Context, data *card.C
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// 卡片同步回调超时时间为2s,2s内同步返回,2s后异步更新卡片
|
||||
startTime := time.Now()
|
||||
|
||||
// action 处理 - 这里先只处理第一个匹配的actionId
|
||||
for _, actionId := range data.CardActionData.CardPrivateData.ActionIdList {
|
||||
switch actionId {
|
||||
case constants.CardActionTypeCreateGroup:
|
||||
// 解析 OutTrackId 以获取 SpaceId 和 BotId
|
||||
spaceId, botId := constants.ParseCardOutTrackId(data.OutTrackId)
|
||||
// 群id+机器人id确认一个群配置
|
||||
var botGroup *model.AiBotGroup
|
||||
botGroup, err = d.botGroupImpl.GetByConversationIdAndRobotCode(spaceId, botId)
|
||||
|
||||
// 获取新群聊人员
|
||||
var userIds []string
|
||||
userIds, err = d.buildNewGroupUserIds(ctx, spaceId, botId, data.UserId)
|
||||
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)
|
||||
}
|
||||
|
||||
// 新群分享链接
|
||||
newGroupShareLink := ""
|
||||
timeOutLimit := 1500 * time.Millisecond
|
||||
|
||||
// 钉钉appKey
|
||||
appKey := dingtalk.AppKey{}
|
||||
|
||||
if data.CardActionData.CardPrivateData.Params["status"] == "confirm" {
|
||||
// 创建群聊 - 这里用的是“统一登录平台”这个应用的接口
|
||||
// 不是很关心成功失败,ws中,后续考虑协程去创建
|
||||
if _, err = d.dingTalkOld.CreateInternalGroupConversation(ctx, "问题处理群", userIds); err != nil {
|
||||
chatId, openConversationId, err := d.dingTalkOld.CreateInternalGroupConversation(ctx, "问题处理群", userIds)
|
||||
if err != nil {
|
||||
fmt.Printf("创建群聊失败: %v", err)
|
||||
}
|
||||
|
||||
_ = openConversationId
|
||||
// 获取机器人配置
|
||||
var botConfig model.AiBotConfig
|
||||
cond := builder.NewCond().And(builder.Eq{"robot_code": botId})
|
||||
err = d.botConfigImpl.GetOneBySearchToStrut(&cond, &botConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 解出 config
|
||||
var config entitys.DingTalkBot
|
||||
err = json.Unmarshal([]byte(botConfig.BotConfig), &config)
|
||||
if err != nil {
|
||||
log.Printf("配置解析失败 %v", err.Error())
|
||||
}
|
||||
appKey = dingtalk.AppKey{
|
||||
AppKey: config.ClientId,
|
||||
AppSecret: config.ClientSecret,
|
||||
}
|
||||
|
||||
// 添加当前机器人到新群
|
||||
_, err = d.dingtalkImClient.AddRobotToConversation(
|
||||
appKey,
|
||||
&im_1_0.AddRobotToConversationRequest{
|
||||
OpenConversationId: tea.String(openConversationId),
|
||||
RobotCode: tea.String(botId),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("添加机器人到会话失败: %v", err)
|
||||
}
|
||||
|
||||
// 返回新群分享链接,直接进群
|
||||
newGroupShareLink, err = d.dingTalkOld.GetJoinGroupQrcode(ctx, chatId, data.UserId)
|
||||
if err != nil {
|
||||
fmt.Printf("获取入群二维码失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
endTime := time.Now()
|
||||
if endTime.Sub(startTime) > timeOutLimit {
|
||||
// 异步更新卡片
|
||||
d.dingtalkCardClient.UpdateCard(appKey, &card_1_0.UpdateCardRequest{
|
||||
OutTrackId: tea.String(data.OutTrackId),
|
||||
CardData: &card_1_0.UpdateCardRequestCardData{
|
||||
CardParamMap: map[string]*string{
|
||||
"button_display": tea.String("false"),
|
||||
"new_group_share_link": tea.String(newGroupShareLink),
|
||||
},
|
||||
},
|
||||
CardUpdateOptions: &card_1_0.UpdateCardRequestCardUpdateOptions{
|
||||
UpdateCardDataByKey: tea.Bool(true),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 构建关闭创建群组卡片按钮的响应
|
||||
resp = d.buildCreateGroupCardResp()
|
||||
resp = d.buildCreateGroupCardResp(newGroupShareLink)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -222,12 +276,49 @@ func (d *DingBotService) OnCardMessageReceived(ctx context.Context, data *card.C
|
|||
return &card.CardResponse{}, nil
|
||||
}
|
||||
|
||||
// 关闭创建群组卡片按钮
|
||||
func (d *DingBotService) buildCreateGroupCardResp() *card.CardResponse {
|
||||
// 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
|
||||
}
|
||||
|
||||
// buildCreateGroupCardResp 构建关闭创建群组卡片按钮
|
||||
func (d *DingBotService) buildCreateGroupCardResp(newGroupShareLink string) *card.CardResponse {
|
||||
return &card.CardResponse{
|
||||
CardData: &card.CardDataDto{
|
||||
CardParamMap: map[string]string{
|
||||
"button_display": "false",
|
||||
"button_display": "false",
|
||||
"new_group_share_link": newGroupShareLink,
|
||||
},
|
||||
},
|
||||
CardUpdateOptions: &card.CardUpdateOptions{
|
||||
|
|
|
|||
Loading…
Reference in New Issue