mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-07-02 06:14:27 +08:00
172 lines
5.3 KiB
Go
172 lines
5.3 KiB
Go
// Copyright 2019 Yunion
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package sender
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/util/httputils"
|
|
|
|
api "yunion.io/x/onecloud/pkg/apis/notify"
|
|
"yunion.io/x/onecloud/pkg/notify/models"
|
|
)
|
|
|
|
type SDingTalkSender struct {
|
|
config map[string]api.SNotifyConfigContent
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) GetSenderType() string {
|
|
return api.DINGTALK
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) Send(ctx context.Context, args api.SendParams) error {
|
|
body := map[string]interface{}{
|
|
"agent_id": models.ConfigMap[fmt.Sprintf("%s-%s", api.DINGTALK, args.DomainId)].Content.AgentId,
|
|
"msg": map[string]interface{}{
|
|
"msgtype": "markdown",
|
|
"markdown": map[string]interface{}{
|
|
"title": args.Title,
|
|
"text": fmt.Sprintf("%s (%s)", args.Message, time.Now().Format("2006-01-02 15:04")),
|
|
},
|
|
},
|
|
"userid_list": args.Receivers.Contact,
|
|
}
|
|
params := url.Values{}
|
|
params.Set("access_token", models.ConfigMap[fmt.Sprintf("%s-%s", api.DINGTALK, args.DomainId)].Content.AccessToken)
|
|
req, err := sendRequest(ctx, ApiDingtalkSendMessage, httputils.POST, nil, params, jsonutils.Marshal(body))
|
|
if err != nil {
|
|
subCode, _ := req.GetString("sub_code")
|
|
switch subCode {
|
|
// token失效或不合法
|
|
case "40014":
|
|
// 尝试重新获取token
|
|
err = dingSender.GetAccessToken(ctx, fmt.Sprintf("%s-%s", api.DINGTALK, args.DomainId))
|
|
if err != nil {
|
|
return errors.Wrap(err, "reset token")
|
|
}
|
|
// 重新发送通知
|
|
params = url.Values{}
|
|
params.Set("access_token", models.ConfigMap[fmt.Sprintf("%s-%s", api.DINGTALK, args.DomainId)].Content.AccessToken)
|
|
req, err = sendRequest(ctx, ApiDingtalkSendMessage, httputils.POST, nil, params, jsonutils.Marshal(body))
|
|
if err != nil {
|
|
return errors.Wrap(err, "dingtalk resend message")
|
|
}
|
|
}
|
|
if err != nil {
|
|
return errors.Wrap(err, "dingtalk send message")
|
|
}
|
|
}
|
|
|
|
// 获取消息通知发送结果
|
|
task_id, _ := req.GetString("task_id")
|
|
body = map[string]interface{}{
|
|
"agent_id": models.ConfigMap[fmt.Sprintf("%s-%s", api.DINGTALK, args.DomainId)].Content.AgentId,
|
|
"task_id": task_id,
|
|
}
|
|
_, err = sendRequest(ctx, ApiDingtalkSendMessage, httputils.POST, nil, params, jsonutils.Marshal(body))
|
|
return err
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) ValidateConfig(ctx context.Context, config api.NotifyConfig) (string, error) {
|
|
// 校验accesstoken
|
|
_, err := dingSender.getAccessToken(ctx, config.AppKey, config.AppSecret)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "40089") {
|
|
return "invalid AppKey or AppSecret", err
|
|
}
|
|
return "", err
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) ContactByMobile(ctx context.Context, mobile, domainId string) (string, error) {
|
|
err := dingSender.GetAccessToken(ctx, domainId)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
body := jsonutils.Marshal(map[string]interface{}{
|
|
"mobile": mobile,
|
|
})
|
|
params := url.Values{}
|
|
params.Set("access_token", models.ConfigMap[fmt.Sprintf("%s-%s", api.DINGTALK, domainId)].Content.AccessToken)
|
|
res, err := sendRequest(ctx, ApiDingtalkGetUserByMobile, httputils.POST, nil, params, body)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "get user by mobile")
|
|
}
|
|
userId, err := res.GetString("result", "userid")
|
|
if err != nil {
|
|
return "", errors.Wrapf(err, "user result:%v", res)
|
|
}
|
|
return userId, err
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) IsPersonal() bool {
|
|
return true
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) IsRobot() bool {
|
|
return false
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) IsValid() bool {
|
|
return len(dingSender.config) > 0
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) IsPullType() bool {
|
|
return true
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) IsSystemConfigContactType() bool {
|
|
return true
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) RegisterConfig(config models.SConfig) {
|
|
models.ConfigMap[fmt.Sprintf("%s-%s", config.Type, config.DomainId)] = config
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) GetAccessToken(ctx context.Context, domainId string) error {
|
|
key := fmt.Sprintf("%s-%s", api.DINGTALK, domainId)
|
|
appKey, appSecret := models.ConfigMap[key].Content.AppKey, models.ConfigMap[key].Content.AppSecret
|
|
token, err := dingSender.getAccessToken(ctx, appKey, appSecret)
|
|
if err != nil {
|
|
return errors.Wrap(err, "dingtalk getAccessToken")
|
|
}
|
|
models.ConfigMap[key].Content.AccessToken = token
|
|
return nil
|
|
}
|
|
|
|
func (dingSender *SDingTalkSender) getAccessToken(ctx context.Context, appKey, appSecret string) (string, error) {
|
|
params := url.Values{}
|
|
params.Set("appkey", appKey)
|
|
params.Set("appsecret", appSecret)
|
|
res, err := sendRequest(ctx, ApiDingtalkGetToken, httputils.GET, nil, params, nil)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "get dingtalk token")
|
|
}
|
|
return res.GetString("access_token")
|
|
}
|
|
|
|
func init() {
|
|
models.Register(&SDingTalkSender{
|
|
config: map[string]api.SNotifyConfigContent{},
|
|
})
|
|
}
|