160 lines
4.0 KiB
Go
160 lines
4.0 KiB
Go
package dingtalk
|
|
|
|
import (
|
|
"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"
|
|
"ai_scheduler/internal/pkg/l_request"
|
|
"ai_scheduler/utils"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2/log"
|
|
"github.com/redis/go-redis/v9"
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
type Auth struct {
|
|
redis *redis.Client
|
|
cfg *config.Config
|
|
botConfigImpl *impl.BotConfigImpl
|
|
}
|
|
|
|
func NewAuth(cfg *config.Config, redis *utils.Rdb, botConfigImpl *impl.BotConfigImpl) *Auth {
|
|
return &Auth{
|
|
redis: redis.Rdb,
|
|
cfg: cfg,
|
|
botConfigImpl: botConfigImpl,
|
|
}
|
|
}
|
|
|
|
func (a *Auth) GetAccessToken(ctx context.Context, clientId string, clientSecret string) (authInfo *AuthInfo, err error) {
|
|
if clientId == "" {
|
|
return nil, errors.New("clientId is empty")
|
|
}
|
|
accessToken := a.redis.Get(ctx, a.getKey(clientId)).Val()
|
|
var expire time.Duration
|
|
if accessToken == "" {
|
|
dingTalkAuthRes, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
|
|
if _err != nil {
|
|
return nil, _err
|
|
}
|
|
expire = time.Duration(dingTalkAuthRes.ExpireIn-3600) * time.Second
|
|
err = a.redis.SetEx(ctx, a.getKey(clientId), dingTalkAuthRes.AccessToken, expire).Err()
|
|
if err != nil {
|
|
return
|
|
}
|
|
accessToken = dingTalkAuthRes.AccessToken
|
|
} else {
|
|
expire, _ = a.redis.TTL(ctx, a.getKey(clientId)).Result()
|
|
}
|
|
return &AuthInfo{
|
|
ClientId: clientId,
|
|
ClientSecret: clientSecret,
|
|
AccessToken: accessToken,
|
|
Expire: expire,
|
|
}, nil
|
|
}
|
|
|
|
func (a *Auth) getKey(clientId string) string {
|
|
return a.cfg.Redis.Key + ":" + constants.DingTalkAuthBaseKeyPrefix + ":" + clientId
|
|
}
|
|
|
|
func (a *Auth) getKeyBot(botCode string) string {
|
|
return a.cfg.Redis.Key + ":" + constants.DingTalkAuthBaseKeyBotPrefix + ":" + botCode
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
req := l_request.Request{
|
|
Method: http.MethodPost,
|
|
Url: "https://api.dingtalk.com/v1.0/oauth2/accessToken",
|
|
Json: map[string]interface{}{
|
|
"appKey": clientId,
|
|
"appSecret": clientSecret,
|
|
},
|
|
}
|
|
res, err := req.Send()
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = json.Unmarshal(res.Content, &auth)
|
|
|
|
return
|
|
}
|
|
|
|
func (a *Auth) GetTokenFromBotOption(ctx context.Context, botOption ...BotOption) (token *AuthInfo, err error) {
|
|
botInfo := &Bot{}
|
|
for _, option := range botOption {
|
|
option(botInfo)
|
|
}
|
|
|
|
if botInfo.Id == 0 && botInfo.BotConfig == nil && botInfo.BotCode == "" {
|
|
err = errors.New("botInfo is nil")
|
|
return
|
|
}
|
|
|
|
if botInfo.BotConfig == nil {
|
|
err = a.GetBotConfigFromModel(botInfo)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
authInfo := a.redis.Get(ctx, a.getKeyBot(botInfo.BotConfig.RobotCode)).Val()
|
|
if authInfo == "" {
|
|
var botConfig entitys.DingTalkBot
|
|
err = json.Unmarshal([]byte(botInfo.BotConfig.BotConfig), &botConfig)
|
|
if err != nil {
|
|
log.Infof("初始化“%s”失败:%s", botInfo.BotConfig.BotName, err.Error())
|
|
return
|
|
}
|
|
token, err = a.GetAccessToken(ctx, botConfig.ClientId, botConfig.ClientSecret)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = a.redis.SetEx(ctx, a.getKeyBot(botInfo.BotConfig.RobotCode), pkg.JsonStringIgonErr(token), token.Expire).Err()
|
|
if err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
var tokenData AuthInfo
|
|
err = json.Unmarshal([]byte(authInfo), &tokenData)
|
|
token = &tokenData
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a *Auth) GetBotConfigFromModel(botInfo *Bot) (err error) {
|
|
var (
|
|
botConfigDo model.AiBotConfig
|
|
)
|
|
cond := builder.NewCond()
|
|
if botInfo.Id > 0 {
|
|
cond = cond.And(builder.Eq{"bot_id": botInfo.Id})
|
|
}
|
|
if botInfo.BotCode != "" {
|
|
cond = cond.And(builder.Eq{"robot_code": botInfo.BotCode})
|
|
}
|
|
err = a.botConfigImpl.GetOneBySearchToStrut(&cond, &botConfigDo)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if botConfigDo.BotID == 0 {
|
|
err = errors.New("未找到机器人服务配置")
|
|
return
|
|
}
|
|
botInfo.BotConfig = &botConfigDo
|
|
return nil
|
|
}
|