refactor: optimize DingTalk integration and add new utilities
This commit is contained in:
parent
92bff0e4b9
commit
9c3f0300ad
|
|
@ -70,7 +70,7 @@ func (d *DingTalkBotBiz) InitRequire(ctx context.Context, data *chatbot.BotCallb
|
|||
}
|
||||
entitys.ResLog(requireData.Ch, "recognize_start", "收到消息,正在处理中,请稍等")
|
||||
|
||||
requireData.UserInfo, err = d.dingTalkUser.GetUserInfo(ctx, data.SenderStaffId, dingtalk.WithId(1))
|
||||
requireData.UserInfo, err = d.dingTalkUser.GetUserInfoFromBot(ctx, data.SenderStaffId, dingtalk.WithId(1))
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,30 +33,34 @@ func NewAuth(cfg *config.Config, redis *utils.Rdb, botConfigImpl *impl.BotConfig
|
|||
}
|
||||
}
|
||||
|
||||
func (a *Auth) GetAccessToken(ctx context.Context, clientId string, clientSecret string) (accessToken string, err error) {
|
||||
func (a *Auth) GetAccessToken(ctx context.Context, clientId string, clientSecret string) (authInfo *AuthInfo, err error) {
|
||||
if clientId == "" {
|
||||
return "", errors.New("clientId is empty")
|
||||
return nil, errors.New("clientId is empty")
|
||||
}
|
||||
accessToken = a.redis.Get(ctx, a.getKey(clientId)).Val()
|
||||
accessToken := a.redis.Get(ctx, a.getKey(clientId)).Val()
|
||||
if accessToken == "" {
|
||||
authInfo, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
|
||||
dingTalkAuthRes, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
|
||||
if _err != nil {
|
||||
return "", _err
|
||||
return nil, _err
|
||||
}
|
||||
err = a.redis.SetEx(ctx, a.getKey(clientId), authInfo.AccessToken, time.Duration(authInfo.ExpireIn-3600)*time.Second).Err()
|
||||
err = a.redis.SetEx(ctx, a.getKey(clientId), dingTalkAuthRes.AccessToken, time.Duration(dingTalkAuthRes.ExpireIn-3600)*time.Second).Err()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
accessToken = authInfo.AccessToken
|
||||
accessToken = dingTalkAuthRes.AccessToken
|
||||
}
|
||||
return
|
||||
return &AuthInfo{
|
||||
ClientId: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
AccessToken: accessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *Auth) getKey(clientId string) string {
|
||||
return a.cfg.Redis.Key + ":" + constants.DingTalkAuthBaseKeyPrefix + ":" + clientId
|
||||
}
|
||||
|
||||
func (a *Auth) getNewAccessToken(ctx context.Context, clientId string, clientSecret string) (auth AuthInfo, err error) {
|
||||
func (a *Auth) getNewAccessToken(ctx context.Context, clientId string, clientSecret string) (auth DingTalkAuthIRes, err error) {
|
||||
if clientId == "" || clientSecret == "" {
|
||||
err = errors.New("clientId or clientSecret is empty")
|
||||
return
|
||||
|
|
@ -79,7 +83,7 @@ func (a *Auth) getNewAccessToken(ctx context.Context, clientId string, clientSec
|
|||
return
|
||||
}
|
||||
|
||||
func (a *Auth) GetTokenFromBotOption(ctx context.Context, botOption ...BotOption) (token string, err error) {
|
||||
func (a *Auth) GetTokenFromBotOption(ctx context.Context, botOption ...BotOption) (token *AuthInfo, err error) {
|
||||
botInfo := &Bot{}
|
||||
for _, option := range botOption {
|
||||
option(botInfo)
|
||||
|
|
@ -98,7 +102,8 @@ func (a *Auth) GetTokenFromBotOption(ctx context.Context, botOption ...BotOption
|
|||
return
|
||||
}
|
||||
if botConfigDo.BotID == 0 {
|
||||
return "", errors.New("未找到机器人服务配置")
|
||||
err = errors.New("未找到机器人服务配置")
|
||||
return
|
||||
}
|
||||
botInfo.botConfig = &botConfigDo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@ func NewDept(dingDeptImpl *impl.BotDeptImpl, auth *Auth) *Dept {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int) (depts []*entitys.Dept, err error) {
|
||||
if len(deptIds) == 0 {
|
||||
func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int, authInfo *AuthInfo) (depts []*entitys.Dept, err error) {
|
||||
if len(deptIds) == 0 || authInfo == nil {
|
||||
return
|
||||
}
|
||||
deptsInfo := make([]model.AiBotDept, 0)
|
||||
var deptsInfo []model.AiBotDept
|
||||
cond := builder.NewCond()
|
||||
cond = cond.And(builder.Eq{"dingtalk_dept_id": deptIds})
|
||||
err = d.dingDeptImpl.GetRangeToMapStruct(&cond, deptsInfo)
|
||||
err = d.dingDeptImpl.GetRangeToMapStruct(&cond, &deptsInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -50,9 +50,9 @@ func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int) (depts [
|
|||
if len(diff) > 0 {
|
||||
deptDo := make([]model.AiBotDept, 0)
|
||||
for _, deptId := range diff {
|
||||
deptInfo, err := d.GetDeptInfoFromDingTalk(ctx, deptId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
deptInfo, _err := d.GetDeptInfoFromDingTalk(ctx, deptId, authInfo.AccessToken)
|
||||
if _err != nil {
|
||||
return nil, _err
|
||||
}
|
||||
depts = append(depts, &entitys.Dept{
|
||||
DeptId: deptInfo.DeptId,
|
||||
|
|
@ -74,12 +74,8 @@ func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int) (depts [
|
|||
return
|
||||
}
|
||||
|
||||
func (d *Dept) GetDeptInfoFromDingTalk(ctx context.Context, deptId int, botOption ...BotOption) (depts DeptResResult, err error) {
|
||||
if deptId == 0 {
|
||||
return
|
||||
}
|
||||
token, err := d.auth.GetTokenFromBotOption(ctx, botOption...)
|
||||
if err != nil {
|
||||
func (d *Dept) GetDeptInfoFromDingTalk(ctx context.Context, deptId int, token string) (depts DeptResResult, err error) {
|
||||
if deptId == 0 || len(token) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dingtalk
|
|||
|
||||
import "time"
|
||||
|
||||
type AuthInfo struct {
|
||||
type DingTalkAuthIRes struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
ExpireIn int64 `json:"expireIn"`
|
||||
}
|
||||
|
|
@ -76,3 +76,9 @@ type DeptResResult struct {
|
|||
DeptId int `json:"dept_id"`
|
||||
} `json:"union_dept_ext"`
|
||||
}
|
||||
|
||||
type AuthInfo struct {
|
||||
ClientId string `json:"clientId"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func NewUser(
|
|||
}
|
||||
}
|
||||
|
||||
func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...BotOption) (userInfo *entitys.DingTalkUserInfo, err error) {
|
||||
func (u *User) GetUserInfoFromBot(ctx context.Context, staffId string, botOption ...BotOption) (userInfo *entitys.DingTalkUserInfo, err error) {
|
||||
if len(staffId) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
@ -46,9 +46,13 @@ func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...Bot
|
|||
return
|
||||
}
|
||||
}
|
||||
authInfo, err := u.auth.GetTokenFromBotOption(ctx, botOption...)
|
||||
if err != nil || authInfo == nil {
|
||||
return
|
||||
}
|
||||
//如果没有找到,则新增
|
||||
if user == nil {
|
||||
DingUserInfo, _err := u.getUserInfoFromDingTalkWithBot(ctx, staffId, botOption...)
|
||||
DingUserInfo, _err := u.getUserInfoFromDingTalk(ctx, authInfo.AccessToken, staffId)
|
||||
if _err != nil {
|
||||
return nil, _err
|
||||
}
|
||||
|
|
@ -60,7 +64,7 @@ func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...Bot
|
|||
DeptIDList: strings.Join(pkg.SliceIntToString(DingUserInfo.DeptIdList), ","),
|
||||
IsBoss: int32(pkg.Ter(DingUserInfo.Boss, constants.IsBossTrue, constants.IsBossFalse)),
|
||||
IsSenior: int32(pkg.Ter(DingUserInfo.Senior, constants.IsSeniorTrue, constants.IsSeniorFalse)),
|
||||
HiredDate: time.Unix(DingUserInfo.HiredDate, 0),
|
||||
HiredDate: time.UnixMilli(DingUserInfo.HiredDate),
|
||||
}
|
||||
|
||||
_, err = u.dingUserImpl.Add(user)
|
||||
|
|
@ -79,7 +83,7 @@ func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...Bot
|
|||
}
|
||||
if len(user.DeptIDList) > 0 {
|
||||
deptIdList := pkg.SliceStringToInt(strings.Split(user.DeptIDList, ","))
|
||||
depts, _err := u.dept.GetDeptInfoByDeptIds(ctx, deptIdList)
|
||||
depts, _err := u.dept.GetDeptInfoByDeptIds(ctx, deptIdList, authInfo)
|
||||
if _err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -91,14 +95,6 @@ func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...Bot
|
|||
return userInfo, nil
|
||||
}
|
||||
|
||||
func (u *User) getUserInfoFromDingTalkWithBot(ctx context.Context, staffId string, botOption ...BotOption) (userInfo UserInfoResResult, err error) {
|
||||
token, err := u.auth.GetTokenFromBotOption(ctx, botOption...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return u.getUserInfoFromDingTalk(ctx, token, staffId)
|
||||
}
|
||||
|
||||
func (u *User) getUserInfoFromDingTalk(ctx context.Context, token string, staffId string) (user UserInfoResResult, err error) {
|
||||
if token == "" && staffId == "" {
|
||||
err = errors.New("获取钉钉用户信息的必要参数不足")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const TableNameAiBotDept = "ai_bot_dept"
|
||||
|
||||
// AiBotDept mapped from table <ai_bot_dept>
|
||||
type AiBotDept struct {
|
||||
DeptID int32 `gorm:"column:dept_id;primaryKey" json:"dept_id"`
|
||||
DingtalkDeptID int32 `gorm:"column:dingtalk_dept_id;not null;comment:标记部门的唯一id,钉钉:钉钉侧提供的dept_id" json:"dingtalk_dept_id"` // 标记部门的唯一id,钉钉:钉钉侧提供的dept_id
|
||||
Name string `gorm:"column:name;not null;comment:用户名称" json:"name"` // 用户名称
|
||||
Status int32 `gorm:"column:status;not null" json:"status"`
|
||||
DeleteAt time.Time `gorm:"column:delete_at" json:"delete_at"`
|
||||
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||
}
|
||||
|
||||
// TableName AiBotDept's table name
|
||||
func (*AiBotDept) TableName() string {
|
||||
return TableNameAiBotDept
|
||||
}
|
||||
|
|
@ -12,19 +12,19 @@ const TableNameAiBotUser = "ai_bot_user"
|
|||
|
||||
// AiBotUser mapped from table <ai_bot_user>
|
||||
type AiBotUser struct {
|
||||
UserID int32 `gorm:"column:user_id;primaryKey" json:"user_id"`
|
||||
StaffID string `gorm:"column:staff_id;not null;comment:标记用户用的唯一id,钉钉:钉钉侧提供的user_id" json:"staff_id"` // 标记用户用的唯一id,钉钉:钉钉侧提供的user_id
|
||||
Name string `gorm:"column:name;not null;comment:用户名称" json:"name"` // 用户名称
|
||||
Title string `gorm:"column:title;not null;comment:职位" json:"title"` // 职位
|
||||
Extension string `gorm:"column:extension;not null;default:1;comment:信息面板" json:"extension"` // 信息面板
|
||||
RoleList string `gorm:"column:role_list;not null;comment:角色列表。" json:"role_list"` // 角色列表。
|
||||
DeptIDList string `gorm:"column:dept_id_list;not null;comment:所在部门id列表" json:"dept_id_list"` // 所在部门id列表
|
||||
IsBoss int32 `gorm:"column:is_boss;not null;comment:是否是老板" json:"is_boss"` // 是否是老板
|
||||
IsSenior int32 `gorm:"column:is_senior;not null;comment:是否是高管" json:"is_senior"` // 是否是高管
|
||||
HiredDate time.Time `gorm:"column:hired_date;not null;default:CURRENT_TIMESTAMP;comment:入职时间" json:"hired_date"` // 入职时间
|
||||
Status int32 `gorm:"column:status;not null" json:"status"`
|
||||
DeleteAt time.Time `gorm:"column:delete_at" json:"delete_at"`
|
||||
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||
UserID int32 `gorm:"column:user_id;primaryKey" json:"user_id"`
|
||||
StaffID string `gorm:"column:staff_id;not null;comment:标记用户用的唯一id,钉钉:钉钉侧提供的user_id" json:"staff_id"` // 标记用户用的唯一id,钉钉:钉钉侧提供的user_id
|
||||
Name string `gorm:"column:name;not null;comment:用户名称" json:"name"` // 用户名称
|
||||
Title string `gorm:"column:title;not null;comment:职位" json:"title"` // 职位
|
||||
Extension string `gorm:"column:extension;not null;default:1;comment:信息面板" json:"extension"` // 信息面板
|
||||
RoleList string `gorm:"column:role_list;not null;comment:角色列表。" json:"role_list"` // 角色列表。
|
||||
DeptIDList string `gorm:"column:dept_id_list;not null;comment:所在部门id列表" json:"dept_id_list"` // 所在部门id列表
|
||||
IsBoss int32 `gorm:"column:is_boss;not null;comment:是否是老板" json:"is_boss"` // 是否是老板
|
||||
IsSenior int32 `gorm:"column:is_senior;not null;comment:是否是高管" json:"is_senior"` // 是否是高管
|
||||
HiredDate time.Time `gorm:"column:hired_date;not null;default:CURRENT_TIMESTAMP;comment:入职时间" json:"hired_date"` // 入职时间
|
||||
Status int32 `gorm:"column:status;not null" json:"status"`
|
||||
DeleteAt *time.Time `gorm:"column:delete_at" json:"delete_at"`
|
||||
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||
}
|
||||
|
||||
// TableName AiBotUser's table name
|
||||
|
|
|
|||
|
|
@ -114,23 +114,22 @@ func Difference[T comparable](a, b []T) []T {
|
|||
|
||||
// SliceStringToInt []string=>[]int
|
||||
func SliceStringToInt(strSlice []string) []int {
|
||||
numSlice := make([]int, len(strSlice), 0)
|
||||
for _, str := range strSlice {
|
||||
numSlice := make([]int, len(strSlice))
|
||||
for i, str := range strSlice {
|
||||
num, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
numSlice = append(numSlice, num)
|
||||
numSlice[i] = num
|
||||
}
|
||||
return numSlice
|
||||
}
|
||||
|
||||
// SliceIntToString []int=>[]string
|
||||
func SliceIntToString(slice []int) []string {
|
||||
numSlice := make([]string, len(slice), 0)
|
||||
for _, str := range slice {
|
||||
|
||||
numSlice = append(numSlice, strconv.Itoa(str))
|
||||
strSlice := make([]string, len(slice)) // len=cap=len(slice)
|
||||
for i, num := range slice {
|
||||
strSlice[i] = strconv.Itoa(num) // 直接赋值,无 append
|
||||
}
|
||||
return numSlice
|
||||
return strSlice
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue