From 6924a2f19779ceb530b6e490d2e722c52ee0df92 Mon Sep 17 00:00:00 2001 From: xinsuiyuandong Date: Sat, 12 Jul 2025 03:42:57 +0800 Subject: [PATCH 1/4] v2.6.2 v2.6.2 --- web/service/inbound.go | 211 +++----- web/service/setting.go | 182 +++---- web/service/tgbot.go | 1147 ++-------------------------------------- 3 files changed, 204 insertions(+), 1336 deletions(-) diff --git a/web/service/inbound.go b/web/service/inbound.go index f2646dbb..a76c5e2c 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -3,7 +3,6 @@ package service import ( "encoding/json" "fmt" - "sort" "strconv" "strings" "time" @@ -414,13 +413,13 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) { return false, err } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(data.Settings), &settings) if err != nil { return false, err } - interfaceClients := settings["clients"].([]any) + interfaceClients := settings["clients"].([]interface{}) existEmail, err := s.checkEmailsExistForClients(clients) if err != nil { return false, err @@ -451,13 +450,13 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) { } } - var oldSettings map[string]any + var oldSettings map[string]interface{} err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings) if err != nil { return false, err } - oldClients := oldSettings["clients"].([]any) + oldClients := oldSettings["clients"].([]interface{}) oldClients = append(oldClients, interfaceClients...) oldSettings["clients"] = oldClients @@ -490,7 +489,7 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) { if oldInbound.Protocol == "shadowsocks" { cipher = oldSettings["method"].(string) } - err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]any{ + err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{ "email": client.Email, "id": client.ID, "security": client.Security, @@ -520,7 +519,7 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool, logger.Error("Load Old Data Error") return false, err } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(oldInbound.Settings), &settings) if err != nil { return false, err @@ -535,11 +534,11 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool, client_key = "email" } - interfaceClients := settings["clients"].([]any) - var newClients []any + interfaceClients := settings["clients"].([]interface{}) + var newClients []interface{} needApiDel := false for _, client := range interfaceClients { - c := client.(map[string]any) + c := client.(map[string]interface{}) c_id := c[client_key].(string) if c_id == clientId { email, _ = c["email"].(string) @@ -589,12 +588,8 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool, logger.Debug("Client deleted by api:", email) needRestart = false } else { - if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", email)) { - logger.Debug("User is already deleted. Nothing to do more...") - } else { - logger.Debug("Error in deleting client by api:", err1) - needRestart = true - } + logger.Debug("Unable to del client by api:", err1) + needRestart = true } s.xrayApi.Close() } @@ -608,13 +603,13 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin return false, err } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(data.Settings), &settings) if err != nil { return false, err } - interfaceClients := settings["clients"].([]any) + interfaceClients := settings["clients"].([]interface{}) oldInbound, err := s.GetInbound(data.Id) if err != nil { @@ -628,7 +623,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin oldEmail := "" newClientId := "" - clientIndex := -1 + clientIndex := 0 for index, oldClient := range oldClients { oldClientId := "" if oldInbound.Protocol == "trojan" { @@ -649,7 +644,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin } // Validate new client ID - if newClientId == "" || clientIndex == -1 { + if newClientId == "" { return false, common.NewError("empty client ID") } @@ -663,12 +658,12 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin } } - var oldSettings map[string]any + var oldSettings map[string]interface{} err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings) if err != nil { return false, err } - settingsClients := oldSettings["clients"].([]any) + settingsClients := oldSettings["clients"].([]interface{}) settingsClients[clientIndex] = interfaceClients[0] oldSettings["clients"] = settingsClients @@ -718,14 +713,10 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin if oldClients[clientIndex].Enable { err1 := s.xrayApi.RemoveUser(oldInbound.Tag, oldEmail) if err1 == nil { - logger.Debug("Old client deleted by api:", oldEmail) + logger.Debug("Old client deleted by api:", clients[0].Email) } else { - if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", oldEmail)) { - logger.Debug("User is already deleted. Nothing to do more...") - } else { - logger.Debug("Error in deleting client by api:", err1) - needRestart = true - } + logger.Debug("Error in deleting client by api:", err1) + needRestart = true } } if clients[0].Enable { @@ -733,7 +724,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin if oldInbound.Protocol == "shadowsocks" { cipher = oldSettings["method"].(string) } - err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]any{ + err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{ "email": clients[0].Email, "id": clients[0].ID, "security": clients[0].Security, @@ -810,7 +801,7 @@ func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic for _, traffic := range traffics { if traffic.IsInbound { err = tx.Model(&model.Inbound{}).Where("tag = ?", traffic.Tag). - Updates(map[string]any{ + Updates(map[string]interface{}{ "up": gorm.Expr("up + ?", traffic.Up), "down": gorm.Expr("down + ?", traffic.Down), }).Error @@ -894,13 +885,13 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl return nil, err } for inbound_index := range inbounds { - settings := map[string]any{} + settings := map[string]interface{}{} json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings) - clients, ok := settings["clients"].([]any) + clients, ok := settings["clients"].([]interface{}) if ok { - var newClients []any + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) for traffic_index := range dbClientTraffics { if dbClientTraffics[traffic_index].ExpiryTime < 0 && c["email"] == dbClientTraffics[traffic_index].Email { oldExpiryTime := c["expiryTime"].(float64) @@ -910,7 +901,7 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl break } } - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } settings["clients"] = newClients modifiedSettings, err := json.MarshalIndent(settings, "", " ") @@ -952,7 +943,7 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) { var clientsToAdd []struct { protocol string tag string - client map[string]any + client map[string]interface{} } for _, traffic := range traffics { @@ -963,11 +954,11 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) { return false, 0, err } for inbound_index := range inbounds { - settings := map[string]any{} + settings := map[string]interface{}{} json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings) - clients := settings["clients"].([]any) + clients := settings["clients"].([]interface{}) for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) for traffic_index, traffic := range traffics { if traffic.Email == c["email"].(string) { newExpiryTime := traffic.ExpiryTime @@ -984,14 +975,14 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) { struct { protocol string tag string - client map[string]any + client map[string]interface{} }{ protocol: string(inbounds[inbound_index].Protocol), tag: inbounds[inbound_index].Tag, client: c, }) } - clients[client_index] = any(c) + clients[client_index] = interface{}(c) break } } @@ -1046,8 +1037,12 @@ func (s *InboundService) disableInvalidInbounds(tx *gorm.DB) (bool, int64, error if err1 == nil { logger.Debug("Inbound disabled by api:", tag) } else { - logger.Debug("Error in disabling inbound by api:", err1) - needRestart = true + if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", tag)) { + logger.Debug("User is already disabled. Nothing to do more...") + } else { + logger.Debug("Error in disabling client by api:", err1) + needRestart = true + } } } s.xrayApi.Close() @@ -1148,7 +1143,7 @@ func (s *InboundService) AddClientStat(tx *gorm.DB, inboundId int, client *model func (s *InboundService) UpdateClientStat(tx *gorm.DB, email string, client *model.Client) error { result := tx.Model(xray.ClientTraffic{}). Where("email = ?", email). - Updates(map[string]any{ + Updates(map[string]interface{}{ "enable": true, "email": client.Email, "total": client.TotalGB, @@ -1259,18 +1254,18 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (boo return false, common.NewError("Client Not Found For Email:", clientEmail) } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(inbound.Settings), &settings) if err != nil { return false, err } - clients := settings["clients"].([]any) - var newClients []any + clients := settings["clients"].([]interface{}) + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) if c["email"] == clientEmail { c["tgId"] = tgId - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } } settings["clients"] = newClients @@ -1344,18 +1339,18 @@ func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, bo return false, false, common.NewError("Client Not Found For Email:", clientEmail) } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(inbound.Settings), &settings) if err != nil { return false, false, err } - clients := settings["clients"].([]any) - var newClients []any + clients := settings["clients"].([]interface{}) + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) if c["email"] == clientEmail { c["enable"] = !clientOldEnabled - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } } settings["clients"] = newClients @@ -1406,18 +1401,18 @@ func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int return false, common.NewError("Client Not Found For Email:", clientEmail) } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(inbound.Settings), &settings) if err != nil { return false, err } - clients := settings["clients"].([]any) - var newClients []any + clients := settings["clients"].([]interface{}) + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) if c["email"] == clientEmail { c["limitIp"] = count - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } } settings["clients"] = newClients @@ -1463,18 +1458,18 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry return false, common.NewError("Client Not Found For Email:", clientEmail) } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(inbound.Settings), &settings) if err != nil { return false, err } - clients := settings["clients"].([]any) - var newClients []any + clients := settings["clients"].([]interface{}) + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) if c["email"] == clientEmail { c["expiryTime"] = expiry_time - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } } settings["clients"] = newClients @@ -1523,18 +1518,18 @@ func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, tota return false, common.NewError("Client Not Found For Email:", clientEmail) } - var settings map[string]any + var settings map[string]interface{} err = json.Unmarshal([]byte(inbound.Settings), &settings) if err != nil { return false, err } - clients := settings["clients"].([]any) - var newClients []any + clients := settings["clients"].([]interface{}) + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) if c["email"] == clientEmail { c["totalGB"] = totalGB * 1024 * 1024 * 1024 - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } } settings["clients"] = newClients @@ -1552,7 +1547,7 @@ func (s *InboundService) ResetClientTrafficByEmail(clientEmail string) error { result := db.Model(xray.ClientTraffic{}). Where("email = ?", clientEmail). - Updates(map[string]any{"enable": true, "up": 0, "down": 0}) + Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0}) err := result.Error if err != nil { @@ -1583,14 +1578,14 @@ func (s *InboundService) ResetClientTraffic(id int, clientEmail string) (bool, e s.xrayApi.Init(p.GetAPIPort()) cipher := "" if string(inbound.Protocol) == "shadowsocks" { - var oldSettings map[string]any + var oldSettings map[string]interface{} err = json.Unmarshal([]byte(inbound.Settings), &oldSettings) if err != nil { return false, err } cipher = oldSettings["method"].(string) } - err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]any{ + err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]interface{}{ "email": client.Email, "id": client.ID, "security": client.Security, @@ -1635,7 +1630,7 @@ func (s *InboundService) ResetAllClientTraffics(id int) error { result := db.Model(xray.ClientTraffic{}). Where(whereText, id). - Updates(map[string]any{"enable": true, "up": 0, "down": 0}) + Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0}) err := result.Error return err @@ -1646,7 +1641,7 @@ func (s *InboundService) ResetAllTraffics() error { result := db.Model(model.Inbound{}). Where("user_id > ?", 0). - Updates(map[string]any{"up": 0, "down": 0}) + Updates(map[string]interface{}{"up": 0, "down": 0}) err := result.Error return err @@ -1682,17 +1677,17 @@ func (s *InboundService) DelDepletedClients(id int) (err error) { if err != nil { return err } - var oldSettings map[string]any + var oldSettings map[string]interface{} err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings) if err != nil { return err } - oldClients := oldSettings["clients"].([]any) - var newClients []any + oldClients := oldSettings["clients"].([]interface{}) + var newClients []interface{} for _, client := range oldClients { deplete := false - c := client.(map[string]any) + c := client.(map[string]interface{}) for _, email := range emails { if email == c["email"].(string) { deplete = true @@ -1908,14 +1903,14 @@ func (s *InboundService) MigrationRequirements() { return } for inbound_index := range inbounds { - settings := map[string]any{} + settings := map[string]interface{}{} json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings) - clients, ok := settings["clients"].([]any) + clients, ok := settings["clients"].([]interface{}) if ok { // Fix Client configuration problems - var newClients []any + var newClients []interface{} for client_index := range clients { - c := clients[client_index].(map[string]any) + c := clients[client_index].(map[string]interface{}) // Add email='' if it is not exists if _, ok := c["email"]; !ok { @@ -1924,7 +1919,7 @@ func (s *InboundService) MigrationRequirements() { // Convert string tgId to int64 if _, ok := c["tgId"]; ok { - var tgId any = c["tgId"] + var tgId interface{} = c["tgId"] if tgIdStr, ok2 := tgId.(string); ok2 { tgIdInt64, err := strconv.ParseInt(strings.ReplaceAll(tgIdStr, " ", ""), 10, 64) if err == nil { @@ -1939,7 +1934,7 @@ func (s *InboundService) MigrationRequirements() { c["flow"] = "" } } - newClients = append(newClients, any(c)) + newClients = append(newClients, interface{}(c)) } settings["clients"] = newClients modifiedSettings, err := json.MarshalIndent(settings, "", " ") @@ -1986,14 +1981,14 @@ func (s *InboundService) MigrationRequirements() { } for _, ep := range externalProxy { - var reverses any - var stream map[string]any + var reverses interface{} + var stream map[string]interface{} json.Unmarshal(ep.StreamSettings, &stream) - if tlsSettings, ok := stream["tlsSettings"].(map[string]any); ok { - if settings, ok := tlsSettings["settings"].(map[string]any); ok { - if domains, ok := settings["domains"].([]any); ok { + if tlsSettings, ok := stream["tlsSettings"].(map[string]interface{}); ok { + if settings, ok := tlsSettings["settings"].(map[string]interface{}); ok { + if domains, ok := settings["domains"].([]interface{}); ok { for _, domain := range domains { - if domainMap, ok := domain.(map[string]any); ok { + if domainMap, ok := domain.(map[string]interface{}); ok { domainMap["forceTls"] = "same" domainMap["port"] = ep.Port domainMap["dest"] = domainMap["domain"].(string) @@ -2026,37 +2021,3 @@ func (s *InboundService) MigrateDB() { func (s *InboundService) GetOnlineClients() []string { return p.GetOnlineClients() } - -func (s *InboundService) FilterAndSortClientEmails(emails []string) ([]string, []string, error) { - db := database.GetDB() - - // Step 1: Get ClientTraffic records for emails in the input list - var clients []xray.ClientTraffic - err := db.Where("email IN ?", emails).Find(&clients).Error - if err != nil && err != gorm.ErrRecordNotFound { - return nil, nil, err - } - - // Step 2: Sort clients by (Up + Down) descending - sort.Slice(clients, func(i, j int) bool { - return (clients[i].Up + clients[i].Down) > (clients[j].Up + clients[j].Down) - }) - - // Step 3: Extract sorted valid emails and track found ones - validEmails := make([]string, 0, len(clients)) - found := make(map[string]bool) - for _, client := range clients { - validEmails = append(validEmails, client.Email) - found[client.Email] = true - } - - // Step 4: Identify emails that were not found in the database - extraEmails := make([]string, 0) - for _, email := range emails { - if !found[email] { - extraEmails = append(extraEmails, email) - } - } - - return validEmails, extraEmails, nil -} diff --git a/web/service/setting.go b/web/service/setting.go index 868d55bc..f6b9087b 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -24,60 +24,56 @@ import ( var xrayTemplateConfig string var defaultValueMap = map[string]string{ - "xrayTemplateConfig": xrayTemplateConfig, - "webListen": "", - "webDomain": "", - "webPort": "2053", - "webCertFile": "", - "webKeyFile": "", - "secret": random.Seq(32), - "webBasePath": "/", - "sessionMaxAge": "60", - "pageSize": "50", - "expireDiff": "0", - "trafficDiff": "0", - "remarkModel": "-ieo", - "timeLocation": "Local", - "tgBotEnable": "false", - "tgBotToken": "", - "tgBotProxy": "", - "tgBotAPIServer": "", - "tgBotChatId": "", - "tgRunTime": "@daily", - "tgBotBackup": "false", - "tgBotLoginNotify": "true", - "tgCpu": "80", - "tgLang": "en-US", - "twoFactorEnable": "false", - "twoFactorToken": "", - "subEnable": "false", - "subTitle": "", - "subListen": "", - "subPort": "2096", - "subPath": "/sub/", - "subDomain": "", - "subCertFile": "", - "subKeyFile": "", - "subUpdates": "12", - "subEncrypt": "true", - "subShowInfo": "true", - "subURI": "", - "subJsonPath": "/json/", - "subJsonURI": "", - "subJsonFragment": "", - "subJsonNoises": "", - "subJsonMux": "", - "subJsonRules": "", - "datepicker": "gregorian", - "warp": "", - "externalTrafficInformEnable": "false", - "externalTrafficInformURI": "", + "xrayTemplateConfig": xrayTemplateConfig, + "webListen": "", + "webDomain": "", + "webPort": "2053", + "webCertFile": "", + "webKeyFile": "", + "secret": random.Seq(32), + "webBasePath": "/", + "sessionMaxAge": "60", + "pageSize": "50", + "expireDiff": "0", + "trafficDiff": "0", + "remarkModel": "-ieo", + "timeLocation": "Asia/Shanghai", + "tgBotEnable": "false", + "tgBotToken": "", + "tgBotProxy": "", + "tgBotAPIServer": "", + "tgBotChatId": "", + "tgRunTime": "@daily", + "tgBotBackup": "false", + "tgBotLoginNotify": "true", + "tgCpu": "30", + "tgLang": "zh-Hans", + "secretEnable": "false", + "subEnable": "false", + "subListen": "", + "subPort": "2096", + "subPath": "/sub/", + "subDomain": "", + "subCertFile": "", + "subKeyFile": "", + "subUpdates": "12", + "subEncrypt": "true", + "subShowInfo": "true", + "subURI": "", + "subJsonPath": "/json/", + "subJsonURI": "", + "subJsonFragment": "", + "subJsonNoises": "", + "subJsonMux": "", + "subJsonRules": "", + "datepicker": "gregorian", + "warp": "", } type SettingService struct{} -func (s *SettingService) GetDefaultJsonConfig() (any, error) { - var jsonData any +func (s *SettingService) GetDefaultJsonConfig() (interface{}, error) { + var jsonData interface{} err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData) if err != nil { return nil, err @@ -167,7 +163,8 @@ func (s *SettingService) ResetSettings() error { return err } return db.Model(model.User{}). - Where("1 = 1").Error + Where("1 = 1"). + Update("login_secret", "").Error } func (s *SettingService) getSetting(key string) (*model.Setting, error) { @@ -318,22 +315,6 @@ func (s *SettingService) GetTgLang() (string, error) { return s.getString("tgLang") } -func (s *SettingService) GetTwoFactorEnable() (bool, error) { - return s.getBool("twoFactorEnable") -} - -func (s *SettingService) SetTwoFactorEnable(value bool) error { - return s.setBool("twoFactorEnable", value) -} - -func (s *SettingService) GetTwoFactorToken() (string, error) { - return s.getString("twoFactorToken") -} - -func (s *SettingService) SetTwoFactorToken(value string) error { - return s.setString("twoFactorToken", value) -} - func (s *SettingService) GetPort() (int, error) { return s.getInt("webPort") } @@ -374,6 +355,14 @@ func (s *SettingService) GetRemarkModel() (string, error) { return s.getString("remarkModel") } +func (s *SettingService) GetSecretStatus() (bool, error) { + return s.getBool("secretEnable") +} + +func (s *SettingService) SetSecretStatus(value bool) error { + return s.setBool("secretEnable", value) +} + func (s *SettingService) GetSecret() ([]byte, error) { secret, err := s.getString("secret") if secret == defaultValueMap["secret"] { @@ -427,10 +416,6 @@ func (s *SettingService) GetSubEnable() (bool, error) { return s.getBool("subEnable") } -func (s *SettingService) GetSubTitle() (string, error) { - return s.getString("subTitle") -} - func (s *SettingService) GetSubListen() (string, error) { return s.getString("subListen") } @@ -511,22 +496,6 @@ func (s *SettingService) SetWarp(data string) error { return s.setString("warp", data) } -func (s *SettingService) GetExternalTrafficInformEnable() (bool, error) { - return s.getBool("externalTrafficInformEnable") -} - -func (s *SettingService) SetExternalTrafficInformEnable(value bool) error { - return s.setBool("externalTrafficInformEnable", value) -} - -func (s *SettingService) GetExternalTrafficInformURI() (string, error) { - return s.getString("externalTrafficInformURI") -} - -func (s *SettingService) SetExternalTrafficInformURI(InformURI string) error { - return s.setString("externalTrafficInformURI", InformURI) -} - func (s *SettingService) GetIpLimitEnable() (bool, error) { accessLogPath, err := xray.GetAccessLogPath() if err != nil { @@ -556,8 +525,8 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error { return common.Combine(errs...) } -func (s *SettingService) GetDefaultXrayConfig() (any, error) { - var jsonData any +func (s *SettingService) GetDefaultXrayConfig() (interface{}, error) { + var jsonData interface{} err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData) if err != nil { return nil, err @@ -565,25 +534,24 @@ func (s *SettingService) GetDefaultXrayConfig() (any, error) { return jsonData, nil } -func (s *SettingService) GetDefaultSettings(host string) (any, error) { - type settingFunc func() (any, error) +func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) { + type settingFunc func() (interface{}, error) settings := map[string]settingFunc{ - "expireDiff": func() (any, error) { return s.GetExpireDiff() }, - "trafficDiff": func() (any, error) { return s.GetTrafficDiff() }, - "pageSize": func() (any, error) { return s.GetPageSize() }, - "defaultCert": func() (any, error) { return s.GetCertFile() }, - "defaultKey": func() (any, error) { return s.GetKeyFile() }, - "tgBotEnable": func() (any, error) { return s.GetTgbotEnabled() }, - "subEnable": func() (any, error) { return s.GetSubEnable() }, - "subTitle": func() (any, error) { return s.GetSubTitle() }, - "subURI": func() (any, error) { return s.GetSubURI() }, - "subJsonURI": func() (any, error) { return s.GetSubJsonURI() }, - "remarkModel": func() (any, error) { return s.GetRemarkModel() }, - "datepicker": func() (any, error) { return s.GetDatepicker() }, - "ipLimitEnable": func() (any, error) { return s.GetIpLimitEnable() }, + "expireDiff": func() (interface{}, error) { return s.GetExpireDiff() }, + "trafficDiff": func() (interface{}, error) { return s.GetTrafficDiff() }, + "pageSize": func() (interface{}, error) { return s.GetPageSize() }, + "defaultCert": func() (interface{}, error) { return s.GetCertFile() }, + "defaultKey": func() (interface{}, error) { return s.GetKeyFile() }, + "tgBotEnable": func() (interface{}, error) { return s.GetTgbotEnabled() }, + "subEnable": func() (interface{}, error) { return s.GetSubEnable() }, + "subURI": func() (interface{}, error) { return s.GetSubURI() }, + "subJsonURI": func() (interface{}, error) { return s.GetSubJsonURI() }, + "remarkModel": func() (interface{}, error) { return s.GetRemarkModel() }, + "datepicker": func() (interface{}, error) { return s.GetDatepicker() }, + "ipLimitEnable": func() (interface{}, error) { return s.GetIpLimitEnable() }, } - result := make(map[string]any) + result := make(map[string]interface{}) for key, fn := range settings { value, err := fn() @@ -595,7 +563,6 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) { if result["subEnable"].(bool) && (result["subURI"].(string) == "" || result["subJsonURI"].(string) == "") { subURI := "" - subTitle, _ := s.GetSubTitle() subPort, _ := s.GetSubPort() subPath, _ := s.GetSubPath() subJsonPath, _ := s.GetSubJsonPath() @@ -622,9 +589,6 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) { if result["subURI"].(string) == "" { result["subURI"] = subURI + subPath } - if result["subTitle"].(string) == "" { - result["subTitle"] = subTitle - } if result["subJsonURI"].(string) == "" { result["subJsonURI"] = subURI + subJsonPath } diff --git a/web/service/tgbot.go b/web/service/tgbot.go index ffdb63f9..af51e253 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -1,16 +1,12 @@ package service import ( - "crypto/rand" "embed" - "encoding/base64" "errors" "fmt" - "math/big" "net" "net/url" "os" - "regexp" "strconv" "strings" "time" @@ -24,7 +20,6 @@ import ( "x-ui/web/locale" "x-ui/xray" - "github.com/google/uuid" "github.com/mymmrac/telego" th "github.com/mymmrac/telego/telegohandler" tu "github.com/mymmrac/telego/telegoutil" @@ -39,29 +34,8 @@ var ( isRunning bool hostname string hashStorage *global.HashStorage - handler *th.Handler - - // clients data to adding new client - receiver_inbound_ID int - client_Id string - client_Flow string - client_Email string - client_LimitIP int - client_TotalGB int64 - client_ExpiryTime int64 - client_Enable bool - client_TgID string - client_SubID string - client_Comment string - client_Reset int - client_Security string - client_ShPassword string - client_TrPassword string - client_Method string ) -var userStates = make(map[int64]string) - type LoginStatus byte const ( @@ -147,19 +121,6 @@ func (t *Tgbot) Start(i18nFS embed.FS) error { return err } - // After bot initialization, set up bot commands with localized descriptions - err = bot.SetMyCommands(&telego.SetMyCommandsParams{ - Commands: []telego.BotCommand{ - {Command: "start", Description: t.I18nBot("tgbot.commands.startDesc")}, - {Command: "help", Description: t.I18nBot("tgbot.commands.helpDesc")}, - {Command: "status", Description: t.I18nBot("tgbot.commands.statusDesc")}, - {Command: "id", Description: t.I18nBot("tgbot.commands.idDesc")}, - }, - }) - if err != nil { - logger.Warning("Failed to set bot commands:", err) - } - // Start receiving Telegram bot messages if !isRunning { logger.Info("Telegram bot receiver started") @@ -260,161 +221,36 @@ func (t *Tgbot) OnReceive() { botHandler, _ = th.NewBotHandler(bot, updates) botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - delete(userStates, message.Chat.ID) t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) }, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - delete(userStates, message.Chat.ID) t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) }, th.AnyCommand()) botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) { - delete(userStates, query.Message.GetChat().ID) t.answerCallback(&query, checkAdmin(query.From.ID)) }, th.AnyCallbackQueryWithMessage()) botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - if userState, exists := userStates[message.Chat.ID]; exists { - switch userState { - case "awaiting_id": - if client_Id == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - return - } - - client_Id = strings.TrimSpace(message.Text) - if t.isSingleWord(client_Id) { - userStates[message.Chat.ID] = "awaiting_id" - - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - - t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup) - } else { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_id"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - case "awaiting_password_tr": - if client_TrPassword == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - return - } - - client_TrPassword = strings.TrimSpace(message.Text) - if t.isSingleWord(client_TrPassword) { - userStates[message.Chat.ID] = "awaiting_password_tr" - - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - - t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup) - } else { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_password"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - case "awaiting_password_sh": - if client_ShPassword == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - return - } - - client_ShPassword = strings.TrimSpace(message.Text) - if t.isSingleWord(client_ShPassword) { - userStates[message.Chat.ID] = "awaiting_password_sh" - - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - - t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup) - } else { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_password"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - case "awaiting_email": - if client_Email == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - return - } - - client_Email = strings.TrimSpace(message.Text) - if t.isSingleWord(client_Email) { - userStates[message.Chat.ID] = "awaiting_email" - - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - - t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup) - } else { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_email"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - case "awaiting_comment": - if client_Comment == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - return - } - - client_Comment = strings.TrimSpace(message.Text) - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_comment"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - - } else { - if message.UsersShared != nil { - if checkAdmin(message.From.ID) { - for _, sharedUser := range message.UsersShared.Users { - userID := sharedUser.UserID - needRestart, err := t.inboundService.SetClientTelegramUserID(message.UsersShared.RequestID, userID) - if needRestart { - t.xrayService.SetToNeedRestart() - } - output := "" - if err != nil { - output += t.I18nBot("tgbot.messages.selectUserFailed") - } else { - output += t.I18nBot("tgbot.messages.userSaved") - } - t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove()) + if message.UsersShared != nil { + if checkAdmin(message.From.ID) { + for _, sharedUser := range message.UsersShared.Users { + userID := sharedUser.UserID + needRestart, err := t.inboundService.SetClientTelegramUserID(message.UsersShared.RequestID, userID) + if needRestart { + t.xrayService.SetToNeedRestart() } - } else { - t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove()) + output := "" + if err != nil { + output += t.I18nBot("tgbot.messages.selectUserFailed") + } else { + output += t.I18nBot("tgbot.messages.userSaved") + } + t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove()) } + } else { + t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove()) } } }, th.AnyMessage()) @@ -471,6 +307,8 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo onlyMessage = true if isAdmin { if len(commandArgs) == 0 { + msg += t.I18nBot("tgbot.commands.restartUsage") + } else if strings.ToLower(commandArgs[0]) == "force" { if t.xrayService.IsXrayRunning() { err := t.xrayService.RestartXray(true) if err != nil { @@ -506,25 +344,6 @@ func (t *Tgbot) sendResponse(chatId int64, msg string, onlyMessage, isAdmin bool } } -func (t *Tgbot) randomLowerAndNum(length int) string { - charset := "abcdefghijklmnopqrstuvwxyz0123456789" - bytes := make([]byte, length) - for i := range bytes { - randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) - bytes[i] = charset[randomIndex.Int64()] - } - return string(bytes) -} - -func (t *Tgbot) randomShadowSocksPassword() string { - array := make([]byte, 32) - _, err := rand.Read(array) - if err != nil { - return t.randomLowerAndNum(32) - } - return base64.StdEncoding.EncodeToString(array) -} - func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool) { chatId := callbackQuery.Message.GetChat().ID @@ -688,78 +507,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) - case "add_client_limit_traffic_c": - limitTraffic, _ := strconv.Atoi(dataArray[1]) - client_TotalGB = int64(limitTraffic) * 1024 * 1024 * 1024 - messageId := callbackQuery.Message.GetMessageID() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId, message_text, messageId) - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) - case "add_client_limit_traffic_in": - if len(dataArray) >= 2 { - oldInputNumber, err := strconv.Atoi(dataArray[1]) - inputNumber := oldInputNumber - if err == nil { - if len(dataArray) == 3 { - num, err := strconv.Atoi(dataArray[2]) - if err == nil { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - inputNumber = (inputNumber * 10) + num - } - } - if inputNumber == oldInputNumber { - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) - return - } - if inputNumber >= 999999 { - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) - return - } - } - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c "+strconv.Itoa(inputNumber))), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 1")), - tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 2")), - tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 3")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 4")), - tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 5")), - tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 6")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 7")), - tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 8")), - tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 9")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -2")), - tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 0")), - tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -1")), - ), - ) - t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard) - return - } - } case "reset_exp": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -891,90 +638,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) - case "add_client_reset_exp_c": - client_ExpiryTime = 0 - days, _ := strconv.Atoi(dataArray[1]) - var date int64 = 0 - if client_ExpiryTime > 0 { - if client_ExpiryTime-time.Now().Unix()*1000 < 0 { - date = -int64(days * 24 * 60 * 60000) - } else { - date = client_ExpiryTime + int64(days*24*60*60000) - } - } else { - date = client_ExpiryTime - int64(days*24*60*60000) - } - client_ExpiryTime = date - - messageId := callbackQuery.Message.GetMessageID() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId, message_text, messageId) - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) - case "add_client_reset_exp_in": - if len(dataArray) >= 2 { - oldInputNumber, err := strconv.Atoi(dataArray[1]) - inputNumber := oldInputNumber - if err == nil { - if len(dataArray) == 3 { - num, err := strconv.Atoi(dataArray[2]) - if err == nil { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - inputNumber = (inputNumber * 10) + num - } - } - if inputNumber == oldInputNumber { - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) - return - } - if inputNumber >= 999999 { - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) - return - } - } - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_reset_exp_c "+strconv.Itoa(inputNumber))), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 1")), - tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 2")), - tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 3")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 4")), - tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 5")), - tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 6")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 7")), - tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 8")), - tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 9")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -2")), - tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 0")), - tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -1")), - ), - ) - t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard) - return - } - } case "ip_limit": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -1082,83 +745,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool } t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) - case "add_client_ip_limit_c": - if len(dataArray) == 2 { - count, _ := strconv.Atoi(dataArray[1]) - client_LimitIP = count - } - - messageId := callbackQuery.Message.GetMessageID() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId, message_text, messageId) - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) - case "add_client_ip_limit_in": - if len(dataArray) >= 2 { - oldInputNumber, err := strconv.Atoi(dataArray[1]) - inputNumber := oldInputNumber - if err == nil { - if len(dataArray) == 3 { - num, err := strconv.Atoi(dataArray[2]) - if err == nil { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - inputNumber = (inputNumber * 10) + num - } - } - if inputNumber == oldInputNumber { - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) - return - } - if inputNumber >= 999999 { - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) - return - } - } - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_ip_limit_c "+strconv.Itoa(inputNumber))), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 1")), - tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 2")), - tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 3")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 4")), - tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 5")), - tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 6")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 7")), - tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 8")), - tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 9")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -2")), - tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 0")), - tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -1")), - ), - ) - t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard) - return - } - } - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) - t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) case "clear_ips": inlineKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( @@ -1252,40 +838,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool return } t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clients) - case "add_client_to": - // assign default values to clients variables - client_Id = uuid.New().String() - client_Flow = "" - client_Email = t.randomLowerAndNum(8) - client_LimitIP = 0 - client_TotalGB = 0 - client_ExpiryTime = 0 - client_Enable = true - client_TgID = "" - client_SubID = t.randomLowerAndNum(16) - client_Comment = "" - client_Reset = 0 - client_Security = "auto" - client_ShPassword = t.randomShadowSocksPassword() - client_TrPassword = t.randomLowerAndNum(10) - client_Method = "" - inboundId := dataArray[1] - inboundIdInt, err := strconv.Atoi(inboundId) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - receiver_inbound_ID = inboundIdInt - inbound, err := t.inboundService.GetInbound(inboundIdInt) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId, message_text) } return } else { @@ -1339,432 +892,9 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool case "commands": t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands")) t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands")) - case "add_client": - // assign default values to clients variables - client_Id = uuid.New().String() - client_Flow = "" - client_Email = t.randomLowerAndNum(8) - client_LimitIP = 0 - client_TotalGB = 0 - client_ExpiryTime = 0 - client_Enable = true - client_TgID = "" - client_SubID = t.randomLowerAndNum(16) - client_Comment = "" - client_Reset = 0 - client_Security = "auto" - client_ShPassword = t.randomShadowSocksPassword() - client_TrPassword = t.randomLowerAndNum(10) - client_Method = "" - - inbounds, err := t.getInboundsAddClient() - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.addClient")) - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds) - case "add_client_ch_default_email": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_email" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - prompt_message := t.I18nBot("tgbot.messages.email_prompt", "ClientEmail=="+client_Email) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_id": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_id" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - prompt_message := t.I18nBot("tgbot.messages.id_prompt", "ClientId=="+client_Id) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_pass_tr": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_password_tr" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - prompt_message := t.I18nBot("tgbot.messages.pass_prompt", "ClientPassword=="+client_TrPassword) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_pass_sh": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_password_sh" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - prompt_message := t.I18nBot("tgbot.messages.pass_prompt", "ClientPassword=="+client_ShPassword) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_comment": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_comment" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) - prompt_message := t.I18nBot("tgbot.messages.comment_prompt", "ClientComment=="+client_Comment) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_traffic": - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 0")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_in 0")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 1")), - tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 5")), - tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 10")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 20")), - tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 30")), - tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 40")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 50")), - tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 60")), - tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 80")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 100")), - tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 150")), - tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 200")), - ), - ) - t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard) - case "add_client_ch_default_exp": - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 0")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_reset_exp_in 0")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 7")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 10")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 14")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 20")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 30")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 90")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 180")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 365")), - ), - ) - t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard) - case "add_client_ch_default_ip_limit": - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_ip_limit_c 0")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_ip_limit_in 0")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 1")), - tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 2")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 3")), - tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 4")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 5")), - tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 6")), - tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 7")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 8")), - tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 9")), - tu.InlineKeyboardButton("10").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 10")), - ), - ) - t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard) - case "add_client_default_info": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, chatId) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(chatId, message_text) - case "add_client_cancel": - delete(userStates, chatId) - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 3, tu.ReplyKeyboardRemove()) - case "add_client_default_traffic_exp": - messageId := callbackQuery.Message.GetMessageID() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(chatId, message_text, messageId) - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email)) - case "add_client_default_ip_limit": - messageId := callbackQuery.Message.GetMessageID() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(chatId, message_text, messageId) - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email)) - case "add_client_submit_disable": - client_Enable = false - _, err := t.SubmitAddClient() - if err != nil { - errorMessage := fmt.Sprintf("%v", err) - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove()) - } else { - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove()) - } - case "add_client_submit_enable": - client_Enable = true - _, err := t.SubmitAddClient() - if err != nil { - errorMessage := fmt.Sprintf("%v", err) - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove()) - } else { - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove()) - } - case "reset_all_traffics_cancel": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 1, tu.ReplyKeyboardRemove()) - case "reset_all_traffics": - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("reset_all_traffics_cancel")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_all_traffics_c")), - ), - ) - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.AreYouSure"), inlineKeyboard) - case "reset_all_traffics_c": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - emails, err := t.inboundService.getAllEmails() - if err != nil { - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove()) - return - } - - for _, email := range emails { - err := t.inboundService.ResetClientTrafficByEmail(email) - if err == nil { - msg := t.I18nBot("tgbot.messages.SuccessResetTraffic", "ClientEmail=="+email) - t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove()) - } else { - msg := t.I18nBot("tgbot.messages.FailedResetTraffic", "ClientEmail=="+email, "ErrorMessage=="+err.Error()) - t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove()) - } - } - - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.FinishProcess"), tu.ReplyKeyboardRemove()) - case "get_sorted_traffic_usage_report": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - emails, err := t.inboundService.getAllEmails() - - if err != nil { - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove()) - return - } - valid_emails, extra_emails, err := t.inboundService.FilterAndSortClientEmails(emails) - - for _, valid_emails := range valid_emails { - traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails) - if err != nil { - logger.Warning(err) - msg := t.I18nBot("tgbot.wentWrong") - t.SendMsgToTgbot(chatId, msg) - continue - } - if traffic == nil { - msg := t.I18nBot("tgbot.noResult") - t.SendMsgToTgbot(chatId, msg) - continue - } - - output := t.clientInfoMsg(traffic, false, false, false, false, true, false) - t.SendMsgToTgbot(chatId, output, tu.ReplyKeyboardRemove()) - } - for _, extra_emails := range extra_emails { - msg := fmt.Sprintf("📧 %s\n%s", extra_emails, t.I18nBot("tgbot.noResult")) - t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove()) - - } } } -func (t *Tgbot) BuildInboundClientDataMessage(inbound_remark string, protocol model.Protocol) (string, error) { - var message string - - currentTime := time.Now() - timestampMillis := currentTime.UnixNano() / int64(time.Millisecond) - - expiryTime := "" - diff := client_ExpiryTime/1000 - timestampMillis - if client_ExpiryTime == 0 { - expiryTime = t.I18nBot("tgbot.unlimited") - } else if diff > 172800 { - expiryTime = time.Unix((client_ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") - } else if client_ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d %s", client_ExpiryTime/-86400000, t.I18nBot("tgbot.days")) - } else { - expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) - } - - traffic_value := "" - if client_TotalGB == 0 { - traffic_value = "♾️ Unlimited(Reset)" - } else { - traffic_value = common.FormatTraffic(client_TotalGB) - } - - ip_limit := "" - if client_LimitIP == 0 { - ip_limit = "♾️ Unlimited(Reset)" - } else { - ip_limit = fmt.Sprint(client_LimitIP) - } - - switch protocol { - case model.VMESS, model.VLESS: - message = t.I18nBot("tgbot.messages.inbound_client_data_id", "InboundRemark=="+inbound_remark, "ClientId=="+client_Id, "ClientEmail=="+client_Email, "ClientTraffic=="+traffic_value, "ClientExp=="+expiryTime, "IpLimit=="+ip_limit, "ClientComment=="+client_Comment) - - case model.Trojan: - message = t.I18nBot("tgbot.messages.inbound_client_data_pass", "InboundRemark=="+inbound_remark, "ClientPass=="+client_TrPassword, "ClientEmail=="+client_Email, "ClientTraffic=="+traffic_value, "ClientExp=="+expiryTime, "IpLimit=="+ip_limit, "ClientComment=="+client_Comment) - - case model.Shadowsocks: - message = t.I18nBot("tgbot.messages.inbound_client_data_pass", "InboundRemark=="+inbound_remark, "ClientPass=="+client_ShPassword, "ClientEmail=="+client_Email, "ClientTraffic=="+traffic_value, "ClientExp=="+expiryTime, "IpLimit=="+ip_limit, "ClientComment=="+client_Comment) - - default: - return "", errors.New("unknown protocol") - } - - return message, nil -} - -func (t *Tgbot) BuildJSONForProtocol(protocol model.Protocol) (string, error) { - var jsonString string - - switch protocol { - case model.VMESS: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "id": "%s", - "security": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_Id, client_Security, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - case model.VLESS: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "id": "%s", - "flow": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_Id, client_Flow, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - case model.Trojan: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "password": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_TrPassword, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - case model.Shadowsocks: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "method": "%s", - "password": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_Method, client_ShPassword, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - default: - return "", errors.New("unknown protocol") - } - - return jsonString, nil -} - -func (t *Tgbot) SubmitAddClient() (bool, error) { - - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - logger.Warning("getIboundClients run failed:", err) - return false, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - jsonString, err := t.BuildJSONForProtocol(inbound.Protocol) - - newInbound := &model.Inbound{ - Id: receiver_inbound_ID, - Settings: jsonString, - } - - return t.inboundService.AddInboundClient(newInbound) -} - func checkAdmin(tgId int64) bool { for _, adminId := range adminIds { if adminId == tgId { @@ -1777,27 +907,20 @@ func checkAdmin(tgId int64) bool { func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { numericKeyboard := tu.InlineKeyboard( tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.SortedTrafficUsageReport")).WithCallbackData(t.encodeQuery("get_sorted_traffic_usage_report")), - ), - tu.InlineKeyboardRow( + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.allClients")).WithCallbackData(t.encodeQuery("get_inbounds")), tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.encodeQuery("get_usage")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ResetAllTraffics")).WithCallbackData(t.encodeQuery("reset_all_traffics")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getBanLogs")).WithCallbackData(t.encodeQuery("get_banlogs")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.encodeQuery("inbounds")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.depleteSoon")).WithCallbackData(t.encodeQuery("deplete_soon")), ), tu.InlineKeyboardRow( tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("commands")), tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.onlines")).WithCallbackData(t.encodeQuery("onlines")), ), tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.allClients")).WithCallbackData(t.encodeQuery("get_inbounds")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.addClient")).WithCallbackData(t.encodeQuery("add_client")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.depleteSoon")).WithCallbackData(t.encodeQuery("deplete_soon")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.encodeQuery("inbounds")), + ), + tu.InlineKeyboardRow( + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getBanLogs")).WithCallbackData(t.encodeQuery("get_banlogs")), + tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")), ), // TODOOOOOOOOOOOOOO: Add restart button here. ) @@ -2043,75 +1166,35 @@ func (t *Tgbot) getInboundUsages() string { } return info } + func (t *Tgbot) getInbounds() (*telego.InlineKeyboardMarkup, error) { inbounds, err := t.inboundService.GetAllInbounds() + var buttons []telego.InlineKeyboardButton + if err != nil { logger.Warning("GetAllInbounds run failed:", err) return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - if len(inbounds) == 0 { - logger.Warning("No inbounds found") - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - var buttons []telego.InlineKeyboardButton - for _, inbound := range inbounds { - status := "❌" - if inbound.Enable { - status = "✅" + } else { + if len(inbounds) > 0 { + for _, inbound := range inbounds { + status := "❌" + if inbound.Enable { + status = "✅" + } + buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(t.encodeQuery("get_clients "+strconv.Itoa(inbound.Id)))) + } + } else { + logger.Warning("GetAllInbounds run failed:", err) + return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) } - callbackData := t.encodeQuery(fmt.Sprintf("%s %d", "get_clients", inbound.Id)) - buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(callbackData)) - } - cols := 1 - if len(buttons) >= 6 { + } + cols := 0 + if len(buttons) < 6 { + cols = 3 + } else { cols = 2 } - - keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) - return keyboard, nil -} - -func (t *Tgbot) getInboundsAddClient() (*telego.InlineKeyboardMarkup, error) { - inbounds, err := t.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("GetAllInbounds run failed:", err) - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - if len(inbounds) == 0 { - logger.Warning("No inbounds found") - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - excludedProtocols := map[model.Protocol]bool{ - model.DOKODEMO: true, - model.Socks: true, - model.WireGuard: true, - model.HTTP: true, - } - - var buttons []telego.InlineKeyboardButton - for _, inbound := range inbounds { - if excludedProtocols[inbound.Protocol] { - continue - } - - status := "❌" - if inbound.Enable { - status = "✅" - } - callbackData := t.encodeQuery(fmt.Sprintf("%s %d", "add_client_to", inbound.Id)) - buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(callbackData)) - } - - cols := 1 - if len(buttons) >= 6 { - cols = 2 - } - keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) return keyboard, nil } @@ -2406,102 +1489,6 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { } } -func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) { - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.SendMsgToTgbot(chatId, err.Error()) - return - } - - protocol := inbound.Protocol - - switch protocol { - case model.VMESS, model.VLESS: - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_id")).WithCallbackData("add_client_ch_default_id"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ipLimit")).WithCallbackData("add_client_ch_default_ip_limit"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitEnable")).WithCallbackData("add_client_submit_enable"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"), - ), - ) - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, msg, inlineKeyboard) - } - case model.Trojan: - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_password")).WithCallbackData("add_client_ch_default_pass_tr"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"), - tu.InlineKeyboardButton("ip limit").WithCallbackData("add_client_ch_default_ip_limit"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitEnable")).WithCallbackData("add_client_submit_enable"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"), - ), - ) - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, msg, inlineKeyboard) - } - case model.Shadowsocks: - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_password")).WithCallbackData("add_client_ch_default_pass_sh"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"), - tu.InlineKeyboardButton("ip limit").WithCallbackData("add_client_ch_default_ip_limit"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitEnable")).WithCallbackData("add_client_submit_enable"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"), - ), - ) - - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, msg, inlineKeyboard) - } - } - -} - func (t *Tgbot) searchInbound(chatId int64, remark string) { inbounds, err := t.inboundService.SearchInbounds(remark) if err != nil { @@ -2872,47 +1859,3 @@ func (t *Tgbot) editMessageTgBot(chatId int64, messageID int, text string, inlin logger.Warning(err) } } - -func (t *Tgbot) SendMsgToTgbotDeleteAfter(chatId int64, msg string, delayInSeconds int, replyMarkup ...telego.ReplyMarkup) { - // Determine if replyMarkup was passed; otherwise, set it to nil - var replyMarkupParam telego.ReplyMarkup - if len(replyMarkup) > 0 { - replyMarkupParam = replyMarkup[0] // Use the first element - } - - // Send the message - sentMsg, err := bot.SendMessage(&telego.SendMessageParams{ - ChatID: tu.ID(chatId), - Text: msg, - ReplyMarkup: replyMarkupParam, // Use the correct replyMarkup value - }) - if err != nil { - logger.Warning("Failed to send message:", err) - return - } - - // Delete the sent message after the specified number of seconds - go func() { - time.Sleep(time.Duration(delayInSeconds) * time.Second) // Wait for the specified delay - t.deleteMessageTgBot(chatId, sentMsg.MessageID) // Delete the message - delete(userStates, chatId) - }() -} - -func (t *Tgbot) deleteMessageTgBot(chatId int64, messageID int) { - params := telego.DeleteMessageParams{ - ChatID: tu.ID(chatId), - MessageID: messageID, - } - if err := bot.DeleteMessage(¶ms); err != nil { - logger.Warning("Failed to delete message:", err) - } else { - logger.Info("Message deleted successfully") - } -} - -func (t *Tgbot) isSingleWord(text string) bool { - text = strings.TrimSpace(text) - re := regexp.MustCompile(`\s+`) - return re.MatchString(text) -} From d5803bf2cf5e46c5daeca31ad04fcc782f04a60a Mon Sep 17 00:00:00 2001 From: xinsuiyuandong Date: Sat, 12 Jul 2025 03:44:45 +0800 Subject: [PATCH 2/4] v2.6.2 v2.6.2 --- web/translation/translate.zh_CN.toml | 253 +++++++-------------------- 1 file changed, 66 insertions(+), 187 deletions(-) diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml index 26cc3322..f746bae6 100644 --- a/web/translation/translate.zh_CN.toml +++ b/web/translation/translate.zh_CN.toml @@ -4,8 +4,6 @@ "confirm" = "确定" "cancel" = "取消" "close" = "关闭" -"create" = "创建" -"update" = "更新" "copy" = "复制" "copied" = "已复制" "download" = "下载" @@ -28,11 +26,9 @@ "edit" = "编辑" "delete" = "删除" "reset" = "重置" -"noData" = "无数据。" "copySuccess" = "复制成功" "sure" = "确定" "encryption" = "加密" -"useIPv4ForHost" = "使用 IPv4 连接主机" "transmission" = "传输" "host" = "主机" "path" = "路径" @@ -48,13 +44,12 @@ "monitor" = "监听" "certificate" = "数字证书" "fail" = "失败" -"comment" = "评论" "success" = "成功" "getVersion" = "获取版本" "install" = "安装" "clients" = "客户端" "usage" = "使用情况" -"twoFactorCode" = "代码" +"secretToken" = "安全密钥" "remained" = "剩余" "security" = "安全" "secAlertTitle" = "安全警报" @@ -65,22 +60,15 @@ "secAlertPanelURI" = "面板默认 URI 路径不安全。请配置复杂的 URI 路径。" "secAlertSubURI" = "订阅默认 URI 路径不安全。请配置复杂的 URI 路径。" "secAlertSubJsonURI" = "订阅 JSON 默认 URI 路径不安全。请配置复杂的 URI 路径。" -"emptyDnsDesc" = "未添加DNS服务器。" -"emptyFakeDnsDesc" = "未添加Fake DNS服务器。" -"emptyBalancersDesc" = "未添加负载均衡器。" -"emptyReverseDesc" = "未添加反向代理。" -"somethingWentWrong" = "出了点问题" [menu] -"theme" = "主题" -"dark" = "暗色" -"ultraDark" = "超暗色" "dashboard" = "系统状态" "inbounds" = "入站列表" "settings" = "面板设置" -"xray" = "Xray 设置" +"xray" = "Xray设置" "logout" = "退出登录" "link" = "管理" +"navigation" = "实用导航" [pages.login] "hello" = "你好" @@ -91,64 +79,39 @@ "invalidFormData" = "数据格式错误" "emptyUsername" = "请输入用户名" "emptyPassword" = "请输入密码" -"wrongUsernameOrPassword" = "用户名、密码或双重验证码无效。" -"successLogin" = "您已成功登录您的账户。" +"wrongUsernameOrPassword" = "用户名或密码错误" +"successLogin" = "登录" [pages.index] "title" = "系统状态" -"cpu" = "CPU" -"logicalProcessors" = "逻辑处理器" -"frequency" = "频率" -"swap" = "交换分区" -"storage" = "存储" "memory" = "内存" -"threads" = "线程" +"hard" = "磁盘" "xrayStatus" = "Xray" "stopXray" = "停止" "restartXray" = "重启" "xraySwitch" = "版本" "xraySwitchClick" = "选择你要切换到的版本" "xraySwitchClickDesk" = "请谨慎选择,因为较旧版本可能与当前配置不兼容" -"xrayStatusUnknown" = "未知" -"xrayStatusRunning" = "运行中" -"xrayStatusStop" = "停止" -"xrayStatusError" = "错误" -"xrayErrorPopoverTitle" = "运行Xray时发生错误" "operationHours" = "系统正常运行时间" "systemLoad" = "系统负载" "systemLoadDesc" = "过去 1、5 和 15 分钟的系统平均负载" "connectionTcpCountDesc" = "系统中所有 TCP 连接数" "connectionUdpCountDesc" = "系统中所有 UDP 连接数" "connectionCount" = "连接数" -"ipAddresses" = "IP地址" -"toggleIpVisibility" = "切换IP可见性" -"overallSpeed" = "整体速度" -"upload" = "上传" -"download" = "下载" -"totalData" = "总数据" -"sent" = "已发送" -"received" = "已接收" -"documentation" = "文档" -"xraySwitchVersionDialog" = "您确定要更改Xray版本吗?" -"xraySwitchVersionDialogDesc" = "这将把Xray版本更改为#version#。" -"xraySwitchVersionPopover" = "Xray 更新成功" -"geofileUpdateDialog" = "您确定要更新地理文件吗?" -"geofileUpdateDialogDesc" = "这将更新 #filename# 文件。" -"geofileUpdatePopover" = "地理文件更新成功" +"upSpeed" = "总上传速度" +"downSpeed" = "总下载速度" +"totalSent" = "系统启动以来发送的总数据量" +"totalReceive" = "系统启动以来接收的总数据量" +"xraySwitchVersionDialog" = "切换 Xray 版本" +"xraySwitchVersionDialogDesc" = "是否切换 Xray 版本至" "dontRefresh" = "安装中,请勿刷新此页面" "logs" = "日志" "config" = "配置" -"backup" = "备份" +"backup" = "备份和恢复" "backupTitle" = "备份和恢复数据库" +"backupDescription" = "恢复数据库之前建议进行备份" "exportDatabase" = "备份" -"exportDatabaseDesc" = "点击下载包含当前数据库备份的 .db 文件到您的设备。" "importDatabase" = "恢复" -"importDatabaseDesc" = "点击选择并上传设备中的 .db 文件以从备份恢复数据库。" -"importDatabaseSuccess" = "数据库导入成功" -"importDatabaseError" = "导入数据库时出错" -"readDatabaseError" = "读取数据库时出错" -"getDatabaseError" = "检索数据库时出错" -"getConfigError" = "检索配置文件时出错" [pages.inbounds] "title" = "入站列表" @@ -167,16 +130,14 @@ "resetTraffic" = "重置流量" "addInbound" = "添加入站" "generalActions" = "通用操作" -"autoRefresh" = "自动刷新" -"autoRefreshInterval" = "间隔" +"create" = "添加" +"update" = "修改" "modifyInbound" = "修改入站" "deleteInbound" = "删除入站" "deleteInboundContent" = "确定要删除入站吗?" "deleteClient" = "删除客户端" "deleteClientContent" = "确定要删除客户端吗?" "resetTrafficContent" = "确定要重置流量吗?" -"inboundUpdateSuccess" = "入站连接已成功更新。" -"inboundCreateSuccess" = "入站连接已成功创建。" "copyLink" = "复制链接" "address" = "地址" "network" = "网络" @@ -211,14 +172,16 @@ "delDepletedClientsTitle" = "删除流量耗尽的客户端" "delDepletedClientsContent" = "确定要删除所有流量耗尽的客户端吗?" "email" = "电子邮件" -"emailDesc" = "电子邮件必须完全唯一" +"emailDesc" = "电子邮件必须确保唯一" "IPLimit" = "IP 限制" "IPLimitDesc" = "如果数量超过设置值,则禁用入站流量。(0 = 禁用)" "IPLimitlog" = "IP 日志" "IPLimitlogDesc" = "IP 历史日志(要启用被禁用的入站流量,请清除日志)" "IPLimitlogclear" = "清除日志" "setDefaultCert" = "从面板设置证书" -"telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或(@userinfobot" +"xtlsDesc" = "Xray 核心需要 1.7.5" +"realityDesc" = "Xray 核心需要 1.8.0 及以上版本" +"telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令或跟@userinfobot机器人对话获取)" "subscriptionDesc" = "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。" "info" = "信息" "same" = "相同" @@ -247,21 +210,6 @@ [pages.inbounds.toasts] "obtain" = "获取" -"updateSuccess" = "更新成功" -"logCleanSuccess" = "日志已清除" -"inboundsUpdateSuccess" = "入站连接已成功更新" -"inboundUpdateSuccess" = "入站连接已成功更新" -"inboundCreateSuccess" = "入站连接已成功创建" -"inboundDeleteSuccess" = "入站连接已成功删除" -"inboundClientAddSuccess" = "已添加入站客户端" -"inboundClientDeleteSuccess" = "入站客户端已删除" -"inboundClientUpdateSuccess" = "入站客户端已更新" -"delDepletedClientsSuccess" = "所有耗尽客户端已删除" -"resetAllClientTrafficSuccess" = "客户端所有流量已重置" -"resetAllTrafficSuccess" = "所有流量已重置" -"resetInboundClientTrafficSuccess" = "流量已重置" -"trafficGetError" = "获取流量数据时出错" -"getNewX25519CertError" = "获取X25519证书时出错。" [pages.inbounds.stream.general] "request" = "请求" @@ -284,12 +232,11 @@ "infoDesc" = "此处的所有更改都需要保存并重启面板才能生效" "restartPanel" = "重启面板" "restartPanelDesc" = "确定要重启面板吗?若重启后无法访问面板,请前往服务器查看面板日志信息" -"restartPanelSuccess" = "面板已成功重启" "actions" = "操作" "resetDefaultConfig" = "重置为默认配置" "panelSettings" = "常规" "securitySettings" = "安全设定" -"TGBotSettings" = "Telegram 机器人配置" +"TGBotSettings" = "Telegram机器人配置" "panelListeningIP" = "面板监听 IP" "panelListeningIPDesc" = "默认留空监听所有 IP" "panelListeningDomain" = "面板监听域名" @@ -297,10 +244,12 @@ "panelPort" = "面板监听端口" "panelPortDesc" = "重启面板生效" "publicKeyPath" = "面板证书公钥文件路径" -"publicKeyPathDesc" = "填写一个 '/' 开头的绝对路径" +"DefaultpublicKeyPath" = "/root/.acme.sh/域名_ecc/域名.cer" +"publicKeyPathDesc" = "填写一个 '/' 开头的绝对路径,〔acme方式〕请自行在填入时修改域名" "privateKeyPath" = "面板证书密钥文件路径" -"privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径" -"panelUrlPath" = "面板 url 根路径" +"DefaultprivateKeyPath" = "/root/.acme.sh/域名_ecc/域名.key" +"privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径,〔acme方式〕请自行在填入时修改域名" +"panelUrlPath" = "面板登录访问路径" "panelUrlPathDesc" = "必须以 '/' 开头,以 '/' 结尾" "pageSize" = "分页大小" "pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用" @@ -316,7 +265,7 @@ "telegramBotEnable" = "启用 Telegram 机器人" "telegramBotEnableDesc" = "启用 Telegram 机器人功能" "telegramToken" = "Telegram 机器人令牌(token)" -"telegramTokenDesc" = "从 '@BotFather' 获取的 Telegram 机器人令牌" +"telegramTokenDesc" = "跟 '@BotFather' 对话获取的 Telegram 机器人令牌" "telegramProxy" = "SOCKS5 Proxy" "telegramProxyDesc" = "启用 SOCKS5 代理连接到 Telegram(根据指南调整设置)" "telegramAPIServer" = "Telegram API Server" @@ -342,8 +291,6 @@ "subSettings" = "订阅设置" "subEnable" = "启用订阅服务" "subEnableDesc" = "启用订阅服务功能" -"subTitle" = "订阅标题" -"subTitleDesc" = "在VPN客户端中显示的标题" "subListen" = "监听 IP" "subListenDesc" = "订阅服务监听的 IP 地址(留空表示监听所有 IP)" "subPort" = "监听端口" @@ -364,10 +311,6 @@ "subShowInfoDesc" = "客户端应用中将显示剩余流量和日期信息" "subURI" = "反向代理 URI" "subURIDesc" = "用于代理后面的订阅 URL 的 URI 路径" -"externalTrafficInformEnable" = "外部交通通知" -"externalTrafficInformEnableDesc" = "每次流量更新时通知外部 API" -"externalTrafficInformURI" = "外部流量通知 URI" -"externalTrafficInformURIDesc" = "流量更新将发送到此 URI" "fragment" = "分片" "fragmentDesc" = "启用 TLS hello 数据包分片" "fragmentSett" = "设置" @@ -378,30 +321,19 @@ "muxSett" = "复用器设置" "direct" = "直接连接" "directDesc" = "直接与特定国家的域或IP范围建立连接" -"notifications" = "通知" -"certs" = "证书" -"externalTraffic" = "外部流量" -"dateAndTime" = "日期和时间" -"proxyAndServer" = "代理和服务器" -"intervals" = "间隔" -"information" = "信息" -"language" = "语言" -"telegramBotLanguage" = "Telegram 机器人语言" + [pages.xray] "title" = "Xray 配置" "save" = "保存" "restart" = "重新启动 Xray" -"restartSuccess" = "Xray 已成功重新启动" -"stopSuccess" = "Xray 已成功停止" -"restartError" = "重启Xray时发生错误。" -"stopError" = "停止Xray时发生错误。" "basicTemplate" = "基础配置" "advancedTemplate" = "高级配置" "generalConfigs" = "常规配置" "generalConfigsDesc" = "这些选项将决定常规配置" "logConfigs" = "日志" "logConfigsDesc" = "日志可能会影响服务器的性能,建议仅在需要时启用" +"blockConfigs" = "防护屏蔽" "blockConfigsDesc" = "这些选项将阻止用户连接到特定协议和网站" "basicRouting" = "基本路由" "blockConnectionsConfigsDesc" = "这些选项将根据特定的请求国家阻止流量。" @@ -421,6 +353,9 @@ "RoutingStrategy" = "配置路由域策略" "RoutingStrategyDesc" = "设置 DNS 解析的整体路由策略" "Torrent" = "屏蔽 BitTorrent 协议" +"TorrentDesc" = "禁止使用 BitTorrent" +"Family" = "家庭保护" +"FamilyDesc" = "屏蔽成人内容和恶意网站" "Inbounds" = "入站规则" "InboundsDesc" = "接受来自特定客户端的流量" "Outbounds" = "出站规则" @@ -439,15 +374,9 @@ "dnsLogDesc" = "是否启用 DNS 查询日志" "maskAddress" = "隐藏地址" "maskAddressDesc" = "IP 地址掩码,启用时会自动替换日志中出现的 IP 地址。" -"statistics" = "统计" -"statsInboundUplink" = "入站上传统计" -"statsInboundUplinkDesc" = "启用所有入站代理的上行流量统计收集。" -"statsInboundDownlink" = "入站下载统计" -"statsInboundDownlinkDesc" = "启用所有入站代理的下行流量统计收集。" -"statsOutboundUplink" = "出站上传统计" -"statsOutboundUplinkDesc" = "启用所有出站代理的上行流量统计收集。" -"statsOutboundDownlink" = "出站下载统计" -"statsOutboundDownlinkDesc" = "启用所有出站代理的下行流量统计收集。" + +[pages.navigation] +"title" = "实用导航" [pages.xray.rules] "first" = "置顶" @@ -455,7 +384,7 @@ "up" = "向上" "down" = "向下" "source" = "来源" -"dest" = "目的地址" +"dest" = "目标地址" "inbound" = "入站" "outbound" = "出站" "balancer" = "负载均衡" @@ -463,6 +392,18 @@ "add" = "添加规则" "edit" = "编辑规则" "useComma" = "逗号分隔的项目" +"DomainMatcher" = "域匹配类型" +"SourceIPs" = "源IP" +"SourcePort" = "源端口" +"Network" = "网络类型" +"Protocol" = "传输协议" +"Attributes" = "属性" +"Domain" = "域地址" +"User" = "用户" +"Port" = "端口" +"InboundTag" = "入站 Tag" +"OutboundTag" = "出站 Tag" +"BalancerTag" = "负载均衡 Tag" [pages.xray.outbound] "addOutbound" = "添加出站" @@ -477,7 +418,6 @@ "type" = "类型" "bridge" = "Bridge" "portal" = "Portal" -"link" = "链接" "intercon" = "互连" "settings" = "设置" "accountInfo" = "帐户信息" @@ -506,26 +446,12 @@ "enableDesc" = "启用内置 DNS 服务器" "tag" = "DNS 入站标签" "tagDesc" = "此标签将在路由规则中可用作入站标签" -"clientIp" = "客户端IP" -"clientIpDesc" = "用于在DNS查询期间通知服务器指定的IP位置" -"disableCache" = "禁用缓存" -"disableCacheDesc" = "禁用DNS缓存" -"disableFallback" = "禁用回退" -"disableFallbackDesc" = "禁用回退DNS查询" -"disableFallbackIfMatch" = "匹配时禁用回退" -"disableFallbackIfMatchDesc" = "当DNS服务器的匹配域名列表命中时,禁用回退DNS查询" "strategy" = "查询策略" "strategyDesc" = "解析域名的总体策略" "add" = "添加服务器" "edit" = "编辑服务器" "domains" = "域" "expectIPs" = "预期 IP" -"unexpectIPs" = "意外IP" -"useSystemHosts" = "使用系统Hosts" -"useSystemHostsDesc" = "使用已安装系统的hosts文件" -"usePreset" = "使用模板" -"dnsPresetTitle" = "DNS模板" -"dnsPresetFamily" = "家庭" [pages.xray.fakedns] "add" = "添加假 DNS" @@ -534,31 +460,19 @@ "poolSize" = "池大小" [pages.settings.security] -"admin" = "管理员凭据" -"twoFactor" = "双重验证" -"twoFactorEnable" = "启用2FA" -"twoFactorEnableDesc" = "增加额外的验证层以提高安全性。" -"twoFactorModalSetTitle" = "启用双重认证" -"twoFactorModalDeleteTitle" = "停用双重认证" -"twoFactorModalSteps" = "要设定双重认证,请执行以下步骤:" -"twoFactorModalFirstStep" = "1. 在认证应用程序中扫描此QR码,或复制QR码附近的令牌并粘贴到应用程序中" -"twoFactorModalSecondStep" = "2. 输入应用程序中的验证码" -"twoFactorModalRemoveStep" = "输入应用程序中的验证码以移除双重认证。" -"twoFactorModalChangeCredentialsTitle" = "更改凭据" -"twoFactorModalChangeCredentialsStep" = "输入应用程序中的代码以更改管理员凭据。" -"twoFactorModalSetSuccess" = "双因素认证已成功建立" -"twoFactorModalDeleteSuccess" = "双因素认证已成功删除" -"twoFactorModalError" = "验证码错误" +"admin" = "管理员" +"secret" = "安全令牌" +"loginSecurity" = "登录安全" +"loginSecurityDesc" = "添加额外的身份验证以提高安全性" +"secretToken" = "安全令牌" +"secretTokenDesc" = "请将此令牌存储在安全的地方。此令牌用于登录,丢失无法恢复。" [pages.settings.toasts] -"modifySettings" = "参数已更改。" -"getSettings" = "获取参数时发生错误" -"modifyUserError" = "更改管理员凭据时发生错误。" -"modifyUser" = "您已成功更改管理员凭据。" +"modifySettings" = "修改设置" +"getSettings" = "获取设置" +"modifyUser" = "修改管理员" "originalUserPassIncorrect" = "原用户名或原密码错误" "userPassMustBeNotEmpty" = "新用户名和新密码不能为空" -"getOutboundTrafficError" = "获取出站流量错误" -"resetOutboundTrafficError" = "重置出站流量错误" [tgbot] "keyboardClosed" = "❌ 自定义键盘已关闭!" @@ -582,23 +496,20 @@ [tgbot.commands] "unknown" = "❗ 未知命令" -"pleaseChoose" = "👇 请选择:\r\n" +"pleaseChoose" = "👇请〔按照需求〕选择下方按钮:\r\n" "help" = "🤖 欢迎使用本机器人!它旨在为您提供来自服务器的特定数据,并允许您进行必要的修改。\r\n\r\n" "start" = "👋 你好,{{ .Firstname }}。\r\n" "welcome" = "🤖 欢迎来到 {{ .Hostname }} 管理机器人。\r\n" "status" = "✅ 机器人正常运行!" "usage" = "❗ 请输入要搜索的文本!" "getID" = "🆔 您的 ID 为:{{ .ID }}" -"helpAdminCommands" = "要重新启动 Xray Core:\r\n/restart\r\n\r\n要搜索客户电子邮件:\r\n/usage [电子邮件]\r\n\r\n要搜索入站(带有客户统计数据):\r\n/inbound [备注]\r\n\r\nTelegram聊天ID:\r\n/id" +"helpAdminCommands" = "要重新启动 Xray Core:\r\n/restart force\r\n\r\n要搜索客户电子邮件:\r\n/usage [电子邮件]\r\n\r\n要搜索入站(带有客户统计数据):\r\n/inbound [备注]\r\n\r\nTelegram聊天ID:\r\n/id" +"helpAdminCommands" = "要重新启动Xray Core:\r\n/restart force\r\n\r\n要搜索客户电子邮件:\r\n/usage [电子邮件]\r\n\r\n要搜索入站(带有客户统计数据):\r\n/inbound [备注]\r\n\r\n要获取Telegram聊天ID:\r\n/id" "helpClientCommands" = "要搜索统计数据,请使用以下命令:\r\n/usage [电子邮件]\r\n\r\nTelegram聊天ID:\r\n/id" -"restartUsage" = "\r\n\r\n/restart" +"restartUsage" = "\r\n\r\n/restart force" "restartSuccess" = "✅ 操作成功!" "restartFailed" = "❗ 操作错误。\r\n\r\n错误: {{ .Error }}." "xrayNotRunning" = "❗ Xray Core 未运行。" -"startDesc" = "显示主菜单" -"helpDesc" = "机器人帮助" -"statusDesc" = "检查机器人状态" -"idDesc" = "显示您的 Telegram ID" [tgbot.messages] "cpuThreshold" = "🔴 CPU 使用率为 {{ .Percent }}%,超过阈值 {{ .Threshold }}%" @@ -609,7 +520,7 @@ "report" = "🕰 定时报告:{{ .RunTime }}\r\n" "datetime" = "⏰ 日期时间:{{ .DateTime }}\r\n" "hostname" = "💻 主机名:{{ .Hostname }}\r\n" -"version" = "🚀 X-UI 版本:{{ .Version }}\r\n" +"version" = "🚀 3X-UI 版本:{{ .Version }}\r\n" "xrayVersion" = "📡 Xray 版本: {{ .XrayVersion }}\r\n" "ipv6" = "🌐 IPv6:{{ .IPv6 }}\r\n" "ipv4" = "🌐 IPv4:{{ .IPv4 }}\r\n" @@ -632,7 +543,7 @@ "active" = "💡 激活:{{ .Enable }}\r\n" "enabled" = "🚨 已启用:{{ .Enable }}\r\n" "online" = "🌐 连接状态:{{ .Status }}\r\n" -"email" = "📧 邮箱:{{ .Email }}\r\n" +"email" = "📧 邮箱(用户):{{ .Email }}\r\n" "upload" = "🔼 上传↑:{{ .Upload }}\r\n" "download" = "🔽 下载↓:{{ .Download }}\r\n" "total" = "📊 总计:{{ .UpDown }} / {{ .Total }}\r\n" @@ -647,26 +558,6 @@ "yes" = "✅ 是的" "no" = "❌ 没有" -"received_id" = "🔑📥 ID 已更新。" -"received_password" = "🔑📥 密码已更新。" -"received_email" = "📧📥 邮箱已更新。" -"received_comment" = "💬📥 评论已更新。" -"id_prompt" = "🔑 默认 ID: {{ .ClientId }}\n\n请输入您的 ID。" -"pass_prompt" = "🔑 默认密码: {{ .ClientPassword }}\n\n请输入您的密码。" -"email_prompt" = "📧 默认邮箱: {{ .ClientEmail }}\n\n请输入您的邮箱。" -"comment_prompt" = "💬 默认评论: {{ .ClientComment }}\n\n请输入您的评论。" -"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日期: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 备注: {{ .ClientComment }}\n\n你现在可以将客户添加到入站了!" -"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密码: {{ .ClientPass }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日期: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 备注: {{ .ClientComment }}\n\n你现在可以将客户添加到入站了!" -"cancel" = "❌ 进程已取消!\n\n您可以随时使用 /start 重新开始。 🔄" -"error_add_client" = "⚠️ 错误:\n\n {{ .error }}" -"using_default_value" = "好的,我会使用默认值。 😊" -"incorrect_input" ="您的输入无效。\n短语应连续输入,不能有空格。\n正确示例: aaaaaa\n错误示例: aaa aaa 🚫" -"AreYouSure" = "你确定吗?🤔" -"SuccessResetTraffic" = "📧 邮箱: {{ .ClientEmail }}\n🏁 结果: ✅ 成功" -"FailedResetTraffic" = "📧 邮箱: {{ .ClientEmail }}\n🏁 结果: ❌ 失败 \n\n🛠️ 错误: [ {{ .ErrorMessage }} ]" -"FinishProcess" = "🔚 所有客户的流量重置已完成。" - - [tgbot.buttons] "closeKeyboard" = "❌ 关闭键盘" "cancel" = "❌ 取消" @@ -677,12 +568,12 @@ "confirmRemoveTGUser" = "✅ 确认移除 Telegram 用户?" "confirmToggle" = "✅ 确认启用/禁用用户?" "dbBackup" = "获取数据库备份" -"serverUsage" = "服务器使用情况" +"serverUsage" = "服务器状态" "getInbounds" = "获取入站信息" "depleteSoon" = "即将耗尽" "clientUsage" = "获取使用情况" "onlines" = "在线客户端" -"commands" = "命令" +"commands" = "常用命令" "refresh" = "🔄 刷新" "clearIPs" = "❌ 清除 IP" "removeTGUser" = "❌ 移除 Telegram 用户" @@ -694,25 +585,13 @@ "ipLimit" = "🔢 IP 限制" "setTGUser" = "👤 设置 Telegram 用户" "toggle" = "🔘 启用/禁用" -"custom" = "🔢 风俗" +"custom" = "🔢 自定义输入" "confirmNumber" = "✅ 确认: {{ .Num }}" "confirmNumberAdd" = "✅ 确认添加:{{ .Num }}" "limitTraffic" = "🚧 流量限制" "getBanLogs" = "禁止日志" "allClients" = "所有客户" -"addClient" = "添加客户" -"submitDisable" = "提交为禁用 ☑️" -"submitEnable" = "提交为启用 ✅" -"use_default" = "🏷️ 使用默认" -"change_id" = "⚙️🔑 ID" -"change_password" = "⚙️🔑 密码" -"change_email" = "⚙️📧 邮箱" -"change_comment" = "⚙️💬 评论" -"ResetAllTraffics" = "重置所有流量" -"SortedTrafficUsageReport" = "排序的流量使用报告" - - [tgbot.answers] "successfulOperation" = "✅ 成功!" "errorOperation" = "❗ 操作错误。" From 3cc434dd1b3978a22065137399a368a1be50cbcc Mon Sep 17 00:00:00 2001 From: xinsuiyuandong Date: Sat, 12 Jul 2025 04:13:35 +0800 Subject: [PATCH 3/4] v2.6.2 v2.6.2 --- web/html/index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/html/index.html b/web/html/index.html index db678cd6..8f3a44ad 100644 --- a/web/html/index.html +++ b/web/html/index.html @@ -216,19 +216,19 @@ - + v{{ .cur_ver }} - + - @XrayUI + TG私聊交流 - + - {{ i18n "pages.index.documentation" }} + 〔3X-UI〕中文交流群 @@ -784,4 +784,4 @@ }, }); -{{ template "page/body_end" .}} \ No newline at end of file +{{ template "page/body_end" .}} From dbbab2838b8b35b99451f4b3afa2bc2dc59ba8eb Mon Sep 17 00:00:00 2001 From: xinsuiyuandong Date: Sat, 12 Jul 2025 04:16:06 +0800 Subject: [PATCH 4/4] v2.6.2 v2.6.2 --- web/html/navigation.html | 167 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 web/html/navigation.html diff --git a/web/html/navigation.html b/web/html/navigation.html new file mode 100644 index 00000000..389c0066 --- /dev/null +++ b/web/html/navigation.html @@ -0,0 +1,167 @@ + + + + + + 实用导航&技巧 + + + + +
+
+

