diff --git a/core/node_temp.go b/core/node_temp.go index 8e1e789..4996a70 100644 --- a/core/node_temp.go +++ b/core/node_temp.go @@ -40,6 +40,9 @@ func (s *PersistentKeyValueStore) Set(key string, value interface{}, dur int) er ExpiredAt: expiredAt, } go func() { + defer func() { + recover() + }() jsonBytes, err := json.Marshal(s.data) if err == nil { ioutil.WriteFile(tempPath, jsonBytes, 0644) diff --git a/core/plugin_utils.go b/core/plugin_utils.go index c21b13b..f931769 100644 --- a/core/plugin_utils.go +++ b/core/plugin_utils.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/cdle/sillyplus/mongodb" "github.com/cdle/sillyplus/utils" "github.com/dop251/goja" "github.com/dop251/goja_nodejs/require" @@ -438,6 +439,11 @@ func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool, running func( vm.Set("os", osjs) vm.Set("fs", osjs) vm.Set("forObject", ForeachObject) + vm.Set("MongoClient", func(uri string) interface{} { + return &mongodb.MongoClient{ + Uri: uri, + } + }) } func EncryptPlugin(script string) string { diff --git a/go.mod b/go.mod index a1d0286..1f9e6f7 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/rivo/uniseg v0.4.4 github.com/robfig/cron/v3 v3.0.1 github.com/stretchr/testify v1.8.3 + go.mongodb.org/mongo-driver v1.11.7 golang.org/x/net v0.10.0 ) @@ -33,12 +34,20 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/golang/snappy v0.0.1 // indirect github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect + github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.1 // indirect + github.com/xdg-go/stringprep v1.0.3 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect golang.org/x/arch v0.3.0 // indirect + golang.org/x/sync v0.1.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cc4d27f..592a70c 100644 --- a/go.sum +++ b/go.sum @@ -72,6 +72,9 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -87,6 +90,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -109,6 +114,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= @@ -141,15 +148,27 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.11.7 h1:LIwYxASDLGUg/8wOhgOOZhX8tQa/9tgZPgzZoVqJvcs= +go.mongodb.org/mongo-driver v1.11.7/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -158,6 +177,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -169,6 +189,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= @@ -176,12 +197,15 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/mongodb/main.go b/mongodb/main.go new file mode 100644 index 0000000..4dca6a3 --- /dev/null +++ b/mongodb/main.go @@ -0,0 +1,156 @@ +package mongodb + +import ( + "context" + + "github.com/dop251/goja" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +type MongoClient struct { + client *mongo.Client + Uri string + Vm *goja.Runtime +} + +func (mc *MongoClient) Connect(uri string) { + var err error + if mc.Uri == "" { + mc.Uri = uri + } + mc.client, err = GetClient(mc.Uri) + if err != nil { + panic(mc.Vm.NewGoError(err)) + } +} + +func (mc *MongoClient) Db(dbname string) interface{} { + if mc.client == nil { + mc.Connect("") + } + return &MongoDB{ + Vm: mc.Vm, + database: mc.client.Database(dbname), + } +} + +type MongoDB struct { + database *mongo.Database + Vm *goja.Runtime +} + +func (db *MongoDB) Collection(clname string) interface{} { + return &Collection{ + Vm: db.Vm, + collection: db.database.Collection(clname), + } +} + +type Collection struct { + collection *mongo.Collection + Vm *goja.Runtime +} + +func (cl *Collection) InsertOne(insert map[string]interface{}) interface{} { + result, err := cl.collection.InsertOne(context.Background(), insert) + if err != nil { + + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) FindOne(filter interface{}) interface{} { + var result = map[string]interface{}{} + err := cl.collection.FindOne(context.Background(), filter).Decode(result) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) FindOneAndDelete(filter interface{}) interface{} { + var result = map[string]interface{}{} + err := cl.collection.FindOneAndDelete(context.Background(), filter).Decode(result) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) FindOneAndReplace(filter interface{}, replace interface{}) interface{} { + var result = map[string]interface{}{} + err := cl.collection.FindOneAndReplace(context.Background(), filter, replace).Decode(result) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) FindOneAndUpdate(filter interface{}, update interface{}) interface{} { + var result = map[string]interface{}{} + err := cl.collection.FindOneAndUpdate(context.Background(), filter, update).Decode(result) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) Find(filter interface{}) interface{} { + cur, err := cl.collection.Find(context.Background(), filter) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + defer cur.Close(context.Background()) + var results = []map[string]interface{}{} + for cur.Next(context.Background()) { + var person = map[string]interface{}{} + err := cur.Decode(&person) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + results = append(results, person) + } + if err := cur.Err(); err != nil { + panic(cl.Vm.NewGoError(err)) + } + return results +} + +func (cl *Collection) UpdateOne(filter, update interface{}, params map[string]interface{}) interface{} { + opts := []*options.UpdateOptions{} + if v, ok := params["upsert"]; ok { + opts = append(opts, options.Update().SetUpsert(v.(bool))) + } + result, err := cl.collection.UpdateOne(context.Background(), filter, update, opts...) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) UpdateMany(filter, update interface{}) interface{} { + + result, err := cl.collection.UpdateMany(context.Background(), filter, update) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) DeleteOne(filter interface{}) interface{} { + result, err := cl.collection.DeleteOne(context.Background(), filter) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} + +func (cl *Collection) DeleteMany(filter interface{}) interface{} { + result, err := cl.collection.DeleteMany(context.Background(), filter) + if err != nil { + panic(cl.Vm.NewGoError(err)) + } + return result +} diff --git a/mongodb/pool.go b/mongodb/pool.go new file mode 100644 index 0000000..f714a20 --- /dev/null +++ b/mongodb/pool.go @@ -0,0 +1,84 @@ +package mongodb + +import ( + "context" + "errors" + "sync" + "time" + + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +// MongoDB连接池 +type MongoDBPool struct { + clients map[string]*mongo.Client // 客户端连接map + mutex sync.Mutex // 互斥锁 +} + +var p *MongoDBPool + +// 创建一个新的MongoDB连接池 +func NewMongoDBPool() *MongoDBPool { + return &MongoDBPool{ + clients: make(map[string]*mongo.Client), + } +} + +// 获取一个MongoDB客户端连接 +func GetClient(uri string) (*mongo.Client, error) { + if p == nil { + p = NewMongoDBPool() + } + // 加锁 + p.mutex.Lock() + defer p.mutex.Unlock() + + // 检查连接是否存在 + if client, ok := p.clients[uri]; ok { + return client, nil + } + + // 创建新的连接 + client, err := mongo.NewClient(options.Client().ApplyURI(uri)) + if err != nil { + return nil, err + } + + // 连接数据库 + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err = client.Connect(ctx) + if err != nil { + return nil, err + } + + // 保存连接 + p.clients[uri] = client + + return client, nil +} + +// 关闭一个MongoDB客户端连接 +func CloseClient(uri string) error { + // 加锁 + p.mutex.Lock() + defer p.mutex.Unlock() + + // 检查连接是否存在 + if client, ok := p.clients[uri]; ok { + // 关闭连接 + err := client.Disconnect(context.Background()) + if err != nil { + return err + } + + // 删除连接 + delete(p.clients, uri) + + return nil + } + + return errors.New("client not found") +}