package main import ( "crypto/rand" "encoding/hex" "fmt" "log" "anticaptcha/internal/captcha" "anticaptcha/internal/config" "anticaptcha/internal/database" "anticaptcha/internal/handler" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" ) func main() { // 检查是否已安装 if !config.IsInstalled() { fmt.Println("系统未安装,请先访问 /install 进行安装配置") } // 加载配置 if err := config.Load(""); err != nil { log.Printf("警告: %v", err) } // 初始化数据库 if config.Cfg != nil { if err := database.Init(&config.Cfg.Database); err != nil { log.Fatalf("数据库初始化失败: %v", err) } defer database.Close() } // 创建 Gin 引擎 gin.SetMode(gin.ReleaseMode) r := gin.New() r.Use(gin.Recovery()) // CORS 配置 r.Use(cors.New(cors.Config{ AllowAllOrigins: true, AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowHeaders: []string{"Origin", "Content-Type", "Authorization"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: true, })) // 静态文件服务(前端) r.Static("/assets", "./web/dist/assets") r.NoRoute(func(c *gin.Context) { c.File("./web/dist/index.html") }) // API 路由 captchaHandler := handler.NewCaptchaHandler(captcha.NewHandler("./models")) captchaHandler.RegisterRoutes(r.Group(""), true) // 安装路由 r.POST("/api/install", handleInstall) r.GET("/api/install/check", func(c *gin.Context) { c.JSON(200, gin.H{"installed": config.IsInstalled()}) }) // 健康检查 r.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{"status": "ok"}) }) // 启动服务 addr := ":6688" if config.Cfg != nil { addr = fmt.Sprintf("%s:%d", config.Cfg.Server.Host, config.Cfg.Server.Port) } fmt.Printf(` ╔════════════════════════════════════════════════════════════════╗ ║ AntiCaptcha Server v1.0.0 ║ ║ https://git.viaeon.com/admin/AntiCaptcha ║ ╠════════════════════════════════════════════════════════════════╣ ║ 服务已启动: http://%s ║ ║ 默认账号: admin / admin ║ ╚════════════════════════════════════════════════════════════════╝ `, addr) if err := r.Run(addr); err != nil { log.Fatalf("服务启动失败: %v", err) } } func handleInstall(c *gin.Context) { var req struct { Database struct { Type string `json:"type"` Host string `json:"host"` Port int `json:"port"` User string `json:"user"` Password string `json:"password"` Database string `json:"database"` SQLite struct { Path string `json:"path"` } `json:"sqlite"` } `json:"database"` Redis struct { Enabled bool `json:"enabled"` Host string `json:"host"` Port int `json:"port"` Password string `json:"password"` DB int `json:"db"` } `json:"redis"` Admin struct { Username string `json:"username"` Password string `json:"password"` } `json:"admin"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } // 生成 JWT Secret jwtSecret := generateRandomSecret() // 构建配置 cfg := &config.Config{ Server: config.ServerConfig{ Host: "0.0.0.0", Port: 6688, Mode: "release", }, Database: config.DatabaseConfig{ Type: req.Database.Type, Host: req.Database.Host, Port: req.Database.Port, User: req.Database.User, Password: req.Database.Password, Database: req.Database.Database, SQLite: config.SQLiteConfig{ Path: req.Database.SQLite.Path, }, }, Redis: config.RedisConfig{ Enabled: req.Redis.Enabled, Host: req.Redis.Host, Port: req.Redis.Port, Password: req.Redis.Password, DB: req.Redis.DB, }, JWT: config.JWTConfig{ Secret: jwtSecret, ExpireTime: 1440, }, Captcha: config.CaptchaConfig{ ModelPath: "./models", }, } // 保存配置 if err := config.Save(cfg); err != nil { c.JSON(500, gin.H{"error": "保存配置失败: " + err.Error()}) return } // 设置全局配置 config.Cfg = cfg // 初始化数据库 if err := database.Init(&cfg.Database); err != nil { c.JSON(500, gin.H{"error": "数据库初始化失败: " + err.Error()}) return } // 创建管理员用户 if err := database.EnsureAdminUser(req.Admin.Username, req.Admin.Password); err != nil { c.JSON(500, gin.H{"error": "创建管理员用户失败: " + err.Error()}) return } c.JSON(200, gin.H{ "message": "安装成功", "restart": true, "restartMsg": "请重启容器以完成安装", }) } func generateRandomSecret() string { b := make([]byte, 32) rand.Read(b) return hex.EncodeToString(b) }