diff --git a/pkg/core/notifier/providers/larkbot/larkbot.go b/pkg/core/notifier/providers/larkbot/larkbot.go index 96a570d21..c297cf5c3 100644 --- a/pkg/core/notifier/providers/larkbot/larkbot.go +++ b/pkg/core/notifier/providers/larkbot/larkbot.go @@ -2,11 +2,13 @@ package larkbot import ( "context" + "encoding/json" "errors" "fmt" "log/slog" + "net/url" - "github.com/go-lark/lark" + "github.com/go-resty/resty/v2" "github.com/certimate-go/certimate/pkg/core" ) @@ -17,8 +19,9 @@ type NotifierProviderConfig struct { } type NotifierProvider struct { - config *NotifierProviderConfig - logger *slog.Logger + config *NotifierProviderConfig + logger *slog.Logger + httpClient *resty.Client } var _ core.Notifier = (*NotifierProvider)(nil) @@ -28,9 +31,14 @@ func NewNotifierProvider(config *NotifierProviderConfig) (*NotifierProvider, err return nil, errors.New("the configuration of the notifier provider is nil") } + client := resty.New(). + SetHeader("Content-Type", "application/json"). + SetHeader("User-Agent", "certimate") + return &NotifierProvider{ - config: config, - logger: slog.Default(), + config: config, + logger: slog.Default(), + httpClient: client, }, nil } @@ -43,17 +51,40 @@ func (n *NotifierProvider) SetLogger(logger *slog.Logger) { } func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (*core.NotifyResult, error) { - bot := lark.NewNotificationBot(n.config.WebhookUrl) - content := lark.NewPostBuilder(). - Title(subject). - TextTag(message, 1, false). - Render() - msg := lark.NewMsgBuffer(lark.MsgPost).Post(content) - resp, err := bot.PostNotificationV2(msg.Build()) + webhookUrl, err := url.Parse(n.config.WebhookUrl) if err != nil { - return nil, fmt.Errorf("lark api error: %w", err) - } else if resp.Code != 0 { - return nil, fmt.Errorf("lark api error: code='%d', message='%s'", resp.Code, resp.Msg) + return nil, fmt.Errorf("lark api error: invalid webhook url: %w", err) + } else { + const hostname = "open.larksuite.com" + const hostname_cn = "open.feishu.cn" + if webhookUrl.Hostname() != hostname && webhookUrl.Hostname() != hostname_cn { + n.logger.Warn(fmt.Sprintf("the webhook url hostname is not '%s' or '%s', please make sure it is correct", hostname, hostname_cn)) + } + } + + // REF: https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot + // REF: https://open.larksuite.com/document/client-docs/bot-v3/add-custom-bot + var result struct { + Code int `json:"code"` + Message string `json:"msg"` + } + req := n.httpClient.R(). + SetContext(ctx). + SetBody(map[string]any{ + "msg_type": "text", + "content": map[string]string{ + "text": subject + "\n\n" + message, + }, + }) + resp, err := req.Post(webhookUrl.String()) + if err != nil { + return nil, fmt.Errorf("lark api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("lark api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) + } else if err := json.Unmarshal(resp.Body(), &result); err != nil { + return nil, fmt.Errorf("lark api error: failed to unmarshal response: %w", err) + } else if result.Code != 0 { + return nil, fmt.Errorf("lark api error: code='%d', msg='%s'", result.Code, result.Message) } return &core.NotifyResult{}, nil