mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-03-03 04:09:53 +00:00
feat: local file type provider will auto update after modify
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
|
||||
"github.com/sagernet/fswatch"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
@@ -30,6 +31,7 @@ type Fetcher[V any] struct {
|
||||
parser Parser[V]
|
||||
interval time.Duration
|
||||
OnUpdate func(V)
|
||||
watcher *fswatch.Watcher
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) Name() string {
|
||||
@@ -113,7 +115,20 @@ func (f *Fetcher[V]) Initial() (V, error) {
|
||||
f.hash = md5.Sum(buf)
|
||||
|
||||
// pull contents automatically
|
||||
if f.interval > 0 {
|
||||
if f.vehicle.Type() == types.File {
|
||||
f.watcher, err = fswatch.NewWatcher(fswatch.Options{
|
||||
Path: []string{f.vehicle.Path()},
|
||||
Direct: true,
|
||||
Callback: f.update,
|
||||
})
|
||||
if err != nil {
|
||||
return lo.Empty[V](), err
|
||||
}
|
||||
err = f.watcher.Start()
|
||||
if err != nil {
|
||||
return lo.Empty[V](), err
|
||||
}
|
||||
} else if f.interval > 0 {
|
||||
go f.pullLoop()
|
||||
}
|
||||
|
||||
@@ -155,6 +170,9 @@ func (f *Fetcher[V]) Destroy() error {
|
||||
if f.interval > 0 {
|
||||
f.done <- struct{}{}
|
||||
}
|
||||
if f.watcher != nil {
|
||||
_ = f.watcher.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -170,27 +188,31 @@ func (f *Fetcher[V]) pullLoop() {
|
||||
select {
|
||||
case <-timer.C:
|
||||
timer.Reset(f.interval)
|
||||
elm, same, err := f.Update()
|
||||
if err != nil {
|
||||
log.Errorln("[Provider] %s pull error: %s", f.Name(), err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
if same {
|
||||
log.Debugln("[Provider] %s's content doesn't change", f.Name())
|
||||
continue
|
||||
}
|
||||
|
||||
log.Infoln("[Provider] %s's content update", f.Name())
|
||||
if f.OnUpdate != nil {
|
||||
f.OnUpdate(elm)
|
||||
}
|
||||
f.update(f.vehicle.Path())
|
||||
case <-f.done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Fetcher[V]) update(path string) {
|
||||
elm, same, err := f.Update()
|
||||
if err != nil {
|
||||
log.Errorln("[Provider] %s pull error: %s", f.Name(), err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if same {
|
||||
log.Debugln("[Provider] %s's content doesn't change", f.Name())
|
||||
return
|
||||
}
|
||||
|
||||
log.Infoln("[Provider] %s's content update", f.Name())
|
||||
if f.OnUpdate != nil {
|
||||
f.OnUpdate(elm)
|
||||
}
|
||||
}
|
||||
|
||||
func safeWrite(path string, buf []byte) error {
|
||||
dir := filepath.Dir(path)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user