feat: 尝试实现脚本rule

This commit is contained in:
Skyxim 2022-06-05 17:28:19 +08:00
parent 20cb4d0643
commit 55c7c4edb3
4 changed files with 91 additions and 5 deletions

View File

@ -3,17 +3,22 @@
package js
import (
"github.com/Dreamacro/clash/log"
"github.com/dop251/goja"
"github.com/dop251/goja_nodejs/console"
"github.com/dop251/goja_nodejs/eventloop"
"github.com/dop251/goja_nodejs/require"
)
func init() {
logPrinter := console.RequireWithPrinter(&JsLog{})
require.RegisterNativeModule("console", logPrinter)
}
func preSetting(rt *goja.Runtime) {
registry := new(require.Registry)
registry.Enable(rt)
logPrinter := console.RequireWithPrinter(&JsLog{})
require.RegisterNativeModule("console", logPrinter)
console.Enable(rt)
eventloop.EnableConsole(true)
}
@ -33,12 +38,20 @@ func compiler(name, code string) (*goja.Program, error) {
}
func run(loop *eventloop.EventLoop, program *goja.Program, args map[string]any, callback func(any, error)) {
loop.RunOnLoop(func(runtime *goja.Runtime) {
loop.Run(func(runtime *goja.Runtime) {
for k, v := range args {
runtime.Set(k, v)
runtime.SetFieldNameMapper(goja.TagFieldNameMapper("json", true))
err := runtime.Set(k, v)
if err != nil {
log.Errorln("Args to script failed, %s", err.Error())
}
}
v, err := runtime.RunProgram(program)
callback(v, err)
if v == nil {
callback(nil, err)
} else {
callback(v.Export(), err)
}
})
}

View File

@ -14,6 +14,7 @@ const (
SrcPort
DstPort
Process
Script
ProcessPath
RuleSet
Network
@ -61,6 +62,8 @@ func (rt RuleType) String() string {
return "RuleSet"
case Network:
return "Network"
case Script:
return "Script"
case Uid:
return "Uid"
case INTYPE:

68
rule/common/script.go Normal file
View File

@ -0,0 +1,68 @@
package common
import (
"github.com/Dreamacro/clash/component/js"
C "github.com/Dreamacro/clash/constant"
"github.com/gofrs/uuid"
)
type Script struct {
*Base
adapter string
name string
}
func (s *Script) RuleType() C.RuleType {
return C.Script
}
func (s *Script) Match(metadata *C.Metadata) bool {
res := false
js.Run(s.name, map[string]any{
"metadata": metadata,
}, func(a any, err error) {
if err != nil {
res = false
}
r, ok := a.(bool)
if !ok {
res = false
}
res = r
})
return res
}
func (s *Script) Adapter() string {
return s.adapter
}
func (s *Script) Payload() string {
return s.adapter
}
func (s *Script) ShouldResolveIP() bool {
return true
}
func NewScript(script string, adapter string) (*Script, error) {
name, err := uuid.NewV4()
if err != nil {
return nil, err
}
if err := js.NewJS(name.String(), script); err != nil {
return nil, err
}
return &Script{
Base: &Base{},
adapter: adapter,
name: name.String(),
}, nil
}
var _ C.Rule = (*Script)(nil)

View File

@ -43,6 +43,8 @@ func ParseSameRule(tp, payload, target string, params []string) (parsed C.Rule,
parsed, parseErr = RC.NewUid(payload, target)
case "IN-TYPE":
parsed, parseErr = RC.NewInType(payload, target)
case "SCRIPT":
parsed, parseErr = RC.NewScript(payload, target)
default:
parseErr = fmt.Errorf("unsupported rule type %s", tp)
}