mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-08 13:39:53 +00:00
refactor: re-implement logic of notify
This commit is contained in:
parent
150b666d4b
commit
5d93334426
2
go.mod
2
go.mod
@ -113,7 +113,7 @@ require (
|
|||||||
github.com/cloudflare/cloudflare-go v0.104.0 // indirect
|
github.com/cloudflare/cloudflare-go v0.104.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/disintegration/imaging v1.6.2 // indirect
|
github.com/disintegration/imaging v1.6.2 // indirect
|
||||||
github.com/domodwyer/mailyak/v3 v3.6.2 // indirect
|
github.com/domodwyer/mailyak/v3 v3.6.2
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
github.com/fatih/color v1.17.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NotifyChannelDingtalk = "dingtalk"
|
NotifyChannelEmail = "email"
|
||||||
NotifyChannelWebhook = "webhook"
|
NotifyChannelWebhook = "webhook"
|
||||||
NotifyChannelTelegram = "telegram"
|
NotifyChannelDingtalk = "dingtalk"
|
||||||
NotifyChannelLark = "lark"
|
NotifyChannelLark = "lark"
|
||||||
|
NotifyChannelTelegram = "telegram"
|
||||||
NotifyChannelServerChan = "serverchan"
|
NotifyChannelServerChan = "serverchan"
|
||||||
NotifyChannelMail = "mail"
|
|
||||||
NotifyChannelBark = "bark"
|
NotifyChannelBark = "bark"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,19 +12,13 @@ import (
|
|||||||
"github.com/usual2970/certimate/internal/utils/xtime"
|
"github.com/usual2970/certimate/internal/utils/xtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type msg struct {
|
|
||||||
subject string
|
|
||||||
message string
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultExpireSubject = "您有{COUNT}张证书即将过期"
|
defaultExpireSubject = "您有 {COUNT} 张证书即将过期"
|
||||||
defaultExpireMsg = "有{COUNT}张证书即将过期,域名分别为{DOMAINS},请保持关注!"
|
defaultExpireMessage = "有 {COUNT} 张证书即将过期,域名分别为 {DOMAINS},请保持关注!"
|
||||||
)
|
)
|
||||||
|
|
||||||
func PushExpireMsg() {
|
func PushExpireMsg() {
|
||||||
// 查询即将过期的证书
|
// 查询即将过期的证书
|
||||||
|
|
||||||
records, err := app.GetApp().Dao().FindRecordsByFilter("domains", "expiredAt<{:time}&&certUrl!=''", "-created", 500, 0,
|
records, err := app.GetApp().Dao().FindRecordsByFilter("domains", "expiredAt<{:time}&&certUrl!=''", "-created", 500, 0,
|
||||||
dbx.Params{"time": xtime.GetTimeAfter(24 * time.Hour * 15)})
|
dbx.Params{"time": xtime.GetTimeAfter(24 * time.Hour * 15)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -34,12 +28,12 @@ func PushExpireMsg() {
|
|||||||
|
|
||||||
// 组装消息
|
// 组装消息
|
||||||
msg := buildMsg(records)
|
msg := buildMsg(records)
|
||||||
|
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Send(msg.subject, msg.message); err != nil {
|
// 发送通知
|
||||||
|
if err := SendToAllChannels(msg.Subject, msg.Message); err != nil {
|
||||||
app.GetApp().Logger().Error("send expire msg", "error", err)
|
app.GetApp().Logger().Error("send expire msg", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,22 +47,27 @@ type notifyTemplate struct {
|
|||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildMsg(records []*models.Record) *msg {
|
type notifyMessage struct {
|
||||||
|
Subject string
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildMsg(records []*models.Record) *notifyMessage {
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询模板信息
|
// 查询模板信息
|
||||||
templateRecord, err := app.GetApp().Dao().FindFirstRecordByFilter("settings", "name='templates'")
|
templateRecord, err := app.GetApp().Dao().FindFirstRecordByFilter("settings", "name='templates'")
|
||||||
title := defaultExpireSubject
|
subject := defaultExpireSubject
|
||||||
content := defaultExpireMsg
|
message := defaultExpireMessage
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var templates *notifyTemplates
|
var templates *notifyTemplates
|
||||||
templateRecord.UnmarshalJSONField("content", templates)
|
templateRecord.UnmarshalJSONField("content", templates)
|
||||||
if templates != nil && len(templates.NotifyTemplates) > 0 {
|
if templates != nil && len(templates.NotifyTemplates) > 0 {
|
||||||
title = templates.NotifyTemplates[0].Title
|
subject = templates.NotifyTemplates[0].Title
|
||||||
content = templates.NotifyTemplates[0].Content
|
message = templates.NotifyTemplates[0].Content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,17 +80,17 @@ func buildMsg(records []*models.Record) *msg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
countStr := strconv.Itoa(count)
|
countStr := strconv.Itoa(count)
|
||||||
domainStr := strings.Join(domains, ",")
|
domainStr := strings.Join(domains, ";")
|
||||||
|
|
||||||
title = strings.ReplaceAll(title, "{COUNT}", countStr)
|
subject = strings.ReplaceAll(subject, "{COUNT}", countStr)
|
||||||
title = strings.ReplaceAll(title, "{DOMAINS}", domainStr)
|
subject = strings.ReplaceAll(subject, "{DOMAINS}", domainStr)
|
||||||
|
|
||||||
content = strings.ReplaceAll(content, "{COUNT}", countStr)
|
message = strings.ReplaceAll(message, "{COUNT}", countStr)
|
||||||
content = strings.ReplaceAll(content, "{DOMAINS}", domainStr)
|
message = strings.ReplaceAll(message, "{DOMAINS}", domainStr)
|
||||||
|
|
||||||
// 返回消息
|
// 返回消息
|
||||||
return &msg{
|
return ¬ifyMessage{
|
||||||
subject: title,
|
Subject: subject,
|
||||||
message: content,
|
Message: message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
internal/notify/factory.go
Normal file
66
internal/notify/factory.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package notify
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/usual2970/certimate/internal/domain"
|
||||||
|
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||||
|
notifierBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
|
||||||
|
notifierDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk"
|
||||||
|
notifierEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||||
|
notifierLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
|
||||||
|
notifierServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
|
||||||
|
notifierTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram"
|
||||||
|
notifierWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
|
||||||
|
"github.com/usual2970/certimate/internal/pkg/utils/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createNotifier(channel string, channelConfig map[string]any) (notifier.Notifier, error) {
|
||||||
|
switch channel {
|
||||||
|
case domain.NotifyChannelEmail:
|
||||||
|
return notifierEmail.New(¬ifierEmail.EmailNotifierConfig{
|
||||||
|
SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"),
|
||||||
|
SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"),
|
||||||
|
SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true),
|
||||||
|
Username: maps.GetValueOrDefaultAsString(channelConfig, "username", maps.GetValueAsString(channelConfig, "senderAddress")),
|
||||||
|
Password: maps.GetValueAsString(channelConfig, "password"),
|
||||||
|
SenderAddress: maps.GetValueAsString(channelConfig, "senderAddress"),
|
||||||
|
ReceiverAddress: maps.GetValueAsString(channelConfig, "receiverAddress"),
|
||||||
|
})
|
||||||
|
|
||||||
|
case domain.NotifyChannelWebhook:
|
||||||
|
return notifierWebhook.New(¬ifierWebhook.WebhookNotifierConfig{
|
||||||
|
Url: maps.GetValueAsString(channelConfig, "url"),
|
||||||
|
})
|
||||||
|
|
||||||
|
case domain.NotifyChannelDingtalk:
|
||||||
|
return notifierDingTalk.New(¬ifierDingTalk.DingTalkNotifierConfig{
|
||||||
|
AccessToken: maps.GetValueAsString(channelConfig, "accessToken"),
|
||||||
|
Secret: maps.GetValueAsString(channelConfig, "secret"),
|
||||||
|
})
|
||||||
|
|
||||||
|
case domain.NotifyChannelLark:
|
||||||
|
return notifierLark.New(¬ifierLark.LarkNotifierConfig{
|
||||||
|
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
|
||||||
|
})
|
||||||
|
|
||||||
|
case domain.NotifyChannelTelegram:
|
||||||
|
return notifierTelegram.New(¬ifierTelegram.TelegramNotifierConfig{
|
||||||
|
ApiToken: maps.GetValueAsString(channelConfig, "apiToken"),
|
||||||
|
ChatId: maps.GetValueAsInt64(channelConfig, "chatId"),
|
||||||
|
})
|
||||||
|
|
||||||
|
case domain.NotifyChannelServerChan:
|
||||||
|
return notifierServerChan.New(¬ifierServerChan.ServerChanNotifierConfig{
|
||||||
|
Url: maps.GetValueAsString(channelConfig, "url"),
|
||||||
|
})
|
||||||
|
|
||||||
|
case domain.NotifyChannelBark:
|
||||||
|
return notifierBark.New(¬ifierBark.BarkNotifierConfig{
|
||||||
|
DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"),
|
||||||
|
ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("unsupported notifier channel")
|
||||||
|
}
|
@ -1,56 +0,0 @@
|
|||||||
package notify
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/mail"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/pocketbase/pocketbase/tools/mailer"
|
|
||||||
)
|
|
||||||
|
|
||||||
const defaultSmtpHostPort = "25"
|
|
||||||
|
|
||||||
type Mail struct {
|
|
||||||
username string
|
|
||||||
to string
|
|
||||||
client *mailer.SmtpClient
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMail(senderAddress, receiverAddresses, smtpHostAddr, smtpHostPort, password string) (*Mail, error) {
|
|
||||||
if smtpHostPort == "" {
|
|
||||||
smtpHostPort = defaultSmtpHostPort
|
|
||||||
}
|
|
||||||
|
|
||||||
port, err := strconv.Atoi(smtpHostPort)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid smtp port: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := mailer.SmtpClient{
|
|
||||||
Host: smtpHostAddr,
|
|
||||||
Port: port,
|
|
||||||
Username: senderAddress,
|
|
||||||
Password: password,
|
|
||||||
Tls: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Mail{
|
|
||||||
username: senderAddress,
|
|
||||||
client: &client,
|
|
||||||
to: receiverAddresses,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mail) Send(ctx context.Context, subject, content string) error {
|
|
||||||
message := &mailer.Message{
|
|
||||||
From: mail.Address{
|
|
||||||
Address: m.username,
|
|
||||||
},
|
|
||||||
To: []mail.Address{{Address: m.to}},
|
|
||||||
Subject: subject,
|
|
||||||
Text: content,
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.client.Send(message)
|
|
||||||
}
|
|
@ -4,22 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
stdhttp "net/http"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||||
|
"github.com/usual2970/certimate/internal/pkg/utils/maps"
|
||||||
"github.com/usual2970/certimate/internal/utils/app"
|
"github.com/usual2970/certimate/internal/utils/app"
|
||||||
|
|
||||||
notifyPackage "github.com/nikoksr/notify"
|
|
||||||
"github.com/nikoksr/notify/service/bark"
|
|
||||||
"github.com/nikoksr/notify/service/dingding"
|
|
||||||
"github.com/nikoksr/notify/service/http"
|
|
||||||
"github.com/nikoksr/notify/service/lark"
|
|
||||||
"github.com/nikoksr/notify/service/telegram"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Send(title, content string) error {
|
func SendToAllChannels(subject, message string) error {
|
||||||
// 获取所有的推送渠道
|
notifiers, err := getEnabledNotifiers()
|
||||||
notifiers, err := getNotifiers()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -27,161 +20,56 @@ func Send(title, content string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
n := notifyPackage.New()
|
var eg errgroup.Group
|
||||||
// 添加推送渠道
|
for _, n := range notifiers {
|
||||||
n.UseServices(notifiers...)
|
if n == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// 发送消息
|
eg.Go(func() error {
|
||||||
return n.Send(context.Background(), title, content)
|
_, err := n.Notify(context.Background(), subject, message)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
err = eg.Wait()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type sendTestParam struct {
|
func SendToChannel(subject, message string, channel string, channelConfig map[string]any) error {
|
||||||
Title string `json:"title"`
|
notifier, err := createNotifier(channel, channelConfig)
|
||||||
Content string `json:"content"`
|
|
||||||
Channel string `json:"channel"`
|
|
||||||
Conf map[string]any `json:"conf"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendTest(param *sendTestParam) error {
|
|
||||||
notifier, err := getNotifier(param.Channel, param.Conf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n := notifyPackage.New()
|
_, err = notifier.Notify(context.Background(), subject, message)
|
||||||
|
return err
|
||||||
// 添加推送渠道
|
|
||||||
n.UseServices(notifier)
|
|
||||||
|
|
||||||
// 发送消息
|
|
||||||
return n.Send(context.Background(), param.Title, param.Content)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNotifiers() ([]notifyPackage.Notifier, error) {
|
func getEnabledNotifiers() ([]notifier.Notifier, error) {
|
||||||
resp, err := app.GetApp().Dao().FindFirstRecordByFilter("settings", "name='notifyChannels'")
|
settings, err := app.GetApp().Dao().FindFirstRecordByFilter("settings", "name='notifyChannels'")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("find notifyChannels error: %w", err)
|
return nil, fmt.Errorf("find notifyChannels error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
notifiers := make([]notifyPackage.Notifier, 0)
|
|
||||||
|
|
||||||
rs := make(map[string]map[string]any)
|
rs := make(map[string]map[string]any)
|
||||||
|
if err := settings.UnmarshalJSONField("content", &rs); err != nil {
|
||||||
if err := resp.UnmarshalJSONField("content", &rs); err != nil {
|
|
||||||
return nil, fmt.Errorf("unmarshal notifyChannels error: %w", err)
|
return nil, fmt.Errorf("unmarshal notifyChannels error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifiers := make([]notifier.Notifier, 0)
|
||||||
for k, v := range rs {
|
for k, v := range rs {
|
||||||
|
if !maps.GetValueAsBool(v, "enabled") {
|
||||||
if !getConfigAsBool(v, "enabled") {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier, err := getNotifier(k, v)
|
notifier, err := createNotifier(k, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
notifiers = append(notifiers, notifier)
|
notifiers = append(notifiers, notifier)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return notifiers, nil
|
return notifiers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNotifier(channel string, conf map[string]any) (notifyPackage.Notifier, error) {
|
|
||||||
switch channel {
|
|
||||||
case domain.NotifyChannelTelegram:
|
|
||||||
temp := getTelegramNotifier(conf)
|
|
||||||
if temp == nil {
|
|
||||||
return nil, fmt.Errorf("telegram notifier config error")
|
|
||||||
}
|
|
||||||
|
|
||||||
return temp, nil
|
|
||||||
case domain.NotifyChannelDingtalk:
|
|
||||||
return getDingTalkNotifier(conf), nil
|
|
||||||
case domain.NotifyChannelLark:
|
|
||||||
return getLarkNotifier(conf), nil
|
|
||||||
case domain.NotifyChannelWebhook:
|
|
||||||
return getWebhookNotifier(conf), nil
|
|
||||||
case domain.NotifyChannelServerChan:
|
|
||||||
return getServerChanNotifier(conf), nil
|
|
||||||
case domain.NotifyChannelMail:
|
|
||||||
return getMailNotifier(conf)
|
|
||||||
case domain.NotifyChannelBark:
|
|
||||||
return getBarkNotifier(conf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("notifier not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getWebhookNotifier(conf map[string]any) notifyPackage.Notifier {
|
|
||||||
rs := http.New()
|
|
||||||
|
|
||||||
rs.AddReceiversURLs(getConfigAsString(conf, "url"))
|
|
||||||
|
|
||||||
return rs
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTelegramNotifier(conf map[string]any) notifyPackage.Notifier {
|
|
||||||
rs, err := telegram.New(getConfigAsString(conf, "apiToken"))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.AddReceivers(getConfigAsInt64(conf, "chatId"))
|
|
||||||
return rs
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServerChanNotifier(conf map[string]any) notifyPackage.Notifier {
|
|
||||||
rs := http.New()
|
|
||||||
|
|
||||||
rs.AddReceivers(&http.Webhook{
|
|
||||||
URL: getConfigAsString(conf, "url"),
|
|
||||||
Header: stdhttp.Header{},
|
|
||||||
ContentType: "application/json",
|
|
||||||
Method: stdhttp.MethodPost,
|
|
||||||
BuildPayload: func(subject, message string) (payload any) {
|
|
||||||
return map[string]string{
|
|
||||||
"text": subject,
|
|
||||||
"desp": message,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return rs
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBarkNotifier(conf map[string]any) notifyPackage.Notifier {
|
|
||||||
deviceKey := getConfigAsString(conf, "deviceKey")
|
|
||||||
serverURL := getConfigAsString(conf, "serverUrl")
|
|
||||||
if serverURL == "" {
|
|
||||||
return bark.New(deviceKey)
|
|
||||||
}
|
|
||||||
return bark.NewWithServers(deviceKey, serverURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDingTalkNotifier(conf map[string]any) notifyPackage.Notifier {
|
|
||||||
return dingding.New(&dingding.Config{
|
|
||||||
Token: getConfigAsString(conf, "accessToken"),
|
|
||||||
Secret: getConfigAsString(conf, "secret"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLarkNotifier(conf map[string]any) notifyPackage.Notifier {
|
|
||||||
return lark.NewWebhookService(getConfigAsString(conf, "webhookUrl"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMailNotifier(conf map[string]any) (notifyPackage.Notifier, error) {
|
|
||||||
rs, err := NewMail(getConfigAsString(conf, "senderAddress"),
|
|
||||||
getConfigAsString(conf, "receiverAddresses"),
|
|
||||||
getConfigAsString(conf, "smtpHostAddr"),
|
|
||||||
getConfigAsString(conf, "smtpHostPort"),
|
|
||||||
getConfigAsString(conf, "password"),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rs, nil
|
|
||||||
}
|
|
||||||
|
@ -29,18 +29,13 @@ func NewNotifyService(settingRepo SettingRepository) *NotifyService {
|
|||||||
func (n *NotifyService) Test(ctx context.Context, req *domain.NotifyTestPushReq) error {
|
func (n *NotifyService) Test(ctx context.Context, req *domain.NotifyTestPushReq) error {
|
||||||
setting, err := n.settingRepo.GetByName(ctx, "notifyChannels")
|
setting, err := n.settingRepo.GetByName(ctx, "notifyChannels")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get notify channels setting failed: %w", err)
|
return fmt.Errorf("failed to get notify channels settings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := setting.GetChannelContent(req.Channel)
|
channelConfig, err := setting.GetChannelContent(req.Channel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get notify channel %s config failed: %w", req.Channel, err)
|
return fmt.Errorf("failed to get notify channel \"%s\" config: %w", req.Channel, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendTest(&sendTestParam{
|
return SendToChannel(notifyTestTitle, notifyTestBody, req.Channel, channelConfig)
|
||||||
Title: notifyTestTitle,
|
|
||||||
Content: notifyTestBody,
|
|
||||||
Channel: req.Channel,
|
|
||||||
Conf: conf,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package notify
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/usual2970/certimate/internal/pkg/utils/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getConfigAsString(conf map[string]any, key string) string {
|
|
||||||
return maps.GetValueAsString(conf, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfigAsInt32(conf map[string]any, key string) int32 {
|
|
||||||
return maps.GetValueAsInt32(conf, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfigAsInt64(conf map[string]any, key string) int64 {
|
|
||||||
return maps.GetValueAsInt64(conf, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfigAsBool(conf map[string]any, key string) bool {
|
|
||||||
return maps.GetValueAsBool(conf, key)
|
|
||||||
}
|
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/domodwyer/mailyak/v3"
|
"github.com/domodwyer/mailyak/v3"
|
||||||
|
|
||||||
@ -44,15 +44,25 @@ func (n *EmailNotifier) Notify(ctx context.Context, subject string, message stri
|
|||||||
smtpAuth = smtp.PlainAuth("", n.config.Username, n.config.Password, n.config.SmtpHost)
|
smtpAuth = smtp.PlainAuth("", n.config.Username, n.config.Password, n.config.SmtpHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var smtpAddr string
|
||||||
|
if n.config.SmtpPort == 0 {
|
||||||
|
if n.config.SmtpTLS {
|
||||||
|
smtpAddr = fmt.Sprintf("%s:465", n.config.SmtpHost)
|
||||||
|
} else {
|
||||||
|
smtpAddr = fmt.Sprintf("%s:25", n.config.SmtpHost)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
smtpAddr = fmt.Sprintf("%s:%d", n.config.SmtpHost, n.config.SmtpPort)
|
||||||
|
}
|
||||||
|
|
||||||
var yak *mailyak.MailYak
|
var yak *mailyak.MailYak
|
||||||
if n.config.SmtpTLS {
|
if n.config.SmtpTLS {
|
||||||
os.Setenv("GODEBUG", "tlsrsakex=1") // Fix for TLS handshake error
|
yak, err = mailyak.NewWithTLS(smtpAddr, smtpAuth, newTlsConfig())
|
||||||
yak, err = mailyak.NewWithTLS(fmt.Sprintf("%s:%d", n.config.SmtpHost, n.config.SmtpPort), smtpAuth, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yak = mailyak.New(fmt.Sprintf("%s:%d", n.config.SmtpHost, n.config.SmtpPort), smtpAuth)
|
yak = mailyak.New(smtpAddr, smtpAuth)
|
||||||
}
|
}
|
||||||
|
|
||||||
yak.From(n.config.SenderAddress)
|
yak.From(n.config.SenderAddress)
|
||||||
@ -67,3 +77,19 @@ func (n *EmailNotifier) Notify(ctx context.Context, subject string, message stri
|
|||||||
|
|
||||||
return ¬ifier.NotifyResult{}, nil
|
return ¬ifier.NotifyResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newTlsConfig() *tls.Config {
|
||||||
|
var suiteIds []uint16
|
||||||
|
for _, suite := range tls.CipherSuites() {
|
||||||
|
suiteIds = append(suiteIds, suite.ID)
|
||||||
|
}
|
||||||
|
for _, suite := range tls.InsecureCipherSuites() {
|
||||||
|
suiteIds = append(suiteIds, suite.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为兼容国内部分低版本 TLS 的 SMTP 服务商
|
||||||
|
return &tls.Config{
|
||||||
|
MinVersion: tls.VersionTLS10,
|
||||||
|
CipherSuites: suiteIds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,7 +9,7 @@ import "strconv"
|
|||||||
// - key: 键。
|
// - key: 键。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是字符串,则返回空字符串。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是字符串,则返回空字符串。
|
||||||
func GetValueAsString(dict map[string]any, key string) string {
|
func GetValueAsString(dict map[string]any, key string) string {
|
||||||
return GetValueOrDefaultAsString(dict, key, "")
|
return GetValueOrDefaultAsString(dict, key, "")
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ func GetValueAsString(dict map[string]any, key string) string {
|
|||||||
// - defaultValue: 默认值。
|
// - defaultValue: 默认值。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是字符串,则返回默认值。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是字符串,则返回默认值。
|
||||||
func GetValueOrDefaultAsString(dict map[string]any, key string, defaultValue string) string {
|
func GetValueOrDefaultAsString(dict map[string]any, key string, defaultValue string) string {
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return defaultValue
|
return defaultValue
|
||||||
@ -44,7 +44,7 @@ func GetValueOrDefaultAsString(dict map[string]any, key string, defaultValue str
|
|||||||
// - key: 键。
|
// - key: 键。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是 32 位整数,则返回 0。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是 32 位整数,则返回 0。
|
||||||
func GetValueAsInt32(dict map[string]any, key string) int32 {
|
func GetValueAsInt32(dict map[string]any, key string) int32 {
|
||||||
return GetValueOrDefaultAsInt32(dict, key, 0)
|
return GetValueOrDefaultAsInt32(dict, key, 0)
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ func GetValueAsInt32(dict map[string]any, key string) int32 {
|
|||||||
// - defaultValue: 默认值。
|
// - defaultValue: 默认值。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是 32 位整数,则返回默认值。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是 32 位整数,则返回默认值。
|
||||||
func GetValueOrDefaultAsInt32(dict map[string]any, key string, defaultValue int32) int32 {
|
func GetValueOrDefaultAsInt32(dict map[string]any, key string, defaultValue int32) int32 {
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return defaultValue
|
return defaultValue
|
||||||
@ -69,8 +69,8 @@ func GetValueOrDefaultAsInt32(dict map[string]any, key string, defaultValue int3
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 兼容字符串类型的值
|
// 兼容字符串类型的值
|
||||||
if s, ok := value.(string); ok {
|
if str, ok := value.(string); ok {
|
||||||
if result, err := strconv.ParseInt(s, 10, 32); err == nil {
|
if result, err := strconv.ParseInt(str, 10, 32); err == nil {
|
||||||
return int32(result)
|
return int32(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func GetValueOrDefaultAsInt32(dict map[string]any, key string, defaultValue int3
|
|||||||
// - key: 键。
|
// - key: 键。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是 64 位整数,则返回 0。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是 64 位整数,则返回 0。
|
||||||
func GetValueAsInt64(dict map[string]any, key string) int64 {
|
func GetValueAsInt64(dict map[string]any, key string) int64 {
|
||||||
return GetValueOrDefaultAsInt64(dict, key, 0)
|
return GetValueOrDefaultAsInt64(dict, key, 0)
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ func GetValueAsInt64(dict map[string]any, key string) int64 {
|
|||||||
// - defaultValue: 默认值。
|
// - defaultValue: 默认值。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是 64 位整数,则返回默认值。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是 64 位整数,则返回默认值。
|
||||||
func GetValueOrDefaultAsInt64(dict map[string]any, key string, defaultValue int64) int64 {
|
func GetValueOrDefaultAsInt64(dict map[string]any, key string, defaultValue int64) int64 {
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return defaultValue
|
return defaultValue
|
||||||
@ -111,8 +111,8 @@ func GetValueOrDefaultAsInt64(dict map[string]any, key string, defaultValue int6
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 兼容字符串类型的值
|
// 兼容字符串类型的值
|
||||||
if s, ok := value.(string); ok {
|
if str, ok := value.(string); ok {
|
||||||
if result, err := strconv.ParseInt(s, 10, 64); err == nil {
|
if result, err := strconv.ParseInt(str, 10, 64); err == nil {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ func GetValueOrDefaultAsInt64(dict map[string]any, key string, defaultValue int6
|
|||||||
// - key: 键。
|
// - key: 键。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是布尔,则返回 false。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是布尔,则返回 false。
|
||||||
func GetValueAsBool(dict map[string]any, key string) bool {
|
func GetValueAsBool(dict map[string]any, key string) bool {
|
||||||
return GetValueOrDefaultAsBool(dict, key, false)
|
return GetValueOrDefaultAsBool(dict, key, false)
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ func GetValueAsBool(dict map[string]any, key string) bool {
|
|||||||
// - defaultValue: 默认值。
|
// - defaultValue: 默认值。
|
||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的值。如果指定键不存在或者类型不是布尔,则返回默认值。
|
// - 字典中键对应的值。如果指定键不存在或者值的类型不是布尔,则返回默认值。
|
||||||
func GetValueOrDefaultAsBool(dict map[string]any, key string, defaultValue bool) bool {
|
func GetValueOrDefaultAsBool(dict map[string]any, key string, defaultValue bool) bool {
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return defaultValue
|
return defaultValue
|
||||||
|
Loading…
x
Reference in New Issue
Block a user