3x-ui/main.go

495 lines
12 KiB
Go
Raw Normal View History

2023-02-09 22:18:06 +03:00
package main
import (
"flag"
2023-02-09 22:18:06 +03:00
"fmt"
"log"
"os"
"os/signal"
"syscall"
_ "unsafe"
2023-02-09 22:18:06 +03:00
"x-ui/config"
"x-ui/database"
"x-ui/logger"
2023-05-22 21:21:52 +03:00
"x-ui/sub"
2023-02-09 22:18:06 +03:00
"x-ui/web"
"x-ui/web/global"
"x-ui/web/service"
"github.com/op/go-logging"
)
func runWebServer() {
2024-07-09 00:08:00 +03:00
log.Printf("Starting %v %v", config.GetName(), config.GetVersion())
2023-02-09 22:18:06 +03:00
switch config.GetLogLevel() {
case config.Debug:
logger.InitLogger(logging.DEBUG)
case config.Info:
logger.InitLogger(logging.INFO)
2023-06-16 17:55:33 +03:00
case config.Notice:
logger.InitLogger(logging.NOTICE)
2023-02-09 22:18:06 +03:00
case config.Warn:
logger.InitLogger(logging.WARNING)
case config.Error:
logger.InitLogger(logging.ERROR)
default:
2024-07-09 00:08:00 +03:00
log.Fatalf("Unknown log level: %v", config.GetLogLevel())
2023-02-09 22:18:06 +03:00
}
err := database.InitDB(config.GetDBPath())
if err != nil {
2024-07-09 00:08:00 +03:00
log.Fatalf("Error initializing database: %v", err)
2023-02-09 22:18:06 +03:00
}
var server *web.Server
server = web.NewServer()
global.SetWebServer(server)
err = server.Start()
if err != nil {
2024-07-09 00:08:00 +03:00
log.Fatalf("Error starting web server: %v", err)
2023-02-09 22:18:06 +03:00
return
}
2023-05-22 21:21:52 +03:00
var subServer *sub.Server
subServer = sub.NewServer()
global.SetSubServer(subServer)
err = subServer.Start()
if err != nil {
2024-07-09 00:08:00 +03:00
log.Fatalf("Error starting sub server: %v", err)
2023-05-22 21:21:52 +03:00
return
}
2023-02-09 22:18:06 +03:00
sigCh := make(chan os.Signal, 1)
// Trap shutdown signals
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM)
2023-02-09 22:18:06 +03:00
for {
sig := <-sigCh
switch sig {
case syscall.SIGHUP:
2024-07-09 00:08:00 +03:00
logger.Info("Received SIGHUP signal. Restarting servers...")
2023-02-09 22:18:06 +03:00
err := server.Stop()
if err != nil {
2024-08-08 18:40:26 +03:00
logger.Debug("Error stopping web server:", err)
2023-02-09 22:18:06 +03:00
}
2023-05-22 21:21:52 +03:00
err = subServer.Stop()
if err != nil {
2024-08-08 18:40:26 +03:00
logger.Debug("Error stopping sub server:", err)
2023-05-22 21:21:52 +03:00
}
2023-02-09 22:18:06 +03:00
server = web.NewServer()
global.SetWebServer(server)
err = server.Start()
if err != nil {
2024-07-09 00:08:00 +03:00
log.Fatalf("Error restarting web server: %v", err)
2023-02-09 22:18:06 +03:00
return
}
2024-07-09 00:08:00 +03:00
log.Println("Web server restarted successfully.")
2023-05-22 21:21:52 +03:00
subServer = sub.NewServer()
global.SetSubServer(subServer)
err = subServer.Start()
if err != nil {
2024-07-09 00:08:00 +03:00
log.Fatalf("Error restarting sub server: %v", err)
2023-05-22 21:21:52 +03:00
return
}
2024-07-09 00:08:00 +03:00
log.Println("Sub server restarted successfully.")
2023-02-09 22:18:06 +03:00
default:
server.Stop()
2023-05-22 21:21:52 +03:00
subServer.Stop()
2024-07-09 00:08:00 +03:00
log.Println("Shutting down servers.")
2023-02-09 22:18:06 +03:00
return
}
}
}
func resetSetting() {
err := database.InitDB(config.GetDBPath())
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Failed to initialize database:", err)
2023-02-09 22:18:06 +03:00
return
}
settingService := service.SettingService{}
err = settingService.ResetSettings()
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Failed to reset settings:", err)
2023-02-09 22:18:06 +03:00
} else {
2024-07-09 00:08:00 +03:00
fmt.Println("Settings successfully reset.")
2023-02-09 22:18:06 +03:00
}
}
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)
2023-02-09 22:18:06 +03:00
}
webBasePath, err := settingService.GetBasePath()
if err != nil {
fmt.Println("get webBasePath failed, error info:", err)
}
2024-10-30 22:26:37 +03:00
certFile, err := settingService.GetCertFile()
if err != nil {
fmt.Println("get cert file failed, error info:", err)
}
keyFile, err := settingService.GetKeyFile()
if err != nil {
fmt.Println("get key file failed, error info:", err)
}
2023-02-09 22:18:06 +03:00
userService := service.UserService{}
userModel, err := userService.GetFirstUser()
if err != nil {
fmt.Println("get current user info failed, error info:", err)
2023-02-09 22:18:06 +03:00
}
2023-02-09 22:18:06 +03:00
username := userModel.Username
userpasswd := userModel.Password
if username == "" || userpasswd == "" {
2023-02-09 22:18:06 +03:00
fmt.Println("current username or password is empty")
}
2023-04-14 16:52:49 +03:00
fmt.Println("current panel settings as follows:")
2024-10-30 22:26:37 +03:00
if certFile == "" || keyFile == "" {
fmt.Println("Warning: Panel is not secure with SSL")
} else {
fmt.Println("Panel is secure with SSL")
}
2023-02-09 22:18:06 +03:00
fmt.Println("username:", username)
2024-05-28 16:16:29 +03:00
fmt.Println("password:", userpasswd)
2023-02-09 22:18:06 +03:00
fmt.Println("port:", port)
2024-10-30 22:26:37 +03:00
fmt.Println("webBasePath:", webBasePath)
2023-02-09 22:18:06 +03:00
}
}
func updateTgbotEnableSts(status bool) {
settingService := service.SettingService{}
2024-07-07 12:55:59 +03:00
currentTgSts, err := settingService.GetTgbotEnabled()
2023-02-09 22:18:06 +03:00
if err != nil {
fmt.Println(err)
return
}
logger.Infof("current enabletgbot status[%v],need update to status[%v]", currentTgSts, status)
if currentTgSts != status {
2024-07-07 12:55:59 +03:00
err := settingService.SetTgbotEnabled(status)
2023-02-09 22:18:06 +03:00
if err != nil {
fmt.Println(err)
return
} else {
2024-07-07 12:55:59 +03:00
logger.Infof("SetTgbotEnabled[%v] success", status)
2023-02-09 22:18:06 +03:00
}
}
}
2023-03-17 19:07:49 +03:00
func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) {
2023-02-09 22:18:06 +03:00
err := database.InitDB(config.GetDBPath())
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Error initializing database:", err)
2023-02-09 22:18:06 +03:00
return
}
settingService := service.SettingService{}
if tgBotToken != "" {
err := settingService.SetTgBotToken(tgBotToken)
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Printf("Error setting Telegram bot token: %v\n", err)
2023-02-09 22:18:06 +03:00
return
}
2024-07-09 00:08:00 +03:00
logger.Info("Successfully updated Telegram bot token.")
2023-02-09 22:18:06 +03:00
}
if tgBotRuntime != "" {
err := settingService.SetTgbotRuntime(tgBotRuntime)
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Printf("Error setting Telegram bot runtime: %v\n", err)
2023-02-09 22:18:06 +03:00
return
}
2024-07-09 00:08:00 +03:00
logger.Infof("Successfully updated Telegram bot runtime to [%s].", tgBotRuntime)
2023-02-09 22:18:06 +03:00
}
2023-03-17 19:07:49 +03:00
if tgBotChatid != "" {
2023-02-09 22:18:06 +03:00
err := settingService.SetTgBotChatId(tgBotChatid)
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Printf("Error setting Telegram bot chat ID: %v\n", err)
2023-02-09 22:18:06 +03:00
return
}
2024-07-09 00:08:00 +03:00
logger.Info("Successfully updated Telegram bot chat ID.")
2023-02-09 22:18:06 +03:00
}
}
func updateSetting(port int, username string, password string, webBasePath string, listenIP string) {
2023-02-09 22:18:06 +03:00
err := database.InitDB(config.GetDBPath())
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Database initialization failed:", err)
2023-02-09 22:18:06 +03:00
return
}
settingService := service.SettingService{}
2024-07-09 00:08:00 +03:00
userService := service.UserService{}
2023-02-09 22:18:06 +03:00
if port > 0 {
err := settingService.SetPort(port)
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Failed to set port:", err)
2023-02-09 22:18:06 +03:00
} else {
2024-07-09 00:08:00 +03:00
fmt.Printf("Port set successfully: %v\n", port)
2023-02-09 22:18:06 +03:00
}
}
2023-02-09 22:18:06 +03:00
if username != "" || password != "" {
err := userService.UpdateFirstUser(username, password)
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Failed to update username and password:", err)
2023-02-09 22:18:06 +03:00
} else {
2024-07-09 00:08:00 +03:00
fmt.Println("Username and password updated successfully")
2023-02-09 22:18:06 +03:00
}
}
if webBasePath != "" {
err := settingService.SetBasePath(webBasePath)
if err != nil {
2024-07-09 00:08:00 +03:00
fmt.Println("Failed to set base URI path:", err)
} else {
2024-07-09 00:08:00 +03:00
fmt.Println("Base URI path set successfully")
}
}
if listenIP != "" {
err := settingService.SetListen(listenIP)
if err != nil {
fmt.Println("Failed to set listen IP:", err)
} else {
fmt.Printf("listen %v set successfully", listenIP)
}
}
2023-02-09 22:18:06 +03:00
}
func updateCert(publicKey string, privateKey string) {
err := database.InitDB(config.GetDBPath())
if err != nil {
fmt.Println(err)
return
}
if (privateKey != "" && publicKey != "") || (privateKey == "" && publicKey == "") {
settingService := service.SettingService{}
err = settingService.SetCertFile(publicKey)
if err != nil {
fmt.Println("set certificate public key failed:", err)
} else {
fmt.Println("set certificate public key success")
}
err = settingService.SetKeyFile(privateKey)
if err != nil {
fmt.Println("set certificate private key failed:", err)
} else {
fmt.Println("set certificate private key success")
}
} else {
fmt.Println("both public and private key should be entered.")
}
}
2024-10-30 22:26:37 +03:00
func GetCertificate(getCert bool) {
if getCert {
settingService := service.SettingService{}
certFile, err := settingService.GetCertFile()
if err != nil {
fmt.Println("get cert file failed, error info:", err)
}
keyFile, err := settingService.GetKeyFile()
if err != nil {
fmt.Println("get key file failed, error info:", err)
}
fmt.Println("cert:", certFile)
fmt.Println("key:", keyFile)
}
}
func GetListenIP(getListen bool) {
if getListen {
settingService := service.SettingService{}
ListenIP, err := settingService.GetListen()
if err != nil {
log.Printf("Failed to retrieve listen IP: %v", err)
return
}
fmt.Println("listenIP:", ListenIP)
}
}
func migrateDb() {
inboundService := service.InboundService{}
err := database.InitDB(config.GetDBPath())
if err != nil {
log.Fatal(err)
}
fmt.Println("Start migrating database...")
inboundService.MigrateDB()
fmt.Println("Migration done!")
}
func removeSecret() {
2024-03-12 20:15:44 +03:00
userService := service.UserService{}
secretExists, err := userService.CheckSecretExistence()
if err != nil {
2024-03-12 20:15:44 +03:00
fmt.Println("Error checking secret existence:", err)
return
}
2024-03-12 20:15:44 +03:00
if !secretExists {
fmt.Println("No secret exists to remove.")
return
}
err = userService.RemoveUserSecret()
if err != nil {
2024-03-12 20:15:44 +03:00
fmt.Println("Error removing secret:", err)
return
}
2024-03-12 20:15:44 +03:00
settingService := service.SettingService{}
err = settingService.SetSecretStatus(false)
if err != nil {
2024-03-12 20:15:44 +03:00
fmt.Println("Error updating secret status:", err)
return
}
2024-03-12 20:15:44 +03:00
fmt.Println("Secret removed successfully.")
}
2023-02-09 22:18:06 +03:00
func main() {
if len(os.Args) < 2 {
runWebServer()
return
2023-02-09 22:18:06 +03:00
}
var showVersion bool
flag.BoolVar(&showVersion, "v", false, "show version")
runCmd := flag.NewFlagSet("run", flag.ExitOnError)
settingCmd := flag.NewFlagSet("setting", flag.ExitOnError)
var port int
var username string
var password string
var webBasePath string
var listenIP string
2024-10-30 22:26:37 +03:00
var getListen bool
var webCertFile string
var webKeyFile string
var tgbottoken string
var tgbotchatid string
var enabletgbot bool
var tgbotRuntime string
var reset bool
var show bool
2024-10-30 22:26:37 +03:00
var getCert bool
var remove_secret bool
2024-07-09 00:08:00 +03:00
settingCmd.BoolVar(&reset, "reset", false, "Reset all settings")
settingCmd.BoolVar(&show, "show", false, "Display current settings")
settingCmd.BoolVar(&remove_secret, "remove_secret", false, "Remove secret key")
settingCmd.IntVar(&port, "port", 0, "Set panel port number")
settingCmd.StringVar(&username, "username", "", "Set login username")
settingCmd.StringVar(&password, "password", "", "Set login password")
settingCmd.StringVar(&webBasePath, "webBasePath", "", "Set base path for Panel")
2024-10-30 22:26:37 +03:00
settingCmd.StringVar(&listenIP, "listenIP", "", "set panel listenIP IP")
settingCmd.BoolVar(&getListen, "getListen", false, "Display current panel listenIP IP")
settingCmd.BoolVar(&getCert, "getCert", false, "Display current certificate settings")
2024-07-09 00:08:00 +03:00
settingCmd.StringVar(&webCertFile, "webCert", "", "Set path to public key file for panel")
settingCmd.StringVar(&webKeyFile, "webCertKey", "", "Set path to private key file for panel")
settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "Set token for Telegram bot")
settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "Set cron time for Telegram bot notifications")
settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "Set chat ID for Telegram bot notifications")
settingCmd.BoolVar(&enabletgbot, "enabletgbot", false, "Enable notifications via Telegram bot")
oldUsage := flag.Usage
flag.Usage = func() {
oldUsage()
fmt.Println()
fmt.Println("Commands:")
fmt.Println(" run run web panel")
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 "setting":
err := settingCmd.Parse(os.Args[2:])
if err != nil {
fmt.Println(err)
return
}
if reset {
2023-02-09 22:18:06 +03:00
resetSetting()
} else {
updateSetting(port, username, password, webBasePath, listenIP)
}
if show {
showSetting(show)
}
2024-10-30 22:26:37 +03:00
if getListen {
GetListenIP(getListen)
}
if getCert {
GetCertificate(getCert)
}
if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") {
updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime)
}
if remove_secret {
removeSecret()
}
if enabletgbot {
updateTgbotEnableSts(enabletgbot)
}
case "cert":
err := settingCmd.Parse(os.Args[2:])
if err != nil {
fmt.Println(err)
return
}
if reset {
updateCert("", "")
} else {
updateCert(webCertFile, webKeyFile)
}
default:
fmt.Println("Invalid subcommands")
fmt.Println()
runCmd.Usage()
fmt.Println()
settingCmd.Usage()
2023-02-09 22:18:06 +03:00
}
}