main.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "log"
  6. "os"
  7. "os/signal"
  8. "syscall"
  9. _ "unsafe"
  10. "x-ui/config"
  11. "x-ui/database"
  12. "x-ui/logger"
  13. "x-ui/sub"
  14. "x-ui/web"
  15. "x-ui/web/global"
  16. "x-ui/web/service"
  17. "github.com/op/go-logging"
  18. )
  19. func runWebServer() {
  20. log.Printf("Starting %v %v", config.GetName(), config.GetVersion())
  21. switch config.GetLogLevel() {
  22. case config.Debug:
  23. logger.InitLogger(logging.DEBUG)
  24. case config.Info:
  25. logger.InitLogger(logging.INFO)
  26. case config.Notice:
  27. logger.InitLogger(logging.NOTICE)
  28. case config.Warn:
  29. logger.InitLogger(logging.WARNING)
  30. case config.Error:
  31. logger.InitLogger(logging.ERROR)
  32. default:
  33. log.Fatalf("Unknown log level: %v", config.GetLogLevel())
  34. }
  35. err := database.InitDB(config.GetDBPath())
  36. if err != nil {
  37. log.Fatalf("Error initializing database: %v", err)
  38. }
  39. var server *web.Server
  40. server = web.NewServer()
  41. global.SetWebServer(server)
  42. err = server.Start()
  43. if err != nil {
  44. log.Fatalf("Error starting web server: %v", err)
  45. return
  46. }
  47. var subServer *sub.Server
  48. subServer = sub.NewServer()
  49. global.SetSubServer(subServer)
  50. err = subServer.Start()
  51. if err != nil {
  52. log.Fatalf("Error starting sub server: %v", err)
  53. return
  54. }
  55. sigCh := make(chan os.Signal, 1)
  56. // Trap shutdown signals
  57. signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM)
  58. for {
  59. sig := <-sigCh
  60. switch sig {
  61. case syscall.SIGHUP:
  62. logger.Info("Received SIGHUP signal. Restarting servers...")
  63. err := server.Stop()
  64. if err != nil {
  65. logger.Debug("Error stopping web server:", err)
  66. }
  67. err = subServer.Stop()
  68. if err != nil {
  69. logger.Debug("Error stopping sub server:", err)
  70. }
  71. server = web.NewServer()
  72. global.SetWebServer(server)
  73. err = server.Start()
  74. if err != nil {
  75. log.Fatalf("Error restarting web server: %v", err)
  76. return
  77. }
  78. log.Println("Web server restarted successfully.")
  79. subServer = sub.NewServer()
  80. global.SetSubServer(subServer)
  81. err = subServer.Start()
  82. if err != nil {
  83. log.Fatalf("Error restarting sub server: %v", err)
  84. return
  85. }
  86. log.Println("Sub server restarted successfully.")
  87. default:
  88. server.Stop()
  89. subServer.Stop()
  90. log.Println("Shutting down servers.")
  91. return
  92. }
  93. }
  94. }
  95. func resetSetting() {
  96. err := database.InitDB(config.GetDBPath())
  97. if err != nil {
  98. fmt.Println("Failed to initialize database:", err)
  99. return
  100. }
  101. settingService := service.SettingService{}
  102. err = settingService.ResetSettings()
  103. if err != nil {
  104. fmt.Println("Failed to reset settings:", err)
  105. } else {
  106. fmt.Println("Settings successfully reset.")
  107. }
  108. }
  109. func showSetting(show bool) {
  110. if show {
  111. settingService := service.SettingService{}
  112. port, err := settingService.GetPort()
  113. if err != nil {
  114. fmt.Println("get current port failed, error info:", err)
  115. }
  116. webBasePath, err := settingService.GetBasePath()
  117. if err != nil {
  118. fmt.Println("get webBasePath failed, error info:", err)
  119. }
  120. userService := service.UserService{}
  121. userModel, err := userService.GetFirstUser()
  122. if err != nil {
  123. fmt.Println("get current user info failed, error info:", err)
  124. }
  125. username := userModel.Username
  126. userpasswd := userModel.Password
  127. if username == "" || userpasswd == "" {
  128. fmt.Println("current username or password is empty")
  129. }
  130. fmt.Println("current panel settings as follows:")
  131. fmt.Println("username:", username)
  132. fmt.Println("password:", userpasswd)
  133. fmt.Println("port:", port)
  134. if webBasePath != "" {
  135. fmt.Println("webBasePath:", webBasePath)
  136. } else {
  137. fmt.Println("webBasePath is not set")
  138. }
  139. }
  140. }
  141. func updateTgbotEnableSts(status bool) {
  142. settingService := service.SettingService{}
  143. currentTgSts, err := settingService.GetTgbotEnabled()
  144. if err != nil {
  145. fmt.Println(err)
  146. return
  147. }
  148. logger.Infof("current enabletgbot status[%v],need update to status[%v]", currentTgSts, status)
  149. if currentTgSts != status {
  150. err := settingService.SetTgbotEnabled(status)
  151. if err != nil {
  152. fmt.Println(err)
  153. return
  154. } else {
  155. logger.Infof("SetTgbotEnabled[%v] success", status)
  156. }
  157. }
  158. }
  159. func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) {
  160. err := database.InitDB(config.GetDBPath())
  161. if err != nil {
  162. fmt.Println("Error initializing database:", err)
  163. return
  164. }
  165. settingService := service.SettingService{}
  166. if tgBotToken != "" {
  167. err := settingService.SetTgBotToken(tgBotToken)
  168. if err != nil {
  169. fmt.Printf("Error setting Telegram bot token: %v\n", err)
  170. return
  171. }
  172. logger.Info("Successfully updated Telegram bot token.")
  173. }
  174. if tgBotRuntime != "" {
  175. err := settingService.SetTgbotRuntime(tgBotRuntime)
  176. if err != nil {
  177. fmt.Printf("Error setting Telegram bot runtime: %v\n", err)
  178. return
  179. }
  180. logger.Infof("Successfully updated Telegram bot runtime to [%s].", tgBotRuntime)
  181. }
  182. if tgBotChatid != "" {
  183. err := settingService.SetTgBotChatId(tgBotChatid)
  184. if err != nil {
  185. fmt.Printf("Error setting Telegram bot chat ID: %v\n", err)
  186. return
  187. }
  188. logger.Info("Successfully updated Telegram bot chat ID.")
  189. }
  190. }
  191. func updateSetting(port int, username string, password string, webBasePath string) {
  192. err := database.InitDB(config.GetDBPath())
  193. if err != nil {
  194. fmt.Println("Database initialization failed:", err)
  195. return
  196. }
  197. settingService := service.SettingService{}
  198. userService := service.UserService{}
  199. if port > 0 {
  200. err := settingService.SetPort(port)
  201. if err != nil {
  202. fmt.Println("Failed to set port:", err)
  203. } else {
  204. fmt.Printf("Port set successfully: %v\n", port)
  205. }
  206. }
  207. if username != "" || password != "" {
  208. err := userService.UpdateFirstUser(username, password)
  209. if err != nil {
  210. fmt.Println("Failed to update username and password:", err)
  211. } else {
  212. fmt.Println("Username and password updated successfully")
  213. }
  214. }
  215. if webBasePath != "" {
  216. err := settingService.SetBasePath(webBasePath)
  217. if err != nil {
  218. fmt.Println("Failed to set base URI path:", err)
  219. } else {
  220. fmt.Println("Base URI path set successfully")
  221. }
  222. }
  223. }
  224. func updateCert(publicKey string, privateKey string) {
  225. err := database.InitDB(config.GetDBPath())
  226. if err != nil {
  227. fmt.Println(err)
  228. return
  229. }
  230. if (privateKey != "" && publicKey != "") || (privateKey == "" && publicKey == "") {
  231. settingService := service.SettingService{}
  232. err = settingService.SetCertFile(publicKey)
  233. if err != nil {
  234. fmt.Println("set certificate public key failed:", err)
  235. } else {
  236. fmt.Println("set certificate public key success")
  237. }
  238. err = settingService.SetKeyFile(privateKey)
  239. if err != nil {
  240. fmt.Println("set certificate private key failed:", err)
  241. } else {
  242. fmt.Println("set certificate private key success")
  243. }
  244. } else {
  245. fmt.Println("both public and private key should be entered.")
  246. }
  247. }
  248. func migrateDb() {
  249. inboundService := service.InboundService{}
  250. err := database.InitDB(config.GetDBPath())
  251. if err != nil {
  252. log.Fatal(err)
  253. }
  254. fmt.Println("Start migrating database...")
  255. inboundService.MigrateDB()
  256. fmt.Println("Migration done!")
  257. }
  258. func removeSecret() {
  259. userService := service.UserService{}
  260. secretExists, err := userService.CheckSecretExistence()
  261. if err != nil {
  262. fmt.Println("Error checking secret existence:", err)
  263. return
  264. }
  265. if !secretExists {
  266. fmt.Println("No secret exists to remove.")
  267. return
  268. }
  269. err = userService.RemoveUserSecret()
  270. if err != nil {
  271. fmt.Println("Error removing secret:", err)
  272. return
  273. }
  274. settingService := service.SettingService{}
  275. err = settingService.SetSecretStatus(false)
  276. if err != nil {
  277. fmt.Println("Error updating secret status:", err)
  278. return
  279. }
  280. fmt.Println("Secret removed successfully.")
  281. }
  282. func main() {
  283. if len(os.Args) < 2 {
  284. runWebServer()
  285. return
  286. }
  287. var showVersion bool
  288. flag.BoolVar(&showVersion, "v", false, "show version")
  289. runCmd := flag.NewFlagSet("run", flag.ExitOnError)
  290. settingCmd := flag.NewFlagSet("setting", flag.ExitOnError)
  291. var port int
  292. var username string
  293. var password string
  294. var webBasePath string
  295. var webCertFile string
  296. var webKeyFile string
  297. var tgbottoken string
  298. var tgbotchatid string
  299. var enabletgbot bool
  300. var tgbotRuntime string
  301. var reset bool
  302. var show bool
  303. var remove_secret bool
  304. settingCmd.BoolVar(&reset, "reset", false, "Reset all settings")
  305. settingCmd.BoolVar(&show, "show", false, "Display current settings")
  306. settingCmd.BoolVar(&remove_secret, "remove_secret", false, "Remove secret key")
  307. settingCmd.IntVar(&port, "port", 0, "Set panel port number")
  308. settingCmd.StringVar(&username, "username", "", "Set login username")
  309. settingCmd.StringVar(&password, "password", "", "Set login password")
  310. settingCmd.StringVar(&webBasePath, "webBasePath", "", "Set base path for Panel")
  311. settingCmd.StringVar(&webCertFile, "webCert", "", "Set path to public key file for panel")
  312. settingCmd.StringVar(&webKeyFile, "webCertKey", "", "Set path to private key file for panel")
  313. settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "Set token for Telegram bot")
  314. settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "Set cron time for Telegram bot notifications")
  315. settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "Set chat ID for Telegram bot notifications")
  316. settingCmd.BoolVar(&enabletgbot, "enabletgbot", false, "Enable notifications via Telegram bot")
  317. oldUsage := flag.Usage
  318. flag.Usage = func() {
  319. oldUsage()
  320. fmt.Println()
  321. fmt.Println("Commands:")
  322. fmt.Println(" run run web panel")
  323. fmt.Println(" migrate migrate form other/old x-ui")
  324. fmt.Println(" setting set settings")
  325. }
  326. flag.Parse()
  327. if showVersion {
  328. fmt.Println(config.GetVersion())
  329. return
  330. }
  331. switch os.Args[1] {
  332. case "run":
  333. err := runCmd.Parse(os.Args[2:])
  334. if err != nil {
  335. fmt.Println(err)
  336. return
  337. }
  338. runWebServer()
  339. case "migrate":
  340. migrateDb()
  341. case "setting":
  342. err := settingCmd.Parse(os.Args[2:])
  343. if err != nil {
  344. fmt.Println(err)
  345. return
  346. }
  347. if reset {
  348. resetSetting()
  349. } else {
  350. updateSetting(port, username, password, webBasePath)
  351. }
  352. if show {
  353. showSetting(show)
  354. }
  355. if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") {
  356. updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime)
  357. }
  358. if remove_secret {
  359. removeSecret()
  360. }
  361. if enabletgbot {
  362. updateTgbotEnableSts(enabletgbot)
  363. }
  364. case "cert":
  365. err := settingCmd.Parse(os.Args[2:])
  366. if err != nil {
  367. fmt.Println(err)
  368. return
  369. }
  370. if reset {
  371. updateCert("", "")
  372. } else {
  373. updateCert(webCertFile, webKeyFile)
  374. }
  375. default:
  376. fmt.Println("Invalid subcommands")
  377. fmt.Println()
  378. runCmd.Usage()
  379. fmt.Println()
  380. settingCmd.Usage()
  381. }
  382. }