diff --git a/.gitignore b/.gitignore index 158f4ee1..781a633d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .cache .sync* *.tar.gz +*.log access.log error.log tmp diff --git a/README.md b/README.md index 14d569db..0b209c77 100644 --- a/README.md +++ b/README.md @@ -311,9 +311,9 @@ If you want to use routing to WARP before v2.1.0 follow steps as below: ```sh "log": { - "access": "./access.log", - "dnsLog": false, - "loglevel": "warning" + "access": "./access.log", + "dnsLog": false, + "loglevel": "warning" }, ``` diff --git a/database/model/model.go b/database/model/model.go index 32ab255f..df41237d 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -2,6 +2,7 @@ package model import ( "fmt" + "x-ui/util/json_util" "x-ui/xray" ) diff --git a/logger/logger.go b/logger/logger.go index ca047cbc..35c5c0ac 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -8,12 +8,14 @@ import ( "github.com/op/go-logging" ) -var logger *logging.Logger -var logBuffer []struct { - time string - level logging.Level - log string -} +var ( + logger *logging.Logger + logBuffer []struct { + time string + level logging.Level + log string + } +) func init() { InitLogger(logging.INFO) diff --git a/main.go b/main.go index fdf54089..4051337b 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "os/signal" "syscall" _ "unsafe" + "x-ui/config" "x-ui/database" "x-ui/logger" diff --git a/sub/sub.go b/sub/sub.go index 2a4a37f4..948adea8 100644 --- a/sub/sub.go +++ b/sub/sub.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "strconv" + "x-ui/config" "x-ui/logger" "x-ui/util/common" @@ -99,7 +100,7 @@ func (s *Server) initRouter() (*gin.Engine, error) { } func (s *Server) Start() (err error) { - //This is an anonymous function, no function name + // This is an anonymous function, no function name defer func() { if err != nil { s.Stop() diff --git a/sub/subController.go b/sub/subController.go index b5c5cbac..8de5b5df 100644 --- a/sub/subController.go +++ b/sub/subController.go @@ -25,8 +25,8 @@ func NewSUBController( showInfo bool, rModel string, update string, - jsonFragment string) *SUBController { - + jsonFragment string, +) *SUBController { a := &SUBController{ subPath: subPath, subJsonPath: jsonPath, diff --git a/sub/subJsonService.go b/sub/subJsonService.go index 8bc98dea..9320306e 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "x-ui/database/model" "x-ui/logger" "x-ui/util/json_util" diff --git a/sub/subService.go b/sub/subService.go index 06d1ed0a..5363149a 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -6,6 +6,7 @@ import ( "net/url" "strings" "time" + "x-ui/database" "x-ui/database/model" "x-ui/logger" diff --git a/util/common/err.go b/util/common/err.go index f6078c33..494e5c82 100644 --- a/util/common/err.go +++ b/util/common/err.go @@ -3,6 +3,7 @@ package common import ( "errors" "fmt" + "x-ui/logger" ) diff --git a/util/random/random.go b/util/random/random.go index 1dd47ec9..67ee0691 100644 --- a/util/random/random.go +++ b/util/random/random.go @@ -4,12 +4,14 @@ import ( "math/rand" ) -var numSeq [10]rune -var lowerSeq [26]rune -var upperSeq [26]rune -var numLowerSeq [36]rune -var numUpperSeq [36]rune -var allSeq [62]rune +var ( + numSeq [10]rune + lowerSeq [26]rune + upperSeq [26]rune + numLowerSeq [36]rune + numUpperSeq [36]rune + allSeq [62]rune +) func init() { for i := 0; i < 10; i++ { diff --git a/web/assets/js/axios-init.js b/web/assets/js/axios-init.js index b864b714..f0b0f4be 100644 --- a/web/assets/js/axios-init.js +++ b/web/assets/js/axios-init.js @@ -14,3 +14,17 @@ axios.interceptors.request.use( }, (error) => Promise.reject(error), ); + +axios.interceptors.response.use( + (response) => response, + (error) => { + if (error.response) { + const statusCode = error.response.status; + // Check the status code + if (statusCode === 401) { // Unauthorized + return window.location.reload(); + } + } + return Promise.reject(error); + } +); diff --git a/web/assets/js/util/utils.js b/web/assets/js/util/utils.js index 61b322bd..f2f05f01 100644 --- a/web/assets/js/util/utils.js +++ b/web/assets/js/util/utils.js @@ -131,11 +131,11 @@ class RandomUtil { static randomUUID() { const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; return template.replace(/[xy]/g, function (c) { - const randomValues = new Uint8Array(1); - crypto.getRandomValues(randomValues); - let randomValue = randomValues[0] % 16; - let calculatedValue = (c === 'x') ? randomValue : (randomValue & 0x3 | 0x8); - return calculatedValue.toString(16); + const randomValues = new Uint8Array(1); + crypto.getRandomValues(randomValues); + let randomValue = randomValues[0] % 16; + let calculatedValue = (c === 'x') ? randomValue : (randomValue & 0x3 | 0x8); + return calculatedValue.toString(16); }); } diff --git a/web/controller/api.go b/web/controller/api.go index 73c36787..6281097b 100644 --- a/web/controller/api.go +++ b/web/controller/api.go @@ -22,91 +22,37 @@ func (a *APIController) initRouter(g *gin.RouterGroup) { g = g.Group("/panel/api/inbounds") g.Use(a.checkLogin) - g.GET("/list", a.getAllInbounds) - g.GET("/get/:id", a.getSingleInbound) - g.GET("/getClientTraffics/:email", a.getClientTraffics) - g.POST("/add", a.addInbound) - g.POST("/del/:id", a.delInbound) - g.POST("/update/:id", a.updateInbound) - g.POST("/clientIps/:email", a.getClientIps) - g.POST("/clearClientIps/:email", a.clearClientIps) - g.POST("/addClient", a.addInboundClient) - g.POST("/:id/delClient/:clientId", a.delInboundClient) - g.POST("/updateClient/:clientId", a.updateInboundClient) - g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) - g.POST("/resetAllTraffics", a.resetAllTraffics) - g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics) - g.POST("/delDepletedClients/:id", a.delDepletedClients) - g.GET("/createbackup", a.createBackup) - g.POST("/onlines", a.onlines) - a.inboundController = NewInboundController(g) -} -func (a *APIController) getAllInbounds(c *gin.Context) { - a.inboundController.getInbounds(c) -} + inboundRoutes := []struct { + Method string + Path string + Handler gin.HandlerFunc + }{ + {"GET", "/createbackup", a.createBackup}, + {"GET", "/list", a.inboundController.getInbounds}, + {"GET", "/get/:id", a.inboundController.getInbound}, + {"GET", "/getClientTraffics/:email", a.inboundController.getClientTraffics}, + {"POST", "/add", a.inboundController.addInbound}, + {"POST", "/del/:id", a.inboundController.delInbound}, + {"POST", "/update/:id", a.inboundController.updateInbound}, + {"POST", "/clientIps/:email", a.inboundController.getClientIps}, + {"POST", "/clearClientIps/:email", a.inboundController.clearClientIps}, + {"POST", "/addClient", a.inboundController.addInboundClient}, + {"POST", "/:id/delClient/:clientId", a.inboundController.delInboundClient}, + {"POST", "/updateClient/:clientId", a.inboundController.updateInboundClient}, + {"POST", "/:id/resetClientTraffic/:email", a.inboundController.resetClientTraffic}, + {"POST", "/resetAllTraffics", a.inboundController.resetAllTraffics}, + {"POST", "/resetAllClientTraffics/:id", a.inboundController.resetAllClientTraffics}, + {"POST", "/delDepletedClients/:id", a.inboundController.delDepletedClients}, + {"POST", "/onlines", a.inboundController.onlines}, + } -func (a *APIController) getSingleInbound(c *gin.Context) { - a.inboundController.getInbound(c) -} - -func (a *APIController) getClientTraffics(c *gin.Context) { - a.inboundController.getClientTraffics(c) -} - -func (a *APIController) addInbound(c *gin.Context) { - a.inboundController.addInbound(c) -} - -func (a *APIController) delInbound(c *gin.Context) { - a.inboundController.delInbound(c) -} - -func (a *APIController) updateInbound(c *gin.Context) { - a.inboundController.updateInbound(c) -} - -func (a *APIController) getClientIps(c *gin.Context) { - a.inboundController.getClientIps(c) -} - -func (a *APIController) clearClientIps(c *gin.Context) { - a.inboundController.clearClientIps(c) -} - -func (a *APIController) addInboundClient(c *gin.Context) { - a.inboundController.addInboundClient(c) -} - -func (a *APIController) delInboundClient(c *gin.Context) { - a.inboundController.delInboundClient(c) -} - -func (a *APIController) updateInboundClient(c *gin.Context) { - a.inboundController.updateInboundClient(c) -} - -func (a *APIController) resetClientTraffic(c *gin.Context) { - a.inboundController.resetClientTraffic(c) -} - -func (a *APIController) resetAllTraffics(c *gin.Context) { - a.inboundController.resetAllTraffics(c) -} - -func (a *APIController) resetAllClientTraffics(c *gin.Context) { - a.inboundController.resetAllClientTraffics(c) -} - -func (a *APIController) delDepletedClients(c *gin.Context) { - a.inboundController.delDepletedClients(c) + for _, route := range inboundRoutes { + g.Handle(route.Method, route.Path, route.Handler) + } } func (a *APIController) createBackup(c *gin.Context) { a.Tgbot.SendBackupToAdmins() } - -func (a *APIController) onlines(c *gin.Context) { - a.inboundController.onlines(c) -} diff --git a/web/controller/base.go b/web/controller/base.go index 674a195d..492fc2dc 100644 --- a/web/controller/base.go +++ b/web/controller/base.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "x-ui/logger" "x-ui/web/locale" "x-ui/web/session" @@ -9,13 +10,12 @@ import ( "github.com/gin-gonic/gin" ) -type BaseController struct { -} +type BaseController struct{} func (a *BaseController) checkLogin(c *gin.Context) { if !session.IsLogin(c) { if isAjax(c) { - pureJsonMsg(c, false, I18nWeb(c, "pages.login.loginAgain")) + pureJsonMsg(c, http.StatusUnauthorized, false, I18nWeb(c, "pages.login.loginAgain")) } else { c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path")) } diff --git a/web/controller/inbound.go b/web/controller/inbound.go index d613453f..7ef3245f 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "strconv" + "x-ui/database/model" "x-ui/web/service" "x-ui/web/session" diff --git a/web/controller/index.go b/web/controller/index.go index 9be88273..bc3c4204 100644 --- a/web/controller/index.go +++ b/web/controller/index.go @@ -3,6 +3,7 @@ package controller import ( "net/http" "time" + "x-ui/logger" "x-ui/web/service" "x-ui/web/session" @@ -49,15 +50,15 @@ func (a *IndexController) login(c *gin.Context) { var form LoginForm err := c.ShouldBind(&form) if err != nil { - pureJsonMsg(c, false, I18nWeb(c, "pages.login.toasts.invalidFormData")) + pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.invalidFormData")) return } if form.Username == "" { - pureJsonMsg(c, false, I18nWeb(c, "pages.login.toasts.emptyUsername")) + pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.emptyUsername")) return } if form.Password == "" { - pureJsonMsg(c, false, I18nWeb(c, "pages.login.toasts.emptyPassword")) + pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.emptyPassword")) return } @@ -66,7 +67,7 @@ func (a *IndexController) login(c *gin.Context) { if user == nil { logger.Warningf("wrong username or password: \"%s\" \"%s\"", form.Username, form.Password) a.tgbot.UserLoginNotify(form.Username, getRemoteIp(c), timeStr, 0) - pureJsonMsg(c, false, I18nWeb(c, "pages.login.toasts.wrongUsernameOrPassword")) + pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.wrongUsernameOrPassword")) return } else { logger.Infof("%s login success, Ip Address: %s\n", form.Username, getRemoteIp(c)) diff --git a/web/controller/server.go b/web/controller/server.go index 10baacb9..0eeca71c 100644 --- a/web/controller/server.go +++ b/web/controller/server.go @@ -5,6 +5,7 @@ import ( "net/http" "regexp" "time" + "x-ui/web/global" "x-ui/web/service" diff --git a/web/controller/setting.go b/web/controller/setting.go index 64cae71b..d04969dc 100644 --- a/web/controller/setting.go +++ b/web/controller/setting.go @@ -3,6 +3,7 @@ package controller import ( "errors" "time" + "x-ui/web/entity" "x-ui/web/service" "x-ui/web/session" diff --git a/web/controller/util.go b/web/controller/util.go index da77189b..a32c9270 100644 --- a/web/controller/util.go +++ b/web/controller/util.go @@ -4,6 +4,7 @@ import ( "net" "net/http" "strings" + "x-ui/config" "x-ui/logger" "x-ui/web/entity" @@ -48,18 +49,11 @@ func jsonMsgObj(c *gin.Context, msg string, obj interface{}, err error) { c.JSON(http.StatusOK, m) } -func pureJsonMsg(c *gin.Context, success bool, msg string) { - if success { - c.JSON(http.StatusOK, entity.Msg{ - Success: true, - Msg: msg, - }) - } else { - c.JSON(http.StatusOK, entity.Msg{ - Success: false, - Msg: msg, - }) - } +func pureJsonMsg(c *gin.Context, statusCode int, success bool, msg string) { + c.JSON(statusCode, entity.Msg{ + Success: success, + Msg: msg, + }) } func html(c *gin.Context, name string, title string, data gin.H) { diff --git a/web/entity/entity.go b/web/entity/entity.go index 06850128..0a9c3a56 100644 --- a/web/entity/entity.go +++ b/web/entity/entity.go @@ -5,6 +5,7 @@ import ( "net" "strings" "time" + "x-ui/util/common" ) diff --git a/web/global/global.go b/web/global/global.go index 7d0b4e1f..e92c375b 100644 --- a/web/global/global.go +++ b/web/global/global.go @@ -7,8 +7,10 @@ import ( "github.com/robfig/cron/v3" ) -var webServer WebServer -var subServer SubServer +var ( + webServer WebServer + subServer SubServer +) type WebServer interface { GetCron() *cron.Cron diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index 0e9f15e4..20a36f63 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -180,7 +180,7 @@ @@ -193,7 +193,7 @@ @@ -765,8 +765,8 @@ }, routingDomainStrategies: ["AsIs", "IPIfNonMatch", "IPOnDemand"], logLevel: ["none" , "debug" , "info" , "warning", "error"], - access: ["none" , "./access.log" ], - error: ["none" , "./error.log" ], + access: [], + error: [], settingsData: { protocols: { bittorrent: ["bittorrent"], @@ -869,10 +869,10 @@ }, async getXrayResult() { const msg = await HttpUtil.get("/panel/xray/getXrayResult"); - if(msg.success){ - this.restartResult=msg.obj; - if(msg.obj.length > 1) Vue.prototype.$message.error(msg.obj); - } + if (msg.success) { + this.restartResult=msg.obj; + if(msg.obj.length > 1) Vue.prototype.$message.error(msg.obj); + } }, async fetchUserSecret() { this.loading(true); @@ -910,9 +910,9 @@ }, async toggleToken(value) { if (value) { - await this.getNewSecret(); + await this.getNewSecret(); } else { - this.user.loginSecret = ""; + this.user.loginSecret = ""; } }, async resetXrayConfigToDefault() { @@ -1001,7 +1001,7 @@ this.cm = CodeMirror.fromTextArea(textAreaObj, this.cmOptions); this.cm.on('change',editor => { value = editor.getValue(); - if(this.isJsonString(value)){ + if (this.isJsonString(value)) { this[this.advSettings] = value; } }); @@ -1403,8 +1403,24 @@ }, computed: { templateSettings: { - get: function () { return this.xraySetting ? JSON.parse(this.xraySetting) : null; }, - set: function (newValue) { this.xraySetting = JSON.stringify(newValue, null, 2); }, + get: function () { + const parsedSettings = this.xraySetting ? JSON.parse(this.xraySetting) : null; + let accessLogPath = "./access.log"; + let errorLogPath = "./error.log"; + if (parsedSettings) { + // if its set to "none" add default value + if (parsedSettings.log.access !== "none") accessLogPath = parsedSettings.log.access; + if (parsedSettings.log.error !== "none") errorLogPath = parsedSettings.log.error; + } + this.access = ["none", accessLogPath]; + this.error = ["none", errorLogPath]; + return parsedSettings; + }, + set: function (newValue) { + this.xraySetting = JSON.stringify(newValue, null, 2); + this.access = ["none", newValue.log.access]; + this.error = ["none", newValue.log.error]; + }, }, inboundSettings: { get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.inbounds, null, 2) : null; }, diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index 344160e1..4b799ab1 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -35,35 +35,27 @@ func (j *CheckClientIpJob) Run() { j.lastClear = time.Now().Unix() } + shouldClearAccessLog := false f2bInstalled := j.checkFail2BanInstalled() - accessLogPath := xray.GetAccessLogPath() - clearAccessLog := false + isAccessLogAvailable := j.checkAccessLogAvailable(f2bInstalled) if j.hasLimitIp() { - if f2bInstalled && accessLogPath == "./access.log" { - clearAccessLog = j.processLogFile() + if f2bInstalled && isAccessLogAvailable { + shouldClearAccessLog = j.processLogFile() } else { if !f2bInstalled { logger.Warning("fail2ban is not installed. IP limiting may not work properly.") } - switch accessLogPath { - case "none": - logger.Warning("Access log is set to 'none', check your Xray Configs") - case "": - logger.Warning("Access log doesn't exist in your Xray Configs") - default: - logger.Warning("Current access.log path is not compatible with IP Limit") - } } } - if clearAccessLog || accessLogPath == "./access.log" && time.Now().Unix() - j.lastClear > 3600 { + if shouldClearAccessLog || isAccessLogAvailable && time.Now().Unix()-j.lastClear > 3600 { j.clearAccessLog() } } func (j *CheckClientIpJob) clearAccessLog() { - logAccessP, err := os.OpenFile(xray.GetAccessPersistentLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + logAccessP, err := os.OpenFile(xray.GetAccessPersistentLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644) j.checkError(err) // reopen the access log file for reading @@ -178,6 +170,25 @@ func (j *CheckClientIpJob) processLogFile() bool { return shouldCleanLog } +func (j *CheckClientIpJob) checkAccessLogAvailable(doWarning bool) bool { + accessLogPath := xray.GetAccessLogPath() + isAvailable := true + warningMsg := "" + // access log is not available if it is set to 'none' or an empty string + switch accessLogPath { + case "none": + warningMsg = "Access log is set to 'none', check your Xray Configs" + isAvailable = false + case "": + warningMsg = "Access log doesn't exist in your Xray Configs" + isAvailable = false + } + if doWarning && warningMsg != "" { + logger.Warning(warningMsg) + } + return isAvailable +} + func (j *CheckClientIpJob) checkError(e error) { if e != nil { logger.Warning("client ip job err:", e) @@ -253,7 +264,7 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun j.disAllowedIps = []string{} // create iplimit log file channel - logIpFile, err := os.OpenFile(xray.GetIPLimitLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + logIpFile, err := os.OpenFile(xray.GetIPLimitLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644) if err != nil { logger.Errorf("failed to create or open ip limit log file: %s", err) } diff --git a/web/job/check_cpu_usage.go b/web/job/check_cpu_usage.go index 74f6a544..b84ad054 100644 --- a/web/job/check_cpu_usage.go +++ b/web/job/check_cpu_usage.go @@ -3,6 +3,7 @@ package job import ( "strconv" "time" + "x-ui/web/service" "github.com/shirou/gopsutil/v3/cpu" diff --git a/web/job/check_xray_running_job.go b/web/job/check_xray_running_job.go index d9ffeb7a..bfef5ece 100644 --- a/web/job/check_xray_running_job.go +++ b/web/job/check_xray_running_job.go @@ -20,7 +20,7 @@ func (j *CheckXrayRunningJob) Run() { j.checkTime = 0 } else { j.checkTime++ - //only restart if it's down 2 times in a row + // only restart if it's down 2 times in a row if j.checkTime > 1 { err := j.xrayService.RestartXray(false) j.checkTime = 0 diff --git a/web/job/clear_logs_job.go b/web/job/clear_logs_job.go index c4cb3c87..70967657 100644 --- a/web/job/clear_logs_job.go +++ b/web/job/clear_logs_job.go @@ -3,6 +3,7 @@ package job import ( "io" "os" + "x-ui/logger" "x-ui/xray" ) @@ -17,7 +18,7 @@ func NewClearLogsJob() *ClearLogsJob { func (j *ClearLogsJob) Run() { logFiles := []string{xray.GetIPLimitLogPath(), xray.GetIPLimitBannedLogPath(), xray.GetAccessPersistentLogPath()} logFilesPrev := []string{xray.GetIPLimitBannedPrevLogPath(), xray.GetAccessPersistentPrevLogPath()} - + // clear old previous logs for i := 0; i < len(logFilesPrev); i++ { if err := os.Truncate(logFilesPrev[i], 0); err != nil { @@ -43,7 +44,7 @@ func (j *ClearLogsJob) Run() { if err != nil { logger.Warning("clear logs job err:", err) } - + logFile.Close() logFilePrev.Close() } diff --git a/web/job/xray_traffic_job.go b/web/job/xray_traffic_job.go index c0de4428..dea407e0 100644 --- a/web/job/xray_traffic_job.go +++ b/web/job/xray_traffic_job.go @@ -36,5 +36,4 @@ func (j *XrayTrafficJob) Run() { if needRestart0 || needRestart1 { j.xrayService.SetToNeedRestart() } - } diff --git a/web/locale/locale.go b/web/locale/locale.go index 4a5f5c6e..adc90ec5 100644 --- a/web/locale/locale.go +++ b/web/locale/locale.go @@ -4,6 +4,7 @@ import ( "embed" "io/fs" "strings" + "x-ui/logger" "github.com/gin-gonic/gin" @@ -12,9 +13,11 @@ import ( "golang.org/x/text/language" ) -var i18nBundle *i18n.Bundle -var LocalizerWeb *i18n.Localizer -var LocalizerBot *i18n.Localizer +var ( + i18nBundle *i18n.Bundle + LocalizerWeb *i18n.Localizer + LocalizerBot *i18n.Localizer +) type I18nType string @@ -79,7 +82,6 @@ func I18n(i18nType I18nType, key string, params ...string) string { MessageID: key, TemplateData: templateData, }) - if err != nil { logger.Errorf("Failed to localize message: %v", err) return "" @@ -135,7 +137,6 @@ func parseTranslationFiles(i18nFS embed.FS, i18nBundle *i18n.Bundle) error { _, err = i18nBundle.ParseMessageFileBytes(data, path) return err }) - if err != nil { return err } diff --git a/web/service/inbound.go b/web/service/inbound.go index a103e256..e9b1e595 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" "time" + "x-ui/database" "x-ui/database/model" "x-ui/logger" @@ -90,7 +91,6 @@ func (s *InboundService) getAllEmails() ([]string, error) { FROM inbounds, JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client `).Scan(&emails).Error - if err != nil { return nil, err } @@ -1074,7 +1074,9 @@ func (s *InboundService) UpdateClientStat(tx *gorm.DB, email string, client *mod "email": client.Email, "total": client.TotalGB, "expiry_time": client.ExpiryTime, - "reset": client.Reset}) + "reset": client.Reset, + }) + err := result.Error if err != nil { return err @@ -1573,7 +1575,6 @@ func (s *InboundService) ResetAllClientTraffics(id int) error { Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0}) err := result.Error - if err != nil { return err } @@ -1588,7 +1589,6 @@ func (s *InboundService) ResetAllTraffics() error { Updates(map[string]interface{}{"up": 0, "down": 0}) err := result.Error - if err != nil { return err } diff --git a/web/service/outbound.go b/web/service/outbound.go index 05791f69..685ac422 100644 --- a/web/service/outbound.go +++ b/web/service/outbound.go @@ -9,8 +9,7 @@ import ( "gorm.io/gorm" ) -type OutboundService struct { -} +type OutboundService struct{} func (s *OutboundService) AddTraffic(traffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) { var err error diff --git a/web/service/panel.go b/web/service/panel.go index f90d3e66..71782a8f 100644 --- a/web/service/panel.go +++ b/web/service/panel.go @@ -4,11 +4,11 @@ import ( "os" "syscall" "time" + "x-ui/logger" ) -type PanelService struct { -} +type PanelService struct{} func (s *PanelService) RestartPanel(delay time.Duration) error { p, err := os.FindProcess(syscall.Getpid()) diff --git a/web/service/server.go b/web/service/server.go index 822918a8..b2dfd22f 100644 --- a/web/service/server.go +++ b/web/service/server.go @@ -382,7 +382,6 @@ func (s *ServerService) UpdateXray(version string) error { } return nil - } func (s *ServerService) GetLogs(count string, level string, syslog string) []string { diff --git a/web/service/setting.go b/web/service/setting.go index 3c7b18fe..00ef13b7 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" "time" + "x-ui/database" "x-ui/database/model" "x-ui/logger" @@ -64,8 +65,7 @@ var defaultValueMap = map[string]string{ "warp": "", } -type SettingService struct { -} +type SettingService struct{} func (s *SettingService) GetDefaultJsonConfig() (interface{}, error) { var jsonData interface{} @@ -444,6 +444,7 @@ func (s *SettingService) GetDatepicker() (string, error) { func (s *SettingService) GetWarp() (string, error) { return s.getString("warp") } + func (s *SettingService) SetWarp(data string) error { return s.setString("warp", data) } diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 30d19dba..40301667 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" "time" + "x-ui/config" "x-ui/database" "x-ui/database/model" @@ -26,12 +27,14 @@ import ( "github.com/valyala/fasthttp/fasthttpproxy" ) -var bot *telego.Bot -var botHandler *th.BotHandler -var adminIds []int64 -var isRunning bool -var hostname string -var hashStorage *global.HashStorage +var ( + bot *telego.Bot + botHandler *th.BotHandler + adminIds []int64 + isRunning bool + hostname string + hashStorage *global.HashStorage +) type LoginStatus byte @@ -280,7 +283,6 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo } func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool) { - chatId := callbackQuery.Message.GetChat().ID if isAdmin { @@ -866,7 +868,7 @@ func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.R Text: message, ParseMode: "HTML", } - //only add replyMarkup to last message + // only add replyMarkup to last message if len(replyMarkup) > 0 && n == (len(allMessages)-1) { params.ReplyMarkup = replyMarkup[0] } @@ -1030,9 +1032,15 @@ func (t *Tgbot) getInboundUsages() string { return info } -func (t *Tgbot) clientInfoMsg(traffic *xray.ClientTraffic, printEnabled bool, printOnline bool, printActive bool, - printDate bool, printTraffic bool, printRefreshed bool) string { - +func (t *Tgbot) clientInfoMsg( + traffic *xray.ClientTraffic, + printEnabled bool, + printOnline bool, + printActive bool, + printDate bool, + printTraffic bool, + printRefreshed bool, +) string { now := time.Now().Unix() expiryTime := "" flag := false @@ -1544,7 +1552,6 @@ func (t *Tgbot) sendBackup(chatId int64) { } } else { logger.Error("Error in opening db file for backup: ", err) - } file, err = os.Open(xray.GetConfigPath()) diff --git a/web/service/user.go b/web/service/user.go index f1868424..b8292000 100644 --- a/web/service/user.go +++ b/web/service/user.go @@ -2,6 +2,7 @@ package service import ( "errors" + "x-ui/database" "x-ui/database/model" "x-ui/logger" @@ -9,8 +10,7 @@ import ( "gorm.io/gorm" ) -type UserService struct { -} +type UserService struct{} func (s *UserService) GetFirstUser() (*model.User, error) { db := database.GetDB() diff --git a/web/service/xray.go b/web/service/xray.go index 7cd1612c..6074216d 100644 --- a/web/service/xray.go +++ b/web/service/xray.go @@ -4,16 +4,19 @@ import ( "encoding/json" "errors" "sync" + "x-ui/logger" "x-ui/xray" "go.uber.org/atomic" ) -var p *xray.Process -var lock sync.Mutex -var isNeedXrayRestart atomic.Bool -var result string +var ( + p *xray.Process + lock sync.Mutex + isNeedXrayRestart atomic.Bool + result string +) type XrayService struct { inboundService InboundService @@ -87,7 +90,6 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) { // check users active or not clientStats := inbound.ClientStats for _, clientTraffic := range clientStats { - indexDecrease := 0 for index, client := range clients { c := client.(map[string]interface{}) @@ -96,20 +98,15 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) { clients = RemoveIndex(clients, index-indexDecrease) indexDecrease++ logger.Info("Remove Inbound User ", c["email"], " due the expire or traffic limit") - } - } } - } // clear client config for additional parameters var final_clients []interface{} for _, client := range clients { - c := client.(map[string]interface{}) - if c["enable"] != nil { if enable, ok := c["enable"].(bool); ok && !enable { continue diff --git a/web/service/xray_setting.go b/web/service/xray_setting.go index 86bb1d7b..a203e649 100644 --- a/web/service/xray_setting.go +++ b/web/service/xray_setting.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "time" + "x-ui/util/common" "x-ui/xray" ) diff --git a/web/session/session.go b/web/session/session.go index 9b9a3589..90c9c217 100644 --- a/web/session/session.go +++ b/web/session/session.go @@ -2,6 +2,7 @@ package session import ( "encoding/gob" + "x-ui/database/model" sessions "github.com/Calidity/gin-sessions" diff --git a/web/web.go b/web/web.go index 968f7dc1..010be186 100644 --- a/web/web.go +++ b/web/web.go @@ -13,6 +13,7 @@ import ( "strconv" "strings" "time" + "x-ui/config" "x-ui/logger" "x-ui/util/common" @@ -295,7 +296,7 @@ func (s *Server) startTask() { } func (s *Server) Start() (err error) { - //This is an anonymous function, no function name + // This is an anonymous function, no function name defer func() { if err != nil { s.Stop() diff --git a/xray/api.go b/xray/api.go index 1ce5afa1..5242a613 100644 --- a/xray/api.go +++ b/xray/api.go @@ -6,6 +6,7 @@ import ( "fmt" "regexp" "time" + "x-ui/logger" "x-ui/util/common" @@ -162,8 +163,8 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) { if x.grpcClient == nil { return nil, nil, common.NewError("xray api is not initialized") } - var trafficRegex = regexp.MustCompile("(inbound|outbound)>>>([^>]+)>>>traffic>>>(downlink|uplink)") - var ClientTrafficRegex = regexp.MustCompile("(user)>>>([^>]+)>>>traffic>>>(downlink|uplink)") + trafficRegex := regexp.MustCompile("(inbound|outbound)>>>([^>]+)>>>traffic>>>(downlink|uplink)") + ClientTrafficRegex := regexp.MustCompile("(user)>>>([^>]+)>>>traffic>>>(downlink|uplink)") client := *x.StatsServiceClient ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) diff --git a/xray/config.go b/xray/config.go index 914f2134..be641b1f 100644 --- a/xray/config.go +++ b/xray/config.go @@ -2,6 +2,7 @@ package xray import ( "bytes" + "x-ui/util/json_util" ) diff --git a/xray/inbound.go b/xray/inbound.go index b3f07c7e..ea11449d 100644 --- a/xray/inbound.go +++ b/xray/inbound.go @@ -2,6 +2,7 @@ package xray import ( "bytes" + "x-ui/util/json_util" ) diff --git a/xray/log_writer.go b/xray/log_writer.go index 6c6a6e17..c8d966b5 100644 --- a/xray/log_writer.go +++ b/xray/log_writer.go @@ -3,6 +3,7 @@ package xray import ( "regexp" "strings" + "x-ui/logger" ) diff --git a/xray/process.go b/xray/process.go index 03d2eced..fcbe6f78 100644 --- a/xray/process.go +++ b/xray/process.go @@ -202,7 +202,7 @@ func (p *process) Start() (err error) { if err != nil { return common.NewErrorf("Failed to generate xray configuration file: %v", err) } - + err = os.MkdirAll(config.GetLogFolder(), 0770) if err != nil { logger.Warningf("Something went wrong: %s", err)