package dingtalk import ( "ai_scheduler/internal/config" "bytes" "context" "encoding/json" "errors" "io" "net/http" "net/url" "os" "github.com/faabiosr/cachego/file" "github.com/fastwego/dingding" ) type Client struct { cfg *config.Config sdkClient *dingding.Client atm *dingding.DefaultAccessTokenManager } func NewDingTalkClient(cfg *config.Config) *Client { atm := &dingding.DefaultAccessTokenManager{ Id: cfg.Tools.DingTalkBot.APIKey, Name: "access_token", GetRefreshRequestFunc: func() *http.Request { params := url.Values{} params.Add("appkey", cfg.Tools.DingTalkBot.APIKey) params.Add("appsecret", cfg.Tools.DingTalkBot.APISecret) req, _ := http.NewRequest(http.MethodGet, dingding.ServerUrl+"/gettoken?"+params.Encode(), nil) return req }, Cache: file.New(os.TempDir()), } return &Client{cfg: cfg, sdkClient: dingding.NewClient(atm), atm: atm} } type UserDetail struct { UserID string `json:"userid"` Name string `json:"name"` UnionID string `json:"unionid"` } func (c *Client) do(ctx context.Context, method, path string, body []byte) ([]byte, error) { var r io.Reader if body != nil { r = bytes.NewReader(body) } req, err := http.NewRequestWithContext(ctx, method, path, r) if err != nil { return nil, err } if body != nil { req.Header.Set("Content-Type", "application/json") } return c.sdkClient.Do(req) } func (c *Client) QueryUserDetails(ctx context.Context, userId string) (*UserDetail, error) { body := struct { UserId string `json:"userid"` Language string `json:"language,omitempty"` }{UserId: userId, Language: "zh_CN"} b, _ := json.Marshal(body) res, err := c.do(ctx, http.MethodPost, "/topapi/v2/user/get", b) if err != nil { return nil, err } var resp struct { Code int `json:"errcode"` Msg string `json:"errmsg"` Result UserDetail `json:"result"` } if err := json.Unmarshal(res, &resp); err != nil { return nil, err } if resp.Code != 0 { return nil, errors.New(resp.Msg) } return &resp.Result, nil } func (c *Client) QueryUserDetailsByMobile(ctx context.Context, mobile string) (*UserDetail, error) { body := struct { Mobile string `json:"mobile"` }{Mobile: mobile} b, _ := json.Marshal(body) res, err := c.do(ctx, http.MethodPost, "/topapi/v2/user/getbymobile", b) if err != nil { return nil, err } var resp struct { Code int `json:"errcode"` Msg string `json:"errmsg"` Result UserDetail `json:"result"` } if err := json.Unmarshal(res, &resp); err != nil { return nil, err } if resp.Code != 0 { return nil, errors.New(resp.Msg) } return &resp.Result, nil } // GetAccessToken 通过 fastwego 的 AccessTokenManager 获取当前可用 access_token func (c *Client) GetAccessToken() (string, error) { return c.atm.GetAccessToken() }