package sub import ( "crypto/tls" "encoding/json" "io" "net/http" "s-ui/logger" "s-ui/util" "strings" ) type Link struct { Type string `json:"type"` Remark string `json:"remark"` Uri string `json:"uri"` } type LinkService struct { } func (s *LinkService) GetLinks(linkJson *json.RawMessage, types string, clientInfo string) []string { links := []Link{} var result []string err := json.Unmarshal(*linkJson, &links) if err != nil { return nil } for _, link := range links { switch link.Type { case "external": result = append(result, link.Uri) case "sub": result = append(result, s.getExternalSub(link.Uri)...) case "local": if types == "all" { result = append(result, s.addClientInfo(link.Uri, clientInfo)) } } } return result } func (s *LinkService) addClientInfo(uri string, clientInfo string) string { protocol := strings.Split(uri, "://") if len(protocol) < 2 { return uri } switch protocol[0] { case "vmess": var vmessJson map[string]interface{} config, err := util.B64StrToByte(protocol[1]) if err != nil { logger.Warning("sub: Error decoding vmess content:", err) return uri } err = json.Unmarshal(config, &vmessJson) if err != nil { logger.Warning("sub: Error decoding vmess content:", err) return uri } vmessJson["ps"] = vmessJson["ps"].(string) + clientInfo result, err := json.MarshalIndent(vmessJson, "", " ") if err != nil { logger.Warning("sub: Error decoding vmess + clientInfo content:", err) return uri } return "vmess://" + util.ByteToB64Str(result) default: return uri + clientInfo } } func (s *LinkService) getExternalSub(url string) []string { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr} // Make the HTTP request response, err := client.Get(url) if err != nil { logger.Warning("sub: Error making HTTP request:", err) return nil } defer response.Body.Close() // Read the response body body, err := io.ReadAll(response.Body) if err != nil { logger.Warning("sub: Error reading response body:", err) return nil } // Convert if the content is Base64 encoded links := util.StrOrBase64Encoded(string(body)) return strings.Split(links, "\n") }