ai_scheduler/internal/biz/handle/dingtalk/auth.go

119 lines
3.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/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()
if accessToken == "" {
dingTalkAuthRes, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
if _err != nil {
return nil, _err
}
err = a.redis.SetEx(ctx, a.getKey(clientId), dingTalkAuthRes.AccessToken, time.Duration(dingTalkAuthRes.ExpireIn-3600)*time.Second).Err()
if err != nil {
return
}
accessToken = dingTalkAuthRes.AccessToken
}
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 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 {
err = errors.New("botInfo is nil")
return
}
if botInfo.botConfig == nil {
var botConfigDo model.AiBotConfig
cond := builder.NewCond()
cond = cond.And(builder.Eq{"bot_id": botInfo.id})
err = a.botConfigImpl.GetOneBySearchToStrut(&cond, &botConfigDo)
if err != nil {
return
}
if botConfigDo.BotID == 0 {
err = errors.New("未找到机器人服务配置")
return
}
botInfo.botConfig = &botConfigDo
}
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
}
return a.GetAccessToken(ctx, botConfig.ClientId, botConfig.ClientSecret)
}