Refactor: script auto load geosite as a rule provider
This commit is contained in:
parent
e03f1d0565
commit
05f0c1060b
@ -249,12 +249,6 @@ Script enables users to programmatically select a policy for the packets with mo
|
|||||||
```yaml
|
```yaml
|
||||||
mode: script
|
mode: script
|
||||||
|
|
||||||
rules:
|
|
||||||
# the rule GEOSITE just as a rule provider in mode script
|
|
||||||
- GEOSITE,category-ads-all,Whatever
|
|
||||||
- GEOSITE,youtube,Whatever
|
|
||||||
- GEOSITE,geolocation-cn,Whatever
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
code: |
|
code: |
|
||||||
def main(ctx, metadata):
|
def main(ctx, metadata):
|
||||||
|
@ -315,9 +315,11 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
|||||||
config.Proxies = proxies
|
config.Proxies = proxies
|
||||||
config.Providers = providers
|
config.Providers = providers
|
||||||
|
|
||||||
if err = parseScript(rawCfg.Script); err != nil {
|
rawRules, err := parseScript(rawCfg.Script, rawCfg.Rule)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
rawCfg.Rule = rawRules
|
||||||
|
|
||||||
rules, ruleProviders, err := parseRules(rawCfg, proxies)
|
rules, ruleProviders, err := parseRules(rawCfg, proxies)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -512,10 +514,10 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin
|
|||||||
var (
|
var (
|
||||||
rules []C.Rule
|
rules []C.Rule
|
||||||
providerNames []string
|
providerNames []string
|
||||||
|
foundRP bool
|
||||||
|
|
||||||
ruleProviders = map[string]C.Rule{}
|
ruleProviders = map[string]C.Rule{}
|
||||||
rulesConfig = cfg.Rule
|
rulesConfig = cfg.Rule
|
||||||
mode = cfg.Mode
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// parse rules
|
// parse rules
|
||||||
@ -550,10 +552,16 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin
|
|||||||
target = rule[l-1]
|
target = rule[l-1]
|
||||||
params = rule[l:]
|
params = rule[l:]
|
||||||
|
|
||||||
if _, ok := proxies[target]; !ok && (mode != T.Script || ruleName != "GEOSITE") {
|
if _, ok := proxies[target]; !ok && ruleName != "GEOSITE" && target != C.ScriptRuleGeoSiteTarget {
|
||||||
return nil, nil, fmt.Errorf("rules[%d] [%s] error: proxy [%s] not found", idx, line, target)
|
return nil, nil, fmt.Errorf("rules[%d] [%s] error: proxy [%s] not found", idx, line, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pvName := "geosite:" + strings.ToLower(payload)
|
||||||
|
_, foundRP = ruleProviders[pvName]
|
||||||
|
if ruleName == "GEOSITE" && target == C.ScriptRuleGeoSiteTarget && foundRP {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
params = trimArr(params)
|
params = trimArr(params)
|
||||||
|
|
||||||
parsed, parseErr := R.ParseRule(ruleName, payload, target, params)
|
parsed, parseErr := R.ParseRule(ruleName, payload, target, params)
|
||||||
@ -561,8 +569,7 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin
|
|||||||
return nil, nil, fmt.Errorf("rules[%d] [%s] error: %s", idx, line, parseErr.Error())
|
return nil, nil, fmt.Errorf("rules[%d] [%s] error: %s", idx, line, parseErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if ruleName == "GEOSITE" {
|
if ruleName == "GEOSITE" && !foundRP {
|
||||||
pvName := "geosite:" + strings.ToLower(payload)
|
|
||||||
providerNames = append(providerNames, pvName)
|
providerNames = append(providerNames, pvName)
|
||||||
ruleProviders[pvName] = parsed
|
ruleProviders[pvName] = parsed
|
||||||
}
|
}
|
||||||
@ -845,7 +852,7 @@ func parseAuthentication(rawRecords []string) []auth.AuthUser {
|
|||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseScript(script Script) error {
|
func parseScript(script Script, rawRules []string) ([]string, error) {
|
||||||
mainCode := script.MainCode
|
mainCode := script.MainCode
|
||||||
shortcutsCode := script.ShortcutsCode
|
shortcutsCode := script.ShortcutsCode
|
||||||
|
|
||||||
@ -890,20 +897,30 @@ time = ClashTime()
|
|||||||
|
|
||||||
err := os.WriteFile(C.Path.Script(), []byte(content), 0o644)
|
err := os.WriteFile(C.Path.Script(), []byte(content), 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("initialized script module failure, %w", err)
|
return nil, fmt.Errorf("initialized script module failure, %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = S.Py_Initialize(C.Path.GetExecutableFullPath(), C.Path.ScriptDir()); err != nil {
|
if err = S.Py_Initialize(C.Path.GetExecutableFullPath(), C.Path.ScriptDir()); err != nil {
|
||||||
return fmt.Errorf("initialized script module failure, %w", err)
|
return nil, fmt.Errorf("initialized script module failure, %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = S.LoadMainFunction(); err != nil {
|
if err = S.LoadMainFunction(); err != nil {
|
||||||
return fmt.Errorf("initialized script module failure, %w", err)
|
return nil, fmt.Errorf("initialized script module failure, %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rpdArr := findRuleProvidersName(content)
|
||||||
|
for _, v := range rpdArr {
|
||||||
|
if !strings.HasPrefix(v, "geosite:") {
|
||||||
|
return nil, fmt.Errorf("initialized script module failure, rule provider name must be start with \"geosite:\"")
|
||||||
|
}
|
||||||
|
v = strings.ToLower(v)
|
||||||
|
rule := fmt.Sprintf("GEOSITE,%s,%s", strings.TrimPrefix(v, "geosite:"), C.ScriptRuleGeoSiteTarget)
|
||||||
|
rawRules = append(rawRules, rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("Start initial script module successful, version: %s", S.Py_GetVersion())
|
log.Infoln("Start initial script module successful, version: %s", S.Py_GetVersion())
|
||||||
|
|
||||||
return nil
|
return rawRules, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanPyKeywords(code string) string {
|
func cleanPyKeywords(code string) string {
|
||||||
@ -916,6 +933,23 @@ func cleanPyKeywords(code string) string {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findRuleProvidersName(s string) []string {
|
||||||
|
ruleProviderRegx := regexp.MustCompile("ctx.rule_providers\\[[\"'](\\S+)[\"']\\]\\.match|match_provider\\([\"'](\\S+)[\"']\\)")
|
||||||
|
arr := ruleProviderRegx.FindAllStringSubmatch(s, -1)
|
||||||
|
|
||||||
|
var rpd []string
|
||||||
|
for _, rpdArr := range arr {
|
||||||
|
for i, v := range rpdArr {
|
||||||
|
if i == 0 || v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rpd = append(rpd, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpd
|
||||||
|
}
|
||||||
|
|
||||||
func parseMitm(rawMitm RawMitm) (*Mitm, error) {
|
func parseMitm(rawMitm RawMitm) (*Mitm, error) {
|
||||||
var (
|
var (
|
||||||
req []C.Rewrite
|
req []C.Rewrite
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/Dreamacro/clash/component/geodata/router"
|
"github.com/Dreamacro/clash/component/geodata/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ScriptRuleGeoSiteTarget = "__WhateverTarget__"
|
||||||
|
|
||||||
type RuleExtra struct {
|
type RuleExtra struct {
|
||||||
Network NetWork
|
Network NetWork
|
||||||
SourceIPs []*netip.Prefix
|
SourceIPs []*netip.Prefix
|
||||||
|
@ -55,6 +55,9 @@ func NewGEOSITE(country string, adapter string) (*GEOSITE, error) {
|
|||||||
if recordsCount == 0 {
|
if recordsCount == 0 {
|
||||||
cont = "from cache"
|
cont = "from cache"
|
||||||
}
|
}
|
||||||
|
if adapter == C.ScriptRuleGeoSiteTarget {
|
||||||
|
adapter = "Script"
|
||||||
|
}
|
||||||
log.Infoln("Start initial GeoSite rule %s => %s, records: %s", country, adapter, cont)
|
log.Infoln("Start initial GeoSite rule %s => %s, records: %s", country, adapter, cont)
|
||||||
|
|
||||||
geoSite := &GEOSITE{
|
geoSite := &GEOSITE{
|
||||||
|
Reference in New Issue
Block a user