package main import ( "flag" "fmt" "log" "os" "os/signal" "syscall" _ "unsafe" "x-ui/config" "x-ui/database" "x-ui/logger" "x-ui/v2ui" "x-ui/web" "x-ui/web/global" "x-ui/web/service" "github.com/op/go-logging" ) func runWebServer() { log.Printf("%v %v", config.GetName(), config.GetVersion()) switch config.GetLogLevel() { case config.Debug: logger.InitLogger(logging.DEBUG) case config.Info: logger.InitLogger(logging.INFO) case config.Warn: logger.InitLogger(logging.WARNING) case config.Error: logger.InitLogger(logging.ERROR) default: log.Fatal("unknown log level:", config.GetLogLevel()) } err := database.InitDB(config.GetDBPath()) if err != nil { log.Fatal(err) } var server *web.Server server = web.NewServer() global.SetWebServer(server) err = server.Start() if err != nil { log.Println(err) return } sigCh := make(chan os.Signal, 1) // Trap shutdown signals signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM) for { sig := <-sigCh switch sig { case syscall.SIGHUP: err := server.Stop() if err != nil { logger.Warning("stop server err:", err) } server = web.NewServer() global.SetWebServer(server) err = server.Start() if err != nil { log.Println(err) return } default: server.Stop() return } } } func resetSetting() { err := database.InitDB(config.GetDBPath()) if err != nil { fmt.Println(err) return } settingService := service.SettingService{} err = settingService.ResetSettings() if err != nil { fmt.Println("reset setting failed:", err) } else { fmt.Println("reset setting success") } } func showSetting(show bool) { if show { settingService := service.SettingService{} port, err := settingService.GetPort() if err != nil { fmt.Println("get current port failed,error info:", err) } userService := service.UserService{} userModel, err := userService.GetFirstUser() if err != nil { fmt.Println("get current user info failed,error info:", err) } username := userModel.Username userpasswd := userModel.Password if (username == "") || (userpasswd == "") { fmt.Println("current username or password is empty") } fmt.Println("current panel settings as follows:") fmt.Println("username:", username) fmt.Println("userpasswd:", userpasswd) fmt.Println("port:", port) } } func updateTgbotEnableSts(status bool) { settingService := service.SettingService{} currentTgSts, err := settingService.GetTgbotenabled() if err != nil { fmt.Println(err) return } logger.Infof("current enabletgbot status[%v],need update to status[%v]", currentTgSts, status) if currentTgSts != status { err := settingService.SetTgbotenabled(status) if err != nil { fmt.Println(err) return } else { logger.Infof("SetTgbotenabled[%v] success", status) } } return } func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) { err := database.InitDB(config.GetDBPath()) if err != nil { fmt.Println(err) return } settingService := service.SettingService{} if tgBotToken != "" { err := settingService.SetTgBotToken(tgBotToken) if err != nil { fmt.Println(err) return } else { logger.Info("updateTgbotSetting tgBotToken success") } } if tgBotRuntime != "" { err := settingService.SetTgbotRuntime(tgBotRuntime) if err != nil { fmt.Println(err) return } else { logger.Infof("updateTgbotSetting tgBotRuntime[%s] success", tgBotRuntime) } } if tgBotChatid != "" { err := settingService.SetTgBotChatId(tgBotChatid) if err != nil { fmt.Println(err) return } else { logger.Info("updateTgbotSetting tgBotChatid success") } } } func updateSetting(port int, username string, password string) { err := database.InitDB(config.GetDBPath()) if err != nil { fmt.Println(err) return } settingService := service.SettingService{} if port > 0 { err := settingService.SetPort(port) if err != nil { fmt.Println("set port failed:", err) } else { fmt.Printf("set port %v success", port) } } if username != "" || password != "" { userService := service.UserService{} err := userService.UpdateFirstUser(username, password) if err != nil { fmt.Println("set username and password failed:", err) } else { fmt.Println("set username and password success") } } } func migrateDb() { inboundService := service.InboundService{} err := database.InitDB(config.GetDBPath()) if err != nil { log.Fatal(err) } fmt.Println("Start migrating database...") inboundService.MigrationRequirements() inboundService.RemoveOrphanedTraffics() fmt.Println("Migration done!") } func removeSecret() { err := database.InitDB(config.GetDBPath()) if err != nil { fmt.Println(err) return } userService := service.UserService{} err = userService.RemoveUserSecret() if err != nil { fmt.Println(err) } settingService := service.SettingService{} err = settingService.SetSecretStatus(false) if err != nil { fmt.Println(err) } } func main() { if len(os.Args) < 2 { runWebServer() return } var showVersion bool flag.BoolVar(&showVersion, "v", false, "show version") runCmd := flag.NewFlagSet("run", flag.ExitOnError) v2uiCmd := flag.NewFlagSet("v2-ui", flag.ExitOnError) var dbPath string v2uiCmd.StringVar(&dbPath, "db", fmt.Sprintf("%s/v2-ui.db", config.GetDBFolderPath()), "set v2-ui db file path") settingCmd := flag.NewFlagSet("setting", flag.ExitOnError) var port int var username string var password string var tgbottoken string var tgbotchatid string var enabletgbot bool var tgbotRuntime string var reset bool var show bool var remove_secret bool settingCmd.BoolVar(&reset, "reset", false, "reset all settings") settingCmd.BoolVar(&show, "show", false, "show current settings") settingCmd.IntVar(&port, "port", 0, "set panel port") settingCmd.StringVar(&username, "username", "", "set login username") settingCmd.StringVar(&password, "password", "", "set login password") settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "set telegram bot token") settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "set telegram bot cron time") settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "set telegram bot chat id") settingCmd.BoolVar(&enabletgbot, "enabletgbot", false, "enable telegram bot notify") oldUsage := flag.Usage flag.Usage = func() { oldUsage() fmt.Println() fmt.Println("Commands:") fmt.Println(" run run web panel") fmt.Println(" v2-ui migrate form v2-ui") fmt.Println(" migrate migrate form other/old x-ui") fmt.Println(" setting set settings") } flag.Parse() if showVersion { fmt.Println(config.GetVersion()) return } switch os.Args[1] { case "run": err := runCmd.Parse(os.Args[2:]) if err != nil { fmt.Println(err) return } runWebServer() case "migrate": migrateDb() case "v2-ui": err := v2uiCmd.Parse(os.Args[2:]) if err != nil { fmt.Println(err) return } err = v2ui.MigrateFromV2UI(dbPath) if err != nil { fmt.Println("migrate from v2-ui failed:", err) } case "setting": err := settingCmd.Parse(os.Args[2:]) if err != nil { fmt.Println(err) return } if reset { resetSetting() } else { updateSetting(port, username, password) } if show { showSetting(show) } if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") { updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime) } if remove_secret { removeSecret() } if enabletgbot { updateTgbotEnableSts(enabletgbot) } default: fmt.Println("except 'run' or 'v2-ui' or 'setting' subcommands") fmt.Println() runCmd.Usage() fmt.Println() v2uiCmd.Usage() fmt.Println() settingCmd.Usage() } }