x
This commit is contained in:
+19
-3
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,6 +15,13 @@ import (
|
|||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func checkFilePlugin(key string, value *string) {
|
||||||
|
if v, ok := plugins_id.Load(key); ok {
|
||||||
|
data, _ := os.ReadFile(v.(string))
|
||||||
|
*value = string(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var sillyGirl = MakeBucket("sillyGirl")
|
var sillyGirl = MakeBucket("sillyGirl")
|
||||||
GinApi(GET, "/api/storage/list", RequireAuth, func(ctx *gin.Context) {
|
GinApi(GET, "/api/storage/list", RequireAuth, func(ctx *gin.Context) {
|
||||||
@@ -35,7 +43,6 @@ func init() {
|
|||||||
ar := strings.SplitN(bk, ".", 2)
|
ar := strings.SplitN(bk, ".", 2)
|
||||||
if len(ar) == 2 {
|
if len(ar) == 2 {
|
||||||
if ar[0] == "plugins" && false { //todo
|
if ar[0] == "plugins" && false { //todo
|
||||||
|
|
||||||
// data[bk] = halfDeEct(MakeBucket(ar[0]).GetString(ar[1]))
|
// data[bk] = halfDeEct(MakeBucket(ar[0]).GetString(ar[1]))
|
||||||
} else {
|
} else {
|
||||||
// data[bk] = MakeBucket(ar[0]).GetString(ar[1])
|
// data[bk] = MakeBucket(ar[0]).GetString(ar[1])
|
||||||
@@ -138,8 +145,13 @@ func init() {
|
|||||||
for _, bk := range arr {
|
for _, bk := range arr {
|
||||||
ar := strings.SplitN(bk, ".", 2)
|
ar := strings.SplitN(bk, ".", 2)
|
||||||
if len(ar) == 2 {
|
if len(ar) == 2 {
|
||||||
if ar[0] == "plugins" && IsCdle { //todo
|
if ar[0] == "plugins" { //todo
|
||||||
data[bk] = DecryptPlugin(halfDeEct(MakeBucket(ar[0]).GetString(ar[1])))
|
value := MakeBucket(ar[0]).GetString(ar[1])
|
||||||
|
checkFilePlugin(ar[1], &value)
|
||||||
|
if IsCdle {
|
||||||
|
value = DecryptPlugin(halfDeEct(value))
|
||||||
|
}
|
||||||
|
data[bk] = value
|
||||||
} else {
|
} else {
|
||||||
data[bk] = TransformBucketKeyValue(MakeBucket(ar[0]).GetString(ar[1]))
|
data[bk] = TransformBucketKeyValue(MakeBucket(ar[0]).GetString(ar[1]))
|
||||||
}
|
}
|
||||||
@@ -182,6 +194,10 @@ func init() {
|
|||||||
for bk, v := range updates {
|
for bk, v := range updates {
|
||||||
ar := strings.SplitN(bk, ".", 2)
|
ar := strings.SplitN(bk, ".", 2)
|
||||||
if len(ar) == 2 {
|
if len(ar) == 2 {
|
||||||
|
if vv, ok := plugins_id.Load(ar[1]); ok {
|
||||||
|
os.WriteFile(vv.(string), []byte(fmt.Sprint(v)), 0755)
|
||||||
|
continue
|
||||||
|
}
|
||||||
msg, changed, err := SetBucketKeyValue(MakeBucket(ar[0]), ar[1], v)
|
msg, changed, err := SetBucketKeyValue(MakeBucket(ar[0]), ar[1], v)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
messages[bk] = msg
|
messages[bk] = msg
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -22,6 +21,8 @@ type Language struct {
|
|||||||
Links []string // 下载链接
|
Links []string // 下载链接
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var plugin_dir = utils.ExecPath + "/plugins"
|
||||||
|
|
||||||
var languages = []Language{
|
var languages = []Language{
|
||||||
{
|
{
|
||||||
Name: "node",
|
Name: "node",
|
||||||
@@ -40,7 +41,6 @@ var languages = []Language{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for _, item := range languages {
|
for _, item := range languages {
|
||||||
if !(item.Os == runtime.GOOS && item.Arch == runtime.GOARCH) {
|
if !(item.Os == runtime.GOOS && item.Arch == runtime.GOARCH) {
|
||||||
@@ -83,7 +83,7 @@ func init() {
|
|||||||
func unzip(filename string, perm fs.FileMode) error {
|
func unzip(filename string, perm fs.FileMode) error {
|
||||||
zipFile, err := zip.OpenReader(filename)
|
zipFile, err := zip.OpenReader(filename)
|
||||||
dir := filepath.Dir(filename)
|
dir := filepath.Dir(filename)
|
||||||
fmt.Println(filename, err)
|
// fmt.Println(filename, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-5
@@ -10,6 +10,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cdle/sillyplus/core/common"
|
"github.com/cdle/sillyplus/core/common"
|
||||||
"github.com/cdle/sillyplus/core/storage"
|
"github.com/cdle/sillyplus/core/storage"
|
||||||
@@ -96,6 +97,15 @@ func initNodePlugins() {
|
|||||||
info, err := os.Stat(event.Name)
|
info, err := os.Stat(event.Name)
|
||||||
// fmt.Println(err)
|
// fmt.Println(err)
|
||||||
if err == nil && info.IsDir() {
|
if err == nil && info.IsDir() {
|
||||||
|
event_name := event.Name + "/main.js"
|
||||||
|
if info, err := os.Stat(event_name); err == nil && !info.IsDir() {
|
||||||
|
AddNodePlugin(event_name, plugin_name)
|
||||||
|
} else {
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
if info, err := os.Stat(event_name); err == nil && !info.IsDir() {
|
||||||
|
AddNodePlugin(event_name, plugin_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
watcher.Add(event.Name)
|
watcher.Add(event.Name)
|
||||||
// fmt.Println("增加插件目录", event.Name)
|
// fmt.Println("增加插件目录", event.Name)
|
||||||
} else {
|
} else {
|
||||||
@@ -103,6 +113,7 @@ func initNodePlugins() {
|
|||||||
}
|
}
|
||||||
} else if plugin_index {
|
} else if plugin_index {
|
||||||
// fmt.Println("增加插件", event.Name)
|
// fmt.Println("增加插件", event.Name)
|
||||||
|
// RemNodePlugin(plugin_name)
|
||||||
AddNodePlugin(event.Name, plugin_name)
|
AddNodePlugin(event.Name, plugin_name)
|
||||||
}
|
}
|
||||||
case "REMOVE", "RENAME", "REMOVE|RENAME":
|
case "REMOVE", "RENAME", "REMOVE|RENAME":
|
||||||
@@ -115,7 +126,7 @@ func initNodePlugins() {
|
|||||||
// fmt.Println("移除插件", plugin_name)
|
// fmt.Println("移除插件", plugin_name)
|
||||||
RemNodePlugin(plugin_name)
|
RemNodePlugin(plugin_name)
|
||||||
}
|
}
|
||||||
case "WRITE":
|
case "WRITE": //, "CHMOD"
|
||||||
if plugin_index {
|
if plugin_index {
|
||||||
RemNodePlugin(plugin_name)
|
RemNodePlugin(plugin_name)
|
||||||
AddNodePlugin(event.Name, plugin_name)
|
AddNodePlugin(event.Name, plugin_name)
|
||||||
@@ -135,6 +146,7 @@ func RemNodePlugin(name string) error {
|
|||||||
pluginLock.Lock()
|
pluginLock.Lock()
|
||||||
defer pluginLock.Unlock()
|
defer pluginLock.Unlock()
|
||||||
key := nameUuid(name)
|
key := nameUuid(name)
|
||||||
|
plugins_id.Delete(key)
|
||||||
// fmt.Println("rem", key, name)
|
// fmt.Println("rem", key, name)
|
||||||
for i := range Functions {
|
for i := range Functions {
|
||||||
if Functions[i].UUID == key {
|
if Functions[i].UUID == key {
|
||||||
@@ -164,9 +176,12 @@ func nameUuid(name string) string {
|
|||||||
return uuid.NewSHA1(uuid.Nil, hash[:]).String()
|
return uuid.NewSHA1(uuid.Nil, hash[:]).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var plugins_id sync.Map
|
||||||
|
|
||||||
func AddNodePlugin(path, name string) error {
|
func AddNodePlugin(path, name string) error {
|
||||||
pluginLock.Lock()
|
pluginLock.Lock()
|
||||||
defer pluginLock.Unlock()
|
defer pluginLock.Unlock()
|
||||||
|
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -176,20 +191,21 @@ func AddNodePlugin(path, name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
uuid := nameUuid(name)
|
uuid := nameUuid(name)
|
||||||
|
plugins_id.Store(uuid, path)
|
||||||
// fmt.Println("add,", uuid, name)
|
// fmt.Println("add,", uuid, name)
|
||||||
f, cbs := pluginParse(string(data), uuid)
|
f, cbs := pluginParse(string(data), uuid)
|
||||||
f.Suffix = ".ts"
|
f.Suffix = ".js"
|
||||||
f.Type = "typescript"
|
f.Type = "typescript"
|
||||||
f.Handle = func(s common.Sender, f func(vm *goja.Runtime)) interface{} {
|
f.Handle = func(s common.Sender, f func(vm *goja.Runtime)) interface{} {
|
||||||
s.SetPluginID(uuid)
|
s.SetPluginID(uuid)
|
||||||
plt := s.GetImType()
|
plt := s.GetImType()
|
||||||
// , "/Users/a1-6/.nvm/versions/node/v18.16.1/lib/node_modules/ts-node/dist/bin.js",
|
// , "/Users/a1-6/.nvm/versions/node/v18.16.1/lib/node_modules/ts-node/dist/bin.js",
|
||||||
cmd := exec.Command(utils.ExecPath+"/language/node/node", path)
|
cmd := exec.Command("./node", path)
|
||||||
|
cmd.Dir = utils.ExecPath + "/language/node"
|
||||||
// cmd := exec.Command(utils.ExecPath+"/language/node/node", path)
|
// cmd := exec.Command(utils.ExecPath+"/language/node/node", path)
|
||||||
id := s.SetID()
|
id := s.SetID()
|
||||||
cmd.Env = append(cmd.Env, "SENDER_ID="+id)
|
cmd.Env = append(cmd.Env, "SENDER_ID="+id)
|
||||||
cmd.Env = append(cmd.Env, "PLUGIN_ID="+uuid)
|
cmd.Env = append(cmd.Env, "PLUGIN_ID="+uuid)
|
||||||
|
|
||||||
// 获取标准输出和标准错误输出的管道
|
// 获取标准输出和标准错误输出的管道
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -217,7 +233,6 @@ func AddNodePlugin(path, name string) error {
|
|||||||
// 处理标准输出
|
// 处理标准输出
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(stdout)
|
scanner := bufio.NewScanner(stdout)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
data := scanner.Text()
|
data := scanner.Text()
|
||||||
@@ -271,6 +286,9 @@ func AddNodePlugin(path, name string) error {
|
|||||||
for _, cb := range cbs {
|
for _, cb := range cbs {
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
|
if !f.OnStart {
|
||||||
|
console.Log("已加载 %s%s", f.Title, f.Suffix)
|
||||||
|
}
|
||||||
AddCommand([]*common.Function{f})
|
AddCommand([]*common.Function{f})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package core
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -113,6 +115,46 @@ func initPlugins() {
|
|||||||
if p.UUID != key {
|
if p.UUID != key {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if p.Type != "goja" { //下载目录插件
|
||||||
|
// Content-Type
|
||||||
|
var prefix = "?uuid=" + p.UUID
|
||||||
|
address := p.Address
|
||||||
|
if !strings.HasSuffix(address, "list.json") {
|
||||||
|
address = address + "/api/plugins/download" + prefix
|
||||||
|
} else {
|
||||||
|
address = strings.ReplaceAll(address, "list.json", "download"+prefix)
|
||||||
|
}
|
||||||
|
resp, err := http.Get(address)
|
||||||
|
if err != nil {
|
||||||
|
return &storage.Final{
|
||||||
|
Error: errors.New("插件源异常!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
zipfile := plugin_dir + "/" + utils.GenUUID() + ".zip"
|
||||||
|
f, err := os.OpenFile(zipfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return &storage.Final{
|
||||||
|
Error: errors.New("文件异常!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
_, err = io.Copy(f, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return &storage.Final{
|
||||||
|
Error: errors.New("下载异常!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer os.Remove(zipfile)
|
||||||
|
if err := unzip(zipfile, 0755); err != nil {
|
||||||
|
return &storage.Final{
|
||||||
|
Error: errors.New("安装异常!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &storage.Final{
|
||||||
|
Now: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
script := string(fetchScript(p.Address, key))
|
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{
|
fin = &storage.Final{
|
||||||
@@ -128,6 +170,7 @@ func initPlugins() {
|
|||||||
Error: errors.New("订阅源异常"),
|
Error: errors.New("订阅源异常"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+77
-3
@@ -1,6 +1,8 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -8,6 +10,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -71,9 +74,80 @@ func initWeb() {
|
|||||||
uuid := c.Query("uuid")
|
uuid := c.Query("uuid")
|
||||||
for _, f := range Functions {
|
for _, f := range Functions {
|
||||||
if f.UUID == uuid && f.Public {
|
if f.UUID == uuid && f.Public {
|
||||||
plugin_downloads.Set(f.UUID, plugin_downloads.GetInt(f.UUID)+1)
|
if f.Type == "goja" {
|
||||||
c.String(200, publicScript(plugins.GetString(f.UUID)))
|
plugin_downloads.Set(f.UUID, plugin_downloads.GetInt(f.UUID)+1)
|
||||||
return
|
c.String(200, publicScript(plugins.GetString(f.UUID)))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
v, ok := plugins_id.Load(f.UUID)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dir := filepath.Dir(v.(string))
|
||||||
|
if _, err := os.Stat(dir); err != nil { //执行压缩
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ss := strings.Split(dir, "/")
|
||||||
|
name := ss[len(ss)-1]
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w := zip.NewWriter(buf)
|
||||||
|
// dir = strings.Replace(dir, utils.ExecPath+"", ".", 1)
|
||||||
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 将路径转换为相对路径
|
||||||
|
relPath, err := filepath.Rel(dir, path)
|
||||||
|
relPath = name + "/" + relPath
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
fh, err := zip.FileInfoHeader(info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用相对路径作为文件名
|
||||||
|
fh.Name = relPath
|
||||||
|
|
||||||
|
wr, err := w.CreateHeader(fh)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(wr, file)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, fmt.Sprintf("ZIP creation failed: %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = w.Close()
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, fmt.Sprintf("ZIP creation failed: %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Data(http.StatusOK, "application/zip", buf.Bytes())
|
||||||
|
// zippath := utils.ExecPath + "/public/" + f.UUID + ".zip"
|
||||||
|
// file, err := os.Open(zippath)
|
||||||
|
// if err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// defer file.Close()
|
||||||
|
// c.Header("Content-Type", "application/zip")
|
||||||
|
// io.Copy(c.Writer, file)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user