mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 03:26:37 +08:00
171 lines
4.8 KiB
Go
171 lines
4.8 KiB
Go
// Package handler — PT 站点管理 HTTP 处理。
|
|
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/ShukeBta/MediaStationGo/internal/model"
|
|
"github.com/ShukeBta/MediaStationGo/internal/service"
|
|
)
|
|
|
|
// SiteHandler 站点管理 CRUD。
|
|
type SiteHandler struct {
|
|
svc *service.Container
|
|
}
|
|
|
|
// NewSiteHandler 创建站点管理 Handler。
|
|
func NewSiteHandler(svc *service.Container) *SiteHandler {
|
|
return &SiteHandler{svc: svc}
|
|
}
|
|
|
|
// ListSites 列出所有站点。
|
|
func (h *SiteHandler) ListSites(c *gin.Context) {
|
|
sites, err := h.svc.Site.List(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
if sites == nil {
|
|
sites = []model.Site{}
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "ok", "data": sites})
|
|
}
|
|
|
|
// GetSite 获取单个站点详情。
|
|
func (h *SiteHandler) GetSite(c *gin.Context) {
|
|
site, err := h.svc.Site.FindByID(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
if site == nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"code": 1, "message": "site not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "ok", "data": site})
|
|
}
|
|
|
|
// CreateSite 创建站点。
|
|
func (h *SiteHandler) CreateSite(c *gin.Context) {
|
|
var body map[string]any
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
|
|
var site model.Site
|
|
// 手动映射字段(因为敏感字段有 json:"-" 标签,不会自动反序列化)
|
|
if v, ok := body["name"].(string); ok {
|
|
site.Name = v
|
|
}
|
|
if v, ok := body["url"].(string); ok {
|
|
site.URL = v
|
|
}
|
|
if v, ok := body["type"].(string); ok {
|
|
site.Type = v
|
|
}
|
|
if v, ok := body["auth_type"].(string); ok {
|
|
site.AuthType = v
|
|
}
|
|
if v, ok := body["api_key"].(string); ok {
|
|
site.APIKey = v
|
|
}
|
|
if v, ok := body["cookie"].(string); ok {
|
|
site.Cookie = v
|
|
}
|
|
if v, ok := body["auth_header"].(string); ok {
|
|
site.AuthHeader = v
|
|
}
|
|
if v, ok := body["enabled"].(bool); ok {
|
|
site.Enabled = v
|
|
}
|
|
if v, ok := body["is_default"].(bool); ok {
|
|
site.IsDefault = v
|
|
}
|
|
if v, ok := body["extra"].(string); ok {
|
|
site.Extra = v
|
|
}
|
|
// 高级设置字段
|
|
if v, ok := body["user_agent"].(string); ok {
|
|
site.UserAgent = v
|
|
}
|
|
if v, ok := body["rss_url"].(string); ok {
|
|
site.RSSURL = v
|
|
}
|
|
if v, ok := body["timeout"].(float64); ok {
|
|
site.Timeout = int(v)
|
|
}
|
|
if v, ok := body["priority"].(float64); ok {
|
|
site.Priority = int(v)
|
|
}
|
|
if v, ok := body["use_proxy"].(bool); ok {
|
|
site.UseProxy = v
|
|
}
|
|
if v, ok := body["rate_limit"].(bool); ok {
|
|
site.RateLimit = v
|
|
}
|
|
if v, ok := body["browser_emulation"].(bool); ok {
|
|
site.BrowserEmulation = v
|
|
}
|
|
if v, ok := body["downloader"].(string); ok {
|
|
site.Downloader = v
|
|
}
|
|
|
|
if err := h.svc.Site.Create(c.Request.Context(), &site); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, gin.H{"code": 0, "message": "ok", "data": site})
|
|
}
|
|
|
|
// UpdateSite 更新站点。
|
|
func (h *SiteHandler) UpdateSite(c *gin.Context) {
|
|
patch := make(map[string]any)
|
|
if err := c.ShouldBindJSON(&patch); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
// 字段名映射:前端使用蛇形命名,GORM 会正确映射到列名
|
|
// 无需额外处理,Updates 直接使用 patch 中的 key-value
|
|
if err := h.svc.Site.Update(c.Request.Context(), c.Param("id"), patch); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "ok"})
|
|
}
|
|
|
|
// DeleteSite 删除站点。
|
|
func (h *SiteHandler) DeleteSite(c *gin.Context) {
|
|
if err := h.svc.Site.Delete(c.Request.Context(), c.Param("id")); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "ok"})
|
|
}
|
|
|
|
// TestSite 测试站点连通性。
|
|
func (h *SiteHandler) TestSite(c *gin.Context) {
|
|
ok, msg, err := h.svc.Site.TestConnection(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"code": 1, "message": err.Error()})
|
|
return
|
|
}
|
|
if !ok {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 1, "message": msg})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": msg})
|
|
}
|
|
|
|
// GetSiteTypes 返回支持的站点类型列表。
|
|
func (h *SiteHandler) GetSiteTypes(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "ok", "data": model.SiteTypes()})
|
|
}
|
|
|
|
// GetAuthTypes 返回支持的认证方式列表。
|
|
func (h *SiteHandler) GetAuthTypes(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "ok", "data": model.AuthTypes()})
|
|
}
|