first commit
This commit is contained in:
@@ -0,0 +1,413 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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) {
|
||||
C.Remove(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool) {
|
||||
vm.Set("Bucket", func(name string) interface{} {
|
||||
return vm.NewProxy(MakeBucketObject(vm, uuid, on_start, MakeBucket(name)), &goja.ProxyTrapConfig{
|
||||
Get: func(target *goja.Object, property string, receiver goja.Value) (value goja.Value) {
|
||||
obj := target.Get(property)
|
||||
if obj != nil {
|
||||
return obj
|
||||
}
|
||||
result := target.Get("get").Export().(func(...interface{}) interface{})(property)
|
||||
return vm.ToValue(result)
|
||||
},
|
||||
Set: func(target *goja.Object, property string, value, receiver goja.Value) (success bool) {
|
||||
result := target.Get("set").Export().(func(interface{}, interface{}) error)(
|
||||
property, value.Export(),
|
||||
)
|
||||
return result == nil
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
sillyplusJsIplm := func(call goja.ConstructorCall) *goja.Object {
|
||||
userId := fmt.Sprintf("%d", rand.Int63())
|
||||
call.This.Set("isSlaveMode", func() bool {
|
||||
return utils.SlaveMode
|
||||
})
|
||||
call.This.Set("uuid", func() string {
|
||||
return uuid
|
||||
})
|
||||
call.This.Set("store", func(str string, v interface{}) {
|
||||
store.Store(str, v)
|
||||
})
|
||||
call.This.Set("load", func(str string) interface{} {
|
||||
v, _ := store.Load(str)
|
||||
return v
|
||||
})
|
||||
call.This.Set("delete", func(str string) {
|
||||
store.Delete(str)
|
||||
})
|
||||
call.This.Set("session", func(info interface{}) func(...int) interface{} {
|
||||
msg := ""
|
||||
imTpye := "carry"
|
||||
var chatId string
|
||||
switch info := info.(type) {
|
||||
case string:
|
||||
msg = info
|
||||
default:
|
||||
props := info.(map[string]interface{})
|
||||
for i := range props {
|
||||
switch strings.ToLower(i) {
|
||||
case "imtype":
|
||||
imTpye = props[i].(string)
|
||||
case "platform":
|
||||
imTpye = props[i].(string)
|
||||
case "msg", "message":
|
||||
msg = props[i].(string)
|
||||
case "chatid", "chat_id":
|
||||
chatId = fmt.Sprint(props[i].(string))
|
||||
case "userid", "user_id":
|
||||
userId = props[i].(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
if msg == "" {
|
||||
return nil
|
||||
}
|
||||
c := &Faker{
|
||||
Type: imTpye,
|
||||
Message: msg,
|
||||
Carry: make(chan string),
|
||||
UserID: userId,
|
||||
ChatID: chatId,
|
||||
Admin: true,
|
||||
}
|
||||
Messages <- c
|
||||
var f = func(i ...int) interface{} {
|
||||
timeOut := 1000 * 100
|
||||
if len(i) > 0 {
|
||||
timeOut = i[0]
|
||||
}
|
||||
select {
|
||||
case v, ok := <-c.Listen():
|
||||
return map[string]interface{}{
|
||||
"hasNext": ok,
|
||||
"message": v,
|
||||
}
|
||||
case <-time.After(time.Millisecond * time.Duration(timeOut)):
|
||||
return map[string]interface{}{
|
||||
"hasNext": false,
|
||||
"message": "已超时",
|
||||
}
|
||||
}
|
||||
}
|
||||
return f
|
||||
})
|
||||
return nil
|
||||
}
|
||||
registry := require.NewRegistry(require.WithLoader(mapFileSystemSourceLoader(uuid)))
|
||||
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 := C.AddFunc(cron, func() {
|
||||
// mutex := GetMutex(uuid)
|
||||
// mutex.Lock()
|
||||
// defer mutex.Unlock()
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
console.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) {
|
||||
C.Remove(id)
|
||||
})
|
||||
return o
|
||||
})
|
||||
|
||||
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,
|
||||
})
|
||||
})
|
||||
}
|
||||
return o
|
||||
})
|
||||
registry.RegisterNativeModule("express", func(runtime *goja.Runtime, module *goja.Object) {
|
||||
o := module.Get("exports").(*goja.Object)
|
||||
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,
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
vm.Set("gofor", func(running func() bool, handle func()) {
|
||||
go func() {
|
||||
for {
|
||||
if !func() bool {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
console.Error("gofor running error:", err)
|
||||
}
|
||||
}()
|
||||
return running()
|
||||
}() {
|
||||
return
|
||||
}
|
||||
func() {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
console.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...)
|
||||
// }()
|
||||
|
||||
// }
|
||||
// }()
|
||||
// }
|
||||
}
|
||||
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)
|
||||
vm.Set("sillyplus", sillyplusJsIplm)
|
||||
vm.Set("call", func(str string) interface{} {
|
||||
return RegistFuncs[str]
|
||||
})
|
||||
vm.Set("fmt", &Fmt{})
|
||||
vm.Set("strings", &Strings{})
|
||||
// vm.Set("Bucket", BucketJsImpl)
|
||||
vm.Set("time", &TimeJsImpl{
|
||||
Second: time.Second,
|
||||
Minute: time.Minute,
|
||||
Hour: time.Hour,
|
||||
Day: time.Hour * 24,
|
||||
})
|
||||
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", func(call goja.ConstructorCall) *goja.Object {
|
||||
return Buffer(vm, call)
|
||||
})
|
||||
vm.Set("request", func(wts ...interface{}) interface{} {
|
||||
promise, resolve, reject := vm.NewPromise()
|
||||
func() {
|
||||
func() {
|
||||
v := recover()
|
||||
if v != nil {
|
||||
if err, ok := v.(error); ok {
|
||||
reject(Error(vm, err))
|
||||
} else {
|
||||
reject(Error(vm, fmt.Sprint(v)))
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
request(vm, resolve, reject, wts...)
|
||||
}()
|
||||
return promise
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user