github.com/yaling888/clash@v1.53.0/component/geodata/geodata.go (about)

     1  package geodata
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/phuslu/log"
     9  
    10  	"github.com/yaling888/clash/component/geodata/router"
    11  )
    12  
    13  type loader struct {
    14  	LoaderImplementation
    15  }
    16  
    17  func (l *loader) LoadGeoSite(list string) ([]*router.Domain, error) {
    18  	return l.LoadGeoSiteWithAttr("geosite.dat", list)
    19  }
    20  
    21  func (l *loader) LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*router.Domain, error) {
    22  	parts := strings.Split(siteWithAttr, "@")
    23  	if len(parts) == 0 {
    24  		return nil, errors.New("empty rule")
    25  	}
    26  	list := strings.TrimSpace(parts[0])
    27  	attrVal := parts[1:]
    28  
    29  	if len(list) == 0 {
    30  		return nil, fmt.Errorf("empty listname in rule: %s", siteWithAttr)
    31  	}
    32  
    33  	domains, err := l.LoadSite(file, list)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	attrs := parseAttrs(attrVal)
    39  	if attrs.IsEmpty() {
    40  		if strings.Contains(siteWithAttr, "@") {
    41  			log.Warn().Str("attr", siteWithAttr).Msg("[GeoSite] empty attribute list")
    42  		}
    43  		return domains, nil
    44  	}
    45  
    46  	filteredDomains := make([]*router.Domain, 0, len(domains))
    47  	hasAttrMatched := false
    48  	for _, domain := range domains {
    49  		if attrs.Match(domain) {
    50  			hasAttrMatched = true
    51  			filteredDomains = append(filteredDomains, domain)
    52  		}
    53  	}
    54  	if !hasAttrMatched {
    55  		log.Warn().Str("attr", siteWithAttr).Msg("[GeoSite] attribute match no rule")
    56  	}
    57  
    58  	return filteredDomains, nil
    59  }
    60  
    61  func (l *loader) LoadGeoIP(country string) ([]*router.CIDR, error) {
    62  	return l.LoadIP("geoip.dat", country)
    63  }
    64  
    65  var loaders map[string]func() LoaderImplementation
    66  
    67  func RegisterGeoDataLoaderImplementationCreator(name string, loader func() LoaderImplementation) {
    68  	if loaders == nil {
    69  		loaders = map[string]func() LoaderImplementation{}
    70  	}
    71  	loaders[name] = loader
    72  }
    73  
    74  func getGeoDataLoaderImplementation(name string) (LoaderImplementation, error) {
    75  	if geoLoader, ok := loaders[name]; ok {
    76  		return geoLoader(), nil
    77  	}
    78  	return nil, fmt.Errorf("unable to locate GeoData loader %s", name)
    79  }
    80  
    81  func GetGeoDataLoader(name string) (Loader, error) {
    82  	loadImpl, err := getGeoDataLoaderImplementation(name)
    83  	if err == nil {
    84  		return &loader{loadImpl}, nil
    85  	}
    86  	return nil, err
    87  }