mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-04-14 19:45:47 +00:00
Merge 0404fce020 into 7e6d80efa5
This commit is contained in:
commit
963d9c5e3b
7 changed files with 65 additions and 86 deletions
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v2/logger"
|
"github.com/mhsanaei/3x-ui/v2/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v2/util/common"
|
"github.com/mhsanaei/3x-ui/v2/util/common"
|
||||||
|
|
@ -362,16 +363,18 @@ func (s *Server) Start() (err error) {
|
||||||
|
|
||||||
// Stop gracefully shuts down the subscription server and closes the listener.
|
// Stop gracefully shuts down the subscription server and closes the listener.
|
||||||
func (s *Server) Stop() error {
|
func (s *Server) Stop() error {
|
||||||
s.cancel()
|
|
||||||
|
|
||||||
var err1 error
|
var err1 error
|
||||||
var err2 error
|
var err2 error
|
||||||
if s.httpServer != nil {
|
if s.httpServer != nil {
|
||||||
err1 = s.httpServer.Shutdown(s.ctx)
|
// Use a fresh timeout context for graceful shutdown
|
||||||
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer shutdownCancel()
|
||||||
|
err1 = s.httpServer.Shutdown(shutdownCtx)
|
||||||
}
|
}
|
||||||
if s.listener != nil {
|
if s.listener != nil {
|
||||||
err2 = s.listener.Close()
|
err2 = s.listener.Close()
|
||||||
}
|
}
|
||||||
|
s.cancel()
|
||||||
return common.Combine(err1, err2)
|
return common.Combine(err1, err2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ func (a *InboundController) addInbound(c *gin.Context) {
|
||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
err := c.ShouldBind(inbound)
|
err := c.ShouldBind(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundCreateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := session.GetLoginUser(c)
|
user := session.GetLoginUser(c)
|
||||||
|
|
@ -136,7 +136,7 @@ func (a *InboundController) addInbound(c *gin.Context) {
|
||||||
func (a *InboundController) delInbound(c *gin.Context) {
|
func (a *InboundController) delInbound(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundDeleteSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
needRestart, err := a.inboundService.DelInbound(id)
|
needRestart, err := a.inboundService.DelInbound(id)
|
||||||
|
|
@ -158,7 +158,7 @@ func (a *InboundController) delInbound(c *gin.Context) {
|
||||||
func (a *InboundController) updateInbound(c *gin.Context) {
|
func (a *InboundController) updateInbound(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inbound := &model.Inbound{
|
inbound := &model.Inbound{
|
||||||
|
|
@ -166,7 +166,7 @@ func (a *InboundController) updateInbound(c *gin.Context) {
|
||||||
}
|
}
|
||||||
err = c.ShouldBind(inbound)
|
err = c.ShouldBind(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inbound, needRestart, err := a.inboundService.UpdateInbound(inbound)
|
inbound, needRestart, err := a.inboundService.UpdateInbound(inbound)
|
||||||
|
|
@ -234,7 +234,7 @@ func (a *InboundController) clearClientIps(c *gin.Context) {
|
||||||
|
|
||||||
err := a.inboundService.ClearClientIps(email)
|
err := a.inboundService.ClearClientIps(email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.updateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.logCleanSuccess"), nil)
|
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.logCleanSuccess"), nil)
|
||||||
|
|
@ -245,7 +245,7 @@ func (a *InboundController) addInboundClient(c *gin.Context) {
|
||||||
data := &model.Inbound{}
|
data := &model.Inbound{}
|
||||||
err := c.ShouldBind(data)
|
err := c.ShouldBind(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,7 +264,7 @@ func (a *InboundController) addInboundClient(c *gin.Context) {
|
||||||
func (a *InboundController) delInboundClient(c *gin.Context) {
|
func (a *InboundController) delInboundClient(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
clientId := c.Param("clientId")
|
clientId := c.Param("clientId")
|
||||||
|
|
@ -287,7 +287,7 @@ func (a *InboundController) updateInboundClient(c *gin.Context) {
|
||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
err := c.ShouldBind(inbound)
|
err := c.ShouldBind(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,7 +306,7 @@ func (a *InboundController) updateInboundClient(c *gin.Context) {
|
||||||
func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
func (a *InboundController) resetClientTraffic(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
email := c.Param("email")
|
email := c.Param("email")
|
||||||
|
|
@ -328,9 +328,8 @@ func (a *InboundController) resetAllTraffics(c *gin.Context) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
a.xrayService.SetToNeedRestart()
|
|
||||||
}
|
}
|
||||||
|
a.xrayService.SetToNeedRestart()
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetAllTrafficSuccess"), nil)
|
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetAllTrafficSuccess"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,7 +337,7 @@ func (a *InboundController) resetAllTraffics(c *gin.Context) {
|
||||||
func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
|
func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,9 +345,8 @@ func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
a.xrayService.SetToNeedRestart()
|
|
||||||
}
|
}
|
||||||
|
a.xrayService.SetToNeedRestart()
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetAllClientTrafficSuccess"), nil)
|
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetAllClientTrafficSuccess"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,7 +384,7 @@ func (a *InboundController) importInbound(c *gin.Context) {
|
||||||
func (a *InboundController) delDepletedClients(c *gin.Context) {
|
func (a *InboundController) delDepletedClients(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = a.inboundService.DelDepletedClients(id)
|
err = a.inboundService.DelDepletedClients(id)
|
||||||
|
|
@ -421,7 +419,7 @@ func (a *InboundController) updateClientTraffic(c *gin.Context) {
|
||||||
var request TrafficUpdateRequest
|
var request TrafficUpdateRequest
|
||||||
err := c.ShouldBindJSON(&request)
|
err := c.ShouldBindJSON(&request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
|
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,35 +33,34 @@ var upgrader = ws.Upgrader{
|
||||||
ReadBufferSize: 4096, // Increased from 1024 for better performance
|
ReadBufferSize: 4096, // Increased from 1024 for better performance
|
||||||
WriteBufferSize: 4096, // Increased from 1024 for better performance
|
WriteBufferSize: 4096, // Increased from 1024 for better performance
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
// Check origin for security
|
|
||||||
origin := r.Header.Get("Origin")
|
origin := r.Header.Get("Origin")
|
||||||
if origin == "" {
|
if origin == "" {
|
||||||
// Allow connections without Origin header (same-origin requests)
|
// Allow connections without Origin header (same-origin requests)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Get the host from the request
|
|
||||||
host := r.Host
|
// Extract host from origin
|
||||||
// Extract scheme and host from origin
|
originHost := origin
|
||||||
originURL := origin
|
if strings.HasPrefix(originHost, "http://") || strings.HasPrefix(originHost, "https://") {
|
||||||
// Simple check: origin should match the request host
|
originHost = strings.TrimPrefix(strings.TrimPrefix(originHost, "http://"), "https://")
|
||||||
// This prevents cross-origin WebSocket hijacking
|
|
||||||
if strings.HasPrefix(originURL, "http://") || strings.HasPrefix(originURL, "https://") {
|
|
||||||
// Extract host from origin
|
|
||||||
originHost := strings.TrimPrefix(strings.TrimPrefix(originURL, "http://"), "https://")
|
|
||||||
if idx := strings.Index(originHost, "/"); idx != -1 {
|
if idx := strings.Index(originHost, "/"); idx != -1 {
|
||||||
originHost = originHost[:idx]
|
originHost = originHost[:idx]
|
||||||
}
|
}
|
||||||
if idx := strings.Index(originHost, ":"); idx != -1 {
|
|
||||||
originHost = originHost[:idx]
|
|
||||||
}
|
|
||||||
// Compare hosts (without port)
|
|
||||||
requestHost := host
|
|
||||||
if idx := strings.Index(requestHost, ":"); idx != -1 {
|
|
||||||
requestHost = requestHost[:idx]
|
|
||||||
}
|
|
||||||
return originHost == requestHost || originHost == "" || requestHost == ""
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
|
// Normalize host for comparison (strip ports and IPv6 brackets)
|
||||||
|
normalizeHost := func(h string) string {
|
||||||
|
h = strings.TrimPrefix(h, "[")
|
||||||
|
if idx := strings.LastIndex(h, "]:"); idx != -1 {
|
||||||
|
h = h[:idx+1]
|
||||||
|
}
|
||||||
|
if idx := strings.LastIndex(h, ":"); idx != -1 && !strings.Contains(h[:idx], "]") {
|
||||||
|
h = h[:idx]
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeHost(originHost) == normalizeHost(r.Host)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ func (j *CheckCpuJob) Run() {
|
||||||
|
|
||||||
// get latest status of server
|
// get latest status of server
|
||||||
percent, err := cpu.Percent(1*time.Minute, false)
|
percent, err := cpu.Percent(1*time.Minute, false)
|
||||||
if err == nil && percent[0] > float64(threshold) {
|
if err == nil && len(percent) > 0 && percent[0] > float64(threshold) {
|
||||||
msg := j.tgbotService.I18nBot("tgbot.messages.cpuThreshold",
|
msg := j.tgbotService.I18nBot("tgbot.messages.cpuThreshold",
|
||||||
"Percent=="+strconv.FormatFloat(percent[0], 'f', 2, 64),
|
"Percent=="+strconv.FormatFloat(percent[0], 'f', 2, 64),
|
||||||
"Threshold=="+strconv.Itoa(threshold))
|
"Threshold=="+strconv.Itoa(threshold))
|
||||||
|
|
|
||||||
|
|
@ -190,23 +190,7 @@ func (s *InboundService) checkEmailExistForInbound(inbound *model.Inbound) (stri
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
allEmails, err := s.getAllEmails()
|
return s.checkEmailsExistForClients(clients)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
var emails []string
|
|
||||||
for _, client := range clients {
|
|
||||||
if client.Email != "" {
|
|
||||||
if s.contains(emails, client.Email) {
|
|
||||||
return client.Email, nil
|
|
||||||
}
|
|
||||||
if s.contains(allEmails, client.Email) {
|
|
||||||
return client.Email, nil
|
|
||||||
}
|
|
||||||
emails = append(emails, client.Email)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddInbound creates a new inbound configuration.
|
// AddInbound creates a new inbound configuration.
|
||||||
|
|
@ -339,7 +323,7 @@ func (s *InboundService) DelInbound(id int) (bool, error) {
|
||||||
}
|
}
|
||||||
s.xrayApi.Close()
|
s.xrayApi.Close()
|
||||||
} else {
|
} else {
|
||||||
logger.Debug("No enabled inbound founded to removing by api", tag)
|
logger.Debug("No enabled inbound found to remove by api for inbound id:", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete client traffics of inbounds
|
// Delete client traffics of inbounds
|
||||||
|
|
@ -1280,12 +1264,8 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error)
|
||||||
if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) {
|
if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) {
|
||||||
logger.Debug("User is already disabled. Nothing to do more...")
|
logger.Debug("User is already disabled. Nothing to do more...")
|
||||||
} else {
|
} else {
|
||||||
if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) {
|
logger.Debug("Error in disabling client by api:", err1)
|
||||||
logger.Debug("User is already disabled. Nothing to do more...")
|
needRestart = true
|
||||||
} else {
|
|
||||||
logger.Debug("Error in disabling client by api:", err1)
|
|
||||||
needRestart = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1458,16 +1438,16 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (boo
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
clients := settings["clients"].([]any)
|
clients := settings["clients"].([]any)
|
||||||
var newClients []any
|
|
||||||
for client_index := range clients {
|
for client_index := range clients {
|
||||||
c := clients[client_index].(map[string]any)
|
c := clients[client_index].(map[string]any)
|
||||||
if c["email"] == clientEmail {
|
if c["email"] == clientEmail {
|
||||||
c["tgId"] = tgId
|
c["tgId"] = tgId
|
||||||
c["updated_at"] = time.Now().Unix() * 1000
|
c["updated_at"] = time.Now().Unix() * 1000
|
||||||
newClients = append(newClients, any(c))
|
clients[client_index] = c
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings["clients"] = newClients
|
settings["clients"] = clients
|
||||||
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
@ -1545,16 +1525,16 @@ func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, bo
|
||||||
return false, false, err
|
return false, false, err
|
||||||
}
|
}
|
||||||
clients := settings["clients"].([]any)
|
clients := settings["clients"].([]any)
|
||||||
var newClients []any
|
|
||||||
for client_index := range clients {
|
for client_index := range clients {
|
||||||
c := clients[client_index].(map[string]any)
|
c := clients[client_index].(map[string]any)
|
||||||
if c["email"] == clientEmail {
|
if c["email"] == clientEmail {
|
||||||
c["enable"] = !clientOldEnabled
|
c["enable"] = !clientOldEnabled
|
||||||
c["updated_at"] = time.Now().Unix() * 1000
|
c["updated_at"] = time.Now().Unix() * 1000
|
||||||
newClients = append(newClients, any(c))
|
clients[client_index] = c
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings["clients"] = newClients
|
settings["clients"] = clients
|
||||||
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, false, err
|
return false, false, err
|
||||||
|
|
@ -1625,16 +1605,16 @@ func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
clients := settings["clients"].([]any)
|
clients := settings["clients"].([]any)
|
||||||
var newClients []any
|
|
||||||
for client_index := range clients {
|
for client_index := range clients {
|
||||||
c := clients[client_index].(map[string]any)
|
c := clients[client_index].(map[string]any)
|
||||||
if c["email"] == clientEmail {
|
if c["email"] == clientEmail {
|
||||||
c["limitIp"] = count
|
c["limitIp"] = count
|
||||||
c["updated_at"] = time.Now().Unix() * 1000
|
c["updated_at"] = time.Now().Unix() * 1000
|
||||||
newClients = append(newClients, any(c))
|
clients[client_index] = c
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings["clients"] = newClients
|
settings["clients"] = clients
|
||||||
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
@ -1684,16 +1664,16 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
clients := settings["clients"].([]any)
|
clients := settings["clients"].([]any)
|
||||||
var newClients []any
|
|
||||||
for client_index := range clients {
|
for client_index := range clients {
|
||||||
c := clients[client_index].(map[string]any)
|
c := clients[client_index].(map[string]any)
|
||||||
if c["email"] == clientEmail {
|
if c["email"] == clientEmail {
|
||||||
c["expiryTime"] = expiry_time
|
c["expiryTime"] = expiry_time
|
||||||
c["updated_at"] = time.Now().Unix() * 1000
|
c["updated_at"] = time.Now().Unix() * 1000
|
||||||
newClients = append(newClients, any(c))
|
clients[client_index] = c
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings["clients"] = newClients
|
settings["clients"] = clients
|
||||||
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
@ -1746,16 +1726,16 @@ func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, tota
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
clients := settings["clients"].([]any)
|
clients := settings["clients"].([]any)
|
||||||
var newClients []any
|
|
||||||
for client_index := range clients {
|
for client_index := range clients {
|
||||||
c := clients[client_index].(map[string]any)
|
c := clients[client_index].(map[string]any)
|
||||||
if c["email"] == clientEmail {
|
if c["email"] == clientEmail {
|
||||||
c["totalGB"] = totalGB * 1024 * 1024 * 1024
|
c["totalGB"] = totalGB * 1024 * 1024 * 1024
|
||||||
c["updated_at"] = time.Now().Unix() * 1000
|
c["updated_at"] = time.Now().Unix() * 1000
|
||||||
newClients = append(newClients, any(c))
|
clients[client_index] = c
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings["clients"] = newClients
|
settings["clients"] = clients
|
||||||
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
||||||
|
|
@ -198,8 +198,7 @@ func (s *SettingService) ResetSettings() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return db.Model(model.User{}).
|
return db.Where("1 = 1").Delete(model.User{}).Error
|
||||||
Where("1 = 1").Error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) getSetting(key string) (*model.Setting, error) {
|
func (s *SettingService) getSetting(key string) (*model.Setting, error) {
|
||||||
|
|
|
||||||
10
web/web.go
10
web/web.go
|
|
@ -344,7 +344,6 @@ func (s *Server) startTask() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a traffic condition every day, 8:30
|
// Make a traffic condition every day, 8:30
|
||||||
var entry cron.EntryID
|
|
||||||
isTgbotenabled, err := s.settingService.GetTgbotEnabled()
|
isTgbotenabled, err := s.settingService.GetTgbotEnabled()
|
||||||
if (err == nil) && (isTgbotenabled) {
|
if (err == nil) && (isTgbotenabled) {
|
||||||
runtime, err := s.settingService.GetTgbotRuntime()
|
runtime, err := s.settingService.GetTgbotRuntime()
|
||||||
|
|
@ -367,8 +366,6 @@ func (s *Server) startTask() {
|
||||||
if (err == nil) && (cpuThreshold > 0) {
|
if (err == nil) && (cpuThreshold > 0) {
|
||||||
s.cron.AddJob("@every 10s", job.NewCheckCpuJob())
|
s.cron.AddJob("@every 10s", job.NewCheckCpuJob())
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
s.cron.Remove(entry)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,7 +450,6 @@ func (s *Server) Start() (err error) {
|
||||||
|
|
||||||
// Stop gracefully shuts down the web server, stops Xray, cron jobs, and Telegram bot.
|
// Stop gracefully shuts down the web server, stops Xray, cron jobs, and Telegram bot.
|
||||||
func (s *Server) Stop() error {
|
func (s *Server) Stop() error {
|
||||||
s.cancel()
|
|
||||||
s.xrayService.StopXray()
|
s.xrayService.StopXray()
|
||||||
if s.cron != nil {
|
if s.cron != nil {
|
||||||
s.cron.Stop()
|
s.cron.Stop()
|
||||||
|
|
@ -468,11 +464,15 @@ func (s *Server) Stop() error {
|
||||||
var err1 error
|
var err1 error
|
||||||
var err2 error
|
var err2 error
|
||||||
if s.httpServer != nil {
|
if s.httpServer != nil {
|
||||||
err1 = s.httpServer.Shutdown(s.ctx)
|
// Use a fresh timeout context for graceful shutdown
|
||||||
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer shutdownCancel()
|
||||||
|
err1 = s.httpServer.Shutdown(shutdownCtx)
|
||||||
}
|
}
|
||||||
if s.listener != nil {
|
if s.listener != nil {
|
||||||
err2 = s.listener.Close()
|
err2 = s.listener.Close()
|
||||||
}
|
}
|
||||||
|
s.cancel()
|
||||||
return common.Combine(err1, err2)
|
return common.Combine(err1, err2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue