mirror of
https://github.com/usual2970/certimate.git
synced 2025-10-04 13:34:52 +00:00
feat: new notification provider: discord bot
This commit is contained in:
@@ -121,6 +121,11 @@ type AccessConfigForDingTalkBot struct {
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type AccessConfigForDiscordBot struct {
|
||||
BotToken string `json:"botToken"`
|
||||
DefaultChannelId string `json:"defaultChannelId,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForDNSLA struct {
|
||||
ApiId string `json:"apiId"`
|
||||
ApiSecret string `json:"apiSecret"`
|
||||
|
@@ -33,6 +33,7 @@ const (
|
||||
AccessProviderTypeDeSEC = AccessProviderType("desec")
|
||||
AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean")
|
||||
AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot")
|
||||
AccessProviderTypeDiscordBot = AccessProviderType("discordbot")
|
||||
AccessProviderTypeDNSLA = AccessProviderType("dnsla")
|
||||
AccessProviderTypeDogeCloud = AccessProviderType("dogecloud")
|
||||
AccessProviderTypeDuckDNS = AccessProviderType("duckdns")
|
||||
@@ -269,6 +270,7 @@ type NotificationProviderType string
|
||||
*/
|
||||
const (
|
||||
NotificationProviderTypeDingTalkBot = NotificationProviderType(AccessProviderTypeDingTalkBot)
|
||||
NotificationProviderTypeDiscordBot = NotificationProviderType(AccessProviderTypeDiscordBot)
|
||||
NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail)
|
||||
NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot)
|
||||
NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost)
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||
pDingTalkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot"
|
||||
pDiscordBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
|
||||
pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||
pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot"
|
||||
pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost"
|
||||
@@ -42,6 +43,19 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
||||
})
|
||||
}
|
||||
|
||||
case domain.NotificationProviderTypeDiscordBot:
|
||||
{
|
||||
access := domain.AccessConfigForDiscordBot{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
return pDiscordBot.NewNotifier(&pDiscordBot.NotifierConfig{
|
||||
BotToken: access.BotToken,
|
||||
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
||||
})
|
||||
}
|
||||
|
||||
case domain.NotificationProviderTypeEmail:
|
||||
{
|
||||
access := domain.AccessConfigForEmail{}
|
||||
|
@@ -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 ¬ifier.NotifyResult{}, nil
|
||||
}
|
@@ -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)
|
||||
})
|
||||
}
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user