402 lines
8.8 KiB
Go
402 lines
8.8 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cdle/sillyplus/mongodb"
|
|
"github.com/cdle/sillyplus/utils"
|
|
"github.com/dop251/goja"
|
|
"github.com/dop251/goja_nodejs/require"
|
|
"github.com/robfig/cron/v3"
|
|
)
|
|
|
|
type ScriptUtils struct {
|
|
matched bool
|
|
ress [][]string
|
|
script string
|
|
}
|
|
|
|
func (su *ScriptUtils) match() {
|
|
su.ress = regexp.MustCompile(
|
|
`(\x20?\*[ ]?@([^\s]+)\s+([^\n]+?)\n)`,
|
|
).FindAllStringSubmatch(su.script, -1)
|
|
su.matched = true
|
|
}
|
|
|
|
func (su *ScriptUtils) GetValue(key string) string {
|
|
if !su.matched {
|
|
su.match()
|
|
}
|
|
value := ""
|
|
for _, res := range su.ress {
|
|
if res[2] == key {
|
|
value = res[3]
|
|
}
|
|
}
|
|
return value
|
|
}
|
|
|
|
// func Error(err error) interface{} {
|
|
// if err != nil {
|
|
// return map[string]string{"name": "Error", "message": err.Error()}
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
func (su *ScriptUtils) SetValue(key, value string) {
|
|
if !su.matched {
|
|
su.match()
|
|
}
|
|
exists := []string{}
|
|
first := ""
|
|
for _, res := range su.ress {
|
|
if first == "" {
|
|
first = res[1]
|
|
}
|
|
if res[2] == key {
|
|
exists = append(exists, res[1])
|
|
}
|
|
}
|
|
if len(exists) != 0 {
|
|
for i := range exists {
|
|
if i == len(exists)-1 {
|
|
su.script = strings.Replace(su.script, exists[i], fmt.Sprintf(" * @%s %s\n", key, value), 1)
|
|
} else {
|
|
su.script = strings.Replace(su.script, exists[i], "", 1)
|
|
}
|
|
}
|
|
} else {
|
|
if first != "" {
|
|
su.script = strings.Replace(su.script, first, first+fmt.Sprintf(" * @%s %s\n", key, value), 1)
|
|
} else {
|
|
su.script = fmt.Sprintf("/**\n%s */\n", fmt.Sprintf(" * @%s %s\n", key, value)) + su.script
|
|
}
|
|
}
|
|
su.match()
|
|
}
|
|
|
|
func (su *ScriptUtils) DeleteValue(key string) {
|
|
if !su.matched {
|
|
su.match()
|
|
}
|
|
exists := []string{}
|
|
for _, res := range su.ress {
|
|
if res[2] == key {
|
|
exists = append(exists, res[1])
|
|
}
|
|
}
|
|
if len(exists) != 0 {
|
|
for i := range exists {
|
|
su.script = strings.Replace(su.script, exists[i], "", 1)
|
|
}
|
|
}
|
|
su.match()
|
|
}
|
|
|
|
var store sync.Map
|
|
var crons sync.Map
|
|
|
|
func CancelPluginCrons(uuid string) {
|
|
v, ok := crons.Load(uuid)
|
|
if ok {
|
|
for _, id := range *v.(*[]cron.EntryID) {
|
|
CRON.Remove(id)
|
|
}
|
|
}
|
|
}
|
|
|
|
func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool, running func() bool) {
|
|
vm.Set("Bucket", func(name string) interface{} {
|
|
return JsBucket(vm, name, uuid, on_start)
|
|
})
|
|
registry := require.NewRegistry(require.WithLoader(mapFileSystemSourceLoader(uuid)))
|
|
registry.RegisterNativeModule("crypto", cryptoModule)
|
|
registry.RegisterNativeModule("buffer", bufferModule)
|
|
if on_start {
|
|
var ids = &[]cron.EntryID{}
|
|
crons.Store(uuid, ids)
|
|
vm.Set("Cron", func() *goja.Object {
|
|
o := vm.NewObject()
|
|
o.Set("add", func(cron string, f func()) interface{} {
|
|
if f == nil {
|
|
return map[string]interface{}{
|
|
"id": 0,
|
|
"error": "未传入handler",
|
|
}
|
|
}
|
|
cron = strings.TrimSpace(cron)
|
|
if len(regexp.MustCompile(`\S+`).FindAllString(cron, -1)) == 5 {
|
|
cron = "0 " + cron
|
|
}
|
|
id, err := CRON.AddFunc(cron, func() {
|
|
// mutex := GetMutex(uuid)
|
|
// mutex.Lock()
|
|
// defer mutex.Unlock()
|
|
defer func() {
|
|
err := recover()
|
|
if err != nil {
|
|
pluginConsole(uuid).Error("C.AddFunc err: %v", err)
|
|
}
|
|
}()
|
|
f()
|
|
})
|
|
if err == nil {
|
|
*ids = append(*ids, id)
|
|
}
|
|
return map[string]interface{}{
|
|
"id": id,
|
|
"error": err,
|
|
}
|
|
})
|
|
o.Set("remove", func(id cron.EntryID) {
|
|
CRON.Remove(id)
|
|
})
|
|
return o
|
|
})
|
|
|
|
vm.Set("gofor", func(running func() bool, handle func()) {
|
|
go func() {
|
|
for {
|
|
if !func() bool {
|
|
defer func() {
|
|
err := recover()
|
|
if err != nil {
|
|
pluginConsole(uuid).Error("gofor running error:", err)
|
|
}
|
|
}()
|
|
return running()
|
|
}() {
|
|
return
|
|
}
|
|
func() {
|
|
defer func() {
|
|
err := recover()
|
|
if err != nil {
|
|
pluginConsole(uuid).Error("gofor error:", err)
|
|
}
|
|
}()
|
|
handle()
|
|
}()
|
|
}
|
|
}()
|
|
})
|
|
// func (f *Factory) Request(running func() bool, wt interface{}, handles ...func(error, map[string]interface{}, interface{}) interface{}) {
|
|
// go func() {
|
|
// for {
|
|
// if !running() {
|
|
// return
|
|
// }
|
|
// func() {
|
|
// defer func() {
|
|
// if debug_mode {
|
|
// return
|
|
// }
|
|
// err := recover()
|
|
// if err != nil {
|
|
// console.Error("Sender(\""+f.platform+"\").request error:", err)
|
|
// }
|
|
// }()
|
|
// request(wt, handles...)
|
|
// }()
|
|
|
|
// }
|
|
// }()
|
|
// }
|
|
}
|
|
vm.Set("Express", func() *goja.Object {
|
|
o := vm.NewObject()
|
|
methods := []string{"get", "post", "delete", "put", "fetch"}
|
|
for i := range methods {
|
|
method := methods[i]
|
|
o.Set(method, func(path string, handles ...func(*Request, *Response)) {
|
|
webs = append(webs, Web{
|
|
uuid: uuid,
|
|
method: strings.ToUpper(method),
|
|
path: path,
|
|
handles: handles,
|
|
})
|
|
})
|
|
}
|
|
o.Set("static", func(path string) {
|
|
addStatic(uuid, path)
|
|
})
|
|
return o
|
|
})
|
|
registry.Enable(vm)
|
|
vm.SetFieldNameMapper(myFieldNameMapper{})
|
|
// vm.Set("sleep", sleep)
|
|
vm.Set("md5", utils.Md5)
|
|
vm.Set("image", utils.ToImageQrcode)
|
|
vm.Set("video", utils.ToVideoQrcode)
|
|
vm.Set("console", &Console{UUID: uuid})
|
|
vm.Set("call", func(str string) interface{} {
|
|
return RegistFuncs[str]
|
|
})
|
|
vm.Set("fmt", &Fmt{})
|
|
vm.Set("strings", &Strings{
|
|
UUID: uuid,
|
|
})
|
|
// vm.Set("Bucket", BucketJsImpl)
|
|
vm.Set("time", &TimeJsImpl{
|
|
Second: time.Second,
|
|
Minute: time.Minute,
|
|
Hour: time.Hour,
|
|
Day: time.Hour * 24,
|
|
Month: 1,
|
|
})
|
|
vm.Set("Regexp", Regexp)
|
|
vm.Set("Form", func(...interface{}) {
|
|
|
|
})
|
|
vm.Set("url2Base64", Url2Base64)
|
|
// 字符串转Base64编码
|
|
vm.Set("stringToBase64", stringToBase64)
|
|
vm.Set("base64ToString", base64ToString)
|
|
vm.Set("Buffer", &BufferObj{vm: vm})
|
|
vm.Set("fetch", func(wts ...interface{}) interface{} {
|
|
promise, resolve, reject := vm.NewPromise()
|
|
go func() {
|
|
defer func() {
|
|
err := recover()
|
|
if err != nil {
|
|
o, ok := err.(*goja.Object)
|
|
if ok {
|
|
(&Console{
|
|
UUID: uuid,
|
|
}).Error(o.Get("value"))
|
|
}
|
|
}
|
|
}()
|
|
obj, err := fetch(vm, uuid, wts...)
|
|
if err != nil {
|
|
reject(err)
|
|
} else {
|
|
resolve(obj)
|
|
}
|
|
}()
|
|
return promise
|
|
})
|
|
vm.Set("request", func(wts ...interface{}) interface{} {
|
|
obj, err := fetch(vm, uuid, wts...)
|
|
if err != nil {
|
|
panic(Error(vm, err))
|
|
}
|
|
return obj
|
|
})
|
|
// for _, method := range []string{"get", "post", "delete", "put", "fetch"} {
|
|
// vm.Set(method, )
|
|
// }
|
|
vm.Set("HttpListen", func(method, api string) *goja.Promise {
|
|
promise, resolve, reject := vm.NewPromise()
|
|
go func() {
|
|
func() {
|
|
v := recover()
|
|
if v != nil {
|
|
if err, ok := v.(error); ok {
|
|
reject(Error(vm, err))
|
|
} else {
|
|
reject(Error(vm, fmt.Sprint(v)))
|
|
}
|
|
|
|
}
|
|
}()
|
|
AddHttpListen(api, strings.ToUpper(method), vm, uuid, resolve, reject)
|
|
}()
|
|
return promise
|
|
})
|
|
vm.Set("getReplyMessage", func(plt string, bots_id []string) *goja.Promise {
|
|
return GetReplyMessage(vm, plt, bots_id)
|
|
})
|
|
vm.Set("Script", func(str string) interface{} {
|
|
if str == "" {
|
|
str = uuid
|
|
}
|
|
return Script(str)
|
|
})
|
|
vm.Set("Temp", func(pre string, sec int) interface{} {
|
|
return map[string]interface{}{
|
|
"set": func(key string, value interface{}, num int) {
|
|
if sec != 0 && num == 0 {
|
|
num = sec
|
|
}
|
|
temp.Set(pre+"_"+key, value, num)
|
|
},
|
|
"get": func(key string, def interface{}) interface{} {
|
|
v := temp.Get(pre + "_" + key)
|
|
if v == nil {
|
|
v = def
|
|
}
|
|
return v
|
|
},
|
|
"delete": func(key string) {
|
|
temp.Delete(pre + "_" + key)
|
|
},
|
|
}
|
|
})
|
|
|
|
osjs := getJsOs(vm, running)
|
|
vm.Set("os", osjs)
|
|
vm.Set("fs", osjs)
|
|
vm.Set("forObject", ForeachObject)
|
|
vm.Set("MongoClient", func(uri string) interface{} {
|
|
return &mongodb.MongoClient{
|
|
Uri: uri,
|
|
Vm: vm,
|
|
}
|
|
})
|
|
vm.Set("importJs", func(file string) error {
|
|
file = strings.Replace(file, ".js", "", -1)
|
|
s, id, ok := getPaterner(uuid, file)
|
|
if !ok {
|
|
panic(Error(vm, "无法通过importJs导入"+file))
|
|
}
|
|
_, err := vm.RunString(s)
|
|
if err != nil {
|
|
pluginConsole(id).Error(err)
|
|
panic(Error(vm, "通过importJs导入"+file+"错误:"+err.Error()))
|
|
}
|
|
return nil
|
|
})
|
|
vm.Set("crypto", &Crypto{
|
|
vm: vm,
|
|
})
|
|
vm.Set("createNickName", CreateNickName)
|
|
}
|
|
|
|
func EncryptPlugin(script string) string {
|
|
res := strings.SplitN(script, "*/\n", 2)
|
|
if len(res) != 2 {
|
|
// logs.Info(len(res))
|
|
return script
|
|
}
|
|
str, err := EncryptByAes([]byte(res[1]))
|
|
if err != nil {
|
|
// logs.Info(err)
|
|
return script
|
|
}
|
|
su := ScriptUtils{script: res[0]}
|
|
if su.GetValue("encrypt_data") != "" {
|
|
return script
|
|
}
|
|
su.SetValue("encrypt_data", str)
|
|
return su.script + "*/\n"
|
|
}
|
|
|
|
func DecryptPlugin(script string) string {
|
|
su := ScriptUtils{script: script}
|
|
encrypt_data := su.GetValue("encrypt_data")
|
|
if encrypt_data == "" {
|
|
return script
|
|
}
|
|
su.DeleteValue("encrypt_data")
|
|
str, err := DecryptByAes(encrypt_data)
|
|
if err != nil {
|
|
return script
|
|
}
|
|
return fmt.Sprintf("%s%s", su.script, str)
|
|
}
|