mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-29 23:46:00 +03:00
Add Surge MITM and scripts
This commit is contained in:
119
script/script_surge_cron.go
Normal file
119
script/script_surge_cron.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package script
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
|
||||
"github.com/adhocore/gronx"
|
||||
)
|
||||
|
||||
var _ adapter.GenericScript = (*SurgeCronScript)(nil)
|
||||
|
||||
type SurgeCronScript struct {
|
||||
GenericScript
|
||||
ctx context.Context
|
||||
expression string
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
func NewSurgeCronScript(ctx context.Context, logger logger.ContextLogger, options option.Script) (*SurgeCronScript, error) {
|
||||
source, err := NewSource(ctx, logger, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !gronx.IsValid(options.CronOptions.Expression) {
|
||||
return nil, E.New("invalid cron expression: ", options.CronOptions.Expression)
|
||||
}
|
||||
return &SurgeCronScript{
|
||||
GenericScript: GenericScript{
|
||||
logger: logger,
|
||||
tag: options.Tag,
|
||||
timeout: time.Duration(options.Timeout),
|
||||
arguments: options.Arguments,
|
||||
source: source,
|
||||
},
|
||||
ctx: ctx,
|
||||
expression: options.CronOptions.Expression,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) Type() string {
|
||||
return C.ScriptTypeSurgeCron
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) Tag() string {
|
||||
return s.tag
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) StartContext(ctx context.Context, startContext *adapter.HTTPStartContext) error {
|
||||
return s.source.StartContext(ctx, startContext)
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) PostStart() error {
|
||||
err := s.source.PostStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go s.loop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) loop() {
|
||||
s.logger.Debug("starting event")
|
||||
err := s.Run(s.ctx)
|
||||
if err != nil {
|
||||
s.logger.Error(E.Cause(err, "running event"))
|
||||
}
|
||||
nextTick, err := gronx.NextTick(s.expression, false)
|
||||
if err != nil {
|
||||
s.logger.Error(E.Cause(err, "determine next tick"))
|
||||
return
|
||||
}
|
||||
s.timer = time.NewTimer(nextTick.Sub(time.Now()))
|
||||
s.logger.Debug("next event at: ", nextTick.Format(log.DefaultTimeFormat))
|
||||
for {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
case <-s.timer.C:
|
||||
s.logger.Debug("starting event")
|
||||
err = s.Run(s.ctx)
|
||||
if err != nil {
|
||||
s.logger.Error(E.Cause(err, "running event"))
|
||||
}
|
||||
nextTick, err = gronx.NextTick(s.expression, false)
|
||||
if err != nil {
|
||||
s.logger.Error(E.Cause(err, "determine next tick"))
|
||||
return
|
||||
}
|
||||
s.timer.Reset(nextTick.Sub(time.Now()))
|
||||
s.logger.Debug("next event at: ", nextTick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) Close() error {
|
||||
return s.source.Close()
|
||||
}
|
||||
|
||||
func (s *SurgeCronScript) Run(ctx context.Context) error {
|
||||
program := s.source.Program()
|
||||
if program == nil {
|
||||
return E.New("invalid script")
|
||||
}
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
defer cancel(nil)
|
||||
vm := NewRuntime(ctx, s.logger, cancel)
|
||||
err := SetSurgeModules(vm, ctx, s.logger, cancel, s.Tag(), s.Type(), s.arguments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ExecuteSurgeGeneral(vm, program, ctx, s.timeout)
|
||||
}
|
||||
Reference in New Issue
Block a user