mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-09-29 14:46:38 +08:00
127 lines
2.6 KiB
Go
127 lines
2.6 KiB
Go
package channel
|
|
|
|
import (
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"one-api/common/requester"
|
|
"one-api/types"
|
|
"time"
|
|
)
|
|
|
|
const dingTalkURL = "https://oapi.dingtalk.com/robot/send?"
|
|
|
|
type DingTalk struct {
|
|
token string
|
|
secret string
|
|
keyWord string
|
|
}
|
|
|
|
type dingTalkMessage struct {
|
|
MsgType string `json:"msgtype"`
|
|
Markdown struct {
|
|
Title string `json:"title"`
|
|
Text string `json:"text"`
|
|
} `json:"markdown"`
|
|
}
|
|
|
|
type dingTalkResponse struct {
|
|
ErrCode int `json:"errcode"`
|
|
ErrMsg string `json:"errmsg"`
|
|
}
|
|
|
|
func NewDingTalk(token string, secret string) *DingTalk {
|
|
return &DingTalk{
|
|
token: token,
|
|
secret: secret,
|
|
}
|
|
}
|
|
|
|
func NewDingTalkWithKeyWord(token string, keyWord string) *DingTalk {
|
|
return &DingTalk{
|
|
token: token,
|
|
keyWord: keyWord,
|
|
}
|
|
}
|
|
|
|
func (d *DingTalk) Name() string {
|
|
return "DingTalk"
|
|
}
|
|
|
|
func (d *DingTalk) Send(ctx context.Context, title, message string) error {
|
|
msg := dingTalkMessage{
|
|
MsgType: "markdown",
|
|
}
|
|
msg.Markdown.Title = title
|
|
msg.Markdown.Text = message
|
|
|
|
if d.keyWord != "" {
|
|
msg.Markdown.Text = fmt.Sprintf("%s\n%s", d.keyWord, msg.Markdown.Text)
|
|
}
|
|
|
|
query := url.Values{}
|
|
query.Set("access_token", d.token)
|
|
if d.secret != "" {
|
|
t := time.Now().UnixMilli()
|
|
query.Set("timestamp", fmt.Sprintf("%d", t))
|
|
query.Set("sign", d.sign(t))
|
|
}
|
|
uri := dingTalkURL + query.Encode()
|
|
|
|
client := requester.NewHTTPRequester("", dingtalkErrFunc)
|
|
client.Context = ctx
|
|
client.IsOpenAI = false
|
|
|
|
req, err := client.NewRequest(http.MethodPost, uri, client.WithHeader(requester.GetJsonHeaders()), client.WithBody(msg))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
resp, errWithOP := client.SendRequestRaw(req)
|
|
if errWithOP != nil {
|
|
return fmt.Errorf("%s", errWithOP.Message)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
dingtalkErr := dingtalkErrFunc(resp)
|
|
if dingtalkErr != nil {
|
|
return fmt.Errorf("%s", dingtalkErr.Message)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *DingTalk) sign(timestamp int64) string {
|
|
stringToHash := fmt.Sprintf("%d\n%s", timestamp, d.secret)
|
|
hmac256 := hmac.New(sha256.New, []byte(d.secret))
|
|
hmac256.Write([]byte(stringToHash))
|
|
data := hmac256.Sum(nil)
|
|
signature := base64.StdEncoding.EncodeToString(data)
|
|
|
|
return url.QueryEscape(signature)
|
|
}
|
|
|
|
func dingtalkErrFunc(resp *http.Response) *types.OpenAIError {
|
|
respMsg := &dingTalkResponse{}
|
|
|
|
err := json.NewDecoder(resp.Body).Decode(respMsg)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
if respMsg.ErrCode == 0 {
|
|
return nil
|
|
}
|
|
|
|
return &types.OpenAIError{
|
|
Message: fmt.Sprintf("send msg err. err msg: %s", respMsg.ErrMsg),
|
|
Type: "dingtalk_error",
|
|
Code: fmt.Sprintf("%d", respMsg.ErrCode),
|
|
}
|
|
}
|