diff --git a/core/plugin_core.go b/core/plugin_core.go index 7ad660f..06e516a 100644 --- a/core/plugin_core.go +++ b/core/plugin_core.go @@ -83,10 +83,13 @@ func CancelPluginlistening(uuid string) { func initPlugins() { plugins.Foreach(func(key, data []byte) error { - f, err := initPlugin(string(data), string(key)) + f, cbs, err := initPlugin(string(data), string(key)) if err != nil { console.Error("初始化插件%s错误: %v", key, err) } + for _, cb := range cbs { + cb() + } AddCommand([]*common.Function{f}) // os.WriteFile(fmt.Sprintf("%s/%s.js", pluginPath, f.Title), data, 0600) return nil @@ -101,7 +104,7 @@ func initPlugins() { continue } script := string(fetchScript(p.Address, key)) - if f, _ := initPlugin(script, p.UUID); f.CreateAt != "" { + if f, _, _ := initPlugin(script, p.UUID); f.CreateAt != "" { fin = &storage.Final{ Now: script, } @@ -117,7 +120,11 @@ func initPlugins() { } } } + if new != "" { + if new == "reload" { + new = old + } fin = &storage.Final{} su := &ScriptUtils{script: new} if version := su.GetValue("version"); version == "" || regexp.MustCompile(`v\d+\.\d+\.\d`).FindString(version) != version { @@ -190,7 +197,7 @@ func initPlugins() { } new = su.script } - f, err := initPlugin(new, key) + f, cbs, err := initPlugin(new, key) if err != nil && new != "" { console.Error(err) } @@ -219,13 +226,16 @@ func initPlugins() { console.Log("已重载 %s.js", f.Title) } } else { - of, _ := initPlugin(old, key) + of, _, _ := initPlugin(old, key) console.Log("已卸载 %s.js", of.Title) } apd = true break } } + for _, cb := range cbs { + cb() + } if !apd { AddCommand([]*common.Function{f}) } @@ -239,7 +249,8 @@ func initPlugins() { }) } -func initPlugin(data string, uuid string) (*common.Function, error) { +func initPlugin(data string, uuid string) (*common.Function, []func(), error) { + var cbs = []func(){} var err error var rules []string var imType *common.Filter @@ -266,6 +277,7 @@ func initPlugin(data string, uuid string) (*common.Function, error) { var FindAll bool var hasForm bool var carry bool + ks := map[string]bool{} ress := regexp.MustCompile( `\*\s?@([\d\w+-]+)\s+([^\n]+?)\n`, ).FindAllStringSubmatch(data, -1) @@ -273,6 +285,21 @@ func initPlugin(data string, uuid string) (*common.Function, error) { switch res[1] { case "rule", "match", "regex", "pattern": rule := strings.TrimSpace(res[2]) + rule = parseReply3(rule, func(s1, s2 string) { + k := s1 + "." + s2 + if _, ok := ks[k]; !ok { + cbs = append(cbs, func() { + storage.Watch(MakeBucket(s1), s2, func(old, new, key string) *storage.Final { + return &storage.Final{ + EndFunc: func() { + plugins.Set(uuid, "reload") + }, + } + }, uuid) + }) + ks[k] = true + } + }) _rs := []string{} FR: ress := regexp.MustCompile(`\[([^\s\[\]]+)\]`).FindAllStringSubmatch(rule, -1) @@ -467,6 +494,7 @@ func initPlugin(data string, uuid string) (*common.Function, error) { // icon = "https://joeschmoe.io/api/v1/random?t=" + fmt.Sprint(time.Now().Nanosecond()) // } var running func() bool + f := &common.Function{ Handle: func(s common.Sender, set func(vm *goja.Runtime)) interface{} { defer func() { @@ -588,7 +616,7 @@ func initPlugin(data string, uuid string) (*common.Function, error) { running = func() bool { return f.Running } - return f, err + return f, cbs, err } func ChatID(p interface{}) string { diff --git a/core/reply.go b/core/reply.go index d184e48..e8f3568 100644 --- a/core/reply.go +++ b/core/reply.go @@ -243,3 +243,35 @@ func parseReply2(str string) string { // return "" }) } + +func parseReply3(str string, f func(string, string)) string { + ks := map[string]bool{} + re := regexp.MustCompile(`\$\{\s*([^{}]+)\s*\}`) + return re.ReplaceAllStringFunc(str, func(match string) string { + script := match[2 : len(match)-1] + script = regexp.MustCompile(`(\w+)\.(\w+)`).ReplaceAllStringFunc(script, func(match string) string { + parts := strings.Split(match, ".") + k := fmt.Sprintf(`%s.%s`, parts[0], parts[1]) + if _, ok := ks[k]; !ok { + ks[k] = true + f(parts[0], parts[1]) + } + return fmt.Sprintf(`Bucket("%s")["%s"]`, parts[0], parts[1]) + }) + vm := goja.New() + vm.Set("Bucket", func(name string) interface{} { + return JsBucket(vm, name, "", false) + }) + v, err := vm.RunString(script) + if err == nil { + return v.String() + } + return match + // b_k := strings.Split(bk, ".") + // if len(b_k) != 3 { + // return fmt.Sprintf("${%s}", bk) + // } + // return MakeBucket(b_k[1]).GetString(b_k[2]) + // return "" + }) +} diff --git a/core/storage/boltdb/init.go b/core/storage/boltdb/init.go index 619c1be..355dd69 100644 --- a/core/storage/boltdb/init.go +++ b/core/storage/boltdb/init.go @@ -158,6 +158,7 @@ func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) { new = fmt.Sprint(value) } var handles []func(string, string, string) *storage.Final + var endFuncs = []func(){} for _, listen := range storage.Listens { if listen.Name == bucket.name && (listen.Key == key || listen.Key == "*") { handles = append(handles, listen.Handle) @@ -165,6 +166,9 @@ func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) { } if len(handles) > 0 { old := bucket.GetString(key) + if old == new { + return msg, nil + } for _, handle := range handles { fin := handle(old, new, k) if fin != nil { @@ -177,10 +181,13 @@ func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) { if fin.Now != "" { new = fin.Now } + if fin.EndFunc != nil { + endFuncs = append(endFuncs, fin.EndFunc) + } } } } - return msg, db.Update(func(tx *bolt.Tx) error { + err := db.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucketIfNotExists([]byte(bucket.name)) if err != nil { return err @@ -196,6 +203,12 @@ func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) { } return nil }) + if err == nil { + for _, f := range endFuncs { + f() + } + } + return msg, err } func (bucket *Bucket) GetString(kv ...interface{}) string { diff --git a/core/storage/main.go b/core/storage/main.go index 5615a19..943769d 100644 --- a/core/storage/main.go +++ b/core/storage/main.go @@ -44,6 +44,7 @@ type Final struct { Now string Message string Error error + EndFunc func() } func Watch(bucket Bucket, key interface{}, handle func(old string, new string, key string) *Final, uuid ...string) { diff --git a/core/storage/redis/init.go b/core/storage/redis/init.go index 613f561..2da20e0 100644 --- a/core/storage/redis/init.go +++ b/core/storage/redis/init.go @@ -217,6 +217,7 @@ func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) { } if !utils.SlaveMode { var handles []func(string, string, string) *storage.Final + var endFuncs = []func(){} for _, listen := range storage.Listens { if listen.Name == bucket.name && (listen.Key == key || listen.Key == "*") { handles = append(handles, listen.Handle) @@ -239,14 +240,24 @@ func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) { if fin.Now != "" { new = fin.Now } + if fin.EndFunc != nil { + endFuncs = append(endFuncs, fin.EndFunc) + } } } } + var err error if new == "" { - return msg, db.HDel(ctx, bucket.name, k).Err() + err = db.HDel(ctx, bucket.name, k).Err() } else { - return msg, db.HSet(ctx, bucket.name, k, new).Err() + err = db.HSet(ctx, bucket.name, k, new).Err() } + if err == nil { + for _, f := range endFuncs { + f() + } + } + return msg, err } else { return toMaster(bucket.name, k, new) }