一、【3x-ui】中文交流群:https://t.me/XUI_CN

+

【3x-ui】详细安装流程步骤:https://xeefei.github.io/xufei/2024/05/3x-ui/

+ +

二、判断VPS服务器的IP是否【送中】?

+

***点击打开:https://music.youtube.com/,能正常打开访问,就代表【没送中】,反之就是送中了。

+

***如果送中了如何解决去【拉回来】?

+

1:关闭/取消登录了谷歌账户的APP定位权限/授权;2:将常用的一个谷歌账号的位置记录功能打开;3:在电脑上打开Chrome/谷歌浏览器,登录开了位置记录功能的谷歌账号,安装Location Guard拓展插件https://chrome.google.com/webstore/detail/location-guard/cfohepagpmnodfdmjliccbbigdkfcgia(也可在其他支持此插件的浏览器使用);4:打开Location Guard插件,选择Fixed Location,并在给出的地图上单击,即可标记上你想要IP所处的国家/地区 +Google IP定位错误,使用Location Guard修改;5:转换到Options选项,Default level默认设置为Use fixed location;6:打开谷歌地图google.com/maps,点击右下角定位授权图标,使google maps获取当前“我的GPS位置” +Google IP定位错误,使用Location Guard修改GPS位置地址;7:谷歌搜索my ip,即可看到谷歌IP定位到了刚才地图上标记的位置;8:在此网页向谷歌报告IP问题:https://support.google.com/websearch/workflow/9308722

