Spaces:
Running
Running
| package main | |
| import ( | |
| "context" | |
| "cursor2api-go/config" | |
| "cursor2api-go/handlers" | |
| "cursor2api-go/middleware" | |
| "cursor2api-go/models" | |
| "fmt" | |
| "net/http" | |
| "os" | |
| "os/signal" | |
| "strings" | |
| "syscall" | |
| "time" | |
| "github.com/gin-gonic/gin" | |
| "github.com/sirupsen/logrus" | |
| ) | |
| func main() { | |
| // ๅ ่ฝฝ้ ็ฝฎ | |
| cfg, err := config.LoadConfig() | |
| if err != nil { | |
| logrus.Fatalf("Failed to load config: %v", err) | |
| } | |
| // ่ฎพ็ฝฎๆฅๅฟ็บงๅซๅ GIN ๆจกๅผ๏ผๅฟ ้กปๅจๅๅปบ่ทฏ็ฑๅจไนๅ่ฎพ็ฝฎ๏ผ | |
| if cfg.Debug { | |
| logrus.SetLevel(logrus.DebugLevel) | |
| gin.SetMode(gin.DebugMode) | |
| } else { | |
| logrus.SetLevel(logrus.InfoLevel) | |
| gin.SetMode(gin.ReleaseMode) | |
| } | |
| // ็ฆ็จ Gin ็่ฐ่ฏไฟกๆฏ่พๅบ | |
| gin.DisableConsoleColor() | |
| // ๅๅปบ่ทฏ็ฑๅจ๏ผไฝฟ็จ gin.New() ่ไธๆฏ gin.Default() ไปฅ้ฟๅ ้ป่ฎคๆฅๅฟ๏ผ | |
| router := gin.New() | |
| // ๆทปๅ ไธญ้ดไปถ | |
| router.Use(gin.Recovery()) | |
| router.Use(middleware.CORS()) | |
| router.Use(middleware.ErrorHandler()) | |
| // ๅชๅจ Debug ๆจกๅผไธๅฏ็จ GIN ็ๆฅๅฟ | |
| if cfg.Debug { | |
| router.Use(gin.Logger()) | |
| } | |
| // ๅๅปบๅค็ๅจ | |
| handler := handlers.NewHandler(cfg) | |
| // ๆณจๅ่ทฏ็ฑ | |
| setupRoutes(router, handler) | |
| // ๅๅปบHTTPๆๅกๅจ | |
| server := &http.Server{ | |
| Addr: fmt.Sprintf(":%d", cfg.Port), | |
| Handler: router, | |
| } | |
| // ๆๅฐๅฏๅจไฟกๆฏ | |
| printStartupBanner(cfg) | |
| // ๅฏๅจๆๅกๅจ็goroutine | |
| go func() { | |
| if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { | |
| logrus.Fatalf("Failed to start server: %v", err) | |
| } | |
| }() | |
| // ็ญๅพ ไธญๆญไฟกๅทไปฅไผ้ ๅ ณ้ญๆๅกๅจ | |
| quit := make(chan os.Signal, 1) | |
| signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) | |
| <-quit | |
| logrus.Info("Shutting down server...") | |
| // ็ปๆๅกๅจ5็งๆถ้ดๅฎๆๅค็ๆญฃๅจ่ฟ่ก็่ฏทๆฑ | |
| ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | |
| defer cancel() | |
| if err := server.Shutdown(ctx); err != nil { | |
| logrus.Fatalf("Server forced to shutdown: %v", err) | |
| } | |
| logrus.Info("Server exited") | |
| } | |
| func setupRoutes(router *gin.Engine, handler *handlers.Handler) { | |
| // ๅฅๅบทๆฃๆฅ | |
| router.GET("/health", func(c *gin.Context) { | |
| c.JSON(http.StatusOK, gin.H{ | |
| "status": "ok", | |
| "time": time.Now().Unix(), | |
| }) | |
| }) | |
| // APIๆๆกฃ้กต้ข | |
| router.GET("/", handler.ServeDocs) | |
| // API v1่ทฏ็ฑ็ป | |
| v1 := router.Group("/v1") | |
| { | |
| // ๆจกๅๅ่กจ | |
| v1.GET("/models", middleware.AuthRequired(), handler.ListModels) | |
| // ่ๅคฉๅฎๆ | |
| v1.POST("/chat/completions", middleware.AuthRequired(), handler.ChatCompletions) | |
| } | |
| // ้ๆๆไปถๆๅก๏ผๅฆๆ้่ฆ๏ผ | |
| router.Static("/static", "./static") | |
| } | |
| // printStartupBanner ๆๅฐๅฏๅจๆจชๅน | |
| func printStartupBanner(cfg *config.Config) { | |
| banner := ` | |
| โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| โ Cursor2API Server โ | |
| โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| ` | |
| fmt.Println(banner) | |
| fmt.Printf("๐ ๆๅกๅฐๅ: http://localhost:%d\n", cfg.Port) | |
| fmt.Printf("๐ API ๆๆกฃ: http://localhost:%d/\n", cfg.Port) | |
| fmt.Printf("๐ ๅฅๅบทๆฃๆฅ: http://localhost:%d/health\n", cfg.Port) | |
| fmt.Printf("๐ API ๅฏ้ฅ: %s\n", maskAPIKey(cfg.APIKey)) | |
| modelList := cfg.GetModels() | |
| fmt.Printf("\n๐ค ๆฏๆๆจกๅ (%d ไธช):\n", len(modelList)) | |
| // ๆ็ฑปๅซๅ็ปๆพ็คบๆจกๅ | |
| providers := make(map[string][]string) | |
| for _, modelID := range modelList { | |
| if config, exists := models.GetModelConfig(modelID); exists { | |
| providers[config.Provider] = append(providers[config.Provider], modelID) | |
| } else { | |
| providers["Other"] = append(providers["Other"], modelID) | |
| } | |
| } | |
| // ๆProviderๆๅบๅนถๆพ็คบ | |
| for _, provider := range []string{"Anthropic", "OpenAI", "Google", "Other"} { | |
| if models, ok := providers[provider]; ok && len(models) > 0 { | |
| fmt.Printf(" %s: %s\n", provider, strings.Join(models, ", ")) | |
| } | |
| } | |
| if cfg.Debug { | |
| fmt.Println("\n๐ ่ฐ่ฏๆจกๅผ: ๅทฒๅฏ็จ") | |
| } | |
| fmt.Println("\nโจ ๆๅกๅทฒๅฏๅจ๏ผๆ Ctrl+C ๅๆญข") | |
| fmt.Println("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ") | |
| } | |
| // maskAPIKey ๆฉ็ API ๅฏ้ฅ๏ผๅชๆพ็คบๅ 4 ไฝ | |
| func maskAPIKey(key string) string { | |
| if len(key) <= 4 { | |
| return "****" | |
| } | |
| return key[:4] + "****" | |
| } | |