package handler import ( "errors" "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "gitea.kmux.cn/zhilv/scriptforge/internal/service" ) type createRequest struct { Title string `json:"title" binding:"required,max=128"` Description string `json:"description" binding:"max=512"` Content string `json:"content" binding:"required,max=16384"` Runtime string `json:"runtime" binding:"required"` ExpiresIn string `json:"expires_in" binding:"required,oneof=1h 24h 7d 30d"` Publish bool `json:"publish"` } func CreateScript(svc *service.ScriptService) gin.HandlerFunc { return func(c *gin.Context) { var req createRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } scheme := "https" if strings.HasPrefix(c.Request.Host, "localhost") || strings.HasPrefix(c.Request.Host, "127.0.0.1") { scheme = "http" } result, err := svc.Create(service.CreateInput{ Title: req.Title, Description: req.Description, Content: req.Content, Runtime: req.Runtime, ExpiresIn: req.ExpiresIn, Publish: req.Publish, }, scheme, c.Request.Host) if errors.Is(err, service.ErrInvalidRuntime) { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid runtime"}) return } if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"}) return } c.JSON(http.StatusCreated, gin.H{ "id": result.Script.ID, "title": result.Script.Title, "description": result.Script.Description, "admin_token": result.AdminToken, "url": result.RawURL, "command": result.Command, "source_command": result.SourceCmd, "runtime": result.Script.Runtime, "status": result.Script.Status, "expires_at": result.Script.ExpiresAt, }) } } func GetScript(svc *service.ScriptService) gin.HandlerFunc { return func(c *gin.Context) { id := c.Param("id") script, err := svc.GetByID(id) if errors.Is(err, service.ErrNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "script not found or expired"}) return } if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"}) return } c.JSON(http.StatusOK, gin.H{ "id": script.ID, "title": script.Title, "description": script.Description, "runtime": script.Runtime, "content": script.Content, "content_length": len(script.Content), "status": script.Status, "created_at": script.CreatedAt, "expires_at": script.ExpiresAt, "published_at": script.PublishedAt, "expired": false, }) } } func PublishScript(svc *service.ScriptService) gin.HandlerFunc { return func(c *gin.Context) { id := c.Param("id") token := c.Query("token") if token == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "token query parameter is required"}) return } script, err := svc.Publish(id, token) if errors.Is(err, service.ErrNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "script not found or invalid token"}) return } if errors.Is(err, service.ErrAlreadyPublished) { c.JSON(http.StatusBadRequest, gin.H{"error": "script already published"}) return } if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"}) return } c.JSON(http.StatusOK, gin.H{ "id": script.ID, "status": script.Status, "published_at": script.PublishedAt, }) } } func ListMarket(svc *service.ScriptService) gin.HandlerFunc { return func(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "20")) runtime := c.Query("runtime") search := c.Query("search") result, err := svc.ListMarket(service.MarketQuery{ Page: page, PerPage: perPage, Runtime: runtime, Search: search, }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"}) return } items := make([]gin.H, len(result.Items)) for i, s := range result.Items { items[i] = gin.H{ "id": s.ID, "title": s.Title, "description": s.Description, "runtime": s.Runtime, "published_at": s.PublishedAt, } } c.JSON(http.StatusOK, gin.H{ "items": items, "total": result.Total, "page": result.Page, "per_page": result.PerPage, }) } } func DeleteScript(svc *service.ScriptService) gin.HandlerFunc { return func(c *gin.Context) { id := c.Param("id") token := c.Query("token") if token == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "token query parameter is required"}) return } if err := svc.Delete(id, token); errors.Is(err, service.ErrNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "script not found or invalid token"}) return } else if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"}) return } c.Status(http.StatusNoContent) } }