+ +

三、在自己的VPS服务器部署【订阅转换】功能

+

如何把vless/vmess等协议转换成Clash/Surge等软件支持的格式? + 1、进入脚本输入x-ui命令调取面板,选择第【24】选项安装订阅转换模块, + 2、等待安装【订阅转换】成功之后,访问地址:你的IP:18080(端口号)进行转换, + 3、因为在转换过程中需要调取后端API,所以请确保端口25500是打开放行的, +4、在得到【转换链接】之后,只要你的VPS服务器25500端口是能ping通的,就能导入Clash/Surge等软件成功下载配置, +5、此功能集成到3x-ui面板中,是为了保证安全,通过调取24选项把【订阅转换】功能部署在自己的VPS中,不会造成链接泄露。

+ +

四、如何保护自己的IP不被墙被封?

+

1、使用的代理协议要安全,加密是必备,推荐使用vless+reality+vision协议组合, +2、因为有时节点会共享,在不同的地区,多个省份之间不要共同连接同一个IP, +3、连接同一个IP就算了,不要同一个端口,不要同IP+同端口到处漫游,要分开, +4、同一台VPS,不要在一天内一直大流量去下载东西使用,不要流量过高要切换, +5、创建【入站协议】的时候,尽量用【高位端口】,比如40000--65000之间的端口号。 +提醒:为什么在特殊时期,比如:两会,春节等被封得最严重最惨? +尼玛同一个IP+同一个端口号,多个省份去漫游,跟开飞机场一样!不封你,封谁的IP和端口? +总结:不要多终端/多省份/多个朋友/共同使用同一个IP和端口号!使用3x-ui多创建几个【入站】, +多做几条备用,各用各的!各行其道才比较安全!GFW的思维模式是干掉机场,机场的特征个人用户不要去沾染,自然IP就保护好了。

