mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-08-23 19:36:54 +00:00
improved - message logs
This commit is contained in:
parent
2f6c2ffdcc
commit
4ed0f6bfc8
13 changed files with 169 additions and 121 deletions
92
main.go
92
main.go
|
@ -21,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func runWebServer() {
|
func runWebServer() {
|
||||||
log.Printf("%v %v", config.GetName(), config.GetVersion())
|
log.Printf("Starting %v %v", config.GetName(), config.GetVersion())
|
||||||
|
|
||||||
switch config.GetLogLevel() {
|
switch config.GetLogLevel() {
|
||||||
case config.Debug:
|
case config.Debug:
|
||||||
|
@ -35,31 +35,29 @@ func runWebServer() {
|
||||||
case config.Error:
|
case config.Error:
|
||||||
logger.InitLogger(logging.ERROR)
|
logger.InitLogger(logging.ERROR)
|
||||||
default:
|
default:
|
||||||
log.Fatal("unknown log level:", config.GetLogLevel())
|
log.Fatalf("Unknown log level: %v", config.GetLogLevel())
|
||||||
}
|
}
|
||||||
|
|
||||||
err := database.InitDB(config.GetDBPath())
|
err := database.InitDB(config.GetDBPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatalf("Error initializing database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var server *web.Server
|
var server *web.Server
|
||||||
|
|
||||||
server = web.NewServer()
|
server = web.NewServer()
|
||||||
global.SetWebServer(server)
|
global.SetWebServer(server)
|
||||||
err = server.Start()
|
err = server.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Fatalf("Error starting web server: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var subServer *sub.Server
|
var subServer *sub.Server
|
||||||
subServer = sub.NewServer()
|
subServer = sub.NewServer()
|
||||||
global.SetSubServer(subServer)
|
global.SetSubServer(subServer)
|
||||||
|
|
||||||
err = subServer.Start()
|
err = subServer.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Fatalf("Error starting sub server: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,34 +69,39 @@ func runWebServer() {
|
||||||
|
|
||||||
switch sig {
|
switch sig {
|
||||||
case syscall.SIGHUP:
|
case syscall.SIGHUP:
|
||||||
|
logger.Info("Received SIGHUP signal. Restarting servers...")
|
||||||
|
|
||||||
err := server.Stop()
|
err := server.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("stop server err:", err)
|
logger.Warning("Error stopping web server:", err)
|
||||||
}
|
}
|
||||||
err = subServer.Stop()
|
err = subServer.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("stop server err:", err)
|
logger.Warning("Error stopping sub server:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
server = web.NewServer()
|
server = web.NewServer()
|
||||||
global.SetWebServer(server)
|
global.SetWebServer(server)
|
||||||
err = server.Start()
|
err = server.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Fatalf("Error restarting web server: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Println("Web server restarted successfully.")
|
||||||
|
|
||||||
subServer = sub.NewServer()
|
subServer = sub.NewServer()
|
||||||
global.SetSubServer(subServer)
|
global.SetSubServer(subServer)
|
||||||
|
|
||||||
err = subServer.Start()
|
err = subServer.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Fatalf("Error restarting sub server: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Println("Sub server restarted successfully.")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
server.Stop()
|
server.Stop()
|
||||||
subServer.Stop()
|
subServer.Stop()
|
||||||
|
log.Println("Shutting down servers.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,16 +110,16 @@ func runWebServer() {
|
||||||
func resetSetting() {
|
func resetSetting() {
|
||||||
err := database.InitDB(config.GetDBPath())
|
err := database.InitDB(config.GetDBPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println("Failed to initialize database:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
settingService := service.SettingService{}
|
settingService := service.SettingService{}
|
||||||
err = settingService.ResetSettings()
|
err = settingService.ResetSettings()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("reset setting failed:", err)
|
fmt.Println("Failed to reset settings:", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("reset setting success")
|
fmt.Println("Settings successfully reset.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +182,7 @@ func updateTgbotEnableSts(status bool) {
|
||||||
func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) {
|
func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) {
|
||||||
err := database.InitDB(config.GetDBPath())
|
err := database.InitDB(config.GetDBPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println("Error initializing database:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,68 +191,65 @@ func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime stri
|
||||||
if tgBotToken != "" {
|
if tgBotToken != "" {
|
||||||
err := settingService.SetTgBotToken(tgBotToken)
|
err := settingService.SetTgBotToken(tgBotToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Printf("Error setting Telegram bot token: %v\n", err)
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
logger.Info("updateTgbotSetting tgBotToken success")
|
|
||||||
}
|
}
|
||||||
|
logger.Info("Successfully updated Telegram bot token.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if tgBotRuntime != "" {
|
if tgBotRuntime != "" {
|
||||||
err := settingService.SetTgbotRuntime(tgBotRuntime)
|
err := settingService.SetTgbotRuntime(tgBotRuntime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Printf("Error setting Telegram bot runtime: %v\n", err)
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
logger.Infof("updateTgbotSetting tgBotRuntime[%s] success", tgBotRuntime)
|
|
||||||
}
|
}
|
||||||
|
logger.Infof("Successfully updated Telegram bot runtime to [%s].", tgBotRuntime)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tgBotChatid != "" {
|
if tgBotChatid != "" {
|
||||||
err := settingService.SetTgBotChatId(tgBotChatid)
|
err := settingService.SetTgBotChatId(tgBotChatid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Printf("Error setting Telegram bot chat ID: %v\n", err)
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
logger.Info("updateTgbotSetting tgBotChatid success")
|
|
||||||
}
|
}
|
||||||
|
logger.Info("Successfully updated Telegram bot chat ID.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSetting(port int, username string, password string, webBasePath string) {
|
func updateSetting(port int, username string, password string, webBasePath string) {
|
||||||
err := database.InitDB(config.GetDBPath())
|
err := database.InitDB(config.GetDBPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println("Database initialization failed:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
settingService := service.SettingService{}
|
settingService := service.SettingService{}
|
||||||
|
userService := service.UserService{}
|
||||||
|
|
||||||
if port > 0 {
|
if port > 0 {
|
||||||
err := settingService.SetPort(port)
|
err := settingService.SetPort(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("set port failed:", err)
|
fmt.Println("Failed to set port:", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("set port %v success", port)
|
fmt.Printf("Port set successfully: %v\n", port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if username != "" || password != "" {
|
if username != "" || password != "" {
|
||||||
userService := service.UserService{}
|
|
||||||
err := userService.UpdateFirstUser(username, password)
|
err := userService.UpdateFirstUser(username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("set username and password failed:", err)
|
fmt.Println("Failed to update username and password:", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("set username and password success")
|
fmt.Println("Username and password updated successfully")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if webBasePath != "" {
|
if webBasePath != "" {
|
||||||
err := settingService.SetBasePath(webBasePath)
|
err := settingService.SetBasePath(webBasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("set base URI path failed:", err)
|
fmt.Println("Failed to set base URI path:", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("set base URI path success")
|
fmt.Println("Base URI path set successfully")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,19 +348,19 @@ func main() {
|
||||||
var reset bool
|
var reset bool
|
||||||
var show bool
|
var show bool
|
||||||
var remove_secret bool
|
var remove_secret bool
|
||||||
settingCmd.BoolVar(&reset, "reset", false, "reset all settings")
|
settingCmd.BoolVar(&reset, "reset", false, "Reset all settings")
|
||||||
settingCmd.BoolVar(&show, "show", false, "show current settings")
|
settingCmd.BoolVar(&show, "show", false, "Display current settings")
|
||||||
settingCmd.BoolVar(&remove_secret, "remove_secret", false, "remove secret")
|
settingCmd.BoolVar(&remove_secret, "remove_secret", false, "Remove secret key")
|
||||||
settingCmd.IntVar(&port, "port", 0, "set panel port")
|
settingCmd.IntVar(&port, "port", 0, "Set panel port number")
|
||||||
settingCmd.StringVar(&username, "username", "", "set login username")
|
settingCmd.StringVar(&username, "username", "", "Set login username")
|
||||||
settingCmd.StringVar(&password, "password", "", "set login password")
|
settingCmd.StringVar(&password, "password", "", "Set login password")
|
||||||
settingCmd.StringVar(&webBasePath, "webBasePath", "", "set web base path")
|
settingCmd.StringVar(&webBasePath, "webBasePath", "", "Set base path for Panel")
|
||||||
settingCmd.StringVar(&webCertFile, "webCert", "", "set web public key path")
|
settingCmd.StringVar(&webCertFile, "webCert", "", "Set path to public key file for panel")
|
||||||
settingCmd.StringVar(&webKeyFile, "webCertKey", "", "set web private key path")
|
settingCmd.StringVar(&webKeyFile, "webCertKey", "", "Set path to private key file for panel")
|
||||||
settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "set telegram bot token")
|
settingCmd.StringVar(&tgbottoken, "tgbottoken", "", "Set token for Telegram bot")
|
||||||
settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "set telegram bot cron time")
|
settingCmd.StringVar(&tgbotRuntime, "tgbotRuntime", "", "Set cron time for Telegram bot notifications")
|
||||||
settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "set telegram bot chat id")
|
settingCmd.StringVar(&tgbotchatid, "tgbotchatid", "", "Set chat ID for Telegram bot notifications")
|
||||||
settingCmd.BoolVar(&enabletgbot, "enabletgbot", false, "enable telegram bot notify")
|
settingCmd.BoolVar(&enabletgbot, "enabletgbot", false, "Enable notifications via Telegram bot")
|
||||||
|
|
||||||
oldUsage := flag.Usage
|
oldUsage := flag.Usage
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
|
|
|
@ -163,13 +163,13 @@ func (s *Server) Start() (err error) {
|
||||||
}
|
}
|
||||||
listener = network.NewAutoHttpsListener(listener)
|
listener = network.NewAutoHttpsListener(listener)
|
||||||
listener = tls.NewListener(listener, c)
|
listener = tls.NewListener(listener, c)
|
||||||
logger.Info("sub server run https on", listener.Addr())
|
logger.Info("Sub server running HTTPS on", listener.Addr())
|
||||||
} else {
|
} else {
|
||||||
logger.Error("error in loading certificates: ", err)
|
logger.Error("Error loading certificates:", err)
|
||||||
logger.Info("sub server run http on", listener.Addr())
|
logger.Info("Sub server running HTTP on", listener.Addr())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Info("sub server run http on", listener.Addr())
|
logger.Info("Sub server running HTTP on", listener.Addr())
|
||||||
}
|
}
|
||||||
s.listener = listener
|
s.listener = listener
|
||||||
|
|
||||||
|
|
|
@ -76,25 +76,25 @@ func (a *IndexController) login(c *gin.Context) {
|
||||||
|
|
||||||
sessionMaxAge, err := a.settingService.GetSessionMaxAge()
|
sessionMaxAge, err := a.settingService.GetSessionMaxAge()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warningf("Unable to get session's max age from DB")
|
logger.Warning("Unable to get session's max age from DB")
|
||||||
}
|
}
|
||||||
|
|
||||||
if sessionMaxAge > 0 {
|
if sessionMaxAge > 0 {
|
||||||
err = session.SetMaxAge(c, sessionMaxAge*60)
|
err = session.SetMaxAge(c, sessionMaxAge*60)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warningf("Unable to set session's max age")
|
logger.Warning("Unable to set session's max age")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = session.SetLoginUser(c, user)
|
err = session.SetLoginUser(c, user)
|
||||||
logger.Info(user.Username, " logged in successfully")
|
logger.Infof("%s logged in successfully", user.Username)
|
||||||
jsonMsg(c, I18nWeb(c, "pages.login.toasts.successLogin"), err)
|
jsonMsg(c, I18nWeb(c, "pages.login.toasts.successLogin"), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *IndexController) logout(c *gin.Context) {
|
func (a *IndexController) logout(c *gin.Context) {
|
||||||
user := session.GetLoginUser(c)
|
user := session.GetLoginUser(c)
|
||||||
if user != nil {
|
if user != nil {
|
||||||
logger.Info(user.Username, " logged out successfully")
|
logger.Infof("%s logged out successfully", user.Username)
|
||||||
}
|
}
|
||||||
session.ClearSession(c)
|
session.ClearSession(c)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path"))
|
c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path"))
|
||||||
|
|
|
@ -252,46 +252,55 @@ func (j *CheckClientIpJob) addInboundClientIps(clientEmail string, ips []string)
|
||||||
|
|
||||||
func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) bool {
|
func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) bool {
|
||||||
jsonIps, err := json.Marshal(ips)
|
jsonIps, err := json.Marshal(ips)
|
||||||
j.checkError(err)
|
if err != nil {
|
||||||
|
logger.Error("failed to marshal IPs to JSON:", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
inboundClientIps.ClientEmail = clientEmail
|
inboundClientIps.ClientEmail = clientEmail
|
||||||
inboundClientIps.Ips = string(jsonIps)
|
inboundClientIps.Ips = string(jsonIps)
|
||||||
|
|
||||||
// check inbound limitation
|
// Fetch inbound settings by client email
|
||||||
inbound, err := j.getInboundByEmail(clientEmail)
|
inbound, err := j.getInboundByEmail(clientEmail)
|
||||||
j.checkError(err)
|
if err != nil {
|
||||||
|
logger.Errorf("failed to fetch inbound settings for email %s: %s", clientEmail, err)
|
||||||
if inbound.Settings == "" {
|
|
||||||
logger.Debug("wrong data ", inbound)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if inbound.Settings == "" {
|
||||||
|
logger.Debug("wrong data:", inbound)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal settings to get client limits
|
||||||
settings := map[string][]model.Client{}
|
settings := map[string][]model.Client{}
|
||||||
json.Unmarshal([]byte(inbound.Settings), &settings)
|
json.Unmarshal([]byte(inbound.Settings), &settings)
|
||||||
clients := settings["clients"]
|
clients := settings["clients"]
|
||||||
shouldCleanLog := false
|
shouldCleanLog := false
|
||||||
j.disAllowedIps = []string{}
|
j.disAllowedIps = []string{}
|
||||||
|
|
||||||
// create iplimit log file channel
|
// Open log file for IP limits
|
||||||
logIpFile, err := os.OpenFile(xray.GetIPLimitLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
|
logIpFile, err := os.OpenFile(xray.GetIPLimitLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("failed to create or open ip limit log file: %s", err)
|
logger.Errorf("failed to open IP limit log file: %s", err)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
defer logIpFile.Close()
|
defer logIpFile.Close()
|
||||||
log.SetOutput(logIpFile)
|
log.SetOutput(logIpFile)
|
||||||
log.SetFlags(log.LstdFlags)
|
log.SetFlags(log.LstdFlags)
|
||||||
|
|
||||||
|
// Check client IP limits
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.Email == clientEmail {
|
if client.Email == clientEmail {
|
||||||
limitIp := client.LimitIP
|
limitIp := client.LimitIP
|
||||||
|
|
||||||
if limitIp != 0 {
|
if limitIp > 0 && inbound.Enable {
|
||||||
shouldCleanLog = true
|
shouldCleanLog = true
|
||||||
|
|
||||||
if limitIp < len(ips) && inbound.Enable {
|
if limitIp < len(ips) {
|
||||||
j.disAllowedIps = append(j.disAllowedIps, ips[limitIp:]...)
|
j.disAllowedIps = append(j.disAllowedIps, ips[limitIp:]...)
|
||||||
for i := limitIp; i < len(ips); i++ {
|
for i := limitIp; i < len(ips); i++ {
|
||||||
log.Printf("[LIMIT_IP] Email = %s || SRC = %s", clientEmail, ips[i])
|
logger.Debugf("[LIMIT_IP] Email = %s || SRC = %s", clientEmail, ips[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,12 +310,15 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
|
||||||
sort.Strings(j.disAllowedIps)
|
sort.Strings(j.disAllowedIps)
|
||||||
|
|
||||||
if len(j.disAllowedIps) > 0 {
|
if len(j.disAllowedIps) > 0 {
|
||||||
logger.Debug("disAllowedIps ", j.disAllowedIps)
|
logger.Debug("disAllowedIps:", j.disAllowedIps)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
err = db.Save(inboundClientIps).Error
|
err = db.Save(inboundClientIps).Error
|
||||||
j.checkError(err)
|
if err != nil {
|
||||||
|
logger.Error("failed to save inboundClientIps:", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return shouldCleanLog
|
return shouldCleanLog
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,8 @@ func (j *XrayTrafficJob) Run() {
|
||||||
if !j.xrayService.IsXrayRunning() {
|
if !j.xrayService.IsXrayRunning() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
traffics, clientTraffics, err := j.xrayService.GetXrayTraffic()
|
traffics, clientTraffics, err := j.xrayService.GetXrayTraffic()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("get xray traffic failed:", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err, needRestart0 := j.inboundService.AddTraffic(traffics, clientTraffics)
|
err, needRestart0 := j.inboundService.AddTraffic(traffics, clientTraffics)
|
||||||
|
|
|
@ -1142,7 +1142,7 @@ func (s *InboundService) GetClientInboundByTrafficID(trafficId int) (traffic *xr
|
||||||
var traffics []*xray.ClientTraffic
|
var traffics []*xray.ClientTraffic
|
||||||
err = db.Model(xray.ClientTraffic{}).Where("id = ?", trafficId).Find(&traffics).Error
|
err = db.Model(xray.ClientTraffic{}).Where("id = ?", trafficId).Find(&traffics).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(err)
|
logger.Warningf("Error retrieving ClientTraffic with trafficId %d: %v", trafficId, err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if len(traffics) > 0 {
|
if len(traffics) > 0 {
|
||||||
|
@ -1157,7 +1157,7 @@ func (s *InboundService) GetClientInboundByEmail(email string) (traffic *xray.Cl
|
||||||
var traffics []*xray.ClientTraffic
|
var traffics []*xray.ClientTraffic
|
||||||
err = db.Model(xray.ClientTraffic{}).Where("email = ?", email).Find(&traffics).Error
|
err = db.Model(xray.ClientTraffic{}).Where("email = ?", email).Find(&traffics).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(err)
|
logger.Warningf("Error retrieving ClientTraffic with email %s: %v", email, err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if len(traffics) > 0 {
|
if len(traffics) > 0 {
|
||||||
|
@ -1698,15 +1698,20 @@ func (s *InboundService) DelDepletedClients(id int) (err error) {
|
||||||
func (s *InboundService) GetClientTrafficTgBot(tgId int64) ([]*xray.ClientTraffic, error) {
|
func (s *InboundService) GetClientTrafficTgBot(tgId int64) ([]*xray.ClientTraffic, error) {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
var inbounds []*model.Inbound
|
var inbounds []*model.Inbound
|
||||||
err := db.Model(model.Inbound{}).Where("settings like ?", fmt.Sprintf(`%%"tgId": %d%%`, tgId)).Find(&inbounds).Error
|
|
||||||
|
// Retrieve inbounds where settings contain the given tgId
|
||||||
|
err := db.Model(model.Inbound{}).Where("settings LIKE ?", fmt.Sprintf(`%%"tgId": %d%%`, tgId)).Find(&inbounds).Error
|
||||||
if err != nil && err != gorm.ErrRecordNotFound {
|
if err != nil && err != gorm.ErrRecordNotFound {
|
||||||
|
logger.Errorf("Error retrieving inbounds with tgId %d: %v", tgId, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var emails []string
|
var emails []string
|
||||||
for _, inbound := range inbounds {
|
for _, inbound := range inbounds {
|
||||||
clients, err := s.GetClients(inbound)
|
clients, err := s.GetClients(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Unable to get clients from inbound")
|
logger.Errorf("Error retrieving clients for inbound %d: %v", inbound.Id, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.TgID == tgId {
|
if client.TgID == tgId {
|
||||||
|
@ -1714,15 +1719,19 @@ func (s *InboundService) GetClientTrafficTgBot(tgId int64) ([]*xray.ClientTraffi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var traffics []*xray.ClientTraffic
|
var traffics []*xray.ClientTraffic
|
||||||
err = db.Model(xray.ClientTraffic{}).Where("email IN ?", emails).Find(&traffics).Error
|
err = db.Model(xray.ClientTraffic{}).Where("email IN ?", emails).Find(&traffics).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
logger.Warning(err)
|
logger.Warning("No ClientTraffic records found for emails:", emails)
|
||||||
return nil, err
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
logger.Errorf("Error retrieving ClientTraffic for emails %v: %v", emails, err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return traffics, err
|
|
||||||
|
return traffics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) GetClientTrafficByEmail(email string) (traffic *xray.ClientTraffic, err error) {
|
func (s *InboundService) GetClientTrafficByEmail(email string) (traffic *xray.ClientTraffic, err error) {
|
||||||
|
@ -1731,7 +1740,7 @@ func (s *InboundService) GetClientTrafficByEmail(email string) (traffic *xray.Cl
|
||||||
|
|
||||||
err = db.Model(xray.ClientTraffic{}).Where("email = ?", email).Find(&traffics).Error
|
err = db.Model(xray.ClientTraffic{}).Where("email = ?", email).Find(&traffics).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(err)
|
logger.Warningf("Error retrieving ClientTraffic with email %s: %v", email, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(traffics) > 0 {
|
if len(traffics) > 0 {
|
||||||
|
@ -1746,38 +1755,51 @@ func (s *InboundService) SearchClientTraffic(query string) (traffic *xray.Client
|
||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
traffic = &xray.ClientTraffic{}
|
traffic = &xray.ClientTraffic{}
|
||||||
|
|
||||||
err = db.Model(model.Inbound{}).Where("settings like ?", "%\""+query+"\"%").First(inbound).Error
|
// Search for inbound settings that contain the query
|
||||||
|
err = db.Model(model.Inbound{}).Where("settings LIKE ?", "%\""+query+"\"%").First(inbound).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
logger.Warning(err)
|
logger.Warningf("Inbound settings containing query %s not found: %v", query, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
logger.Errorf("Error searching for inbound settings with query %s: %v", query, err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
traffic.InboundId = inbound.Id
|
traffic.InboundId = inbound.Id
|
||||||
|
|
||||||
// get settings clients
|
// Unmarshal settings to get clients
|
||||||
settings := map[string][]model.Client{}
|
settings := map[string][]model.Client{}
|
||||||
json.Unmarshal([]byte(inbound.Settings), &settings)
|
if err := json.Unmarshal([]byte(inbound.Settings), &settings); err != nil {
|
||||||
|
logger.Errorf("Error unmarshalling inbound settings for inbound ID %d: %v", inbound.Id, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
clients := settings["clients"]
|
clients := settings["clients"]
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.ID == query && client.Email != "" {
|
if (client.ID == query || client.Password == query) && client.Email != "" {
|
||||||
traffic.Email = client.Email
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if client.Password == query && client.Email != "" {
|
|
||||||
traffic.Email = client.Email
|
traffic.Email = client.Email
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if traffic.Email == "" {
|
if traffic.Email == "" {
|
||||||
return nil, err
|
logger.Warningf("No client found with query %s in inbound ID %d", query, inbound.Id)
|
||||||
|
return nil, gorm.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve ClientTraffic based on the found email
|
||||||
err = db.Model(xray.ClientTraffic{}).Where("email = ?", traffic.Email).First(traffic).Error
|
err = db.Model(xray.ClientTraffic{}).Where("email = ?", traffic.Email).First(traffic).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(err)
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
logger.Warningf("ClientTraffic for email %s not found: %v", traffic.Email, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
logger.Errorf("Error retrieving ClientTraffic for email %s: %v", traffic.Email, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return traffic, err
|
|
||||||
|
return traffic, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) GetInboundClientIps(clientEmail string) (string, error) {
|
func (s *InboundService) GetInboundClientIps(clientEmail string) (string, error) {
|
||||||
|
|
|
@ -70,7 +70,7 @@ func (s *OutboundService) GetOutboundsTraffic() ([]*model.OutboundTraffics, erro
|
||||||
|
|
||||||
err := db.Model(model.OutboundTraffics{}).Find(&traffics).Error
|
err := db.Model(model.OutboundTraffics{}).Find(&traffics).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(err)
|
logger.Warning("Error retrieving OutboundTraffics: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ func (s *PanelService) RestartPanel(delay time.Duration) error {
|
||||||
time.Sleep(delay)
|
time.Sleep(delay)
|
||||||
err := p.Signal(syscall.SIGHUP)
|
err := p.Signal(syscall.SIGHUP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("send signal SIGHUP failed:", err)
|
logger.Error("failed to send SIGHUP signal:", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -64,52 +64,59 @@ func (t *Tgbot) GetHashStorage() *global.HashStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tgbot) Start(i18nFS embed.FS) error {
|
func (t *Tgbot) Start(i18nFS embed.FS) error {
|
||||||
|
// Initialize localizer
|
||||||
err := locale.InitLocalizer(i18nFS, &t.settingService)
|
err := locale.InitLocalizer(i18nFS, &t.settingService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// init hash storage => store callback queries
|
// Initialize hash storage to store callback queries
|
||||||
hashStorage = global.NewHashStorage(20 * time.Minute)
|
hashStorage = global.NewHashStorage(20 * time.Minute)
|
||||||
|
|
||||||
t.SetHostname()
|
t.SetHostname()
|
||||||
tgBottoken, err := t.settingService.GetTgBotToken()
|
|
||||||
if err != nil || tgBottoken == "" {
|
// Get Telegram bot token
|
||||||
logger.Warning("Get TgBotToken failed:", err)
|
tgBotToken, err := t.settingService.GetTgBotToken()
|
||||||
|
if err != nil || tgBotToken == "" {
|
||||||
|
logger.Warning("Failed to get Telegram bot token:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tgBotid, err := t.settingService.GetTgBotChatId()
|
// Get Telegram bot chat ID(s)
|
||||||
|
tgBotID, err := t.settingService.GetTgBotChatId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Get GetTgBotChatId failed:", err)
|
logger.Warning("Failed to get Telegram bot chat ID:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if tgBotid != "" {
|
// Parse admin IDs from comma-separated string
|
||||||
for _, adminId := range strings.Split(tgBotid, ",") {
|
if tgBotID != "" {
|
||||||
id, err := strconv.Atoi(adminId)
|
for _, adminID := range strings.Split(tgBotID, ",") {
|
||||||
|
id, err := strconv.Atoi(adminID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Failed to get IDs from GetTgBotChatId:", err)
|
logger.Warning("Failed to parse admin ID from Telegram bot chat ID:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
adminIds = append(adminIds, int64(id))
|
adminIds = append(adminIds, int64(id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Telegram bot proxy URL
|
||||||
tgBotProxy, err := t.settingService.GetTgBotProxy()
|
tgBotProxy, err := t.settingService.GetTgBotProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Failed to get ProxyUrl:", err)
|
logger.Warning("Failed to get Telegram bot proxy URL:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bot, err = t.NewBot(tgBottoken, tgBotProxy)
|
// Create new Telegram bot instance
|
||||||
|
bot, err = t.NewBot(tgBotToken, tgBotProxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Get tgbot's api error:", err)
|
logger.Error("Failed to initialize Telegram bot API:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// listen for TG bot income messages
|
// Start receiving Telegram bot messages
|
||||||
if !isRunning {
|
if !isRunning {
|
||||||
logger.Info("Starting Telegram receiver ...")
|
logger.Info("Telegram bot receiver started")
|
||||||
go t.OnReceive()
|
go t.OnReceive()
|
||||||
isRunning = true
|
isRunning = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
||||||
if !clientTraffic.Enable {
|
if !clientTraffic.Enable {
|
||||||
clients = RemoveIndex(clients, index-indexDecrease)
|
clients = RemoveIndex(clients, index-indexDecrease)
|
||||||
indexDecrease++
|
indexDecrease++
|
||||||
logger.Info("Remove Inbound User ", c["email"], " due the expire or traffic limit")
|
logger.Infof("Remove Inbound User %s due to expiration or traffic limit", c["email"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,11 +165,20 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
||||||
|
|
||||||
func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, []*xray.ClientTraffic, error) {
|
func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, []*xray.ClientTraffic, error) {
|
||||||
if !s.IsXrayRunning() {
|
if !s.IsXrayRunning() {
|
||||||
return nil, nil, errors.New("xray is not running")
|
err := errors.New("xray is not running")
|
||||||
|
logger.Debug("Attempted to fetch Xray traffic, but Xray is not running:", err)
|
||||||
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
s.xrayAPI.Init(p.GetAPIPort())
|
apiPort := p.GetAPIPort()
|
||||||
|
s.xrayAPI.Init(apiPort)
|
||||||
defer s.xrayAPI.Close()
|
defer s.xrayAPI.Close()
|
||||||
return s.xrayAPI.GetTraffic(true)
|
|
||||||
|
traffic, clientTraffic, err := s.xrayAPI.GetTraffic(true)
|
||||||
|
if err != nil {
|
||||||
|
logger.Debug("Failed to fetch Xray traffic:", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return traffic, clientTraffic, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *XrayService) RestartXray(isForce bool) error {
|
func (s *XrayService) RestartXray(isForce bool) error {
|
||||||
|
@ -202,7 +211,7 @@ func (s *XrayService) RestartXray(isForce bool) error {
|
||||||
func (s *XrayService) StopXray() error {
|
func (s *XrayService) StopXray() error {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
logger.Debug("stop xray")
|
logger.Debug("Attempting to stop Xray...")
|
||||||
if s.IsXrayRunning() {
|
if s.IsXrayRunning() {
|
||||||
return p.Stop()
|
return p.Stop()
|
||||||
}
|
}
|
||||||
|
|
|
@ -344,13 +344,13 @@ func (s *Server) Start() (err error) {
|
||||||
}
|
}
|
||||||
listener = network.NewAutoHttpsListener(listener)
|
listener = network.NewAutoHttpsListener(listener)
|
||||||
listener = tls.NewListener(listener, c)
|
listener = tls.NewListener(listener, c)
|
||||||
logger.Info("web server run https on", listener.Addr())
|
logger.Info("Web server running HTTPS on", listener.Addr())
|
||||||
} else {
|
} else {
|
||||||
logger.Error("error in loading certificates: ", err)
|
logger.Error("Error loading certificates:", err)
|
||||||
logger.Info("web server run http on", listener.Addr())
|
logger.Info("Web server running HTTP on", listener.Addr())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Info("web server run http on", listener.Addr())
|
logger.Info("Web server running HTTP on", listener.Addr())
|
||||||
}
|
}
|
||||||
s.listener = listener
|
s.listener = listener
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
|
||||||
|
|
||||||
resp, err := (*x.StatsServiceClient).QueryStats(ctx, &statsService.QueryStatsRequest{Reset_: reset})
|
resp, err := (*x.StatsServiceClient).QueryStats(ctx, &statsService.QueryStatsRequest{Reset_: reset})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Debug("Failed to query Xray stats:", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +197,6 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
|
||||||
processClientTraffic(matches, stat.Value, emailTrafficMap)
|
processClientTraffic(matches, stat.Value, emailTrafficMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil
|
return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,14 +60,14 @@ func GetAccessPersistentPrevLogPath() string {
|
||||||
func GetAccessLogPath() (string, error) {
|
func GetAccessLogPath() (string, error) {
|
||||||
config, err := os.ReadFile(GetConfigPath())
|
config, err := os.ReadFile(GetConfigPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warningf("Something went wrong: %s", err)
|
logger.Warningf("Failed to read configuration file: %s", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonConfig := map[string]interface{}{}
|
jsonConfig := map[string]interface{}{}
|
||||||
err = json.Unmarshal([]byte(config), &jsonConfig)
|
err = json.Unmarshal([]byte(config), &jsonConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warningf("Something went wrong: %s", err)
|
logger.Warningf("Failed to parse JSON configuration: %s", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ func (p *process) Start() (err error) {
|
||||||
|
|
||||||
err = os.MkdirAll(config.GetLogFolder(), 0o770)
|
err = os.MkdirAll(config.GetLogFolder(), 0o770)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warningf("Something went wrong: %s", err)
|
logger.Warningf("Failed to create log folder: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
configPath := GetConfigPath()
|
configPath := GetConfigPath()
|
||||||
|
@ -224,7 +224,7 @@ func (p *process) Start() (err error) {
|
||||||
go func() {
|
go func() {
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failure in running xray-core: ", err)
|
logger.Error("Failure in running xray-core:", err)
|
||||||
p.exitErr = err
|
p.exitErr = err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
Loading…
Reference in a new issue