x
This commit is contained in:
+43
-9
@@ -532,17 +532,32 @@ func (f *Factory) SetIsAdmin(function func(string) bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Factory) Sender2() *CustomSender {
|
||||
func (f *Factory) Sender2(options map[string]string) *CustomSender {
|
||||
var demo = *f.demo
|
||||
sender := &demo
|
||||
sender.SetID()
|
||||
if options != nil {
|
||||
fsp := &common.FakerSenderParams{}
|
||||
if v, ok := options[CONETNT]; ok {
|
||||
fsp.Content = v
|
||||
}
|
||||
if v, ok := options[USER_ID]; ok {
|
||||
fsp.UserID = v
|
||||
}
|
||||
if v, ok := options[CHAT_ID]; ok {
|
||||
fsp.ChatID = v
|
||||
}
|
||||
if v, ok := options[MESSAGE_ID]; ok {
|
||||
fsp.MessageID = v
|
||||
}
|
||||
sender.SetFsps(fsp)
|
||||
}
|
||||
return sender
|
||||
}
|
||||
|
||||
func (f *Factory) Sender() interface{} {
|
||||
var demo = *f.demo
|
||||
sender := &demo
|
||||
return &SenderJsIplm{
|
||||
Message: sender,
|
||||
Message: f.Sender2(nil),
|
||||
Vm: f.vm,
|
||||
Private: "private",
|
||||
Group: "group",
|
||||
@@ -552,10 +567,11 @@ func (f *Factory) Sender() interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Factory) Receive(wt interface{}) *CustomSender {
|
||||
func (f *Factory) Receive(props map[string]interface{}) *CustomSender {
|
||||
var demo = *f.demo
|
||||
sender := &demo
|
||||
props := wt.(map[string]interface{})
|
||||
sender.SetID()
|
||||
console.Log("senderId", sender.GetID())
|
||||
emf := map[string]interface{}{}
|
||||
for i := range props {
|
||||
h := false
|
||||
@@ -636,12 +652,12 @@ func (sender *CustomSender) GetBotID() string {
|
||||
|
||||
type PUSH string
|
||||
|
||||
func (sender *CustomSender) Action(options map[string]interface{}) (interface{}, string) {
|
||||
func (sender *CustomSender) Action(options map[string]interface{}) (interface{}, error) {
|
||||
var platform = sender.f.botplt
|
||||
var any *common.Function
|
||||
var one *common.Function
|
||||
var result interface{}
|
||||
var err = ""
|
||||
var err error
|
||||
for _, function := range Functions {
|
||||
if function.Reply != nil && function.Reply.Platform == platform {
|
||||
if len(function.Reply.BotsID) == 0 {
|
||||
@@ -668,7 +684,7 @@ func (sender *CustomSender) Action(options map[string]interface{}) (interface{},
|
||||
result = value
|
||||
}
|
||||
if property == "error" {
|
||||
err = value.String()
|
||||
err = errors.New(value.String())
|
||||
}
|
||||
return true
|
||||
},
|
||||
@@ -897,3 +913,21 @@ func (sender *CustomSender) IsAdmin() bool {
|
||||
}
|
||||
return sender.f.isAdmin(sender.GetUserID())
|
||||
}
|
||||
|
||||
func (sender *CustomSender) GetID() string {
|
||||
return sender.id
|
||||
}
|
||||
|
||||
var test = "4d6371a8-2778-11ee-a3c2-821680fbbf6b"
|
||||
|
||||
func (sender *CustomSender) SetID() {
|
||||
if test != "" {
|
||||
sender.id = test
|
||||
test = ""
|
||||
} else {
|
||||
sender.id = utils.GenUUID()
|
||||
}
|
||||
|
||||
sender.CreatedAt = time.Now()
|
||||
senders.Store(sender.id, sender)
|
||||
}
|
||||
|
||||
+18
-3
@@ -160,6 +160,8 @@ type BaseSender struct {
|
||||
params []string
|
||||
level int
|
||||
emf map[string]interface{}
|
||||
id string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (sender *BaseSender) SetLevel(l int) {
|
||||
@@ -369,8 +371,22 @@ func (sender *BaseSender) Event() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sender *BaseSender) Action(map[string]interface{}) (interface{}, string) {
|
||||
return nil, ""
|
||||
func (sender *BaseSender) Action(map[string]interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (sender *BaseSender) GetID() string {
|
||||
return sender.id
|
||||
}
|
||||
|
||||
func (sender *BaseSender) SetID() {
|
||||
sender.id = utils.GenUUID()
|
||||
sender.CreatedAt = time.Now()
|
||||
senders.Store(sender.id, sender)
|
||||
}
|
||||
|
||||
func (sender *BaseSender) GetTime() time.Time {
|
||||
return sender.CreatedAt
|
||||
}
|
||||
|
||||
func (sender *BaseSender) IsAtLast() bool {
|
||||
@@ -581,7 +597,6 @@ func (s *BaseSender) Await(message common.Sender, callback func(common.Sender) i
|
||||
c.Result <- result
|
||||
return s.GetContent()
|
||||
}
|
||||
|
||||
case error:
|
||||
if handleErr != nil {
|
||||
handleErr(s)
|
||||
|
||||
+3
-3
@@ -63,7 +63,7 @@ func initCarry() {
|
||||
q := value.(*Queue)
|
||||
for _, qm := range q.GetValues() {
|
||||
if qm.From != nil && qm.From.GetMessageID() == event["message_id"] {
|
||||
qm.To.Sender2().RecallMessage(qm.MessageID)
|
||||
qm.To.Sender2(nil).RecallMessage(qm.MessageID)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -434,7 +434,7 @@ func init() {
|
||||
functions := Functions
|
||||
for _, function := range functions {
|
||||
if function.UUID != "" {
|
||||
scripts[function.UUID] = function.Title + ".js"
|
||||
scripts[function.UUID] = function.Title + function.Suffix
|
||||
}
|
||||
}
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
@@ -496,7 +496,7 @@ func init() {
|
||||
functions := Functions
|
||||
for _, function := range functions {
|
||||
if function.UUID != "" && ((len(function.Rules) == 0 && !function.OnStart && !function.Module && len(function.Https) == 0 && function.Reply == nil) || function.Carry) {
|
||||
scripts[function.UUID] = function.Title + ".js"
|
||||
scripts[function.UUID] = function.Title + function.Suffix
|
||||
}
|
||||
}
|
||||
var user_names = []NicklabeL{}
|
||||
|
||||
@@ -19,6 +19,8 @@ type Function struct {
|
||||
Origin string `json:"-"`
|
||||
UUID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"type"` //脚本类型
|
||||
Suffix string `json:"suffix"` //脚本后缀
|
||||
Description string `json:"description"`
|
||||
Public bool `json:"public"`
|
||||
Icon string `json:"icon"`
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package common
|
||||
|
||||
import "time"
|
||||
|
||||
type Sender interface {
|
||||
GetID() string
|
||||
GetTime() time.Time
|
||||
SetID()
|
||||
GetUserID() string
|
||||
GetChatID() string
|
||||
GetBotID() string
|
||||
@@ -51,7 +56,7 @@ type Sender interface {
|
||||
SetLevel(int)
|
||||
GetLevel() int
|
||||
Event() map[string]interface{}
|
||||
Action(map[string]interface{}) (interface{}, string)
|
||||
Action(map[string]interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
type FakerSenderParams struct {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/cdle/sillyplus/proto3/srpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// protoc --go_out=. -I. --go-grpc_out=. bucket.proto
|
||||
func init() {
|
||||
go func() {
|
||||
lis, err := net.Listen("tcp", ":50051")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
srpc.RegisterSillyGirlServiceServer(s, &SillyGirlService{})
|
||||
log.Printf("grpc server listening at %v", lis.Addr())
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cdle/sillyplus/proto3/srpc"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
)
|
||||
|
||||
func (sg *SillyGirlService) AdapterRegist(stream srpc.SillyGirlService_AdapterRegistServer) error {
|
||||
var adapter *Factory
|
||||
var echos sync.Map
|
||||
for {
|
||||
req, err := stream.Recv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if adapter == nil {
|
||||
bot_id := req.GetBotId()
|
||||
platform := req.GetPlatform()
|
||||
adapter = &Factory{}
|
||||
defer adapter.Destroy()
|
||||
adapter.Init(platform, bot_id, nil)
|
||||
adapter.SetReplyHandler(func(m map[string]interface{}) string {
|
||||
m["__type__"] = "reply"
|
||||
echo := utils.GenUUID()
|
||||
ch := make(chan string)
|
||||
echos.Store(echo, ch)
|
||||
defer echos.Delete(echo)
|
||||
m["echo"] = echo
|
||||
stream.Send(&srpc.Default{
|
||||
Value: string(utils.JsonMarshal(m)),
|
||||
})
|
||||
select {
|
||||
case v := <-ch:
|
||||
return v
|
||||
case <-time.After(time.Second * 5):
|
||||
}
|
||||
return ""
|
||||
})
|
||||
} else {
|
||||
echo := req.GetBotId()
|
||||
message_id := req.GetPlatform()
|
||||
v, ok := echos.Load(echo)
|
||||
if ok {
|
||||
select {
|
||||
case v.(chan string) <- message_id:
|
||||
case <-time.After(time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) AdapterReceive(ctx context.Context, req *srpc.AdapterRequest) (*srpc.Default, error) {
|
||||
msgs := map[string]interface{}{}
|
||||
bot_id := req.GetBotId()
|
||||
platform := req.GetPlatform()
|
||||
json.Unmarshal([]byte(req.Value), &msgs)
|
||||
adapter, err := GetAdapter(bot_id, platform)
|
||||
if err == nil {
|
||||
s := adapter.Receive(msgs)
|
||||
return &srpc.Default{Value: s.GetID()}, nil
|
||||
}
|
||||
return &srpc.Default{Value: ""}, err
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) AdapterPush(ctx context.Context, req *srpc.AdapterRequest) (*srpc.Default, error) {
|
||||
msgs := map[string]string{}
|
||||
bot_id := req.GetBotId()
|
||||
platform := req.GetPlatform()
|
||||
json.Unmarshal([]byte(req.Value), &msgs)
|
||||
adapter, err := GetAdapter(bot_id, platform)
|
||||
if err == nil {
|
||||
result := adapter.Push(msgs)
|
||||
message_id := result["message_id"]
|
||||
error := result["error"]
|
||||
if error != "" {
|
||||
return &srpc.Default{Value: ""}, err
|
||||
}
|
||||
return &srpc.Default{Value: message_id}, err
|
||||
}
|
||||
return &srpc.Default{Value: ""}, err
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) AdapterSender(ctx context.Context, req *srpc.AdapterRequest) (*srpc.Default, error) {
|
||||
msgs := map[string]string{}
|
||||
bot_id := req.GetBotId()
|
||||
platform := req.GetPlatform()
|
||||
json.Unmarshal([]byte(req.Value), &msgs)
|
||||
adapter, err := GetAdapter(bot_id, platform)
|
||||
if err == nil {
|
||||
s := adapter.Sender2(msgs)
|
||||
return &srpc.Default{Value: s.GetID()}, nil
|
||||
}
|
||||
return &srpc.Default{Value: ""}, err
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) AdapterDestroy(ctx context.Context, req *srpc.AdapterRequest) (*srpc.Empty, error) {
|
||||
bot_id := req.GetBotId()
|
||||
platform := req.GetPlatform()
|
||||
adapter, err := GetAdapter(bot_id, platform)
|
||||
if err == nil {
|
||||
adapter.Destroy()
|
||||
}
|
||||
return &srpc.Empty{}, err
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cdle/sillyplus/proto3/srpc"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
)
|
||||
|
||||
type SillyGirlService struct {
|
||||
srpc.UnsafeSillyGirlServiceServer
|
||||
}
|
||||
|
||||
// Get implements BucketServiceServer.Get.
|
||||
func (sg *SillyGirlService) BucketGet(ctx context.Context, req *srpc.BucketKeyRequest) (*srpc.Default, error) {
|
||||
value := MakeBucket(req.Name).GetString(req.Key)
|
||||
return &srpc.Default{Value: value}, nil
|
||||
}
|
||||
|
||||
// Set implements BucketServiceServer.Set.
|
||||
func (sg *SillyGirlService) BucketSet(ctx context.Context, req *srpc.BucketSetRequest) (*srpc.BucketSetResponse, error) {
|
||||
message, changed, err := MakeBucket(req.Name).Set(req.Key, req.Value)
|
||||
return &srpc.BucketSetResponse{Changed: changed, Message: message}, err
|
||||
}
|
||||
|
||||
// Delete implements BucketServiceServer.Delete.
|
||||
func (sg *SillyGirlService) BucketDelete(ctx context.Context, req *srpc.BucketRequest) (*srpc.Empty, error) {
|
||||
err := MakeBucket(req.Name).Delete()
|
||||
return &srpc.Empty{}, err
|
||||
}
|
||||
|
||||
// Keys implements BucketServiceServer.Keys.
|
||||
func (sg *SillyGirlService) BucketKeys(ctx context.Context, req *srpc.BucketRequest) (*srpc.BucketKeysResponse, error) {
|
||||
keys, err := MakeBucket(req.Name).Keys()
|
||||
return &srpc.BucketKeysResponse{Keys: keys}, err
|
||||
}
|
||||
|
||||
// Len implements BucketServiceServer.Len.
|
||||
func (sg *SillyGirlService) BucketLen(ctx context.Context, req *srpc.BucketRequest) (*srpc.LenResponse, error) {
|
||||
keys, err := MakeBucket(req.Name).Keys()
|
||||
return &srpc.LenResponse{Length: int32(len(keys))}, err
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) BucketGetAll(ctx context.Context, req *srpc.BucketRequest) (*srpc.Default, error) {
|
||||
var values = map[string]string{}
|
||||
MakeBucket(req.Name).Foreach(func(b1, b2 []byte) error {
|
||||
values[string(b1)] = string(b2)
|
||||
return nil
|
||||
})
|
||||
return &srpc.Default{Value: string(utils.JsonMarshal(values))}, nil
|
||||
}
|
||||
|
||||
// Buckets implements BucketServiceServer.Buckets.
|
||||
func (sg *SillyGirlService) BucketBuckets(ctx context.Context, req *srpc.Empty) (*srpc.BucketsResponse, error) {
|
||||
return &srpc.BucketsResponse{Buckets: MakeBucket("app").Buckets()}, nil
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/cdle/sillyplus/core/common"
|
||||
"github.com/cdle/sillyplus/core/storage"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/google/uuid"
|
||||
cron "github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
go initNodePlugins()
|
||||
}
|
||||
|
||||
func initNodePlugins() {
|
||||
root := utils.ExecPath + "/plugins"
|
||||
plugins := []string{root}
|
||||
os.Mkdir(root, 0755)
|
||||
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if !strings.HasPrefix(path, "/Users/a1-6/Code/sillyplus/plugins/") {
|
||||
return nil
|
||||
}
|
||||
files := strings.Split(strings.Replace(path, root+"/", "", 1), "/")
|
||||
// var plugin_dir = false
|
||||
// var plugin_index = false
|
||||
switch len(files) {
|
||||
case 1:
|
||||
// plugin_dir = true
|
||||
if info.IsDir() {
|
||||
plugins = append(plugins, path)
|
||||
}
|
||||
case 2:
|
||||
if (files[1] == "main.ts" || files[1] == "main.js") && !info.IsDir() {
|
||||
AddNodePlugin(path, files[0])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
fmt.Println("创建监视器失败:", err)
|
||||
return
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
// 要监控的文件夹路径
|
||||
|
||||
for _, dir := range plugins {
|
||||
err = watcher.Add(dir)
|
||||
if err != nil {
|
||||
fmt.Println("添加监视目录失败:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
// fmt.Println(event.Name, "op", event.Op.String())
|
||||
files := strings.Split(strings.Replace(event.Name, root+"/", "", 1), "/")
|
||||
var plugin_dir = false
|
||||
var plugin_index = false
|
||||
var plugin_name = ""
|
||||
switch len(files) {
|
||||
case 1:
|
||||
plugin_dir = true
|
||||
fmt.Println("目录事件")
|
||||
plugin_name = files[0]
|
||||
case 2:
|
||||
if files[1] == "main.ts" || files[1] == "main.js" {
|
||||
plugin_index = true
|
||||
fmt.Println("入口文件事件")
|
||||
}
|
||||
plugin_name = files[0]
|
||||
}
|
||||
switch event.Op.String() {
|
||||
case "CREATE":
|
||||
if plugin_dir {
|
||||
info, err := os.Stat(event.Name)
|
||||
// fmt.Println(err)
|
||||
if err == nil && info.IsDir() {
|
||||
watcher.Add(event.Name)
|
||||
// fmt.Println("增加插件目录", event.Name)
|
||||
} else {
|
||||
// fmt.Println("非插件目录", event.Name)
|
||||
}
|
||||
} else if plugin_index {
|
||||
// fmt.Println("增加插件", event.Name)
|
||||
AddNodePlugin(event.Name, plugin_name)
|
||||
}
|
||||
case "REMOVE", "RENAME", "REMOVE|RENAME":
|
||||
if plugin_dir {
|
||||
watcher.Remove(event.Name)
|
||||
// fmt.Println("移除插件目录", event.Name)
|
||||
// fmt.Println("移除插件", plugin_name)
|
||||
RemNodePlugin(plugin_name)
|
||||
} else if plugin_index {
|
||||
// fmt.Println("移除插件", plugin_name)
|
||||
RemNodePlugin(plugin_name)
|
||||
}
|
||||
case "WRITE":
|
||||
if plugin_index {
|
||||
RemNodePlugin(plugin_name)
|
||||
AddNodePlugin(event.Name, plugin_name)
|
||||
// fmt.Println("变更插件", event.Name, plugin_name)
|
||||
}
|
||||
}
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
fmt.Println("错误:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RemNodePlugin(name string) error {
|
||||
pluginLock.Lock()
|
||||
defer pluginLock.Unlock()
|
||||
key := nameUuid(name)
|
||||
fmt.Println("rem", key, name)
|
||||
for i := range Functions {
|
||||
if Functions[i].UUID == key {
|
||||
fmt.Println("pl", key)
|
||||
DestroyAdapterByUUID(key)
|
||||
Functions[i].Running = false
|
||||
if len(Functions[i].CronIds) != 0 {
|
||||
for _, id := range Functions[i].CronIds {
|
||||
CRON.Remove(cron.EntryID(id))
|
||||
}
|
||||
}
|
||||
Functions = append(Functions[:i], Functions[i+1:]...)
|
||||
CancelPluginCrons(key)
|
||||
CancelPluginWebs(key)
|
||||
CancelPluginlistening(key)
|
||||
CancelHttpListen(key)
|
||||
remStatic(key)
|
||||
storage.DisableHandle(key)
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func nameUuid(name string) string {
|
||||
hash := sha1.Sum([]byte(name))
|
||||
return uuid.NewSHA1(uuid.Nil, hash[:]).String()
|
||||
}
|
||||
|
||||
func AddNodePlugin(path, name string) error {
|
||||
pluginLock.Lock()
|
||||
defer pluginLock.Unlock()
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uuid := nameUuid(name)
|
||||
// fmt.Println("add,", uuid, name)
|
||||
f, cbs := pluginParse(string(data), uuid)
|
||||
f.Suffix = ".ts"
|
||||
f.Type = "typescript"
|
||||
f.Handle = func(s common.Sender, f func(vm *goja.Runtime)) interface{} {
|
||||
cmd := exec.Command("node", "/Users/a1-6/.nvm/versions/node/v18.16.1/lib/node_modules/ts-node/dist/bin.js", path)
|
||||
cmd.Env = append(cmd.Env, "SENDER_ID="+s.GetID())
|
||||
// 执行命令,并捕获其输出
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
fmt.Println("命令执行失败:", err)
|
||||
return nil
|
||||
}
|
||||
// 输出命令的输出结果
|
||||
fmt.Println(string(output))
|
||||
return nil
|
||||
}
|
||||
for _, cb := range cbs {
|
||||
cb()
|
||||
}
|
||||
AddCommand([]*common.Function{f})
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cdle/sillyplus/core/common"
|
||||
"github.com/cdle/sillyplus/proto3/srpc"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
)
|
||||
|
||||
var senders sync.Map
|
||||
|
||||
func init() {
|
||||
//垃圾回收
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(time.Minute)
|
||||
senders.Range(func(key, value any) bool {
|
||||
s := value.(common.Sender)
|
||||
if s.GetTime().Add(time.Minute * 20).Before(time.Now()) {
|
||||
senders.Delete(s.GetID())
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func GetSender(uuid string) (common.Sender, error) {
|
||||
v, ok := senders.Load(uuid)
|
||||
if !ok {
|
||||
return nil, errors.New("not found sender")
|
||||
}
|
||||
return v.(common.Sender), nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetUserId(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetChatID()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetUserName(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetUserName()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetChatId(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetChatID()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetChatName(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetChatName()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetMessageId(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetMessageID()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetPlatform(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetImType()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetBotId(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetBotID()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderGetContent(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: s.GetContent()}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderSetContent(ctx context.Context, req *srpc.SenderContentRequest) (*srpc.Empty, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.SetContent(req.Content)
|
||||
return &srpc.Empty{}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderContinue(ctx context.Context, req *srpc.SenderRequest) (*srpc.Empty, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Continue()
|
||||
return &srpc.Empty{}, nil
|
||||
}
|
||||
|
||||
// todo
|
||||
func (sg *SillyGirlService) SenderListen(ctx context.Context, req *srpc.SenderListenRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
options := []interface{}{}
|
||||
var carry = &Carry{
|
||||
ListenPrivate: req.ListenPrivate,
|
||||
ListenGroup: req.ListenGroup,
|
||||
RequireAdmin: req.RequireAdmin,
|
||||
AllowPlatforms: req.AllowPlatforms,
|
||||
ProhibitPlatforms: req.ProhibitPlatforms,
|
||||
AllowGroups: req.AllowGroups,
|
||||
ProhibitGroups: req.ProhibitGroups,
|
||||
AllowUsers: req.AllowUsers,
|
||||
ProhibitUsers: req.ProhibitUsers,
|
||||
UserID: s.GetUserID(),
|
||||
ChatID: s.GetChatID(),
|
||||
}
|
||||
|
||||
if req.Timeout != 0 {
|
||||
options = append(options, time.Duration(req.Timeout)*time.Millisecond)
|
||||
}
|
||||
if len(req.Rules) != 0 {
|
||||
for _, rule := range req.Rules {
|
||||
_rs := formatRule(rule)
|
||||
if len(_rs) != 0 {
|
||||
carry.Function.Rules = append(carry.Function.Rules, _rs...)
|
||||
} else {
|
||||
carry.Function.Rules = append(carry.Function.Rules, rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
options = append(options, carry)
|
||||
id := ""
|
||||
s.Await(s, func(s common.Sender) interface{} {
|
||||
id = s.GetID()
|
||||
return nil
|
||||
}, options...)
|
||||
return &srpc.Default{Value: id}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderEvent(ctx context.Context, req *srpc.SenderRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &srpc.Default{Value: string(utils.JsonMarshal(s.Event()))}, nil
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderReply(ctx context.Context, req *srpc.ReplyRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
message_id, err := s.Reply(req.Content)
|
||||
return &srpc.Default{Value: message_id}, err
|
||||
}
|
||||
|
||||
func (sg *SillyGirlService) SenderAction(ctx context.Context, req *srpc.ReplyRequest) (*srpc.Default, error) {
|
||||
s, err := GetSender(req.Uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var params = map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(req.Content), ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := s.Action(params)
|
||||
return &srpc.Default{Value: string(utils.JsonMarshal(result))}, err
|
||||
}
|
||||
+115
-368
@@ -19,6 +19,8 @@ import (
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
var pluginLock = new(sync.Mutex)
|
||||
|
||||
type myFieldNameMapper struct{}
|
||||
|
||||
var mutexMap = make(map[string]*sync.Mutex)
|
||||
@@ -89,7 +91,9 @@ func initPlugins() {
|
||||
return nil
|
||||
})
|
||||
plugins.Foreach(func(key, data []byte) error {
|
||||
f, cbs, err := initPlugin(string(data), string(key))
|
||||
pluginLock.Lock()
|
||||
defer pluginLock.Unlock()
|
||||
f, cbs, err := initPlugin(string(data), string(key), "")
|
||||
if err != nil {
|
||||
console.Error("初始化插件%s错误: %v", key, err)
|
||||
}
|
||||
@@ -100,7 +104,7 @@ func initPlugins() {
|
||||
// os.WriteFile(fmt.Sprintf("%s/%s.js", pluginPath, f.Title), data, 0600)
|
||||
return nil
|
||||
})
|
||||
var pluginLock = new(sync.Mutex)
|
||||
|
||||
storage.Watch(plugins, nil, func(old, new, key string) (fin *storage.Final) {
|
||||
pluginLock.Lock()
|
||||
defer pluginLock.Unlock()
|
||||
@@ -110,7 +114,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,
|
||||
}
|
||||
@@ -203,7 +207,7 @@ func initPlugins() {
|
||||
}
|
||||
new = su.script
|
||||
}
|
||||
f, cbs, err := initPlugin(new, key)
|
||||
f, cbs, err := initPlugin(new, key, "")
|
||||
if err != nil && new != "" {
|
||||
pluginConsole(key).Error(err)
|
||||
}
|
||||
@@ -227,13 +231,13 @@ func initPlugins() {
|
||||
if new != "" {
|
||||
AddCommand([]*common.Function{f})
|
||||
if old == "" {
|
||||
console.Log("已加载 %s.js", f.Title)
|
||||
console.Log("已加载 %s%s", f.Title, f.Suffix)
|
||||
} else if !f.OnStart {
|
||||
console.Log("已重载 %s.js", f.Title)
|
||||
console.Log("已重载 %s%s", f.Title, f.Suffix)
|
||||
}
|
||||
} else {
|
||||
of, _, _ := initPlugin(old, key)
|
||||
console.Log("已卸载 %s.js", of.Title)
|
||||
of, _, _ := initPlugin(old, key, "")
|
||||
console.Log("已卸载 %s%s", of.Title, of.Suffix)
|
||||
}
|
||||
apd = true
|
||||
break
|
||||
@@ -255,236 +259,12 @@ func initPlugins() {
|
||||
})
|
||||
}
|
||||
|
||||
func initPlugin(data string, uuid string) (*common.Function, []func(), error) {
|
||||
var cbs = []func(){}
|
||||
var err error
|
||||
var rules []string
|
||||
var imType *common.Filter
|
||||
var userId *common.Filter
|
||||
var groupId *common.Filter
|
||||
var cron = map[string]string{}
|
||||
var admin bool
|
||||
var disable bool
|
||||
var priority int
|
||||
var title string
|
||||
var public bool
|
||||
var description string
|
||||
var icon string
|
||||
var version string = "v1.0.0"
|
||||
var author string
|
||||
var create_at string
|
||||
var module bool
|
||||
var web bool
|
||||
var encrypt bool
|
||||
var onStart bool
|
||||
var origin = "自定义"
|
||||
var https = []*common.Http{}
|
||||
var message *common.Reply
|
||||
var FindAll bool
|
||||
var hasForm bool
|
||||
var carry bool
|
||||
var classes = []string{}
|
||||
ks := map[string]bool{}
|
||||
ress := regexp.MustCompile(
|
||||
`\*\s?@([\d\w+-]+)\s+([^\n]+?)\n`,
|
||||
).FindAllStringSubmatch(data, -1)
|
||||
for _, res := range ress {
|
||||
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)
|
||||
if len(ress) != 0 {
|
||||
res := ress[len(ress)-1]
|
||||
var inner = res[1]
|
||||
slice := strings.SplitN(inner, ":", 2)
|
||||
name := slice[0]
|
||||
ps := ""
|
||||
if len(slice) == 2 {
|
||||
ps = slice[1]
|
||||
}
|
||||
if strings.HasSuffix(name, "?") {
|
||||
name = strings.TrimRight(name, "?")
|
||||
rep := ""
|
||||
if ps == "" {
|
||||
rep = fmt.Sprintf("[%s]", name)
|
||||
} else {
|
||||
rep = fmt.Sprintf("[%s:%s]", name, ps)
|
||||
}
|
||||
for l := range _rs {
|
||||
_rs[l] = strings.Replace(_rs[l], res[0], rep, 1)
|
||||
}
|
||||
rule1 := strings.Replace(rule, res[0], rep, 1)
|
||||
if len(_rs) == 0 {
|
||||
_rs = append(_rs, rule1)
|
||||
}
|
||||
rule = strings.Replace(rule, res[0], "", 1)
|
||||
rule = regexp.MustCompile("\x20{2,}").ReplaceAllString(rule, " ")
|
||||
rule = strings.TrimSpace(rule)
|
||||
_rs = append(_rs, rule)
|
||||
goto FR
|
||||
}
|
||||
}
|
||||
if len(_rs) != 0 {
|
||||
rules = append(rules, _rs...)
|
||||
} else {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
case "class":
|
||||
classes = append(classes, regexp.MustCompile(`[\S]+`).FindAllString(res[2], -1)...)
|
||||
classes = utils.Unique(classes)
|
||||
case "platform", "imType", "platform+", "imType+":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
imType = &common.Filter{
|
||||
BlackMode: false,
|
||||
Items: item,
|
||||
}
|
||||
case "platform-", "imType-":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
imType = &common.Filter{
|
||||
BlackMode: true,
|
||||
Items: item,
|
||||
}
|
||||
case "userId", "userID", "uid", "userId+", "userID+", "uid+":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
userId = &common.Filter{
|
||||
BlackMode: false,
|
||||
Items: item,
|
||||
}
|
||||
case "userId-", "userID-", "uid-":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
userId = &common.Filter{
|
||||
BlackMode: true,
|
||||
Items: item,
|
||||
}
|
||||
case "groupId", "groupID", "groupCode", "chat_id", "chat_id+", "chatId", "chatID", "gid", "groupId+", "groupID+", "groupCode+", "chatId+", "chatID+", "gid+":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
groupId = &common.Filter{
|
||||
BlackMode: false,
|
||||
Items: item,
|
||||
}
|
||||
case "groupId-", "groupID-", "groupCode-", "chatId-", "chat_id-", "chatID-", "gid-":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
groupId = &common.Filter{
|
||||
BlackMode: true,
|
||||
Items: item,
|
||||
}
|
||||
|
||||
case "admin":
|
||||
admin = strings.TrimSpace(res[2]) == "true"
|
||||
case "disable":
|
||||
disable = strings.TrimSpace(res[2]) == "true"
|
||||
case "findall":
|
||||
FindAll = strings.TrimSpace(res[2]) == "true"
|
||||
case "priority":
|
||||
priority = utils.Int(strings.TrimSpace(res[2]))
|
||||
case "title", "name", "show":
|
||||
title = strings.TrimSpace(res[2])
|
||||
case "public":
|
||||
public = strings.TrimSpace(res[2]) == "true"
|
||||
case "description":
|
||||
description = strings.TrimSpace(res[2])
|
||||
case "icon":
|
||||
icon = strings.TrimSpace(res[2])
|
||||
case "version":
|
||||
version = strings.TrimSpace(res[2])
|
||||
case "author":
|
||||
author = strings.TrimSpace(res[2])
|
||||
case "http":
|
||||
ss := regexp.MustCompile(`[\S]+`).FindAllString(strings.TrimSpace(res[2]), -1)
|
||||
if len(ss) == 2 {
|
||||
https = append(https, &common.Http{
|
||||
Path: ss[1],
|
||||
Method: strings.ToUpper(ss[0]),
|
||||
})
|
||||
} else {
|
||||
console.Warn("http param is not 2")
|
||||
}
|
||||
case "message":
|
||||
ss := regexp.MustCompile(`[\S]+`).FindAllString(strings.TrimSpace(res[2]), -1)
|
||||
if len(ss) > 1 {
|
||||
if len(ss) == 2 && ss[1] == "*" {
|
||||
message = &common.Reply{
|
||||
Platform: ss[0],
|
||||
BotsID: []string{},
|
||||
}
|
||||
} else {
|
||||
message = &common.Reply{
|
||||
Platform: ss[0],
|
||||
BotsID: ss[1:],
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
console.Warn("message param is 0")
|
||||
}
|
||||
case "create_at":
|
||||
create_at = strings.TrimSpace(res[2])
|
||||
case "origin":
|
||||
origin = strings.TrimSpace(res[2])
|
||||
case "module":
|
||||
module = strings.TrimSpace(res[2]) == "true"
|
||||
case "web":
|
||||
web = strings.TrimSpace(res[2]) == "true"
|
||||
case "carry":
|
||||
carry = strings.TrimSpace(res[2]) == "true"
|
||||
case "encrypt":
|
||||
encrypt = strings.TrimSpace(res[2]) == "true"
|
||||
case "on_start":
|
||||
onStart = strings.TrimSpace(res[2]) == "true"
|
||||
case "form":
|
||||
hasForm = true
|
||||
case "paterner":
|
||||
paterner := strings.TrimSpace(res[2])
|
||||
go func() {
|
||||
time.Sleep(time.Second * 2)
|
||||
getPaterner(uuid, strings.TrimSpace(paterner))
|
||||
}()
|
||||
default:
|
||||
cron_ := strings.TrimSpace(res[2])
|
||||
cron_ = strings.ReplaceAll(cron_, `\/`, "/")
|
||||
if strings.HasPrefix(res[1], "cron") {
|
||||
cron[res[1]] = cron_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func initPlugin(data string, uuid string, scriptType string) (*common.Function, []func(), error) {
|
||||
f, cbs := pluginParse(data, uuid)
|
||||
f.Suffix = ".js"
|
||||
f.Type = "goja"
|
||||
script := ""
|
||||
if encrypt {
|
||||
if f.Encrypt {
|
||||
script = DecryptPlugin(string(data))
|
||||
} else {
|
||||
script = string(data)
|
||||
@@ -494,152 +274,119 @@ func initPlugin(data string, uuid string) (*common.Function, []func(), error) {
|
||||
script = strings.ReplaceAll(script, "new Bucket", "Bucket")
|
||||
// script = regexp.MustCompile(`import\s+\{\s*([^\}]+)\s*\}\s*from\s*['"]([^'"]+)['"]\s*;`).ReplaceAllString(script, "const {$1} = require('$2');")
|
||||
// script = regexp.MustCompile(`import\s+\s*([^\}]+)\s*\s*from\s*['"]([^'"]+)['"]\s*;`).ReplaceAllString(script, "const $1 = require('$2');")
|
||||
if !hasForm {
|
||||
hasForm = strings.Contains(script, "Form(")
|
||||
}
|
||||
prg, err2 := goja.Compile(title+".js", script, false)
|
||||
var err error
|
||||
prg, err2 := goja.Compile(f.Title+".js", script, false)
|
||||
if err == nil && err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
// if err == nil && len(rules) == 0 && cron != "" {
|
||||
// err = fmt.Errorf("无效的脚本%s", title)
|
||||
// }
|
||||
if web {
|
||||
onStart = true
|
||||
}
|
||||
// if icon == "" {
|
||||
// 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{} {
|
||||
if !debug {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
pluginConsole(uuid).Error(err)
|
||||
// s.Reply(fmt.Sprint(err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err2 != nil {
|
||||
panic(err2)
|
||||
}
|
||||
loop := eventloop.NewEventLoop()
|
||||
loop.Run(func(vm *goja.Runtime) {
|
||||
SetPluginMethod(vm, uuid, onStart, running)
|
||||
ss := &SenderJsIplm{
|
||||
Message: s,
|
||||
Vm: vm,
|
||||
Private: "private",
|
||||
Group: "group",
|
||||
Routine: "routine",
|
||||
Persistent: "persistent",
|
||||
UUID: uuid,
|
||||
}
|
||||
vm.Set("msg", goja.Undefined())
|
||||
vm.Set("message", goja.Undefined())
|
||||
vm.Set("res", goja.Undefined())
|
||||
vm.Set("req", goja.Undefined())
|
||||
vm.Set("action", goja.Undefined())
|
||||
vm.Set("sender", ss)
|
||||
vm.Set("run", func(uuid string) bool { //执行子脚本
|
||||
fs := Functions
|
||||
for i := range fs {
|
||||
if fs[i].UUID == uuid {
|
||||
fs[i].Handle(s, nil)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
vm.Set("s", ss)
|
||||
vm.Set("InitAdapter", func(plt, botid string, params map[string]interface{}) *Factory {
|
||||
f := &Factory{
|
||||
uuid: uuid,
|
||||
vm: vm,
|
||||
}
|
||||
f.Init(plt, botid, params)
|
||||
return f
|
||||
})
|
||||
vm.Set("initAdapter", func(plt, botid string, params map[string]interface{}) *Factory {
|
||||
f := &Factory{
|
||||
uuid: uuid,
|
||||
vm: vm,
|
||||
}
|
||||
f.Init(plt, botid, params)
|
||||
return f
|
||||
})
|
||||
getAdapter := func(plt, botid string) map[string]interface{} {
|
||||
adapter, err := GetAdapter(plt, botid)
|
||||
errstr := ""
|
||||
if err != nil {
|
||||
errstr = err.Error()
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"error": errstr,
|
||||
"adapter": adapter,
|
||||
}
|
||||
}
|
||||
vm.Set("GetAdapter", getAdapter)
|
||||
vm.Set("getAdapter", getAdapter)
|
||||
vm.Set("getAdapterBotsID", GetAdapterBotsID)
|
||||
vm.Set("getAdapterBotPlts", GetAdapterBotPlts)
|
||||
vm.Set("GetAdapterBotsID", GetAdapterBotsID)
|
||||
vm.Set("GetAdapterBotPlts", GetAdapterBotPlts)
|
||||
vm.Set("running", running)
|
||||
vm.Set("Running", running)
|
||||
vm.Set("uuid", func() string {
|
||||
return uuid
|
||||
})
|
||||
vm.Set("genUuid", func() string {
|
||||
return utils.GenUUID()
|
||||
})
|
||||
vm.Set("genUUID", func() string {
|
||||
return utils.GenUUID()
|
||||
})
|
||||
vm.Set("UUID", func() string {
|
||||
return uuid
|
||||
})
|
||||
if set != nil {
|
||||
set(vm)
|
||||
}
|
||||
_, err := vm.RunProgram(prg)
|
||||
f.Handle = func(s common.Sender, set func(vm *goja.Runtime)) interface{} {
|
||||
if !debug {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
pluginConsole(uuid).Error(strings.ReplaceAll(strings.ReplaceAll(err.Error(), "node_modules/", ""), "github.com/dop251/goja_nodejs/require", ""))
|
||||
pluginConsole(uuid).Error(err)
|
||||
// s.Reply(fmt.Sprint(err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err2 != nil {
|
||||
panic(err2)
|
||||
}
|
||||
loop := eventloop.NewEventLoop()
|
||||
loop.Run(func(vm *goja.Runtime) {
|
||||
SetPluginMethod(vm, uuid, f.OnStart, running)
|
||||
ss := &SenderJsIplm{
|
||||
Message: s,
|
||||
Vm: vm,
|
||||
Private: "private",
|
||||
Group: "group",
|
||||
Routine: "routine",
|
||||
Persistent: "persistent",
|
||||
UUID: uuid,
|
||||
}
|
||||
vm.Set("msg", goja.Undefined())
|
||||
vm.Set("message", goja.Undefined())
|
||||
vm.Set("res", goja.Undefined())
|
||||
vm.Set("req", goja.Undefined())
|
||||
vm.Set("action", goja.Undefined())
|
||||
vm.Set("sender", ss)
|
||||
vm.Set("run", func(uuid string) bool { //执行子脚本
|
||||
fs := Functions
|
||||
for i := range fs {
|
||||
if fs[i].UUID == uuid {
|
||||
fs[i].Handle(s, nil)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
return nil
|
||||
},
|
||||
Rules: rules,
|
||||
ImType: imType,
|
||||
UserId: userId,
|
||||
GroupId: groupId,
|
||||
Cron: cron,
|
||||
Admin: admin,
|
||||
Priority: priority,
|
||||
Disable: disable,
|
||||
UUID: uuid,
|
||||
Title: title,
|
||||
Public: public,
|
||||
Description: description,
|
||||
Icon: icon,
|
||||
Version: version,
|
||||
Author: author,
|
||||
CreateAt: create_at,
|
||||
Module: module,
|
||||
Encrypt: encrypt,
|
||||
OnStart: onStart,
|
||||
Origin: origin,
|
||||
Running: onStart,
|
||||
Reply: message,
|
||||
Https: https,
|
||||
FindAll: FindAll,
|
||||
HasForm: hasForm,
|
||||
Carry: carry,
|
||||
Classes: classes,
|
||||
vm.Set("s", ss)
|
||||
vm.Set("InitAdapter", func(plt, botid string, params map[string]interface{}) *Factory {
|
||||
f := &Factory{
|
||||
uuid: uuid,
|
||||
vm: vm,
|
||||
}
|
||||
f.Init(plt, botid, params)
|
||||
return f
|
||||
})
|
||||
vm.Set("initAdapter", func(plt, botid string, params map[string]interface{}) *Factory {
|
||||
f := &Factory{
|
||||
uuid: uuid,
|
||||
vm: vm,
|
||||
}
|
||||
f.Init(plt, botid, params)
|
||||
return f
|
||||
})
|
||||
getAdapter := func(plt, botid string) map[string]interface{} {
|
||||
adapter, err := GetAdapter(plt, botid)
|
||||
errstr := ""
|
||||
if err != nil {
|
||||
errstr = err.Error()
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"error": errstr,
|
||||
"adapter": adapter,
|
||||
}
|
||||
}
|
||||
vm.Set("GetAdapter", getAdapter)
|
||||
vm.Set("getAdapter", getAdapter)
|
||||
vm.Set("getAdapterBotsID", GetAdapterBotsID)
|
||||
vm.Set("getAdapterBotPlts", GetAdapterBotPlts)
|
||||
vm.Set("GetAdapterBotsID", GetAdapterBotsID)
|
||||
vm.Set("GetAdapterBotPlts", GetAdapterBotPlts)
|
||||
vm.Set("running", running)
|
||||
vm.Set("Running", running)
|
||||
vm.Set("uuid", func() string {
|
||||
return uuid
|
||||
})
|
||||
vm.Set("genUuid", func() string {
|
||||
return utils.GenUUID()
|
||||
})
|
||||
vm.Set("genUUID", func() string {
|
||||
return utils.GenUUID()
|
||||
})
|
||||
vm.Set("UUID", func() string {
|
||||
return uuid
|
||||
})
|
||||
if set != nil {
|
||||
set(vm)
|
||||
}
|
||||
_, err := vm.RunProgram(prg)
|
||||
if err != nil {
|
||||
pluginConsole(uuid).Error(strings.ReplaceAll(strings.ReplaceAll(err.Error(), "node_modules/", ""), "github.com/dop251/goja_nodejs/require", ""))
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
running = func() bool {
|
||||
return f.Running
|
||||
}
|
||||
|
||||
+2
-2
@@ -23,10 +23,10 @@ var sleep = func(i int) {
|
||||
func GetScriptNameByUUID(uuid string) string {
|
||||
for _, f := range Functions {
|
||||
if f.UUID == uuid {
|
||||
return fmt.Sprintf("%s.js", f.Title)
|
||||
return fmt.Sprintf("%s%s", f.Title, f.Suffix)
|
||||
}
|
||||
}
|
||||
return "未知脚本.js"
|
||||
return "未知脚本"
|
||||
}
|
||||
|
||||
type SenderJsIplm struct {
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/cdle/sillyplus/core/common"
|
||||
"github.com/cdle/sillyplus/core/storage"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
)
|
||||
|
||||
func pluginParse(script string, uuid string) (*common.Function, []func()) {
|
||||
var cbs = []func(){}
|
||||
var rules []string
|
||||
var imType *common.Filter
|
||||
var userId *common.Filter
|
||||
var groupId *common.Filter
|
||||
var cron = map[string]string{}
|
||||
var admin bool
|
||||
var disable bool
|
||||
var priority int
|
||||
var title string
|
||||
var public bool
|
||||
var description string
|
||||
var icon string
|
||||
var version string = "v1.0.0"
|
||||
var author string
|
||||
var create_at string
|
||||
var module bool
|
||||
var encrypt bool
|
||||
var onStart bool
|
||||
var origin = "自定义"
|
||||
var https = []*common.Http{}
|
||||
var message *common.Reply
|
||||
var FindAll bool
|
||||
var hasForm bool
|
||||
var carry bool
|
||||
var classes = []string{}
|
||||
ks := map[string]bool{}
|
||||
ress := regexp.MustCompile(
|
||||
`\*\s?@([\d\w+-]+)\s+([^\n]+?)\n`,
|
||||
).FindAllStringSubmatch(script, -1)
|
||||
for _, res := range ress {
|
||||
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)
|
||||
if len(ress) != 0 {
|
||||
res := ress[len(ress)-1]
|
||||
var inner = res[1]
|
||||
slice := strings.SplitN(inner, ":", 2)
|
||||
name := slice[0]
|
||||
ps := ""
|
||||
if len(slice) == 2 {
|
||||
ps = slice[1]
|
||||
}
|
||||
if strings.HasSuffix(name, "?") {
|
||||
name = strings.TrimRight(name, "?")
|
||||
rep := ""
|
||||
if ps == "" {
|
||||
rep = fmt.Sprintf("[%s]", name)
|
||||
} else {
|
||||
rep = fmt.Sprintf("[%s:%s]", name, ps)
|
||||
}
|
||||
for l := range _rs {
|
||||
_rs[l] = strings.Replace(_rs[l], res[0], rep, 1)
|
||||
}
|
||||
rule1 := strings.Replace(rule, res[0], rep, 1)
|
||||
if len(_rs) == 0 {
|
||||
_rs = append(_rs, rule1)
|
||||
}
|
||||
rule = strings.Replace(rule, res[0], "", 1)
|
||||
rule = regexp.MustCompile("\x20{2,}").ReplaceAllString(rule, " ")
|
||||
rule = strings.TrimSpace(rule)
|
||||
_rs = append(_rs, rule)
|
||||
goto FR
|
||||
}
|
||||
}
|
||||
if len(_rs) != 0 {
|
||||
rules = append(rules, _rs...)
|
||||
} else {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
case "class":
|
||||
classes = append(classes, regexp.MustCompile(`[\S]+`).FindAllString(res[2], -1)...)
|
||||
classes = utils.Unique(classes)
|
||||
case "platform", "imType", "platform+", "imType+":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
imType = &common.Filter{
|
||||
BlackMode: false,
|
||||
Items: item,
|
||||
}
|
||||
case "platform-", "imType-":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
imType = &common.Filter{
|
||||
BlackMode: true,
|
||||
Items: item,
|
||||
}
|
||||
case "userId", "userID", "uid", "userId+", "userID+", "uid+":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
userId = &common.Filter{
|
||||
BlackMode: false,
|
||||
Items: item,
|
||||
}
|
||||
case "userId-", "userID-", "uid-":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
userId = &common.Filter{
|
||||
BlackMode: true,
|
||||
Items: item,
|
||||
}
|
||||
case "groupId", "groupID", "groupCode", "chat_id", "chat_id+", "chatId", "chatID", "gid", "groupId+", "groupID+", "groupCode+", "chatId+", "chatID+", "gid+":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
groupId = &common.Filter{
|
||||
BlackMode: false,
|
||||
Items: item,
|
||||
}
|
||||
case "groupId-", "groupID-", "groupCode-", "chatId-", "chat_id-", "chatID-", "gid-":
|
||||
var item []string
|
||||
for _, i := range regexp.MustCompile(`[\d\w-]+`).FindAllString(res[2], -1) {
|
||||
item = append(item, strings.TrimSpace(i))
|
||||
}
|
||||
groupId = &common.Filter{
|
||||
BlackMode: true,
|
||||
Items: item,
|
||||
}
|
||||
|
||||
case "admin":
|
||||
admin = strings.TrimSpace(res[2]) == "true"
|
||||
case "disable":
|
||||
disable = strings.TrimSpace(res[2]) == "true"
|
||||
case "findall":
|
||||
FindAll = strings.TrimSpace(res[2]) == "true"
|
||||
case "priority":
|
||||
priority = utils.Int(strings.TrimSpace(res[2]))
|
||||
case "title", "name", "show":
|
||||
title = strings.TrimSpace(res[2])
|
||||
case "public":
|
||||
public = strings.TrimSpace(res[2]) == "true"
|
||||
case "description":
|
||||
description = strings.TrimSpace(res[2])
|
||||
case "icon":
|
||||
icon = strings.TrimSpace(res[2])
|
||||
case "version":
|
||||
version = strings.TrimSpace(res[2])
|
||||
case "author":
|
||||
author = strings.TrimSpace(res[2])
|
||||
case "http":
|
||||
ss := regexp.MustCompile(`[\S]+`).FindAllString(strings.TrimSpace(res[2]), -1)
|
||||
if len(ss) == 2 {
|
||||
https = append(https, &common.Http{
|
||||
Path: ss[1],
|
||||
Method: strings.ToUpper(ss[0]),
|
||||
})
|
||||
} else {
|
||||
console.Warn("http param is not 2")
|
||||
}
|
||||
case "message":
|
||||
ss := regexp.MustCompile(`[\S]+`).FindAllString(strings.TrimSpace(res[2]), -1)
|
||||
if len(ss) > 1 {
|
||||
if len(ss) == 2 && ss[1] == "*" {
|
||||
message = &common.Reply{
|
||||
Platform: ss[0],
|
||||
BotsID: []string{},
|
||||
}
|
||||
} else {
|
||||
message = &common.Reply{
|
||||
Platform: ss[0],
|
||||
BotsID: ss[1:],
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
console.Warn("message param is 0")
|
||||
}
|
||||
case "create_at":
|
||||
create_at = strings.TrimSpace(res[2])
|
||||
case "origin":
|
||||
origin = strings.TrimSpace(res[2])
|
||||
case "module":
|
||||
module = strings.TrimSpace(res[2]) == "true"
|
||||
case "carry":
|
||||
carry = strings.TrimSpace(res[2]) == "true"
|
||||
case "encrypt":
|
||||
encrypt = strings.TrimSpace(res[2]) == "true"
|
||||
case "on_start":
|
||||
onStart = strings.TrimSpace(res[2]) == "true"
|
||||
case "form":
|
||||
hasForm = true
|
||||
case "paterner":
|
||||
// paterner := strings.TrimSpace(res[2])
|
||||
// go func() {
|
||||
// time.Sleep(time.Second * 2)
|
||||
// getPaterner(uuid, strings.TrimSpace(paterner))
|
||||
// }()
|
||||
default:
|
||||
cron_ := strings.TrimSpace(res[2])
|
||||
cron_ = strings.ReplaceAll(cron_, `\/`, "/")
|
||||
if strings.HasPrefix(res[1], "cron") {
|
||||
cron[res[1]] = cron_
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasForm {
|
||||
hasForm = strings.Contains(script, "Form(")
|
||||
}
|
||||
return &common.Function{
|
||||
Rules: rules,
|
||||
ImType: imType,
|
||||
UserId: userId,
|
||||
GroupId: groupId,
|
||||
Cron: cron,
|
||||
Admin: admin,
|
||||
Priority: priority,
|
||||
Disable: disable,
|
||||
UUID: uuid,
|
||||
Title: title,
|
||||
Public: public,
|
||||
Description: description,
|
||||
Icon: icon,
|
||||
Version: version,
|
||||
Author: author,
|
||||
CreateAt: create_at,
|
||||
Module: module,
|
||||
Encrypt: encrypt,
|
||||
OnStart: onStart,
|
||||
Origin: origin,
|
||||
Running: onStart,
|
||||
Reply: message,
|
||||
Https: https,
|
||||
FindAll: FindAll,
|
||||
HasForm: hasForm,
|
||||
Carry: carry,
|
||||
Classes: classes,
|
||||
}, cbs
|
||||
}
|
||||
+2
-2
@@ -55,7 +55,7 @@ func RegistTasks(pt *Tasks) {
|
||||
for _, meta := range pt.Senders {
|
||||
adapter, _ := GetAdapter(meta.Platfrom, meta.BotID)
|
||||
if adapter != nil {
|
||||
sender := adapter.Sender2()
|
||||
sender := adapter.Sender2(nil)
|
||||
sender.SetFsps(&common.FakerSenderParams{
|
||||
Content: content,
|
||||
ChatID: meta.ChatID,
|
||||
@@ -324,7 +324,7 @@ func init() {
|
||||
functions := Functions
|
||||
for _, function := range functions {
|
||||
if function.UUID != "" {
|
||||
scripts[function.UUID] = function.Title + ".js"
|
||||
scripts[function.UUID] = function.Title + function.Suffix
|
||||
}
|
||||
}
|
||||
var user_names = []NicklabeL{}
|
||||
|
||||
Reference in New Issue
Block a user