+ +

五、检测IP纯净度的方法:

+

网址:https://scamalytics.com/,输入IP进行检测,看【欺诈分数】,分数越高IP越脏。

+ +

六、常见的软件工具:

+
    +

    1、Windows系统v2rayN:https://github.com/2dust/v2rayN

    +

    2、安卓手机版【v2rayNG】:https://github.com/2dust/v2rayNG

    +

    3、苹果手机IOS【小火箭】:https://apple02.com/

    +

    4、苹果MacOS电脑【Clash Verge】:https://github.com/clash-verge-rev/clash-verge-rev/releases

    +
+ +

七、查看节点【指定端口】的网络连接数/命令:

+

netstat -ntu | grep :节点端口 | grep ESTABLISHED | awk '{print $5}'

+ +

八、用3x-ui如何实现【自己偷自己】?

+

其实很简单,只要你为面板设置了证书, + 开启了HTTPS登录,就可以将3x-ui自身作为web server, + 无需Nginx等,这里给一个示例: + 其中目标网站(Dest)请填写面板监听端口, + 可选域名(SNI)填写面板登录域名, + 如果您使用其他web server(如nginx)等, + 将目标网站改为对应监听端口也可。 + 需要说明的是,如果您处于白名单地区,自己“偷”自己并不适合你;其次,可选域名一项实际上可以填写任意SNI,只要客户端保持一致即可,不过并不推荐这样做。

