Chore: make sure script module always initialized

This commit is contained in:
yaling888 2022-05-08 06:17:09 +08:00
parent 4334b45e82
commit f23d1d5d7c

View File

@ -311,8 +311,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
config.Proxies = proxies config.Proxies = proxies
config.Providers = providers config.Providers = providers
err = parseScript(rawCfg) if err = parseScript(rawCfg.Script); err != nil {
if err != nil {
return nil, err return nil, err
} }
@ -497,7 +496,6 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin
ruleProviders = map[string]C.Rule{} ruleProviders = map[string]C.Rule{}
rulesConfig = cfg.Rule rulesConfig = cfg.Rule
mode = cfg.Mode mode = cfg.Mode
isPyInit = S.Py_IsInitialized()
) )
// parse rules // parse rules
@ -510,10 +508,6 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin
ruleName = strings.ToUpper(rule[0]) ruleName = strings.ToUpper(rule[0])
) )
if mode == T.Script && ruleName != "GEOSITE" {
continue
}
l := len(rule) l := len(rule)
if l < 2 { if l < 2 {
@ -536,7 +530,7 @@ 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]; mode != T.Script && !ok { if _, ok := proxies[target]; !ok && (mode != T.Script || ruleName != "GEOSITE") {
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)
} }
@ -547,29 +541,22 @@ 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 isPyInit {
if ruleName == "GEOSITE" { if ruleName == "GEOSITE" {
pvName := "geosite:" + strings.ToLower(payload) pvName := "geosite:" + strings.ToLower(payload)
providerNames = append(providerNames, pvName) providerNames = append(providerNames, pvName)
ruleProviders[pvName] = parsed ruleProviders[pvName] = parsed
} }
}
if mode != T.Script {
rules = append(rules, parsed) rules = append(rules, parsed)
} }
}
runtime.GC() if err := S.NewClashPyContext(providerNames); err != nil {
if isPyInit {
err := S.NewClashPyContext(providerNames)
if err != nil {
return nil, nil, err return nil, nil, err
} else { } else {
log.Infoln("Start initial script context successful, provider records: %v", len(providerNames)) log.Infoln("Start initial script context successful, provider records: %v", len(providerNames))
} }
}
runtime.GC()
return rules, ruleProviders, nil return rules, ruleProviders, nil
} }
@ -882,16 +869,17 @@ func parseTun(rawTun RawTun, general *General) (*Tun, error) {
}, nil }, nil
} }
func parseScript(cfg *RawConfig) error { func parseScript(script Script) error {
mode := cfg.Mode mainCode := script.MainCode
script := cfg.Script
mainCode := cleanPyKeywords(script.MainCode)
shortcutsCode := script.ShortcutsCode shortcutsCode := script.ShortcutsCode
if mode != T.Script && len(shortcutsCode) == 0 { if strings.TrimSpace(mainCode) == "" {
return nil mainCode = `
} else if mode == T.Script && len(mainCode) == 0 { def main(ctx, metadata):
return fmt.Errorf("initialized script module failure, can't find script code in the config file") return "DIRECT"
`
} else {
mainCode = cleanPyKeywords(mainCode)
} }
content := `# -*- coding: UTF-8 -*- content := `# -*- coding: UTF-8 -*-
@ -912,25 +900,16 @@ time = ClashTime()
` `
var shouldInitPy bool
if mode == T.Script {
content += mainCode + "\n\n" content += mainCode + "\n\n"
shouldInitPy = true
}
for k, v := range shortcutsCode { for k, v := range shortcutsCode {
v = cleanPyKeywords(v) v = cleanPyKeywords(v)
v = strings.TrimSpace(v) v = strings.TrimSpace(v)
if len(v) == 0 { if v == "" {
return fmt.Errorf("initialized rule SCRIPT failure, shortcut [%s] code invalid syntax", k) return fmt.Errorf("initialized rule SCRIPT failure, shortcut [%s] code invalid syntax", k)
} }
content += "def " + strings.ToLower(k) + "(ctx, network, process_name, host, src_ip, src_port, dst_ip, dst_port):\n return " + v + "\n\n" content += "def " + strings.ToLower(k) + "(ctx, network, process_name, host, src_ip, src_port, dst_ip, dst_port):\n return " + v + "\n\n"
shouldInitPy = true
}
if !shouldInitPy {
return nil
} }
err := os.WriteFile(C.Path.Script(), []byte(content), 0o644) err := os.WriteFile(C.Path.Script(), []byte(content), 0o644)
@ -940,11 +919,11 @@ time = ClashTime()
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, %s", err.Error()) return fmt.Errorf("initialized script module failure, %s", err.Error())
} else if mode == T.Script { }
if err = S.LoadMainFunction(); err != nil { if err = S.LoadMainFunction(); err != nil {
return fmt.Errorf("initialized script module failure, %s", err.Error()) return fmt.Errorf("initialized script module failure, %s", err.Error())
} }
}
log.Infoln("Start initial script module successful, version: %s", S.Py_GetVersion()) log.Infoln("Start initial script module successful, version: %s", S.Py_GetVersion())
@ -952,9 +931,6 @@ time = ClashTime()
} }
func cleanPyKeywords(code string) string { func cleanPyKeywords(code string) string {
if len(code) == 0 {
return code
}
keywords := []string{"import", "print"} keywords := []string{"import", "print"}
for _, kw := range keywords { for _, kw := range keywords {