diff --git a/rule/common/base.go b/rule/common/base.go index 97a46eb7..381eab82 100644 --- a/rule/common/base.go +++ b/rule/common/base.go @@ -10,8 +10,8 @@ import ( var ( errPayload = errors.New("payload error") - - noResolve = "no-resolve" + initFlag bool + noResolve = "no-resolve" ) type Base struct { diff --git a/rule/common/geosite.go b/rule/common/geosite.go index 3e6fbe42..211cb570 100644 --- a/rule/common/geosite.go +++ b/rule/common/geosite.go @@ -2,6 +2,9 @@ package common import ( "fmt" + "io" + "net/http" + "os" "github.com/Dreamacro/clash/component/geodata" "github.com/Dreamacro/clash/component/geodata/router" @@ -50,6 +53,14 @@ func (gs *GEOSITE) GetRecodeSize() int { } func NewGEOSITE(country string, adapter string) (*GEOSITE, error) { + if !initFlag { + if err := initGeoSite(); err != nil { + log.Errorln("can't initial GeoSite: %s", err) + return nil, err + } + initFlag = true + } + matcher, size, err := geodata.LoadGeoSiteMatcher(country) if err != nil { return nil, fmt.Errorf("load GeoSite data error, %s", err.Error()) @@ -69,3 +80,45 @@ func NewGEOSITE(country string, adapter string) (*GEOSITE, error) { } var _ C.Rule = (*GEOSITE)(nil) + +func downloadGeoSite(path string) (err error) { + resp, err := http.Get(C.GeoSiteUrl) + if err != nil { + return + } + defer resp.Body.Close() + + f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + return err + } + defer f.Close() + _, err = io.Copy(f, resp.Body) + + return err +} + +func initGeoSite() error { + if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) { + log.Infoln("Can't find GeoSite.dat, start download") + if err := downloadGeoSite(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) + } + log.Infoln("Download GeoSite.dat finish") + } + if !initFlag { + err := geodata.Verify(C.GeositeName) + if err != nil { + log.Warnln("GeoSite.dat invalid, remove and download: %s", err) + if err := os.Remove(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't remove invalid GeoSite.dat: %s", err.Error()) + } + if err := downloadGeoSite(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) + } + } else { + initFlag = true + } + } + return nil +} diff --git a/rule/logic/common.go b/rule/logic/common.go index 4272b943..66aa1d37 100644 --- a/rule/logic/common.go +++ b/rule/logic/common.go @@ -4,12 +4,8 @@ import ( "fmt" "github.com/Dreamacro/clash/common/collections" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/log" RC "github.com/Dreamacro/clash/rule/common" "github.com/Dreamacro/clash/rule/provider" - "io" - "net/http" - "os" "regexp" "strings" ) @@ -60,12 +56,6 @@ func payloadToRule(subPayload string) (C.Rule, error) { if tp == "NOT" || tp == "OR" || tp == "AND" { return parseRule(tp, payload, nil) } - if tp == "GEOSITE" { - if err := initGeoSite(); err != nil { - log.Errorln("can't initial GeoSite: %s", err) - } - } - param := strings.Split(payload, ",") return parseRule(tp, param[0], param[1:]) } @@ -202,32 +192,3 @@ func findSubRuleRange(payload string, ruleRanges []Range) []Range { return subRuleRange } - -func downloadGeoSite(path string) (err error) { - resp, err := http.Get("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat") - if err != nil { - return - } - defer resp.Body.Close() - - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) - if err != nil { - return err - } - defer f.Close() - _, err = io.Copy(f, resp.Body) - - return err -} - -func initGeoSite() error { - if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) { - log.Infoln("Need GeoSite but can't find GeoSite.dat, start download") - if err := downloadGeoSite(C.Path.GeoSite()); err != nil { - return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) - } - log.Infoln("Download GeoSite.dat finish") - } - - return nil -}