From 6041d10e3d5d8b0021dd596bdee8f0064a495f80 Mon Sep 17 00:00:00 2001 From: Ilya Kryuchkov <42733472+kr-ilya@users.noreply.github.com> Date: Mon, 5 Jan 2026 07:54:56 +0300 Subject: [PATCH] Refactor code and fix linter warnings (#3627) * refactor: use any instead of empty interface * refactor: code cleanup --- main.go | 6 +++--- sub/subJsonService.go | 6 +++--- sub/subService.go | 11 ++++------- util/crypto/crypto.go | 3 +-- util/ldap/ldap.go | 38 ++++++++++++++++++++++++++---------- util/random/random.go | 6 +++--- util/reflect_util/reflect.go | 4 ++-- util/sys/sys_darwin.go | 4 ++-- web/controller/server.go | 6 +++--- web/global/global.go | 2 +- web/job/clear_logs_job.go | 2 +- web/service/server.go | 4 ++-- web/web.go | 2 +- web/websocket/hub.go | 6 +++--- web/websocket/notifier.go | 6 +++--- xray/api.go | 2 +- 16 files changed, 61 insertions(+), 47 deletions(-) diff --git a/main.go b/main.go index e2af2beb..8096616c 100644 --- a/main.go +++ b/main.go @@ -80,8 +80,8 @@ func runWebServer() { // --- FIX FOR TELEGRAM BOT CONFLICT (409): Stop bot before restart --- service.StopBot() - // -- - + // -- + err := server.Stop() if err != nil { logger.Debug("Error stopping web server:", err) @@ -113,7 +113,7 @@ func runWebServer() { // --- FIX FOR TELEGRAM BOT CONFLICT (409) on full shutdown --- service.StopBot() // ------------------------------------------------------------ - + server.Stop() subServer.Stop() log.Println("Shutting down servers.") diff --git a/sub/subJsonService.go b/sub/subJsonService.go index 86a7a405..8222491a 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -4,6 +4,7 @@ import ( _ "embed" "encoding/json" "fmt" + "maps" "strings" "github.com/mhsanaei/3x-ui/v2/database/model" @@ -197,9 +198,8 @@ func (s *SubJsonService) getConfig(inbound *model.Inbound, client model.Client, newOutbounds = append(newOutbounds, s.defaultOutbounds...) newConfigJson := make(map[string]any) - for key, value := range s.configJson { - newConfigJson[key] = value - } + maps.Copy(newConfigJson, s.configJson) + newConfigJson["outbounds"] = newOutbounds newConfigJson["remarks"] = s.SubService.genRemark(inbound, client.Email, extPrxy["remark"].(string)) diff --git a/sub/subService.go b/sub/subService.go index ade871df..e046ebb4 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -484,8 +484,8 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { externalProxies, _ := stream["externalProxy"].([]any) if len(externalProxies) > 0 { - links := "" - for index, externalProxy := range externalProxies { + links := make([]string, 0, len(externalProxies)) + for _, externalProxy := range externalProxies { ep, _ := externalProxy.(map[string]any) newSecurity, _ := ep["forceTls"].(string) dest, _ := ep["dest"].(string) @@ -511,12 +511,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) - if index > 0 { - links += "\n" - } - links += url.String() + links = append(links, url.String()) } - return links + return strings.Join(links, "\n") } link := fmt.Sprintf("vless://%s@%s:%d", uuid, address, port) diff --git a/util/crypto/crypto.go b/util/crypto/crypto.go index 05d088a8..2db5bd83 100644 --- a/util/crypto/crypto.go +++ b/util/crypto/crypto.go @@ -13,6 +13,5 @@ func HashPasswordAsBcrypt(password string) (string, error) { // CheckPasswordHash verifies if the given password matches the bcrypt hash. func CheckPasswordHash(hash, password string) bool { - err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) - return err == nil + return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil } diff --git a/util/ldap/ldap.go b/util/ldap/ldap.go index 795d0e23..1b9faa53 100644 --- a/util/ldap/ldap.go +++ b/util/ldap/ldap.go @@ -24,13 +24,22 @@ type Config struct { // FetchVlessFlags returns map[email]enabled func FetchVlessFlags(cfg Config) (map[string]bool, error) { addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port) - var conn *ldap.Conn - var err error + + scheme := "ldap" if cfg.UseTLS { - conn, err = ldap.DialTLS("tcp", addr, &tls.Config{InsecureSkipVerify: false}) - } else { - conn, err = ldap.Dial("tcp", addr) + scheme = "ldaps" } + + ldapURL := fmt.Sprintf("%s://%s", scheme, addr) + + var opts []ldap.DialOpt + if cfg.UseTLS { + opts = append(opts, ldap.DialWithTLSConfig(&tls.Config{ + InsecureSkipVerify: false, + })) + } + + conn, err := ldap.DialURL(ldapURL, opts...) if err != nil { return nil, err } @@ -91,13 +100,22 @@ func FetchVlessFlags(cfg Config) (map[string]bool, error) { // AuthenticateUser searches user by cfg.UserAttr and attempts to bind with provided password. func AuthenticateUser(cfg Config, username, password string) (bool, error) { addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port) - var conn *ldap.Conn - var err error + + scheme := "ldap" if cfg.UseTLS { - conn, err = ldap.DialTLS("tcp", addr, &tls.Config{InsecureSkipVerify: false}) - } else { - conn, err = ldap.Dial("tcp", addr) + scheme = "ldaps" } + + ldapURL := fmt.Sprintf("%s://%s", scheme, addr) + + var opts []ldap.DialOpt + if cfg.UseTLS { + opts = append(opts, ldap.DialWithTLSConfig(&tls.Config{ + InsecureSkipVerify: false, + })) + } + + conn, err := ldap.DialURL(ldapURL, opts...) if err != nil { return false, err } diff --git a/util/random/random.go b/util/random/random.go index c746df63..ddb819c1 100644 --- a/util/random/random.go +++ b/util/random/random.go @@ -18,10 +18,10 @@ var ( // init initializes the character sequences used for random string generation. // It sets up arrays for numbers, lowercase letters, uppercase letters, and combinations. func init() { - for i := 0; i < 10; i++ { + for i := range 10 { numSeq[i] = rune('0' + i) } - for i := 0; i < 26; i++ { + for i := range 26 { lowerSeq[i] = rune('a' + i) upperSeq[i] = rune('A' + i) } @@ -40,7 +40,7 @@ func init() { // Seq generates a random string of length n containing alphanumeric characters (numbers, lowercase and uppercase letters). func Seq(n int) string { runes := make([]rune, n) - for i := 0; i < n; i++ { + for i := range n { idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(allSeq)))) if err != nil { panic("crypto/rand failed: " + err.Error()) diff --git a/util/reflect_util/reflect.go b/util/reflect_util/reflect.go index 1f557e0d..b56f1456 100644 --- a/util/reflect_util/reflect.go +++ b/util/reflect_util/reflect.go @@ -7,7 +7,7 @@ import "reflect" func GetFields(t reflect.Type) []reflect.StructField { num := t.NumField() fields := make([]reflect.StructField, 0, num) - for i := 0; i < num; i++ { + for i := range num { fields = append(fields, t.Field(i)) } return fields @@ -17,7 +17,7 @@ func GetFields(t reflect.Type) []reflect.StructField { func GetFieldValues(v reflect.Value) []reflect.Value { num := v.NumField() fields := make([]reflect.Value, 0, num) - for i := 0; i < num; i++ { + for i := range num { fields = append(fields, v.Field(i)) } return fields diff --git a/util/sys/sys_darwin.go b/util/sys/sys_darwin.go index 6ecc78c0..b635b549 100644 --- a/util/sys/sys_darwin.go +++ b/util/sys/sys_darwin.go @@ -47,11 +47,11 @@ func CPUPercentRaw() (float64, error) { var out [5]uint64 switch len(raw) { case 5 * 8: - for i := 0; i < 5; i++ { + for i := range 5 { out[i] = binary.LittleEndian.Uint64(raw[i*8 : (i+1)*8]) } case 5 * 4: - for i := 0; i < 5; i++ { + for i := range 5 { out[i] = uint64(binary.LittleEndian.Uint32(raw[i*4 : (i+1)*4])) } default: diff --git a/web/controller/server.go b/web/controller/server.go index 5b39700e..d32209e1 100644 --- a/web/controller/server.go +++ b/web/controller/server.go @@ -210,10 +210,10 @@ func (a *ServerController) getXrayLogs(c *gin.Context) { //getting tags for freedom and blackhole outbounds config, err := a.settingService.GetDefaultXrayConfig() if err == nil && config != nil { - if cfgMap, ok := config.(map[string]interface{}); ok { - if outbounds, ok := cfgMap["outbounds"].([]interface{}); ok { + if cfgMap, ok := config.(map[string]any); ok { + if outbounds, ok := cfgMap["outbounds"].([]any); ok { for _, outbound := range outbounds { - if obMap, ok := outbound.(map[string]interface{}); ok { + if obMap, ok := outbound.(map[string]any); ok { switch obMap["protocol"] { case "freedom": if tag, ok := obMap["tag"].(string); ok { diff --git a/web/global/global.go b/web/global/global.go index f72c7bfe..5556b486 100644 --- a/web/global/global.go +++ b/web/global/global.go @@ -17,7 +17,7 @@ var ( type WebServer interface { GetCron() *cron.Cron // Get the cron scheduler GetCtx() context.Context // Get the server context - GetWSHub() interface{} // Get the WebSocket hub (using interface{} to avoid circular dependency) + GetWSHub() any // Get the WebSocket hub (using any to avoid circular dependency) } // SubServer interface defines methods for accessing the subscription server instance. diff --git a/web/job/clear_logs_job.go b/web/job/clear_logs_job.go index 85e0d64a..4ec0ec7f 100644 --- a/web/job/clear_logs_job.go +++ b/web/job/clear_logs_job.go @@ -45,7 +45,7 @@ func (j *ClearLogsJob) Run() { } // Clear log files and copy to previous logs - for i := 0; i < len(logFiles); i++ { + for i := range len(logFiles) { if i > 0 { // Copy to previous logs logFilePrev, err := os.OpenFile(logFilesPrev[i-1], os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) diff --git a/web/service/server.go b/web/service/server.go index 970c5c0f..49f13b91 100644 --- a/web/service/server.go +++ b/web/service/server.go @@ -1205,7 +1205,7 @@ func (s *ServerService) GetNewmldsa65() (any, error) { return keyPair, nil } -func (s *ServerService) GetNewEchCert(sni string) (interface{}, error) { +func (s *ServerService) GetNewEchCert(sni string) (any, error) { // Run the command cmd := exec.Command(xray.GetBinaryPath(), "tls", "ech", "--serverName", sni) var out bytes.Buffer @@ -1223,7 +1223,7 @@ func (s *ServerService) GetNewEchCert(sni string) (interface{}, error) { configList := lines[1] serverKeys := lines[3] - return map[string]interface{}{ + return map[string]any{ "echServerKeys": serverKeys, "echConfigList": configList, }, nil diff --git a/web/web.go b/web/web.go index 7dae08e3..300572a3 100644 --- a/web/web.go +++ b/web/web.go @@ -487,6 +487,6 @@ func (s *Server) GetCron() *cron.Cron { } // GetWSHub returns the WebSocket hub instance. -func (s *Server) GetWSHub() interface{} { +func (s *Server) GetWSHub() any { return s.wsHub } diff --git a/web/websocket/hub.go b/web/websocket/hub.go index 7ee93405..8aa5903c 100644 --- a/web/websocket/hub.go +++ b/web/websocket/hub.go @@ -26,7 +26,7 @@ const ( // Message represents a WebSocket message type Message struct { Type MessageType `json:"type"` - Payload interface{} `json:"payload"` + Payload any `json:"payload"` Time int64 `json:"time"` } @@ -250,7 +250,7 @@ func (h *Hub) broadcastParallel(clients []*Client, message []byte) { } // Broadcast sends a message to all connected clients -func (h *Hub) Broadcast(messageType MessageType, payload interface{}) { +func (h *Hub) Broadcast(messageType MessageType, payload any) { if h == nil { return } @@ -289,7 +289,7 @@ func (h *Hub) Broadcast(messageType MessageType, payload interface{}) { } // BroadcastToTopic sends a message only to clients subscribed to the specific topic -func (h *Hub) BroadcastToTopic(messageType MessageType, payload interface{}) { +func (h *Hub) BroadcastToTopic(messageType MessageType, payload any) { if h == nil { return } diff --git a/web/websocket/notifier.go b/web/websocket/notifier.go index 416adaff..91e52c7c 100644 --- a/web/websocket/notifier.go +++ b/web/websocket/notifier.go @@ -25,7 +25,7 @@ func GetHub() *Hub { } // BroadcastStatus broadcasts server status update to all connected clients -func BroadcastStatus(status interface{}) { +func BroadcastStatus(status any) { hub := GetHub() if hub != nil { hub.Broadcast(MessageTypeStatus, status) @@ -33,7 +33,7 @@ func BroadcastStatus(status interface{}) { } // BroadcastTraffic broadcasts traffic statistics update to all connected clients -func BroadcastTraffic(traffic interface{}) { +func BroadcastTraffic(traffic any) { hub := GetHub() if hub != nil { hub.Broadcast(MessageTypeTraffic, traffic) @@ -41,7 +41,7 @@ func BroadcastTraffic(traffic interface{}) { } // BroadcastInbounds broadcasts inbounds list update to all connected clients -func BroadcastInbounds(inbounds interface{}) { +func BroadcastInbounds(inbounds any) { hub := GetHub() if hub != nil { hub.Broadcast(MessageTypeInbounds, inbounds) diff --git a/xray/api.go b/xray/api.go index 95d8c473..2312d2e4 100644 --- a/xray/api.go +++ b/xray/api.go @@ -116,7 +116,7 @@ func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]an } // Add testseed if provided if testseedVal, ok := user["testseed"]; ok { - if testseedArr, ok := testseedVal.([]interface{}); ok && len(testseedArr) >= 4 { + if testseedArr, ok := testseedVal.([]any); ok && len(testseedArr) >= 4 { testseed := make([]uint32, len(testseedArr)) for i, v := range testseedArr { if num, ok := v.(float64); ok {