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 }