150 lines
3.7 KiB
Go
150 lines
3.7 KiB
Go
package adminpush
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
|
|
"hfb_sys/backend/internal/integrations/push"
|
|
)
|
|
|
|
var (
|
|
ErrDependencyUnavailable = errors.New("dependency unavailable")
|
|
ErrChannelNotFound = errors.New("push channel not found")
|
|
ErrRuleNotFound = errors.New("push rule not found")
|
|
ErrInvalidChannel = errors.New("invalid channel type or config")
|
|
)
|
|
|
|
type Service struct {
|
|
repo *Repository
|
|
}
|
|
|
|
func NewService(repo *Repository) *Service {
|
|
return &Service{repo: repo}
|
|
}
|
|
|
|
func (s *Service) ListChannels(ctx context.Context) ([]ChannelDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.ListChannels(ctx)
|
|
}
|
|
|
|
func (s *Service) CreateChannel(ctx context.Context, req CreateChannelRequest) (*ChannelDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if req.Name == "" || req.Type == "" {
|
|
return nil, ErrInvalidChannel
|
|
}
|
|
if err := validateChannelConfig(req.Type, req.Config); err != nil {
|
|
return nil, err
|
|
}
|
|
return s.repo.CreateChannel(ctx, req)
|
|
}
|
|
|
|
func (s *Service) UpdateChannel(ctx context.Context, id uint64, req UpdateChannelRequest) (*ChannelDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if req.Config != nil {
|
|
current, err := s.repo.GetChannel(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := validateChannelConfig(current.Type, *req.Config); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return s.repo.UpdateChannel(ctx, id, req)
|
|
}
|
|
|
|
func (s *Service) DeleteChannel(ctx context.Context, id uint64) error {
|
|
if s.repo == nil {
|
|
return ErrDependencyUnavailable
|
|
}
|
|
return s.repo.DeleteChannel(ctx, id)
|
|
}
|
|
|
|
func (s *Service) ListRules(ctx context.Context) ([]RuleDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.ListRules(ctx)
|
|
}
|
|
|
|
func (s *Service) UpdateRule(ctx context.Context, id uint64, req UpdateRuleRequest) (*RuleDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if req.Threshold != nil && *req.Threshold < 1 {
|
|
return nil, ErrInvalidChannel
|
|
}
|
|
return s.repo.UpdateRule(ctx, id, req)
|
|
}
|
|
|
|
func (s *Service) TestChannel(ctx context.Context, id uint64) error {
|
|
if s.repo == nil {
|
|
return ErrDependencyUnavailable
|
|
}
|
|
ch, err := s.repo.GetChannel(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
provider, err := buildProvider(ch.Type, ch.Config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return provider.Send(ctx, push.Message{
|
|
Title: "推送测试",
|
|
Content: "这是一条测试消息,如果你收到了说明推送配置正确。",
|
|
})
|
|
}
|
|
|
|
func validateChannelConfig(channelType string, cfg json.RawMessage) error {
|
|
switch channelType {
|
|
case "bark":
|
|
var c struct {
|
|
DeviceKey string `json:"device_key"`
|
|
}
|
|
if err := json.Unmarshal(cfg, &c); err != nil || strings.TrimSpace(c.DeviceKey) == "" {
|
|
return ErrInvalidChannel
|
|
}
|
|
case "wpush":
|
|
var c struct {
|
|
APIKey string `json:"api_key"`
|
|
}
|
|
if err := json.Unmarshal(cfg, &c); err != nil || strings.TrimSpace(c.APIKey) == "" {
|
|
return ErrInvalidChannel
|
|
}
|
|
default:
|
|
return ErrInvalidChannel
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func buildProvider(channelType string, cfg json.RawMessage) (push.Provider, error) {
|
|
switch channelType {
|
|
case "bark":
|
|
var c struct {
|
|
DeviceKey string `json:"device_key"`
|
|
Server string `json:"server"`
|
|
}
|
|
if err := json.Unmarshal(cfg, &c); err != nil {
|
|
return nil, err
|
|
}
|
|
return push.NewBarkProvider(push.BarkConfig{DeviceKey: c.DeviceKey, Server: c.Server})
|
|
case "wpush":
|
|
var c struct {
|
|
APIKey string `json:"api_key"`
|
|
}
|
|
if err := json.Unmarshal(cfg, &c); err != nil {
|
|
return nil, err
|
|
}
|
|
return push.NewWPushProvider(push.WPushConfig{APIKey: c.APIKey})
|
|
default:
|
|
return nil, errors.New("unknown channel type")
|
|
}
|
|
}
|