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

     1  package standard
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strings"
     8  
     9  	"google.golang.org/protobuf/proto"
    10  
    11  	"github.com/yaling888/clash/component/geodata"
    12  	"github.com/yaling888/clash/component/geodata/router"
    13  	C "github.com/yaling888/clash/constant"
    14  )
    15  
    16  func ReadFile(path string) ([]byte, error) {
    17  	reader, err := os.Open(path)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	defer func(reader *os.File) {
    22  		_ = reader.Close()
    23  	}(reader)
    24  
    25  	return io.ReadAll(reader)
    26  }
    27  
    28  func ReadAsset(file string) ([]byte, error) {
    29  	return ReadFile(C.Path.Resolve(file))
    30  }
    31  
    32  func loadIP(filename, country string) ([]*router.CIDR, error) {
    33  	geoipBytes, err := ReadAsset(filename)
    34  	if err != nil {
    35  		return nil, fmt.Errorf("failed to open file: %s, base error: %w", filename, err)
    36  	}
    37  	var geoipList router.GeoIPList
    38  	if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	for _, geoip := range geoipList.Entry {
    43  		if strings.EqualFold(geoip.CountryCode, country) {
    44  			return geoip.Cidr, nil
    45  		}
    46  	}
    47  
    48  	return nil, fmt.Errorf("country not found in %s%s%s", filename, ": ", country)
    49  }
    50  
    51  func loadSite(filename, list string) ([]*router.Domain, error) {
    52  	geositeBytes, err := ReadAsset(filename)
    53  	if err != nil {
    54  		return nil, fmt.Errorf("failed to open file: %s, base error: %w", filename, err)
    55  	}
    56  	var geositeList router.GeoSiteList
    57  	if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	for _, site := range geositeList.Entry {
    62  		if strings.EqualFold(site.CountryCode, list) {
    63  			return site.Domain, nil
    64  		}
    65  	}
    66  
    67  	return nil, fmt.Errorf("list not found in %s%s%s", filename, ": ", list)
    68  }
    69  
    70  type standardLoader struct{}
    71  
    72  func (d standardLoader) LoadSite(filename, list string) ([]*router.Domain, error) {
    73  	return loadSite(filename, list)
    74  }
    75  
    76  func (d standardLoader) LoadIP(filename, country string) ([]*router.CIDR, error) {
    77  	return loadIP(filename, country)
    78  }
    79  
    80  func init() {
    81  	geodata.RegisterGeoDataLoaderImplementationCreator("standard", func() geodata.LoaderImplementation {
    82  		return standardLoader{}
    83  	})
    84  }