108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
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")
|
|
}
|