feat: 尝试实现脚本rule
This commit is contained in:
parent
20cb4d0643
commit
55c7c4edb3
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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
68
rule/common/script.go
Normal 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)
|
@ -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)
|
||||
}
|
||||
|
Reference in New Issue
Block a user