+ +

九、【接码】网站:

+

网址:https://sms-activate.org/cn,直接注册账号购买。

+ +

十、一些MJJ经常逛的网站和群组:

+
    +

    1、NodeSeek论坛:https://www.nodeseek.com/

    +

    2、V2EX论坛:https://www.v2ex.com/

    +

    3、搬瓦工TG群:https://t.me/BWHOfficial

    +

    4、Xray的官方群:https://t.me/projectXray

    +

    5、Dmit交流群:https://t.me/DmitChat

    +

    6、白丝云用户群:https://t.me/+VHZLKELTQyzPNgOV

    +

    7、NameSilo域名注册:https://www.namesilo.com/

    +
+ +

十一、若此项目对你有帮助,你正想购买VPS的话,可以走一下我的AFF:

+
    +

    1、搬瓦工GIA线路:https://bandwagonhost.com/aff.php?aff=75015

    +

    2、Dmit高端GIA:https://www.dmit.io/aff.php?aff=9326

    +

    3、白丝云【4837】:https://cloudsilk.io/aff.php?aff=706

    +
+ +

十二、若需要进行GV保号,请主动发信息到:+1 215 346 6666

+ +

十三、项目〔声明和注意〕

+
    +

    1、声明: 此项目仅供个人学习、交流使用,请遵守当地法律法规,勿用于非法用途;请勿用于生产环境;

    +

    2、注意: 在使用此项目和〔教程〕过程中,若因违反以上声明使用规则而产生的一切后果由使用者自负。

    +
+
+ +