初始提交: ScriptForge 脚本快速转运行链接服务
Some checks failed
Release / build-and-release (push) Failing after 1m31s
Some checks failed
Release / build-and-release (push) Failing after 1m31s
- Go 后端 (Gin + GORM + SQLite) 提供 API 和纯文本脚本服务 - Vite + React + TypeScript + Tailwind 前端 - 单二进制部署 (Go embed 前端静态文件) - Gitea Actions CI/CD: 打标签自动构建多平台 Release - 支持 bash/zsh/sh/fish/python3/node/ruby/php 8种运行环境 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
113
backend/internal/service/script.go
Normal file
113
backend/internal/service/script.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"gitea.kmux.cn/zhilv/scriptforge/internal/config"
|
||||
"gitea.kmux.cn/zhilv/scriptforge/internal/idgen"
|
||||
"gitea.kmux.cn/zhilv/scriptforge/internal/model"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidRuntime = errors.New("invalid runtime")
|
||||
ErrNotFound = errors.New("script not found or expired")
|
||||
)
|
||||
|
||||
type ScriptService struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewScriptService(db *gorm.DB) *ScriptService {
|
||||
return &ScriptService{db: db}
|
||||
}
|
||||
|
||||
type CreateInput struct {
|
||||
Content string
|
||||
Runtime string
|
||||
ExpiresIn string
|
||||
}
|
||||
|
||||
type CreateResult struct {
|
||||
Script model.Script
|
||||
AdminToken string
|
||||
Command string
|
||||
RawURL string
|
||||
}
|
||||
|
||||
func (s *ScriptService) Create(input CreateInput, scheme, host string) (*CreateResult, error) {
|
||||
if !config.IsValidRuntime(input.Runtime) {
|
||||
return nil, ErrInvalidRuntime
|
||||
}
|
||||
|
||||
var d time.Duration
|
||||
switch input.ExpiresIn {
|
||||
case "1h":
|
||||
d = 1 * time.Hour
|
||||
case "24h":
|
||||
d = 24 * time.Hour
|
||||
case "7d":
|
||||
d = 7 * 24 * time.Hour
|
||||
case "30d":
|
||||
d = 30 * 24 * time.Hour
|
||||
default:
|
||||
d = 24 * time.Hour
|
||||
}
|
||||
|
||||
id, err := idgen.GenerateID(8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
adminToken, err := idgen.GenerateToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
script := model.Script{
|
||||
ID: id,
|
||||
Content: input.Content,
|
||||
Runtime: input.Runtime,
|
||||
AdminToken: adminToken,
|
||||
ExpiresAt: time.Now().Add(d),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := s.db.Create(&script).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawURL := scheme + "://" + host + "/raw/" + id
|
||||
command := "curl " + rawURL + " | " + input.Runtime
|
||||
|
||||
return &CreateResult{
|
||||
Script: script,
|
||||
AdminToken: adminToken,
|
||||
Command: command,
|
||||
RawURL: rawURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *ScriptService) GetByID(id string) (*model.Script, error) {
|
||||
var script model.Script
|
||||
err := s.db.Where("id = ? AND expires_at > ?", id, time.Now()).First(&script).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return &script, err
|
||||
}
|
||||
|
||||
func (s *ScriptService) Delete(id, token string) error {
|
||||
result := s.db.Where("id = ? AND admin_token = ?", id, token).Delete(&model.Script{})
|
||||
if result.RowsAffected == 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
func (s *ScriptService) CleanupExpired() (int64, error) {
|
||||
result := s.db.Where("expires_at <= ?", time.Now()).Delete(&model.Script{})
|
||||
return result.RowsAffected, result.Error
|
||||
}
|
||||
Reference in New Issue
Block a user