mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
1e19d8114a
- Split shared monolithic consts into bot, push, and errs with typed sentinel errors - Restructure model layer into distinct bot and push subdomains - Refactor DAO layer to enforce single-owner principle and remove cross-table raw SQL queries - Decompose 1150+ line service/push.go into push_channel, push_event, push_trigger, push_worker, and push_template - Clean up controller layer with generic request handlers and parameter validation in controller/base.go - Streamline plugin.go to core Cordis lifecycle orchestration and remove re-export bloat - Verify all unit tests, race tests, Cordis architecture rules, and Swagger generation pass cleanly
169 lines
5.2 KiB
Go
169 lines
5.2 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package service
|
|
|
|
import (
|
|
"Wavelet/plugins/domain/msg_gateway/consts"
|
|
"Wavelet/plugins/domain/msg_gateway/dao"
|
|
"Wavelet/plugins/domain/msg_gateway/model/do"
|
|
"Wavelet/plugins/domain/msg_gateway/model/entity"
|
|
pkgpush "Wavelet/plugins/domain/msg_gateway/push"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// ListPushChannels returns every configured push channel.
|
|
func ListPushChannels(ctx context.Context) ([]entity.PushChannel, error) {
|
|
return dao.ListPushChannelsRecord(ctx)
|
|
}
|
|
|
|
// CreatePushChannel validates uniqueness and persists a new push channel.
|
|
func CreatePushChannel(ctx context.Context, req do.CreatePushChannelRequest) (entity.PushChannel, error) {
|
|
count, err := dao.CountPushChannelsByNameRecord(ctx, req.Name)
|
|
if err != nil {
|
|
return entity.PushChannel{}, err
|
|
}
|
|
if count > 0 {
|
|
return entity.PushChannel{}, errors.New(consts.ErrChannelNameExists)
|
|
}
|
|
|
|
channel := entity.PushChannel{
|
|
Name: req.Name,
|
|
Description: req.Description,
|
|
Type: req.Type,
|
|
Token: req.Token,
|
|
URL: req.URL,
|
|
Other: req.Other,
|
|
Enabled: req.Enabled,
|
|
}
|
|
if err := channel.Validate(); err != nil {
|
|
return entity.PushChannel{}, err
|
|
}
|
|
if err := dao.CreatePushChannelRecord(ctx, &channel); err != nil {
|
|
return entity.PushChannel{}, err
|
|
}
|
|
return channel, nil
|
|
}
|
|
|
|
// UpdatePushChannel replaces the mutable fields of an existing push channel.
|
|
func UpdatePushChannel(ctx context.Context, id uint64, req do.UpdatePushChannelRequest) (entity.PushChannel, error) {
|
|
channel, err := dao.GetPushChannelByIDRecord(ctx, id)
|
|
if err != nil {
|
|
return entity.PushChannel{}, err
|
|
}
|
|
|
|
channel.Description = req.Description
|
|
channel.Type = req.Type
|
|
channel.Token = req.Token
|
|
channel.URL = req.URL
|
|
channel.Other = req.Other
|
|
channel.Enabled = req.Enabled
|
|
if err := channel.Validate(); err != nil {
|
|
return entity.PushChannel{}, err
|
|
}
|
|
if err := dao.SavePushChannelRecord(ctx, &channel); err != nil {
|
|
return entity.PushChannel{}, err
|
|
}
|
|
return channel, nil
|
|
}
|
|
|
|
// DeletePushChannel removes a push channel by id.
|
|
func DeletePushChannel(ctx context.Context, id uint64) error {
|
|
channel, err := dao.GetPushChannelByIDRecord(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return dao.DeletePushChannelRecord(ctx, &channel)
|
|
}
|
|
|
|
// LoadChannelForTest resolves the credentials under test, either from a stored
|
|
// channel name or from the ad-hoc values sent by the caller.
|
|
func LoadChannelForTest(ctx context.Context, req do.TestPushChannelRequest) (string, string, string, string, error) {
|
|
if req.Name != "" {
|
|
channel, err := dao.GetPushChannelByNameRecord(ctx, req.Name)
|
|
if err != nil {
|
|
return "", "", "", "", errors.New(consts.ErrChannelNotFoundText)
|
|
}
|
|
return channel.URL, channel.Token, channel.Other, channel.Type, nil
|
|
}
|
|
return req.URL, req.Token, req.Other, req.Type, nil
|
|
}
|
|
|
|
// PreparePushChannelTest builds the connectivity probe payload for a channel.
|
|
func PreparePushChannelTest(ctx context.Context, req do.TestPushChannelRequest) (do.SendPayload, error) {
|
|
url, token, other, channelType, err := LoadChannelForTest(ctx, req)
|
|
if err != nil {
|
|
return do.SendPayload{}, err
|
|
}
|
|
|
|
tempChannel := entity.PushChannel{
|
|
Name: "test_temp",
|
|
URL: url,
|
|
Token: token,
|
|
Other: other,
|
|
Type: channelType,
|
|
Enabled: true,
|
|
}
|
|
if err := tempChannel.Validate(); err != nil {
|
|
return do.SendPayload{}, err
|
|
}
|
|
url = tempChannel.URL
|
|
|
|
var config pkgpush.Config
|
|
var renderedJSON string
|
|
switch channelType {
|
|
case consts.ChannelLark:
|
|
config = pkgpush.Config{Channel: consts.ChannelLark, URL: url, Secret: token}
|
|
renderedJSON = other
|
|
case consts.ChannelEmail:
|
|
config = pkgpush.Config{Channel: consts.ChannelEmail, URL: url, Key: token, Secret: other}
|
|
case consts.ChannelTelegram:
|
|
config = pkgpush.Config{Channel: consts.ChannelTelegram, URL: url, Secret: token, Key: other}
|
|
default:
|
|
config = pkgpush.Config{Channel: consts.ChannelCustom, URL: url}
|
|
customPushReq := do.CustomPushRequest{
|
|
Title: "通道测试通知",
|
|
Content: "这是一条来自系统的消息通道连通性测试消息。",
|
|
Description: "系统通道测试",
|
|
URL: "https://example.com",
|
|
To: req.Target,
|
|
}
|
|
renderedJSON = RenderCustomPayload(other, customPushReq)
|
|
}
|
|
|
|
return do.SendPayload{
|
|
EventKey: "test_channel",
|
|
Config: config,
|
|
Target: req.Target,
|
|
Body: do.NotificationMessage{
|
|
Title: "通道测试通知",
|
|
Content: "这是一条来自系统的消息通道连通性测试消息。",
|
|
Level: consts.DefaultLevelInfo,
|
|
},
|
|
Template: renderedJSON,
|
|
}, nil
|
|
}
|
|
|
|
// RunPushTest validates an ad-hoc channel config and sends a connectivity probe.
|
|
func RunPushTest(ctx context.Context, cfg pkgpush.Config, target string) error {
|
|
pusher, err := pkgpush.GetPusher(cfg.Channel)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := pusher.ValidateConfig(cfg); err != nil {
|
|
return fmt.Errorf("%s: %w", consts.ErrValidationFailed, err)
|
|
}
|
|
|
|
testBody := map[string]any{
|
|
consts.KeyTitle: "测试通道推送",
|
|
consts.KeyContent: "当您收到这条消息,说明当前渠道连通性测试通过。",
|
|
consts.KeyLevel: consts.DefaultLevelInfo,
|
|
}
|
|
if _, err := pusher.Send(ctx, cfg, target, testBody, "", nil); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|