package main import ( "embed" "fmt" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "log" "net/http" "one-api/common" "one-api/controller" "one-api/middleware" "one-api/model" "one-api/router" "os" "strconv" _ "net/http/pprof" ) //go:embed web/build var buildFS embed.FS //go:embed web/build/index.html var indexPage []byte func main() { common.SetupLogger() common.SysLog("New API " + common.Version + " started") if os.Getenv("GIN_MODE") != "debug" { gin.SetMode(gin.ReleaseMode) } if common.DebugEnabled { common.SysLog("running in debug mode") } // Initialize SQL Database err := model.InitDB() if err != nil { common.FatalLog("failed to initialize database: " + err.Error()) } defer func() { err := model.CloseDB() if err != nil { common.FatalLog("failed to close database: " + err.Error()) } }() // Initialize Redis err = common.InitRedisClient() if err != nil { common.FatalLog("failed to initialize Redis: " + err.Error()) } // Initialize options model.InitOptionMap() if common.RedisEnabled { // for compatibility with old versions common.MemoryCacheEnabled = true } if common.MemoryCacheEnabled { common.SysLog("memory cache enabled") common.SysError(fmt.Sprintf("sync frequency: %d seconds", common.SyncFrequency)) model.InitChannelCache() } if common.RedisEnabled { go model.SyncTokenCache(common.SyncFrequency) } if common.MemoryCacheEnabled { go model.SyncOptions(common.SyncFrequency) go model.SyncChannelCache(common.SyncFrequency) } // 数据看板 go model.UpdateQuotaData() if os.Getenv("CHANNEL_UPDATE_FREQUENCY") != "" { frequency, err := strconv.Atoi(os.Getenv("CHANNEL_UPDATE_FREQUENCY")) if err != nil { common.FatalLog("failed to parse CHANNEL_UPDATE_FREQUENCY: " + err.Error()) } go controller.AutomaticallyUpdateChannels(frequency) } if os.Getenv("CHANNEL_TEST_FREQUENCY") != "" { frequency, err := strconv.Atoi(os.Getenv("CHANNEL_TEST_FREQUENCY")) if err != nil { common.FatalLog("failed to parse CHANNEL_TEST_FREQUENCY: " + err.Error()) } go controller.AutomaticallyTestChannels(frequency) } common.SafeGoroutine(func() { controller.UpdateMidjourneyTaskBulk() }) if os.Getenv("BATCH_UPDATE_ENABLED") == "true" { common.BatchUpdateEnabled = true common.SysLog("batch update enabled with interval " + strconv.Itoa(common.BatchUpdateInterval) + "s") model.InitBatchUpdater() } if os.Getenv("ENABLE_PPROF") == "true" { go func() { log.Println(http.ListenAndServe("0.0.0.0:8005", nil)) }() go common.Monitor() common.SysLog("pprof enabled") } controller.InitTokenEncoders() // Initialize HTTP server server := gin.New() server.Use(gin.CustomRecovery(func(c *gin.Context, err any) { common.SysError(fmt.Sprintf("panic detected: %v", err)) c.JSON(http.StatusInternalServerError, gin.H{ "error": gin.H{ "message": fmt.Sprintf("Panic detected, error: %v. Please submit a issue here: https://github.com/Calcium-Ion/new-api", err), "type": "new_api_panic", }, }) })) // This will cause SSE not to work!!! //server.Use(gzip.Gzip(gzip.DefaultCompression)) server.Use(middleware.RequestId()) middleware.SetUpLogger(server) // Initialize session store store := cookie.NewStore([]byte(common.SessionSecret)) server.Use(sessions.Sessions("session", store)) router.SetRouter(server, buildFS, indexPage) var port = os.Getenv("PORT") if port == "" { port = strconv.Itoa(*common.Port) } err = server.Run(":" + port) if err != nil { common.FatalLog("failed to start HTTP server: " + err.Error()) } }