feat: new notification provider: discord bot

This commit is contained in:
Fu Diwei
2025-05-26 15:55:09 +08:00
parent cd9dac7765
commit 8e23b14bf3
21 changed files with 361 additions and 41 deletions

View File

@@ -0,0 +1,67 @@
package discordbot
import (
"context"
"fmt"
"log/slog"
"github.com/go-resty/resty/v2"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
type NotifierConfig struct {
// Discord Bot API Token。
BotToken string `json:"botToken"`
// Discord Channel ID。
ChannelId string `json:"channelId"`
}
type NotifierProvider struct {
config *NotifierConfig
logger *slog.Logger
httpClient *resty.Client
}
var _ notifier.Notifier = (*NotifierProvider)(nil)
func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
panic("config is nil")
}
client := resty.New()
return &NotifierProvider{
config: config,
logger: slog.Default(),
httpClient: client,
}, nil
}
func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
if logger == nil {
n.logger = slog.Default()
} else {
n.logger = logger
}
return n
}
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://discord.com/developers/docs/resources/message#create-message
req := n.httpClient.R().
SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bot "+n.config.BotToken).
SetBody(map[string]any{
"content": subject + "\n" + message,
})
resp, err := req.Post(fmt.Sprintf("https://discord.com/api/v9/channels/%s/messages", n.config.ChannelId))
if err != nil {
return nil, fmt.Errorf("discord api error: failed to send request: %w", err)
} else if resp.IsError() {
return nil, fmt.Errorf("discord api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return &notifier.NotifyResult{}, nil
}

View File

@@ -0,0 +1,64 @@
package discordbot_test
import (
"context"
"flag"
"fmt"
"strings"
"testing"
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
)
const (
mockSubject = "test_subject"
mockMessage = "test_message"
)
var (
fApiToken string
fChannelId string
)
func init() {
argsPrefix := "CERTIMATE_NOTIFIER_DISCORDBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "")
}
/*
Shell command to run this test:
go test -v ./discordbot_test.go -args \
--CERTIMATE_NOTIFIER_DISCORDBOT_APITOKEN="your-bot-token" \
--CERTIMATE_NOTIFIER_DISCORDBOT_CHANNELID="your-channel-id"
*/
func TestNotify(t *testing.T) {
flag.Parse()
t.Run("Notify", func(t *testing.T) {
t.Log(strings.Join([]string{
"args:",
fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("CHANNELID: %v", fChannelId),
}, "\n"))
notifier, err := provider.NewNotifier(&provider.NotifierConfig{
BotToken: fApiToken,
ChannelId: fChannelId,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
res, err := notifier.Notify(context.Background(), mockSubject, mockMessage)
if err != nil {
t.Errorf("err: %+v", err)
return
}
t.Logf("ok: %v", res)
})
}

View File

@@ -17,14 +17,14 @@ const (
var (
fApiToken string
fChartId int64
fChatId int64
)
func init() {
argsPrefix := "CERTIMATE_NOTIFIER_TELEGRAMBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.Int64Var(&fChartId, argsPrefix+"CHATID", 0, "")
flag.Int64Var(&fChatId, argsPrefix+"CHATID", 0, "")
}
/*
@@ -41,12 +41,12 @@ func TestNotify(t *testing.T) {
t.Log(strings.Join([]string{
"args:",
fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("CHATID: %v", fChartId),
fmt.Sprintf("CHATID: %v", fChatId),
}, "\n"))
notifier, err := provider.NewNotifier(&provider.NotifierConfig{
BotToken: fApiToken,
ChatId: fChartId,
ChatId: fChatId,
})
if err != nil {
t.Errorf("err: %+v", err)