mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 03:26:37 +08:00
197 lines
5.1 KiB
Go
197 lines
5.1 KiB
Go
// Package handler — 通知渠道管理 HTTP 端点。
|
|
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/ShukeBta/MediaStationGo/internal/model"
|
|
"github.com/ShukeBta/MediaStationGo/internal/service"
|
|
)
|
|
|
|
// NotifyHandler 处理通知渠道的 CRUD 操作。
|
|
type NotifyHandler struct {
|
|
svc *service.Container
|
|
log *zap.Logger
|
|
}
|
|
|
|
// NewNotifyHandler 创建通知渠道处理器。
|
|
func NewNotifyHandler(svc *service.Container, log *zap.Logger) *NotifyHandler {
|
|
return &NotifyHandler{svc: svc, log: log}
|
|
}
|
|
|
|
// notifyCreateRequest 创建通知渠道请求体。
|
|
type notifyCreateRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
Type string `json:"type" binding:"required,oneof=telegram wechat bark webhook email"`
|
|
Enabled bool `json:"enabled"`
|
|
Config map[string]string `json:"config" binding:"required"`
|
|
Events []string `json:"events"`
|
|
}
|
|
|
|
// notifyUpdateRequest 更新通知渠道请求体。
|
|
type notifyUpdateRequest struct {
|
|
Name string `json:"name"`
|
|
Enabled *bool `json:"enabled"`
|
|
Config map[string]string `json:"config"`
|
|
Events []string `json:"events"`
|
|
}
|
|
|
|
// Create 创建新的通知渠道。
|
|
func (h *NotifyHandler) Create(c *gin.Context) {
|
|
var req notifyCreateRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
Error(c, http.StatusBadRequest, ErrInvalidParams, err.Error())
|
|
return
|
|
}
|
|
|
|
ctx := c.Request.Context()
|
|
|
|
// 验证配置
|
|
if err := h.svc.Notify.ValidateChannelConfig(req.Type, req.Config); err != nil {
|
|
Error(c, http.StatusBadRequest, ErrInvalidParams, "配置验证失败: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// 加密配置
|
|
configJSON, _ := json.Marshal(req.Config)
|
|
configStr := string(configJSON)
|
|
if h.svc.Crypto != nil {
|
|
configStr = h.svc.Crypto.Encrypt(configStr)
|
|
}
|
|
|
|
// 序列化事件列表
|
|
eventsJSON, _ := json.Marshal(req.Events)
|
|
eventsStr := string(eventsJSON)
|
|
|
|
channel := &model.NotifyChannel{
|
|
Name: req.Name,
|
|
Type: req.Type,
|
|
Enabled: req.Enabled,
|
|
Config: configStr,
|
|
Events: eventsStr,
|
|
}
|
|
|
|
if err := h.svc.Repo.NotifyChannel.Create(ctx, channel); err != nil {
|
|
Error(c, http.StatusInternalServerError, ErrInternal, "创建失败: "+err.Error())
|
|
return
|
|
}
|
|
|
|
Success(c, channel)
|
|
}
|
|
|
|
// List 返回所有通知渠道。
|
|
func (h *NotifyHandler) List(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
channels, err := h.svc.Repo.NotifyChannel.List(ctx)
|
|
if err != nil {
|
|
Error(c, http.StatusInternalServerError, ErrInternal, "查询失败")
|
|
return
|
|
}
|
|
Success(c, channels)
|
|
}
|
|
|
|
// Get 返回指定通知渠道详情。
|
|
func (h *NotifyHandler) Get(c *gin.Context) {
|
|
id := c.Param("id")
|
|
ctx := c.Request.Context()
|
|
channel, err := h.svc.Repo.NotifyChannel.FindByID(ctx, id)
|
|
if err != nil || channel == nil {
|
|
Error(c, http.StatusNotFound, ErrNotFound, "通知渠道不存在")
|
|
return
|
|
}
|
|
Success(c, channel)
|
|
}
|
|
|
|
// Update 更新通知渠道。
|
|
func (h *NotifyHandler) Update(c *gin.Context) {
|
|
id := c.Param("id")
|
|
var req notifyUpdateRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
Error(c, http.StatusBadRequest, ErrInvalidParams, err.Error())
|
|
return
|
|
}
|
|
|
|
ctx := c.Request.Context()
|
|
channel, err := h.svc.Repo.NotifyChannel.FindByID(ctx, id)
|
|
if err != nil || channel == nil {
|
|
Error(c, http.StatusNotFound, ErrNotFound, "通知渠道不存在")
|
|
return
|
|
}
|
|
|
|
if req.Name != "" {
|
|
channel.Name = req.Name
|
|
}
|
|
if req.Enabled != nil {
|
|
channel.Enabled = *req.Enabled
|
|
}
|
|
|
|
// 更新配置
|
|
if len(req.Config) > 0 {
|
|
if err := h.svc.Notify.ValidateChannelConfig(channel.Type, req.Config); err != nil {
|
|
Error(c, http.StatusBadRequest, ErrInvalidParams, "配置验证失败: "+err.Error())
|
|
return
|
|
}
|
|
configJSON, _ := json.Marshal(req.Config)
|
|
configStr := string(configJSON)
|
|
if h.svc.Crypto != nil {
|
|
configStr = h.svc.Crypto.Encrypt(configStr)
|
|
}
|
|
channel.Config = configStr
|
|
}
|
|
|
|
// 更新事件列表
|
|
if req.Events != nil {
|
|
eventsJSON, _ := json.Marshal(req.Events)
|
|
channel.Events = string(eventsJSON)
|
|
}
|
|
|
|
if err := h.svc.Repo.NotifyChannel.Update(ctx, channel); err != nil {
|
|
Error(c, http.StatusInternalServerError, ErrInternal, "更新失败")
|
|
return
|
|
}
|
|
|
|
Success(c, channel)
|
|
}
|
|
|
|
// Delete 删除通知渠道。
|
|
func (h *NotifyHandler) Delete(c *gin.Context) {
|
|
id := c.Param("id")
|
|
ctx := c.Request.Context()
|
|
|
|
_, err := h.svc.Repo.NotifyChannel.FindByID(ctx, id)
|
|
if err != nil {
|
|
Error(c, http.StatusNotFound, ErrNotFound, "通知渠道不存在")
|
|
return
|
|
}
|
|
|
|
if delErr := h.svc.Repo.NotifyChannel.Delete(ctx, id); delErr != nil {
|
|
Error(c, http.StatusInternalServerError, ErrInternal, "删除失败")
|
|
return
|
|
}
|
|
|
|
SuccessWithMessage(c, "已删除", nil)
|
|
}
|
|
|
|
// Test 发送测试通知。
|
|
func (h *NotifyHandler) Test(c *gin.Context) {
|
|
id := c.Param("id")
|
|
ctx := c.Request.Context()
|
|
|
|
if err := h.svc.Notify.SendTest(ctx, id); err != nil {
|
|
Error(c, http.StatusBadRequest, ErrExternal, "测试通知发送失败: "+err.Error())
|
|
return
|
|
}
|
|
|
|
SuccessWithMessage(c, "测试通知已发送", nil)
|
|
}
|
|
|
|
// GetTypes 返回支持的通知渠道类型列表。
|
|
func (h *NotifyHandler) GetTypes(c *gin.Context) {
|
|
types := h.svc.Notify.GetProviderTypes()
|
|
Success(c, types)
|
|
}
|