package main import ( "context" "errors" "net/http" "os" "os/signal" "path/filepath" "strings" "syscall" "time" commonHttp "video-factory/common" "video-factory/shortdrama/controller" "video-factory/shortdrama/service" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/util/gvalid" _ "github.com/gogf/gf/contrib/drivers/sqlite/v2" ) func init() { gvalid.RegisterRule("password-complex", func(ctx context.Context, input gvalid.RuleFuncInput) error { pwd := input.Value.String() var hasUpper, hasLower, hasDigit, hasSpecial bool for _, c := range pwd { switch { case c >= 'A' && c <= 'Z': hasUpper = true case c >= 'a' && c <= 'z': hasLower = true case c >= '0' && c <= '9': hasDigit = true default: hasSpecial = true } } if !hasUpper { return errors.New("密码必须包含大写字母") } if !hasLower { return errors.New("密码必须包含小写字母") } if !hasDigit { return errors.New("密码必须包含数字") } if !hasSpecial { return errors.New("密码必须包含特殊符号") } return nil }) } func main() { // ==================== API 路由(通过 RouteRegister 自动注册,遵循 ai-agent 规范) ==================== commonHttp.RouteRegister([]interface{}{ controller.Drama, controller.Scene, controller.Character, controller.Prop, controller.Bgm, controller.Episode, controller.Generation, controller.ModelConfig, controller.UserModelConfig, controller.User, controller.Agent, controller.Customer, controller.Transaction, controller.PaymentOrder, controller.PaymentChannelTrade, controller.PaymentConfig, controller.RegionPricing, }) // ==================== Workspace 文件服务(鉴权保护) ==================== // 通过 BindHandler 代替 AddStaticPath,确保经过 JWT 中间件鉴权 commonHttp.Httpserver.BindHandler("/workspace/*", func(r *ghttp.Request) { relPath := strings.TrimPrefix(r.URL.Path, "/workspace/") if relPath == "" || strings.Contains(relPath, "..") { r.Response.WriteStatus(http.StatusForbidden) return } filePath := filepath.Join("workspace", relPath) if _, err := os.Stat(filePath); os.IsNotExist(err) { r.Response.WriteStatus(http.StatusNotFound) return } r.Response.ServeFile(filePath) }) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() // 启动时恢复未完成的视频生成轮询 service.GenerationService.StartVideoPoller(ctx) g.Log().Info(ctx, "service started on :3006") <-ctx.Done() g.Log().Info(ctx, "shutting down...") time.Sleep(3 * time.Second) // 等待当前任务完成 g.Log().Info(ctx, "bye") }