x
This commit is contained in:
+79
@@ -0,0 +1,79 @@
|
|||||||
|
# 使用Alpine镜像作为基础镜像
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# 将APK源更换为国内源(这里使用阿里云的源)
|
||||||
|
RUN echo "https://mirrors.aliyun.com/alpine/latest-stable/main" > /etc/apk/repositories && \
|
||||||
|
echo "https://mirrors.aliyun.com/alpine/latest-stable/community" >> /etc/apk/repositories
|
||||||
|
|
||||||
|
# 更新软件包索引并安装必要的工具
|
||||||
|
RUN apk update && apk add --no-cache \
|
||||||
|
python3 \
|
||||||
|
py3-pip \
|
||||||
|
php \
|
||||||
|
php-json \
|
||||||
|
php-phar \
|
||||||
|
php-openssl \
|
||||||
|
php-pdo \
|
||||||
|
php-mysqli \
|
||||||
|
php-session \
|
||||||
|
php-ctype \
|
||||||
|
php-tokenizer \
|
||||||
|
php-dom \
|
||||||
|
php-xml \
|
||||||
|
php-xmlwriter \
|
||||||
|
php-mbstring \
|
||||||
|
php-simplexml \
|
||||||
|
php-fileinfo \
|
||||||
|
php-opcache \
|
||||||
|
php-zlib \
|
||||||
|
php-curl \
|
||||||
|
php-ftp \
|
||||||
|
php-gd \
|
||||||
|
php-xmlreader \
|
||||||
|
php-pdo_mysql \
|
||||||
|
php-pdo_sqlite \
|
||||||
|
php-pdo_pgsql \
|
||||||
|
php-posix \
|
||||||
|
php-sockets \
|
||||||
|
php-bcmath \
|
||||||
|
php-redis \
|
||||||
|
php-pear \
|
||||||
|
php-dev \
|
||||||
|
php-pear-grpc \
|
||||||
|
curl \
|
||||||
|
git
|
||||||
|
|
||||||
|
# 安装gRPC扩展
|
||||||
|
RUN pecl install grpc
|
||||||
|
|
||||||
|
# 清理缓存和临时文件
|
||||||
|
RUN rm -rf /tmp/* /var/cache/apk/*
|
||||||
|
|
||||||
|
# 下载文件
|
||||||
|
RUN mkdir -p /usr/local/sillyGirl \
|
||||||
|
&& ARCH=$(uname -m) \
|
||||||
|
&& DOWNLOAD_URL="" \
|
||||||
|
&& if [ "$ARCH" = "x86_64" ]; then \
|
||||||
|
DOWNLOAD_URL="https://github.com/cdle/sillyGirl/releases/download/main/sillyGirl_linux_amd64"; \
|
||||||
|
elif [ "$ARCH" = "aarch64" ]; then \
|
||||||
|
DOWNLOAD_URL="https://github.com/cdle/sillyGirl/releases/download/main/sillyGirl_linux_arm64"; \
|
||||||
|
elif [ "$ARCH" = "armv7l" ]; then \
|
||||||
|
DOWNLOAD_URL="https://github.com/cdle/sillyGirl/releases/download/main/sillyGirl_linux_armv7"; \
|
||||||
|
else \
|
||||||
|
echo "Unsupported architecture: $ARCH"; \
|
||||||
|
exit 1; \
|
||||||
|
fi \
|
||||||
|
&& curl -sSL --connect-timeout 20 -f "$DOWNLOAD_URL" -o /usr/local/sillyGirl/sillyGirl \
|
||||||
|
|| (echo "Download from original address failed, trying proxy address..." \
|
||||||
|
&& curl -sSL --connect-timeout 60 -f https://ghproxy.com/"$DOWNLOAD_URL" -o /usr/local/sillyGirl/sillyGirl) \
|
||||||
|
&& chmod +x /usr/local/sillyGirl/sillyGirl
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /usr/local/sillyGirl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 指定容器启动时要运行的命令
|
||||||
|
CMD ["/usr/local/sillyGirl/sillyGirl"]
|
||||||
@@ -18,6 +18,9 @@ type SillyGirlService struct {
|
|||||||
func (sg *SillyGirlService) BucketWatch(stream srpc.SillyGirlService_BucketWatchServer) error {
|
func (sg *SillyGirlService) BucketWatch(stream srpc.SillyGirlService_BucketWatchServer) error {
|
||||||
var watcher func(old, new, key string) *storage.Final
|
var watcher func(old, new, key string) *storage.Final
|
||||||
var echos sync.Map
|
var echos sync.Map
|
||||||
|
defer func() {
|
||||||
|
watcher = nil
|
||||||
|
}()
|
||||||
for {
|
for {
|
||||||
req, err := stream.Recv()
|
req, err := stream.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -25,6 +28,9 @@ func (sg *SillyGirlService) BucketWatch(stream srpc.SillyGirlService_BucketWatch
|
|||||||
}
|
}
|
||||||
if watcher == nil {
|
if watcher == nil {
|
||||||
watcher = func(old, new, key string) *storage.Final {
|
watcher = func(old, new, key string) *storage.Final {
|
||||||
|
if watcher == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
echo := utils.GenUUID()
|
echo := utils.GenUUID()
|
||||||
ch := make(chan *storage.Final)
|
ch := make(chan *storage.Final)
|
||||||
echos.Store(echo, ch)
|
echos.Store(echo, ch)
|
||||||
@@ -64,6 +70,7 @@ func (sg *SillyGirlService) BucketWatch(stream srpc.SillyGirlService_BucketWatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get implements BucketServiceServer.Get.
|
// Get implements BucketServiceServer.Get.
|
||||||
|
|||||||
+100
-42
@@ -7,6 +7,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -32,7 +33,6 @@ func initNodePlugins() {
|
|||||||
plugins := []string{root}
|
plugins := []string{root}
|
||||||
os.Mkdir(root, 0755)
|
os.Mkdir(root, 0755)
|
||||||
// fmt.Println("root", root)
|
// fmt.Println("root", root)
|
||||||
|
|
||||||
files, _ := ioutil.ReadDir(root)
|
files, _ := ioutil.ReadDir(root)
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if !file.IsDir() {
|
if !file.IsDir() {
|
||||||
@@ -41,9 +41,10 @@ func initNodePlugins() {
|
|||||||
name := file.Name()
|
name := file.Name()
|
||||||
path := root + "/" + name
|
path := root + "/" + name
|
||||||
plugins = append(plugins, path)
|
plugins = append(plugins, path)
|
||||||
index := path + "/main.js"
|
index, class := FindMainIndex(path)
|
||||||
if info, err := os.Stat(index); err == nil && !info.IsDir() {
|
|
||||||
AddNodePlugin(index, name)
|
if index != "" {
|
||||||
|
AddNodePlugin(index, name, class)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
@@ -73,18 +74,20 @@ func initNodePlugins() {
|
|||||||
var plugin_dir = false
|
var plugin_dir = false
|
||||||
var plugin_index = false
|
var plugin_index = false
|
||||||
var plugin_name = ""
|
var plugin_name = ""
|
||||||
|
var class = ""
|
||||||
switch len(files) {
|
switch len(files) {
|
||||||
case 1:
|
case 1:
|
||||||
plugin_dir = true
|
plugin_dir = true
|
||||||
// fmt.Println("目录事件")
|
// fmt.Println("目录事件")
|
||||||
plugin_name = files[0]
|
plugin_name = files[0]
|
||||||
case 2:
|
case 2:
|
||||||
if files[1] == "main.ts" || files[1] == "main.js" {
|
class, plugin_index = CheckMainIndex(files[1])
|
||||||
if files[1] == "main.js" {
|
// if files[1] == "main.js" {
|
||||||
plugin_index = true
|
// if files[1] == "main.js" {
|
||||||
}
|
// plugin_index = true
|
||||||
// fmt.Println("入口文件事件")
|
// }
|
||||||
}
|
// // fmt.Println("入口文件事件")
|
||||||
|
// }
|
||||||
plugin_name = files[0]
|
plugin_name = files[0]
|
||||||
}
|
}
|
||||||
if plugin_name == "." {
|
if plugin_name == "." {
|
||||||
@@ -96,52 +99,62 @@ 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"
|
index, class := FindMainIndex(event.Name)
|
||||||
if info, err := os.Stat(event_name); err == nil && !info.IsDir() {
|
switch class {
|
||||||
AddNodePlugin(event_name, plugin_name)
|
case NODE:
|
||||||
} else {
|
AddNodePlugin(index, plugin_name, class)
|
||||||
time.Sleep(time.Millisecond * 100)
|
case PYTHON:
|
||||||
if info, err := os.Stat(event_name); err == nil && !info.IsDir() {
|
case "":
|
||||||
AddNodePlugin(event_name, plugin_name)
|
// time.Sleep(time.Millisecond * 100) //如果没有
|
||||||
}
|
// if info, err := os.Stat(event.Name + "/demo.main.js"); 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 {
|
||||||
// fmt.Println("非插件目录", event.Name)
|
// fmt.Println("非插件目录", event.Name)
|
||||||
}
|
}
|
||||||
tf := event.Name + "/node_modules/sillygirl.d.ts"
|
// tf := event.Name + "/node_modules/sillygirl.d.ts"
|
||||||
ti := event.Name + "/main.js"
|
// ti := event.Name + "/demo.main.js"
|
||||||
if _, err := os.Stat(tf); err != nil {
|
// if _, err := os.Stat(tf); err != nil {
|
||||||
os.Mkdir(event.Name+"/node_modules", 0700)
|
// os.Mkdir(event.Name+"/node_modules", 0700)
|
||||||
os.WriteFile(tf, []byte(typeat), 0700)
|
// os.WriteFile(tf, []byte(typeat), 0700)
|
||||||
}
|
// }
|
||||||
go func() {
|
// go func() {
|
||||||
time.Sleep(time.Second)
|
// time.Sleep(time.Second)
|
||||||
if _, err := os.Stat(ti); err != nil {
|
// if _, err := os.Stat(ti); err != nil {
|
||||||
os.Mkdir(event.Name+"/node_modules", 0700)
|
// os.Mkdir(event.Name+"/node_modules", 0700)
|
||||||
os.WriteFile(ti, []byte(defaultScript(plugin_name)), 0700)
|
// os.WriteFile(ti, []byte(defaultScript(plugin_name)), 0700)
|
||||||
}
|
// }
|
||||||
}()
|
// }()
|
||||||
} else if plugin_index {
|
} else if plugin_index {
|
||||||
// fmt.Println("增加插件", event.Name)
|
// fmt.Println("增加插件", event.Name)
|
||||||
// RemNodePlugin(plugin_name)
|
// RemNodePlugin(plugin_name)
|
||||||
AddNodePlugin(event.Name, plugin_name)
|
AddNodePlugin(event.Name, plugin_name, class)
|
||||||
}
|
}
|
||||||
case "REMOVE", "RENAME", "REMOVE|RENAME", "REMOVE|WRITE":
|
case "REMOVE", "RENAME", "REMOVE|RENAME", "REMOVE|WRITE":
|
||||||
if plugin_dir {
|
if plugin_dir {
|
||||||
watcher.Remove(event.Name)
|
watcher.Remove(event.Name)
|
||||||
// fmt.Println("移除插件目录", event.Name)
|
// fmt.Println("移除插件目录", event.Name)
|
||||||
// fmt.Println("移除插件", plugin_name)
|
// fmt.Println("移除插件", plugin_name)
|
||||||
AddNodePlugin(event.Name, plugin_name)
|
AddNodePlugin(event.Name, plugin_name, UNKNOWN)
|
||||||
|
|
||||||
} else if plugin_index {
|
} else if plugin_index {
|
||||||
// fmt.Println("移除插件", plugin_name)
|
// fmt.Println("移除插件", plugin_name)
|
||||||
AddNodePlugin(event.Name, plugin_name)
|
AddNodePlugin(event.Name, plugin_name, class)
|
||||||
}
|
}
|
||||||
case "WRITE": //, "CHMOD"
|
case "WRITE": //, "CHMOD"
|
||||||
if plugin_index {
|
if plugin_index {
|
||||||
AddNodePlugin(event.Name, plugin_name)
|
AddNodePlugin(event.Name, plugin_name, class)
|
||||||
// fmt.Println("变更插件", event.Name, plugin_name)
|
// fmt.Println("变更插件", event.Name, plugin_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +176,8 @@ func isNameUuid(uuid string) bool {
|
|||||||
return strings.Contains(uuid, "_")
|
return strings.Contains(uuid, "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddNodePlugin(path, name string) error {
|
func AddNodePlugin(path, name, class string) error {
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -212,17 +226,34 @@ func AddNodePlugin(path, name string) error {
|
|||||||
// fmt.Println("add,", uuid, name)
|
// fmt.Println("add,", uuid, name)
|
||||||
f, cbs := pluginParse(script, uuid)
|
f, cbs := pluginParse(script, uuid)
|
||||||
f.Reload = func() { //重载
|
f.Reload = func() { //重载
|
||||||
AddNodePlugin(path, name)
|
AddNodePlugin(path, name, class)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Type = class
|
||||||
|
switch f.Type {
|
||||||
|
case NODE:
|
||||||
|
f.Suffix = ".js"
|
||||||
|
case PYTHON:
|
||||||
|
f.Suffix = ".py"
|
||||||
}
|
}
|
||||||
f.Suffix = ".js"
|
|
||||||
f.Type = "node"
|
|
||||||
f.Path = path
|
f.Path = path
|
||||||
f.Handle = func(s common.Sender, _ func(vm *goja.Runtime)) interface{} {
|
f.Handle = func(s common.Sender, _ func(vm *goja.Runtime)) interface{} {
|
||||||
console := &Console{UUID: uuid}
|
console := &Console{UUID: uuid}
|
||||||
s.SetPluginID(uuid)
|
s.SetPluginID(uuid)
|
||||||
plt := s.GetImType()
|
plt := s.GetImType()
|
||||||
cmd := exec.Command("./node", path)
|
bin := ""
|
||||||
cmd.Dir = utils.ExecPath + "/language/node"
|
var cmd *exec.Cmd
|
||||||
|
switch class {
|
||||||
|
case NODE:
|
||||||
|
bin = utils.ExecPath + "/language/node/node"
|
||||||
|
cmd = exec.Command(bin, path)
|
||||||
|
case PYTHON:
|
||||||
|
bin = "python3"
|
||||||
|
cmd = exec.Command(bin, "-u", path)
|
||||||
|
cmd.Env = append(cmd.Env, "PYTHONPATH=/Users/a1-6/Code/sillyplus/proto3")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Dir = filepath.Dir(path)
|
||||||
RUNTIME_ID := utils.GenUUID()
|
RUNTIME_ID := utils.GenUUID()
|
||||||
cmd.Env = append(cmd.Env, "RUNTIME_ID="+RUNTIME_ID)
|
cmd.Env = append(cmd.Env, "RUNTIME_ID="+RUNTIME_ID)
|
||||||
cmd.Env = append(cmd.Env, "PLUGIN_ID="+uuid)
|
cmd.Env = append(cmd.Env, "PLUGIN_ID="+uuid)
|
||||||
@@ -249,6 +280,7 @@ 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()
|
||||||
@@ -467,3 +499,29 @@ const {
|
|||||||
} = require("sillygirl");
|
} = require("sillygirl");
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
NODE = "node"
|
||||||
|
PYTHON = "python3"
|
||||||
|
UNKNOWN = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FindMainIndex(home string) (string, string) {
|
||||||
|
if info, err := os.Stat(home + "/main.js"); err == nil && !info.IsDir() {
|
||||||
|
return home + "/main.js", NODE
|
||||||
|
}
|
||||||
|
if info, err := os.Stat(home + "/main.py"); err == nil && !info.IsDir() {
|
||||||
|
return home + "/main.py", PYTHON
|
||||||
|
}
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckMainIndex(filename string) (string, bool) {
|
||||||
|
switch filename {
|
||||||
|
case "main.js":
|
||||||
|
return NODE, true
|
||||||
|
case "main.py":
|
||||||
|
return PYTHON, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ import (
|
|||||||
var senderRegisters sync.Map
|
var senderRegisters sync.Map
|
||||||
|
|
||||||
func getRegisterSenderByCtx(ctx context.Context, uuid string) (common.Sender, error) {
|
func getRegisterSenderByCtx(ctx context.Context, uuid string) (common.Sender, error) {
|
||||||
|
// if uuid == "" { //临时---====+++测试
|
||||||
|
// plt, _ := GetAdapter("terminal", "default")
|
||||||
|
// return plt.Sender2(map[string]string{
|
||||||
|
// CONETNT: "hello",
|
||||||
|
// USER_ID: "user_id",
|
||||||
|
// CHAT_ID: "chat_id",
|
||||||
|
// MESSAGE_ID: "MESSAGE_ID",
|
||||||
|
// }), nil
|
||||||
|
// }
|
||||||
md, ok := metadata.FromIncomingContext(ctx)
|
md, ok := metadata.FromIncomingContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing metadata")
|
return nil, fmt.Errorf("missing metadata")
|
||||||
|
|||||||
+20
-5
@@ -114,9 +114,12 @@ func (sg *SillyGirlService) SenderListen(stream srpc.SillyGirlService_SenderList
|
|||||||
var carry *Carry
|
var carry *Carry
|
||||||
var echos sync.Map
|
var echos sync.Map
|
||||||
var persistent bool
|
var persistent bool
|
||||||
// defer fmt.Println("已关闭,", "===")
|
ctx := stream.Context()
|
||||||
|
|
||||||
|
defer fmt.Println("已关闭,", "===")
|
||||||
for {
|
for {
|
||||||
req, err := stream.Recv()
|
req, err := stream.Recv()
|
||||||
|
// fmt.Println("req", string(utils.JsonMarshal(req)))
|
||||||
// fmt.Println("carry", carry, err)
|
// fmt.Println("carry", carry, err)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break // 如果流已经关闭,则退出循环
|
break // 如果流已经关闭,则退出循环
|
||||||
@@ -187,30 +190,42 @@ func (sg *SillyGirlService) SenderListen(stream srpc.SillyGirlService_SenderList
|
|||||||
persistent = req.Persistent
|
persistent = req.Persistent
|
||||||
options = append(options, "persistent")
|
options = append(options, "persistent")
|
||||||
} else {
|
} else {
|
||||||
options = append(options, func(err error) {
|
// fmt.Println("???")
|
||||||
stream.Send(&srpc.SenderListenResponse{Echo: ""})
|
options = append(options, func(err error) { //超时
|
||||||
|
stream.Send(&srpc.SenderListenResponse{Echo: "END"})
|
||||||
})
|
})
|
||||||
|
// fmt.Println("?????")
|
||||||
}
|
}
|
||||||
level := s.GetLevel()
|
level := s.GetLevel()
|
||||||
|
|
||||||
go s.Await(s, func(s common.Sender) interface{} {
|
go s.Await(s, func(s common.Sender) interface{} {
|
||||||
s.SetLevel(level + 1)
|
s.SetLevel(level + 1)
|
||||||
echo := utils.GenUUID()
|
echo := utils.GenUUID()
|
||||||
ch := make(chan string)
|
ch := make(chan string)
|
||||||
echos.Store(echo, ch)
|
echos.Store(echo, ch)
|
||||||
defer echos.Delete(echo)
|
defer echos.Delete(echo)
|
||||||
|
// fmt.Println("tosend")
|
||||||
stream.Send(&srpc.SenderListenResponse{Echo: echo, Uuid: register(s)})
|
stream.Send(&srpc.SenderListenResponse{Echo: echo, Uuid: register(s)})
|
||||||
value := <-ch
|
// fmt.Println("sended")
|
||||||
|
value := ""
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
case value = <-ch:
|
||||||
|
}
|
||||||
|
// fmt.Println("value := <-ch")
|
||||||
if !persistent {
|
if !persistent {
|
||||||
if strings.HasPrefix(value, "go_again_") {
|
if strings.HasPrefix(value, "go_again_") {
|
||||||
value = strings.Replace(value, "go_again_", "", 1)
|
value = strings.Replace(value, "go_again_", "", 1)
|
||||||
return GoAgain(value)
|
return GoAgain(value)
|
||||||
} else {
|
} else {
|
||||||
|
// fmt.Println("toend")
|
||||||
stream.Send(&srpc.SenderListenResponse{Echo: "END"})
|
stream.Send(&srpc.SenderListenResponse{Echo: "END"})
|
||||||
|
// fmt.Println("ended")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = strings.Replace(value, "go_again_", "", 1)
|
value = strings.Replace(value, "go_again_", "", 1)
|
||||||
}
|
}
|
||||||
|
// fmt.Println("watch pver")
|
||||||
return value
|
return value
|
||||||
}, options...)
|
}, options...)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -201,7 +201,7 @@ func initPlugins() {
|
|||||||
// fmt.Println(strings.Join(ss, " "))
|
// fmt.Println(strings.Join(ss, " "))
|
||||||
l := len(ss)
|
l := len(ss)
|
||||||
if l > 2 {
|
if l > 2 {
|
||||||
go AddNodePlugin(filename, ss[l-1])
|
go AddNodePlugin(filename, ss[l-1], f.Type)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := os.WriteFile(filename, []byte(new), 0755)
|
err := os.WriteFile(filename, []byte(new), 0755)
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ func main() {
|
|||||||
a := &core.Factory{}
|
a := &core.Factory{}
|
||||||
a.Init("terminal", "default", nil)
|
a.Init("terminal", "default", nil)
|
||||||
i := 0
|
i := 0
|
||||||
|
a.SetIsAdmin(func(s string) bool {
|
||||||
|
return true
|
||||||
|
})
|
||||||
a.SetReplyHandler(func(m map[string]interface{}) string {
|
a.SetReplyHandler(func(m map[string]interface{}) string {
|
||||||
i++
|
i++
|
||||||
fmt.Printf("\x1b[%dm%s \x1b[0m\n", 31, m[core.CONETNT])
|
fmt.Printf("\x1b[%dm%s \x1b[0m\n", 31, m[core.CONETNT])
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from distutils.core import setup
|
||||||
|
from Cython.Build import cythonize
|
||||||
|
|
||||||
|
setup(
|
||||||
|
ext_modules = cythonize("sillygirl.py"),
|
||||||
|
libraries=[
|
||||||
|
"srpc_pb2",
|
||||||
|
"srpc_pb2_grpc",
|
||||||
|
"grpc",
|
||||||
|
"google.protobuf",
|
||||||
|
] # 指定第三方依赖项所在的库
|
||||||
|
)
|
||||||
+446
-80
@@ -1,20 +1,26 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json, pickle, base64, os, grpc
|
import json, pickle, base64, os, grpc
|
||||||
import time
|
|
||||||
import random
|
|
||||||
import threading
|
|
||||||
from queue import Queue
|
|
||||||
|
|
||||||
import srpc_pb2, srpc_pb2_grpc
|
import srpc_pb2, srpc_pb2_grpc
|
||||||
|
|
||||||
plugin_id = os.environ.get("PLUGIN_ID", "")
|
plugin_id = os.environ.get("PLUGIN_ID", "")
|
||||||
runtime_id = os.environ.get("RUNTIME_ID", "")
|
runtime_id = os.environ.get("RUNTIME_ID", "")
|
||||||
|
|
||||||
metadata = (("RUNTIME_ID", runtime_id),)
|
metadata = [("runtime_id", runtime_id)]
|
||||||
metadata = grpc.metadata_call_credentials(metadata)
|
channel = None
|
||||||
|
stub = None
|
||||||
|
|
||||||
channel = grpc.insecure_channel("localhost:50051")
|
|
||||||
stub = srpc_pb2_grpc.SillyGirlServiceStub(channel)
|
def get_stub(): # 异步
|
||||||
|
global stub, channel
|
||||||
|
if stub == None:
|
||||||
|
channel = grpc.insecure_channel("localhost:50051")
|
||||||
|
stub = srpc_pb2_grpc.SillyGirlServiceStub(channel)
|
||||||
|
return stub
|
||||||
|
|
||||||
|
|
||||||
|
channel2 = grpc.aio.insecure_channel("localhost:50051")
|
||||||
|
stub2 = srpc_pb2_grpc.SillyGirlServiceStub(channel2)
|
||||||
|
|
||||||
|
|
||||||
def transform(value):
|
def transform(value):
|
||||||
@@ -57,136 +63,496 @@ def reverseTransform(value):
|
|||||||
class Bucket:
|
class Bucket:
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.__name = name
|
self.__name = name
|
||||||
print("name=", name, "self.__name=", self.__name)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.get(key)
|
return self.__get(key)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return self.get(name)
|
return self.__get(name)
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.set(key, value)
|
self.__set(key, value)
|
||||||
|
# asyncio.ensure_future(self.set(key, value))
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name in ["data", "_Bucket__name"]:
|
if name in ["data", "_Bucket__name"]:
|
||||||
# 使用object类的方法设置属性,避免无限递归
|
# 使用object类的方法设置属性,避免无限递归
|
||||||
object.__setattr__(self, name, value)
|
object.__setattr__(self, name, value)
|
||||||
else:
|
else:
|
||||||
self.set(name, value)
|
self.__set(name, value)
|
||||||
|
# asyncio.ensure_future(self.set(name, value))
|
||||||
|
|
||||||
def get(self, key, defaultValue=None):
|
async def get(self, key, defaultValue=None):
|
||||||
request = srpc_pb2.BucketKeyRequest(name=self.__name, key=key)
|
request = srpc_pb2.BucketKeyRequest(name=self.__name, key=key)
|
||||||
response = stub.BucketGet(request)
|
response = await stub2.BucketGet(request)
|
||||||
if response.value != "":
|
if response.value != "":
|
||||||
return transform(response.value)
|
return transform(response.value)
|
||||||
else:
|
else:
|
||||||
return defaultValue
|
return defaultValue
|
||||||
|
|
||||||
def set(self, key, value):
|
def __get(self, key, defaultValue=None):
|
||||||
request = srpc_pb2.BucketSetRequest(
|
request = srpc_pb2.BucketKeyRequest(name=self.__name, key=key)
|
||||||
name=self.__name, key=key, value=reverseTransform(value)
|
response = get_stub().BucketGet(request)
|
||||||
)
|
if response.value != "":
|
||||||
response = stub.BucketSet(request)
|
return transform(response.value)
|
||||||
return {"message": response.message, "changed": response.changed}
|
else:
|
||||||
|
return defaultValue
|
||||||
|
|
||||||
def delete(self, key):
|
def __set(self, key, value):
|
||||||
return self.set(key, None)
|
try:
|
||||||
|
request = srpc_pb2.BucketSetRequest(
|
||||||
|
name=self.__name, key=key, value=reverseTransform(value)
|
||||||
|
)
|
||||||
|
response = get_stub().BucketSet(request)
|
||||||
|
return {"message": response.message, "changed": response.changed}
|
||||||
|
except Exception as e:
|
||||||
|
return {"error": "fail to set value"}
|
||||||
|
|
||||||
def deleteAll(self):
|
async def set(self, key, value):
|
||||||
|
try:
|
||||||
|
request = srpc_pb2.BucketSetRequest(
|
||||||
|
name=self.__name, key=key, value=reverseTransform(value)
|
||||||
|
)
|
||||||
|
response = await stub2.BucketSet(request)
|
||||||
|
return {"message": response.message, "changed": response.changed}
|
||||||
|
except Exception as e:
|
||||||
|
return {"error": "fail to set value"}
|
||||||
|
|
||||||
|
async def delete(self, key):
|
||||||
|
return await self.set(key, None)
|
||||||
|
|
||||||
|
async def deleteAll(self):
|
||||||
request = srpc_pb2.BucketRequest(name=self.__name)
|
request = srpc_pb2.BucketRequest(name=self.__name)
|
||||||
stub.BucketDelete(request)
|
await stub2.BucketDelete(request)
|
||||||
|
|
||||||
def keys(self):
|
async def keys(self):
|
||||||
print("name", self.__name)
|
print("name", self.__name)
|
||||||
request = srpc_pb2.BucketKeyRequest(name=self.__name)
|
request = srpc_pb2.BucketKeyRequest(name=self.__name)
|
||||||
response = stub.BucketKeys(request)
|
response = await stub2.BucketKeys(request)
|
||||||
return list(response.keys)
|
return list(response.keys)
|
||||||
|
|
||||||
def len(self):
|
async def len(self):
|
||||||
request = srpc_pb2.BucketRequest(name=self.__name)
|
request = srpc_pb2.BucketRequest(name=self.__name)
|
||||||
response = stub.BucketLen(request)
|
response = await stub2.BucketLen(request)
|
||||||
return response.length
|
return response.length
|
||||||
|
|
||||||
def buckets(self):
|
async def buckets(self):
|
||||||
request = srpc_pb2.Empty()
|
request = srpc_pb2.Empty()
|
||||||
response = stub.BucketBuckets(request)
|
response = await stub2.BucketBuckets(request)
|
||||||
return list(response.buckets)
|
return list(response.buckets)
|
||||||
|
|
||||||
def watch(self):
|
def watch(self, key, handle):
|
||||||
def watch_thread(self, key, handle):
|
async def __watch(self, key, handle):
|
||||||
queue = Queue()
|
queue = asyncio.Queue()
|
||||||
def entry_request_iterator():
|
|
||||||
|
async def entry_request_iterator():
|
||||||
yield srpc_pb2.BucketWatchRequest(
|
yield srpc_pb2.BucketWatchRequest(
|
||||||
name=self.__name, key=key, plugin_id=plugin_id
|
name=self.__name, key=key, plugin_id=plugin_id
|
||||||
)
|
)
|
||||||
while True:
|
while True:
|
||||||
yield queue.get()
|
yield await queue.get()
|
||||||
print("queue.get()")
|
|
||||||
# 阻塞A区 等待B区发送数据
|
|
||||||
|
|
||||||
generator = entry_request_iterator()
|
generator = entry_request_iterator()
|
||||||
for response in stub.BucketWatch(generator):
|
response_iterator = stub2.BucketWatch(generator)
|
||||||
print("Server response:", response)
|
async for response in response_iterator:
|
||||||
old = transform(response.old)
|
old = transform(response.old)
|
||||||
now = transform(response.now)
|
now = transform(response.now)
|
||||||
result = handle(old, now, response.key)
|
|
||||||
try:
|
try:
|
||||||
fin = result
|
result = await handle(old, now, response.key)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
continue
|
continue
|
||||||
storage_modifier = {
|
storage_modifier = {
|
||||||
"echo": response.echo,
|
"echo": response.echo,
|
||||||
}
|
}
|
||||||
if not fin:
|
if not result:
|
||||||
storage_modifier["error"] = "VOID"
|
storage_modifier["error"] = "VOID"
|
||||||
else:
|
else:
|
||||||
if "now" in fin:
|
if "now" in result:
|
||||||
storage_modifier["now"] = reverseTransform(fin["now"])
|
storage_modifier["now"] = reverseTransform(result["now"])
|
||||||
if "message" in fin:
|
if "message" in result:
|
||||||
storage_modifier["message"] = fin["message"]
|
storage_modifier["message"] = result["message"]
|
||||||
if "error" in fin:
|
if "error" in result:
|
||||||
storage_modifier["error"] = fin["error"]
|
storage_modifier["error"] = result["error"]
|
||||||
queue.put(srpc_pb2.BucketWatchRequest(**storage_modifier))
|
await queue.put(srpc_pb2.BucketWatchRequest(**storage_modifier))
|
||||||
|
|
||||||
|
asyncio.ensure_future(__watch(self, key, handle))
|
||||||
|
|
||||||
|
|
||||||
app = Bucket("test")
|
# test = Bucket("test")
|
||||||
|
# test.name = "777"
|
||||||
|
# print(test.name)
|
||||||
|
|
||||||
|
# async def handle(old_value, new_value, key):
|
||||||
|
# print("Bucket value changed!")
|
||||||
|
# print("Key:", key)
|
||||||
|
# print("Old value:", old_value)
|
||||||
|
# print("New value:", new_value)
|
||||||
|
# return {
|
||||||
|
# "now": "shit",
|
||||||
|
# "message": "hehe",
|
||||||
|
# "error": "xxx",
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
def handle(old_value, new_value, key):
|
# async def main():
|
||||||
print("Bucket value changed!")
|
# asyncio.ensure_future(test.watch(key="*", handle=handle))
|
||||||
print("Key:", key)
|
# await asyncio.sleep(0.1)
|
||||||
print("Old value:", old_value)
|
# print("test.set", await test.set("name", random.randint(1, 10)))
|
||||||
print("New value:", new_value)
|
# print("test.name", await test.get("name"))
|
||||||
return {
|
# print("test.keys", await test.keys())
|
||||||
"now": "shit",
|
# print("test.buckets", await test.buckets())
|
||||||
}
|
# # print("test.delete", await test.delete("name"))
|
||||||
|
# # print("test.deleteAll", await test.deleteAll())
|
||||||
|
# print("test.name", await test.get("name"))
|
||||||
|
|
||||||
|
# loop = asyncio.get_event_loop()
|
||||||
app.watch(key="*", handle=handle)
|
# loop.run_until_complete(main())
|
||||||
# app.name = 1
|
|
||||||
# print(app.name)
|
|
||||||
# app["name"] = (1,3, {3,4,5})
|
|
||||||
# print(app["name"])
|
|
||||||
# app.set("name", 1.23)
|
|
||||||
# print(app.get("name"))
|
|
||||||
# print("keys", app.keys())
|
|
||||||
# print("len", app.len())
|
|
||||||
# print("buckets", app.buckets())
|
|
||||||
# # app.delete("name")
|
|
||||||
# app.name = 0
|
|
||||||
# print(app.name)
|
|
||||||
# print("==")
|
|
||||||
# app.name = random.randrange(1,100,1)
|
|
||||||
# print("==")
|
|
||||||
# app.deleteAll()
|
|
||||||
print("app.name", app.name)
|
|
||||||
|
|
||||||
|
|
||||||
class Sender:
|
class Sender:
|
||||||
pass
|
def __init__(self, uuid):
|
||||||
|
self.__uuid = uuid
|
||||||
|
self.destoried = False
|
||||||
|
|
||||||
|
async def destroy(self):
|
||||||
|
if self.destoried:
|
||||||
|
return
|
||||||
|
self.destoried = True
|
||||||
|
await stub2.SenderDestroy(
|
||||||
|
srpc_pb2.ReplyRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
|
||||||
|
async def getUserId(self):
|
||||||
|
response = await stub2.SenderGetUserId(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getUserName(self):
|
||||||
|
response = await stub2.SenderGetUserName(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getChatId(self):
|
||||||
|
response = await stub2.SenderGetChatId(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getChatName(self):
|
||||||
|
response = await stub2.SenderGetChatName(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getMessageId(self):
|
||||||
|
response = await stub2.SenderGetMessageId(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getPlatform(self):
|
||||||
|
response = await stub2.SenderGetPlatform(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getBotId(self):
|
||||||
|
response = await stub2.SenderGetBotId(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def getContent(self):
|
||||||
|
response = await stub2.SenderGetContent(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def isAdmin(self):
|
||||||
|
response = await stub2.SenderIsAdmin(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def param(self, key):
|
||||||
|
response = await stub2.SenderParam(
|
||||||
|
request=srpc_pb2.ReplyRequest(uuid=self.__uuid, content=str(key)),
|
||||||
|
metadata=metadata,
|
||||||
|
)
|
||||||
|
return response.value
|
||||||
|
|
||||||
|
async def setContent(self, content):
|
||||||
|
await stub2.SenderSetContent(
|
||||||
|
request=srpc_pb2.SenderContentRequest(uuid=self.__uuid, content=content),
|
||||||
|
metadata=metadata,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def next(self):
|
||||||
|
await stub2.SenderContinue(
|
||||||
|
request=srpc_pb2.SenderRequest(uuid=self.__uuid), metadata=metadata
|
||||||
|
)
|
||||||
|
|
||||||
|
async def getAdapter(self):
|
||||||
|
bot_id = await self.getBotId()
|
||||||
|
platform = await self.getPlatform()
|
||||||
|
return Adapter(bot_id, platform)
|
||||||
|
|
||||||
|
async def listen(
|
||||||
|
self,
|
||||||
|
timeout=0,
|
||||||
|
rules=[],
|
||||||
|
handle=None,
|
||||||
|
listen_private=False,
|
||||||
|
listen_group=False,
|
||||||
|
allow_platforms=[],
|
||||||
|
prohibit_platforms=[],
|
||||||
|
allow_groups=[],
|
||||||
|
prohibit_groups=[],
|
||||||
|
allow_users=[],
|
||||||
|
prohibit_users=[],
|
||||||
|
):
|
||||||
|
queue = asyncio.Queue()
|
||||||
|
|
||||||
|
async def entry_request_iterator():
|
||||||
|
yield srpc_pb2.SenderListenRequest(
|
||||||
|
uuid=self.__uuid,
|
||||||
|
timeout=timeout,
|
||||||
|
rules=rules,
|
||||||
|
listen_private=listen_private,
|
||||||
|
listen_group=listen_group,
|
||||||
|
allow_platforms=allow_platforms,
|
||||||
|
prohibit_platforms=prohibit_platforms,
|
||||||
|
allow_groups=allow_groups,
|
||||||
|
prohibit_groups=prohibit_groups,
|
||||||
|
allow_users=allow_users,
|
||||||
|
prohibit_users=prohibit_users,
|
||||||
|
persistent=self.__uuid == "",
|
||||||
|
plugin_id=plugin_id,
|
||||||
|
)
|
||||||
|
while True:
|
||||||
|
next_request = await queue.get()
|
||||||
|
if next_request is None:
|
||||||
|
return
|
||||||
|
yield next_request
|
||||||
|
|
||||||
|
generator = entry_request_iterator()
|
||||||
|
response_iterator = stub2.SenderListen(generator, metadata=metadata)
|
||||||
|
s = None
|
||||||
|
async for response in response_iterator:
|
||||||
|
if response.echo == "END":
|
||||||
|
break
|
||||||
|
s = Sender(response.uuid) if response.uuid != "" else None
|
||||||
|
if handle is not None and s is not None:
|
||||||
|
try:
|
||||||
|
value = await handle(s)
|
||||||
|
await queue.put(
|
||||||
|
srpc_pb2.SenderListenRequest(
|
||||||
|
uuid=response.echo,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
else:
|
||||||
|
await queue.put(
|
||||||
|
srpc_pb2.SenderListenRequest(
|
||||||
|
uuid=response.echo,
|
||||||
|
value="",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
await queue.put(None)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def holdOn(self, string):
|
||||||
|
return "go_again_" + string
|
||||||
|
|
||||||
|
async def reply(self, content):
|
||||||
|
return (
|
||||||
|
await stub2.SenderReply(
|
||||||
|
request=srpc_pb2.ReplyRequest(uuid=self.__uuid, content=content),
|
||||||
|
metadata=metadata,
|
||||||
|
)
|
||||||
|
).value
|
||||||
|
|
||||||
|
async def doAction(self, properties):
|
||||||
|
# Perform action based on the provided properties
|
||||||
|
# ...
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
sender = Sender(os.environ.get("SENDER_ID", ""))
|
||||||
|
|
||||||
|
|
||||||
class Adapter:
|
class Adapter:
|
||||||
pass
|
def __init__(self, platform, bot_id, replyHandler=None, actionHandler=None):
|
||||||
|
self.platform = platform
|
||||||
|
self.bot_id = bot_id
|
||||||
|
|
||||||
|
if replyHandler is not None:
|
||||||
|
asyncio.create_task(self.__run(replyHandler, actionHandler))
|
||||||
|
|
||||||
|
async def __run(self, replyHandler, actionHandler):
|
||||||
|
self.queue = asyncio.Queue()
|
||||||
|
|
||||||
|
async def entry_request_iterator():
|
||||||
|
yield srpc_pb2.AdapterRegistRequest(
|
||||||
|
bot_id=self.bot_id, platform=self.platform
|
||||||
|
)
|
||||||
|
while True:
|
||||||
|
next_request = await self.queue.get()
|
||||||
|
if next_request is None:
|
||||||
|
return
|
||||||
|
yield next_request
|
||||||
|
|
||||||
|
generator = entry_request_iterator()
|
||||||
|
|
||||||
|
response_iterator = stub2.AdapterRegist(generator, metadata=metadata)
|
||||||
|
try:
|
||||||
|
async for response in response_iterator:
|
||||||
|
message = json.loads(response.value)
|
||||||
|
echo = message["echo"]
|
||||||
|
__type__ = message["__type__"]
|
||||||
|
del message["__type__"]
|
||||||
|
del message["echo"]
|
||||||
|
if __type__ == "reply":
|
||||||
|
try:
|
||||||
|
v = replyHandler(message) or ""
|
||||||
|
await self.queue.put(
|
||||||
|
srpc_pb2.AdapterRegistRequest(bot_id=echo, platform=v)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
if __type__ == "action" and actionHandler is not None:
|
||||||
|
try:
|
||||||
|
v = actionHandler(message) or ""
|
||||||
|
await self.queue.put(
|
||||||
|
srpc_pb2.AdapterRegistRequest(bot_id=echo, platform=v)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def receive(self, message):
|
||||||
|
# 投递消息
|
||||||
|
return await stub2.AdapterReceive(
|
||||||
|
srpc_pb2.AdapterRequest(
|
||||||
|
platform=self.platform, bot_id=self.bot_id, value=json.dumps(message)
|
||||||
|
),
|
||||||
|
metadata=metadata,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def push(self, message):
|
||||||
|
# 推送消息
|
||||||
|
response = await stub2.AdapterPush(
|
||||||
|
srpc_pb2.AdapterRequest(
|
||||||
|
platform=self.platform, bot_id=self.bot_id, value=json.dumps(message)
|
||||||
|
),
|
||||||
|
metadata=metadata,
|
||||||
|
)
|
||||||
|
return response.value or ""
|
||||||
|
|
||||||
|
async def destroy(self):
|
||||||
|
if not hasattr(self, "self.__destroyed"):
|
||||||
|
await self.queue.put(None)
|
||||||
|
self.__destroyed = True
|
||||||
|
|
||||||
|
async def sender(self, options={}):
|
||||||
|
response = await stub2.AdapterSender(
|
||||||
|
srpc_pb2.AdapterRequest(
|
||||||
|
platform=self.platform, bot_id=self.bot_id, value=json.dumps(options)
|
||||||
|
),
|
||||||
|
metadata=metadata,
|
||||||
|
)
|
||||||
|
if response.value:
|
||||||
|
return Sender(response.value)
|
||||||
|
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class Utils:
|
||||||
|
def buildCQTag(self, type, params, prefix="CQ"):
|
||||||
|
param_strings = []
|
||||||
|
for key, value in params.items():
|
||||||
|
param_string = f"{key}={value}"
|
||||||
|
param_strings.append(param_string)
|
||||||
|
param_string = ",".join(param_strings)
|
||||||
|
cq_string = f"[{prefix}:{type}{',' + param_string if param_string else ''}]"
|
||||||
|
return cq_string
|
||||||
|
|
||||||
|
def parseCQText(self, text, prefix="CQ"):
|
||||||
|
cq_regex = re.compile(rf"\[{prefix}:(\w+)(.*?)\]", re.DOTALL)
|
||||||
|
cq_matches = cq_regex.finditer(text)
|
||||||
|
result = []
|
||||||
|
|
||||||
|
last_index = 0
|
||||||
|
for match in cq_matches:
|
||||||
|
# 添加 CQ 码前的文本
|
||||||
|
match_index = text.index(match.group(0), last_index)
|
||||||
|
if match_index > last_index:
|
||||||
|
result.append(text[last_index:match_index])
|
||||||
|
|
||||||
|
# 解析 CQ 码
|
||||||
|
params = {}
|
||||||
|
param_regex = re.compile(r"(\w+)=([^,]+)")
|
||||||
|
param_matches = param_regex.findall(match.group(2))
|
||||||
|
for param_match in param_matches:
|
||||||
|
params[param_match[0]] = param_match[1].strip()
|
||||||
|
result.append(
|
||||||
|
{
|
||||||
|
"type": match.group(1),
|
||||||
|
"params": params,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
last_index = match_index + len(match.group(0))
|
||||||
|
|
||||||
|
if last_index < len(text):
|
||||||
|
result.append(text[last_index:])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def image(self, url):
|
||||||
|
return self.buildCQTag("image", {"url": url})
|
||||||
|
|
||||||
|
def video(self, url):
|
||||||
|
return self.buildCQTag("video", {"url": url})
|
||||||
|
|
||||||
|
|
||||||
|
utils = Utils()
|
||||||
|
|
||||||
|
import srpc_pb2
|
||||||
|
import srpc_pb2_grpc
|
||||||
|
|
||||||
|
|
||||||
|
class Console:
|
||||||
|
def __init__(self, plugin_id):
|
||||||
|
self.plugin_id = plugin_id
|
||||||
|
|
||||||
|
def log(self, *args):
|
||||||
|
self.send_console_request("log", *args)
|
||||||
|
|
||||||
|
def info(self, *args):
|
||||||
|
self.send_console_request("info", *args)
|
||||||
|
|
||||||
|
def error(self, *args):
|
||||||
|
self.send_console_request("error", *args)
|
||||||
|
|
||||||
|
def debug(self, *args):
|
||||||
|
self.send_console_request("debug", *args)
|
||||||
|
|
||||||
|
def send_console_request(self, console_type, *args):
|
||||||
|
content = " ".join(map(str, args))
|
||||||
|
request = srpc_pb2.ConsoleRequest(
|
||||||
|
type=console_type, content=content, plugin_id=self.plugin_id
|
||||||
|
)
|
||||||
|
stub2.Console(request)
|
||||||
|
|
||||||
|
|
||||||
|
console = Console(plugin_id)
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
data-uri-to-buffer@^4.0.0:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
|
||||||
|
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
||||||
|
|
||||||
|
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
|
||||||
|
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
|
||||||
|
dependencies:
|
||||||
|
node-domexception "^1.0.0"
|
||||||
|
web-streams-polyfill "^3.0.3"
|
||||||
|
|
||||||
|
formdata-polyfill@^4.0.10:
|
||||||
|
version "4.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||||
|
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
|
||||||
|
dependencies:
|
||||||
|
fetch-blob "^3.1.2"
|
||||||
|
|
||||||
|
node-domexception@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||||
|
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||||
|
|
||||||
|
node-fetch@^3.3.2:
|
||||||
|
version "3.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
|
||||||
|
integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer "^4.0.0"
|
||||||
|
fetch-blob "^3.1.4"
|
||||||
|
formdata-polyfill "^4.0.10"
|
||||||
|
|
||||||
|
web-streams-polyfill@^3.0.3:
|
||||||
|
version "3.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
|
||||||
|
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
|
||||||
Reference in New Issue
Block a user