package generator import ( "fmt" "net/url" "strconv" "strings" ) // GroupDefinition captures parsed custom proxy group metadata. type GroupDefinition struct { Name string Type string Proxies []string UseProviders []string URL string Interval *int Timeout *int Tolerance *int Extras map[string]string } // ParseGroupDefinition converts a custom group definition string into a GroupDefinition. func ParseGroupDefinition(definition string) (*GroupDefinition, error) { values, err := url.ParseQuery(definition) if err != nil { return nil, fmt.Errorf("invalid group definition: %v", err) } name := strings.TrimSpace(values.Get("name")) if name == "" { return nil, fmt.Errorf("custom group missing name") } typeVal := strings.TrimSpace(values.Get("type")) if typeVal == "" { typeVal = "select" } group := &GroupDefinition{ Name: name, Type: typeVal, Extras: make(map[string]string), } if proxyStr := strings.TrimSpace(values.Get("proxies")); proxyStr != "" { parts := strings.Split(proxyStr, ",") for _, entry := range parts { entry = strings.TrimSpace(entry) if entry != "" { group.Proxies = append(group.Proxies, entry) } } } if useStr := strings.TrimSpace(values.Get("use")); useStr != "" { parts := strings.Split(useStr, ",") for _, entry := range parts { entry = strings.TrimSpace(entry) if entry != "" { group.UseProviders = append(group.UseProviders, entry) } } } if raw := strings.TrimSpace(values.Get("url")); raw != "" { group.URL = raw } if raw := strings.TrimSpace(values.Get("interval")); raw != "" { if n, err := strconv.Atoi(raw); err == nil && n >= 0 { group.Interval = &n } else { return nil, fmt.Errorf("invalid interval for group %s: %v", name, err) } } if raw := strings.TrimSpace(values.Get("timeout")); raw != "" { if n, err := strconv.Atoi(raw); err == nil && n >= 0 { group.Timeout = &n } else { return nil, fmt.Errorf("invalid timeout for group %s: %v", name, err) } } if raw := strings.TrimSpace(values.Get("tolerance")); raw != "" { if n, err := strconv.Atoi(raw); err == nil && n >= 0 { group.Tolerance = &n } else { return nil, fmt.Errorf("invalid tolerance for group %s: %v", name, err) } } for key, vals := range values { if key == "name" || key == "type" || key == "proxies" || key == "use" || key == "url" || key == "interval" || key == "timeout" || key == "tolerance" { continue } if len(vals) == 0 { continue } value := strings.TrimSpace(vals[len(vals)-1]) if value == "" { continue } group.Extras[strings.ReplaceAll(key, "_", "-")] = value } return group, nil }