package app import ( "os" "sort" "strings" ) // --------------------------------------------------------------------- // EN: `loadList` loads list from storage or config. // RU: `loadList` - загружает list из хранилища или конфига. // --------------------------------------------------------------------- func loadList(path string) []string { data, err := os.ReadFile(path) if err != nil { return nil } var out []string for _, ln := range strings.Split(string(data), "\n") { ln = strings.TrimSpace(strings.SplitN(ln, "#", 2)[0]) if ln == "" { continue } out = append(out, ln) } return out } // --------------------------------------------------------------------- // EN: `loadSmartDNSWildcardDomains` loads SmartDNS wildcard domains from canonical API state. // RU: `loadSmartDNSWildcardDomains` - загружает wildcard-домены SmartDNS из каноничного API-состояния. // --------------------------------------------------------------------- func loadSmartDNSWildcardDomains(logf func(string, ...any)) []string { out, source := loadSmartDNSWildcardDomainsState(logf) sort.Strings(out) if logf != nil { logf("smartdns wildcards loaded: source=%s count=%d", source, len(out)) } return out } // --------------------------------------------------------------------- // EN: `isGoogleLike` checks whether google like is true. // RU: `isGoogleLike` - проверяет, является ли google like истинным условием. // --------------------------------------------------------------------- func isGoogleLike(d string) bool { low := strings.ToLower(d) for _, base := range googleLikeDomains { if low == base || strings.HasSuffix(low, "."+base) { return true } } return false } // --------------------------------------------------------------------- // EN: `readNonEmptyLines` reads non empty lines from input data. // RU: `readNonEmptyLines` - читает non empty lines из входных данных. // --------------------------------------------------------------------- func readNonEmptyLines(path string) []string { data, err := os.ReadFile(path) if err != nil { return nil } var out []string for _, ln := range strings.Split(string(data), "\n") { ln = strings.TrimSpace(ln) if ln != "" { out = append(out, ln) } } return out } func writeLines(path string, lines []string) error { if len(lines) == 0 { return os.WriteFile(path, []byte{}, 0o644) } return os.WriteFile(path, []byte(strings.Join(lines, "\n")+"\n"), 0o644) } func writeMapPairs(path string, pairs [][2]string) error { if len(pairs) == 0 { return os.WriteFile(path, []byte{}, 0o644) } lines := make([]string, 0, len(pairs)) for _, p := range pairs { lines = append(lines, p[0]+"\t"+p[1]) } return os.WriteFile(path, []byte(strings.Join(lines, "\n")+"\n"), 0o644) } func countDomainsFromPairs(pairs [][2]string) int { seen := make(map[string]struct{}) for _, p := range pairs { if len(p) < 2 { continue } d := strings.TrimSpace(p[1]) if d == "" || strings.HasPrefix(d, "[") { continue } seen[d] = struct{}{} } return len(seen) } func wildcardHostIPMap(pairs [][2]string) map[string][]string { hostToIPs := make(map[string]map[string]struct{}) for _, p := range pairs { if len(p) < 2 { continue } ip := strings.TrimSpace(p[0]) host := strings.TrimSpace(p[1]) if ip == "" || host == "" || strings.HasPrefix(host, "[") { continue } ips := hostToIPs[host] if ips == nil { ips = map[string]struct{}{} hostToIPs[host] = ips } ips[ip] = struct{}{} } out := make(map[string][]string, len(hostToIPs)) for host, ipset := range hostToIPs { ips := make([]string, 0, len(ipset)) for ip := range ipset { ips = append(ips, ip) } sort.Strings(ips) out[host] = ips } return out } // --------------------------------------------------------------------- // EN: `countDomainsFromMap` counts items for domains from map. // RU: `countDomainsFromMap` - считает элементы для domains from map. // --------------------------------------------------------------------- func countDomainsFromMap(path string) int { data, err := os.ReadFile(path) if err != nil { return 0 } seen := make(map[string]struct{}) for _, ln := range strings.Split(string(data), "\n") { ln = strings.TrimSpace(ln) if ln == "" { continue } fields := strings.Fields(ln) if len(fields) < 2 { continue } d := fields[1] if strings.HasPrefix(d, "[") { continue } seen[d] = struct{}{} } return len(seen) }