package subscription import ( "strings" "gopkg.in/yaml.v3" "gitea.epss.net.cn/klesh/ss/internal/yamlutil" ) // convertContent converts subscription content to Clash YAML format if // needed. Direct port of SubscriptionManager._convert_content. func convertContent(content string) string { // Check if content is already valid YAML with a "proxies" key. var parsed map[string]interface{} if err := yamlutil.Unmarshal([]byte(content), &parsed); err == nil { if _, ok := parsed["proxies"]; ok { return content } } var lines []string // Try treating as Base64-encoded list first. if !strings.Contains(content, "ss://") && !strings.Contains(content, "trojan://") && !strings.Contains(content, "vless://") { if decoded, err := base64StdDecodeWithPadding(content); err == nil { lines = splitLines(decoded) } } // Fallback to reading lines directly. if len(lines) == 0 { lines = splitLines(content) } var proxies []map[string]interface{} for _, line := range lines { line = strings.TrimSpace(line) if line == "" { continue } var proxy map[string]interface{} switch { case strings.HasPrefix(line, "ss://"): proxy = parseSS(line) case strings.HasPrefix(line, "trojan://"): proxy = parseTrojan(line) case strings.HasPrefix(line, "vless://"): proxy = parseVless(line) } if proxy != nil { proxies = append(proxies, proxy) } } if len(proxies) > 0 { out, err := yaml.Marshal(map[string]interface{}{"proxies": proxies}) if err == nil { return string(out) } } return content } // splitLines mirrors Python's str.splitlines(): split on \n, \r\n, and \r, // without keeping the line endings, and without producing a trailing empty // element for a final newline. func splitLines(s string) []string { s = strings.ReplaceAll(s, "\r\n", "\n") s = strings.ReplaceAll(s, "\r", "\n") s = strings.TrimSuffix(s, "\n") if s == "" { return nil } return strings.Split(s, "\n") }