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", "收到消息,正在处理中,请稍等")
|
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
|
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 == "" {
|
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 == "" {
|
if accessToken == "" {
|
||||||
authInfo, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
|
dingTalkAuthRes, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
|
||||||
if _err != nil {
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
accessToken = authInfo.AccessToken
|
accessToken = dingTalkAuthRes.AccessToken
|
||||||
}
|
}
|
||||||
return
|
return &AuthInfo{
|
||||||
|
ClientId: clientId,
|
||||||
|
ClientSecret: clientSecret,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Auth) getKey(clientId string) string {
|
func (a *Auth) getKey(clientId string) string {
|
||||||
return a.cfg.Redis.Key + ":" + constants.DingTalkAuthBaseKeyPrefix + ":" + clientId
|
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 == "" {
|
if clientId == "" || clientSecret == "" {
|
||||||
err = errors.New("clientId or clientSecret is empty")
|
err = errors.New("clientId or clientSecret is empty")
|
||||||
return
|
return
|
||||||
|
|
@ -79,7 +83,7 @@ func (a *Auth) getNewAccessToken(ctx context.Context, clientId string, clientSec
|
||||||
return
|
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{}
|
botInfo := &Bot{}
|
||||||
for _, option := range botOption {
|
for _, option := range botOption {
|
||||||
option(botInfo)
|
option(botInfo)
|
||||||
|
|
@ -98,7 +102,8 @@ func (a *Auth) GetTokenFromBotOption(ctx context.Context, botOption ...BotOption
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if botConfigDo.BotID == 0 {
|
if botConfigDo.BotID == 0 {
|
||||||
return "", errors.New("未找到机器人服务配置")
|
err = errors.New("未找到机器人服务配置")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
botInfo.botConfig = &botConfigDo
|
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) {
|
func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int, authInfo *AuthInfo) (depts []*entitys.Dept, err error) {
|
||||||
if len(deptIds) == 0 {
|
if len(deptIds) == 0 || authInfo == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deptsInfo := make([]model.AiBotDept, 0)
|
var deptsInfo []model.AiBotDept
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
cond = cond.And(builder.Eq{"dingtalk_dept_id": deptIds})
|
cond = cond.And(builder.Eq{"dingtalk_dept_id": deptIds})
|
||||||
err = d.dingDeptImpl.GetRangeToMapStruct(&cond, deptsInfo)
|
err = d.dingDeptImpl.GetRangeToMapStruct(&cond, &deptsInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -50,9 +50,9 @@ func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int) (depts [
|
||||||
if len(diff) > 0 {
|
if len(diff) > 0 {
|
||||||
deptDo := make([]model.AiBotDept, 0)
|
deptDo := make([]model.AiBotDept, 0)
|
||||||
for _, deptId := range diff {
|
for _, deptId := range diff {
|
||||||
deptInfo, err := d.GetDeptInfoFromDingTalk(ctx, deptId)
|
deptInfo, _err := d.GetDeptInfoFromDingTalk(ctx, deptId, authInfo.AccessToken)
|
||||||
if err != nil {
|
if _err != nil {
|
||||||
return nil, err
|
return nil, _err
|
||||||
}
|
}
|
||||||
depts = append(depts, &entitys.Dept{
|
depts = append(depts, &entitys.Dept{
|
||||||
DeptId: deptInfo.DeptId,
|
DeptId: deptInfo.DeptId,
|
||||||
|
|
@ -74,12 +74,8 @@ func (d *Dept) GetDeptInfoByDeptIds(ctx context.Context, deptIds []int) (depts [
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dept) GetDeptInfoFromDingTalk(ctx context.Context, deptId int, botOption ...BotOption) (depts DeptResResult, err error) {
|
func (d *Dept) GetDeptInfoFromDingTalk(ctx context.Context, deptId int, token string) (depts DeptResResult, err error) {
|
||||||
if deptId == 0 {
|
if deptId == 0 || len(token) == 0 {
|
||||||
return
|
|
||||||
}
|
|
||||||
token, err := d.auth.GetTokenFromBotOption(ctx, botOption...)
|
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package dingtalk
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type AuthInfo struct {
|
type DingTalkAuthIRes struct {
|
||||||
AccessToken string `json:"accessToken"`
|
AccessToken string `json:"accessToken"`
|
||||||
ExpireIn int64 `json:"expireIn"`
|
ExpireIn int64 `json:"expireIn"`
|
||||||
}
|
}
|
||||||
|
|
@ -76,3 +76,9 @@ type DeptResResult struct {
|
||||||
DeptId int `json:"dept_id"`
|
DeptId int `json:"dept_id"`
|
||||||
} `json:"union_dept_ext"`
|
} `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 {
|
if len(staffId) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -46,9 +46,13 @@ func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...Bot
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
authInfo, err := u.auth.GetTokenFromBotOption(ctx, botOption...)
|
||||||
|
if err != nil || authInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
//如果没有找到,则新增
|
//如果没有找到,则新增
|
||||||
if user == nil {
|
if user == nil {
|
||||||
DingUserInfo, _err := u.getUserInfoFromDingTalkWithBot(ctx, staffId, botOption...)
|
DingUserInfo, _err := u.getUserInfoFromDingTalk(ctx, authInfo.AccessToken, staffId)
|
||||||
if _err != nil {
|
if _err != nil {
|
||||||
return nil, _err
|
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), ","),
|
DeptIDList: strings.Join(pkg.SliceIntToString(DingUserInfo.DeptIdList), ","),
|
||||||
IsBoss: int32(pkg.Ter(DingUserInfo.Boss, constants.IsBossTrue, constants.IsBossFalse)),
|
IsBoss: int32(pkg.Ter(DingUserInfo.Boss, constants.IsBossTrue, constants.IsBossFalse)),
|
||||||
IsSenior: int32(pkg.Ter(DingUserInfo.Senior, constants.IsSeniorTrue, constants.IsSeniorFalse)),
|
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)
|
_, 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 {
|
if len(user.DeptIDList) > 0 {
|
||||||
deptIdList := pkg.SliceStringToInt(strings.Split(user.DeptIDList, ","))
|
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 {
|
if _err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -91,14 +95,6 @@ func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...Bot
|
||||||
return userInfo, nil
|
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) {
|
func (u *User) getUserInfoFromDingTalk(ctx context.Context, token string, staffId string) (user UserInfoResResult, err error) {
|
||||||
if token == "" && staffId == "" {
|
if token == "" && staffId == "" {
|
||||||
err = errors.New("获取钉钉用户信息的必要参数不足")
|
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
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ type AiBotUser struct {
|
||||||
IsSenior int32 `gorm:"column:is_senior;not null;comment:是否是高管" json:"is_senior"` // 是否是高管
|
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"` // 入职时间
|
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"`
|
Status int32 `gorm:"column:status;not null" json:"status"`
|
||||||
DeleteAt time.Time `gorm:"column:delete_at" json:"delete_at"`
|
DeleteAt *time.Time `gorm:"column:delete_at" json:"delete_at"`
|
||||||
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,23 +114,22 @@ func Difference[T comparable](a, b []T) []T {
|
||||||
|
|
||||||
// SliceStringToInt []string=>[]int
|
// SliceStringToInt []string=>[]int
|
||||||
func SliceStringToInt(strSlice []string) []int {
|
func SliceStringToInt(strSlice []string) []int {
|
||||||
numSlice := make([]int, len(strSlice), 0)
|
numSlice := make([]int, len(strSlice))
|
||||||
for _, str := range strSlice {
|
for i, str := range strSlice {
|
||||||
num, err := strconv.Atoi(str)
|
num, err := strconv.Atoi(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
numSlice = append(numSlice, num)
|
numSlice[i] = num
|
||||||
}
|
}
|
||||||
return numSlice
|
return numSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
// SliceIntToString []int=>[]string
|
// SliceIntToString []int=>[]string
|
||||||
func SliceIntToString(slice []int) []string {
|
func SliceIntToString(slice []int) []string {
|
||||||
numSlice := make([]string, len(slice), 0)
|
strSlice := make([]string, len(slice)) // len=cap=len(slice)
|
||||||
for _, str := range slice {
|
for i, num := range slice {
|
||||||
|
strSlice[i] = strconv.Itoa(num) // 直接赋值,无 append
|
||||||
numSlice = append(numSlice, strconv.Itoa(str))
|
|
||||||
}
|
}
|
||||||
return numSlice
|
return strSlice
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue