From 7eab31081cd7c3bd798f1770d8d07cf2cd522d4c Mon Sep 17 00:00:00 2001 From: Sheyiyuan <2125107118@qq.com> Date: Sun, 2 Mar 2025 11:25:49 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E9=87=8D=E6=96=B0=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=BA=86=E5=8D=8F=E8=AE=AE=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/{app_admin_unix.go => app_admin.go} | 33 +--- core/app_admin_windows.go | 231 ----------------------- core/web_socket.go | 17 +- typed/typed.go | 20 +- utils.go | 75 +++----- 5 files changed, 48 insertions(+), 328 deletions(-) rename core/{app_admin_unix.go => app_admin.go} (87%) delete mode 100644 core/app_admin_windows.go diff --git a/core/app_admin_unix.go b/core/app_admin.go similarity index 87% rename from core/app_admin_unix.go rename to core/app_admin.go index d7bd4fd..a02b4a2 100644 --- a/core/app_admin_unix.go +++ b/core/app_admin.go @@ -1,6 +1,3 @@ -//go:build linux || darwin -// +build linux darwin - package core import ( @@ -9,7 +6,6 @@ import ( "github.com/dop251/goja" "os" "path/filepath" - "plugin" ) var CmdMap = make(map[string]wba.Cmd) @@ -39,33 +35,6 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i } ext := filepath.Ext(file.Name()) - if ext == ".so" { - pluginPath := filepath.Join(appsDir, file.Name()) - p, err := plugin.Open(pluginPath) - if err != nil { - LOG.Error("打开应用 %s 时发生错误: %v", pluginPath, err) - return 1, 0 - } - AppInit, err := p.Lookup("AppInit") - if err != nil { - LOG.Error("找不到应用 %s 提供的 AppInit 接口: %v", pluginPath, err) - return 1, 0 - } - app := AppInit.(func() wba.AppInfo)() - - err = app.Init(&AppApi) - if err != nil { - LOG.Error("初始化应用 %s 失败: %v", pluginPath, err) - } - - CmdMap = mergeMaps(CmdMap, app.Get().CmdMap) - ScheduledTasks := app.Get().ScheduledTasks - for _, task := range ScheduledTasks { - RegisterCron(app.Get().Name, task) - } - LOG.Info("应用 %s 加载成功", pluginPath) - return 1, 1 - } if ext == ".js" { pluginPath := filepath.Join(appsDir, file.Name()) jsCode, err := os.ReadFile(pluginPath) @@ -96,7 +65,7 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i _ = wbaObj.Set("WithLicense", wba.WithLicense) _ = wbaObj.Set("WithAppType", wba.WithAppType) _ = wbaObj.Set("WithRule", wba.WithRule) - _ = wbaObj.Set("WSP", wsp) + _ = wbaObj.Set("wsp", wsp) _ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg) _ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg) _ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg) diff --git a/core/app_admin_windows.go b/core/app_admin_windows.go deleted file mode 100644 index 258d0db..0000000 --- a/core/app_admin_windows.go +++ /dev/null @@ -1,231 +0,0 @@ -//go:build windows -// +build windows - -package core - -import ( - "ProjectWIND/LOG" - "ProjectWIND/wba" - "fmt" - "os" - "path/filepath" - "syscall" - "unsafe" -) - -var CmdMap = make(map[string]wba.Cmd) - -func ReloadApps() (total int, success int) { - appsDir := "./data/app/" - appFiles, err := os.ReadDir(appsDir) - total = 0 - success = 0 - if err != nil { - LOG.Error("加载应用所在目录失败:%v", err) - return - } - - for _, file := range appFiles { - totalDelta, successDelta := reloadAPP(file, appsDir) - total += totalDelta - success += successDelta - } - CmdMap = mergeMaps(CmdMap, AppCore.CmdMap) - return total, success -} - -func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta int) { - if file.IsDir() { - return 0, 0 - } - ext := filepath.Ext(file.Name()) - if ext == ".dll" { - pluginPath := filepath.Join(appsDir, file.Name()) - lib, err := syscall.LoadLibrary(pluginPath) - if err != nil { - LOG.Error("加载应用 %s 失败: %v", pluginPath, err) - return 1, 0 - } - defer func(handle syscall.Handle) { - err := syscall.FreeLibrary(handle) - if err != nil { - LOG.Error("释放应用 %s 时发生错误: %v", pluginPath, err) - } - }(lib) - - // 获取函数地址 - sym, err := syscall.GetProcAddress(lib, "AppInit") - if err != nil { - fmt.Println("找不到应用 %s 提供的 AppInit 接口: %v", err) - return 1, 0 - } - - // 定义函数类型 - AppInitPtr := (*func() wba.AppInfo)(unsafe.Pointer(&sym)) - AppInit := *AppInitPtr - - app := AppInit() - - err = app.Init(&AppApi) - if err != nil { - LOG.Error("初始化应用 %s 失败: %v", pluginPath, err) - } - - CmdMap = mergeMaps(CmdMap, app.Get().CmdMap) - LOG.Info("应用 %s 加载成功", pluginPath) - return 1, 1 - - } - if ext == ".js" { - pluginPath := filepath.Join(appsDir, file.Name()) - jsCode, err := os.ReadFile(pluginPath) - if err != nil { - LOG.Error("读取应用 %s 时发生错误: %v", pluginPath, err) - return 1, 0 - } - - runtime := goja.New() - _, err = runtime.RunString(string(jsCode)) - if err != nil { - LOG.Error("执行应用 %s 失败: %v", pluginPath, err) - return 1, 0 - } - - // 创建JS可用的wbaObj对象 - wbaObj := runtime.NewObject() - wsp := runtime.NewObject() - _ = runtime.Set("wba", wbaObj) - _ = wbaObj.Set("NewApp", wba.NewApp) - _ = wbaObj.Set("NewCmd", wba.NewCmd) - _ = wbaObj.Set("NewScheduledTask", wba.NewScheduledTask) - _ = wbaObj.Set("WithName", wba.WithName) - _ = wbaObj.Set("WithAuthor", wba.WithAuthor) - _ = wbaObj.Set("WithVersion", wba.WithVersion) - _ = wbaObj.Set("WithDescription", wba.WithDescription) - _ = wbaObj.Set("WithWebUrl", wba.WithWebUrl) - _ = wbaObj.Set("WithLicense", wba.WithLicense) - _ = wbaObj.Set("WithAppType", wba.WithAppType) - _ = wbaObj.Set("WithRule", wba.WithRule) - _ = wbaObj.Set("WSP", wsp) - _ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg) - _ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg) - _ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg) - _ = wsp.Set("SendMsg", AppApi.SendMsg) - _ = wsp.Set("SendPrivateMsg", AppApi.SendPrivateMsg) - _ = wsp.Set("SendGroupMsg", AppApi.SendGroupMsg) - _ = wsp.Set("UnsafelyDeleteMsg", AppApi.UnsafelyDeleteMsg) - _ = wsp.Set("DeleteMsg", AppApi.DeleteMsg) - _ = wsp.Set("SendLike", AppApi.SendLike) - _ = wsp.Set("SetGroupKick", AppApi.SetGroupKick) - _ = wsp.Set("SetGroupBan", AppApi.SetGroupBan) - _ = wsp.Set("SetGroupWholeBan", AppApi.SetGroupWholeBan) - _ = wsp.Set("SetGroupAdmin", AppApi.SetGroupAdmin) - _ = wsp.Set("SetGroupLeave", AppApi.SetGroupLeave) - _ = wsp.Set("SetGroupCard", AppApi.SetGroupCard) - _ = wsp.Set("SetGroupName", AppApi.SetGroupName) - _ = wsp.Set("SetGroupSpecialTitle", AppApi.SetGroupSpecialTitle) - _ = wsp.Set("SetFriendAddRequest", AppApi.SetFriendAddRequest) - _ = wsp.Set("SetGroupAddRequest", AppApi.SetGroupAddRequest) - _ = wsp.Set("GetLoginInfo", AppApi.GetLoginInfo) - _ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo) - _ = wsp.Set("GetMsg", AppApi.GetMsg) - _ = wsp.Set("GetGroupInfo", AppApi.GetGroupInfo) - _ = wsp.Set("GetForwardMsg", AppApi.GetForwardMsg) - _ = wsp.Set("GetStrangerInfo", AppApi.GetStrangerInfo) - _ = wsp.Set("GetGroupList", AppApi.GetGroupList) - _ = wsp.Set("GetGroupMemberList", AppApi.GetGroupMemberList) - _ = wsp.Set("GetFriendList", AppApi.GetFriendList) - _ = wsp.Set("GetGroupMemberInfo", AppApi.GetGroupMemberInfo) - _ = wsp.Set("GetGroupHonorInfo", AppApi.GetGroupHonorInfo) - _ = wsp.Set("GetStatus", AppApi.GetStatus) - _ = wsp.Set("GetCookies", AppApi.GetCookies) - _ = wsp.Set("GetCSRFToken", AppApi.GetCSRFToken) - _ = wsp.Set("GetCredentials", AppApi.GetCredentials) - _ = wsp.Set("GetImage", AppApi.GetImage) - _ = wsp.Set("GetRecord", AppApi.GetRecord) - _ = wsp.Set("CanSendImage", AppApi.CanSendImage) - _ = wsp.Set("CanSendRecord", AppApi.CanSendRecord) - _ = wsp.Set("SetRestart", AppApi.SetRestart) - _ = wsp.Set("CleanCache", AppApi.CleanCache) - _ = wsp.Set("GetLoginInfo", AppApi.LogWith) - _ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo) - - // 获取AppInit函数 - appInitVal := runtime.Get("AppInit") - if appInitVal == nil || goja.IsUndefined(appInitVal) { - LOG.Error("应用 %s 缺少AppInit函数", pluginPath) - return 1, 0 - } - appInitFunc, ok := goja.AssertFunction(appInitVal) - if !ok { - LOG.Error("应用 %s 的AppInit不是有效函数", pluginPath) - return 1, 0 - } - - // 调用AppInit获取应用实例 - jsApp, err := appInitFunc(goja.Undefined()) - if err != nil { - LOG.Error("初始化应用实例失败: %v", err) - return 1, 0 - } - - // 调用Init方法 - initVal := jsApp.ToObject(runtime).Get("Init") - initFunc, ok := goja.AssertFunction(initVal) - if !ok { - LOG.Error("应用 %s 缺少有效的Init方法", pluginPath) - return 1, 0 - } - - _, err = initFunc(wbaObj) - if err != nil { - LOG.Trace("应用初始化失败: %v", err) - return 1, 0 - } - - // 调用Get方法 - getVal := jsApp.ToObject(runtime).Get("Get") - getFunc, ok := goja.AssertFunction(getVal) - if !ok { - LOG.Error("应用 %s 缺少有效的Get方法", pluginPath) - return 1, 0 - } - - appInfoVal, err := getFunc(jsApp) - if err != nil { - LOG.Error("获取应用信息失败: %v", err) - return 1, 0 - } - - // 转换应用信息 - var appInfo wba.AppInfo - if err := runtime.ExportTo(appInfoVal, &appInfo); err != nil { - LOG.Error("应用信息转换失败: %v", err) - return 1, 0 - } - - // 合并命令 - CmdMap = mergeMaps(CmdMap, appInfo.CmdMap) - - // 注册定时任务 - for _, task := range appInfo.ScheduledTasks { - RegisterCron(appInfo.Name, task) - } - - LOG.Info("JS应用 %s 加载成功", pluginPath) - return 1, 1 - } - return 0, 0 -} - -func mergeMaps(map1, map2 map[string]wba.Cmd) map[string]wba.Cmd { - // 合并map1和map2到map3中 - map3 := make(map[string]wba.Cmd) - for key, value := range map1 { - map3[key] = value - } - for key, value := range map2 { - map3[key] = value - } - return map3 -} diff --git a/core/web_socket.go b/core/web_socket.go index eb36408..c092f52 100644 --- a/core/web_socket.go +++ b/core/web_socket.go @@ -2,6 +2,7 @@ package core import ( "ProjectWIND/LOG" + "ProjectWIND/typed" "ProjectWIND/wba" "encoding/json" "fmt" @@ -10,16 +11,14 @@ import ( "net/url" ) -var gProtocolAddr string -var gToken string +var gProtocol typed.Protocol // WebSocketHandler 接收WebSocket连接处的消息并处理 -func WebSocketHandler(protocolAddr string, token string) error { +func WebSocketHandler(protocol typed.Protocol) error { // 保存全局变量 - gProtocolAddr = protocolAddr - gToken = token + gProtocol = protocol // 解析连接URL - u, err := url.Parse(protocolAddr) + u, err := url.Parse(protocol.Addr) if err != nil { LOG.Error("Parse URL error: %v", err) return err @@ -30,7 +29,7 @@ func WebSocketHandler(protocolAddr string, token string) error { if err != nil { LOG.Fatal("创建请求出错:%v", err) } - req.Header.Set("Authorization", "Bearer "+token) + req.Header.Set("Authorization", "Bearer "+protocol.Token) // 配置WebSocket连接升级器 dialer := websocket.DefaultDialer // 使用升级器建立WebSocket连接 @@ -126,7 +125,7 @@ func wsAPI(body wba.APIRequestInfo) (Response wba.APIResponseInfo, err error) { return wba.APIResponseInfo{}, err } // 解析连接URL - u, err := url.Parse(gProtocolAddr) + u, err := url.Parse(gProtocol.Addr) if err != nil { LOG.Error("Parse URL error: %v", err) return wba.APIResponseInfo{}, err @@ -136,7 +135,7 @@ func wsAPI(body wba.APIRequestInfo) (Response wba.APIResponseInfo, err error) { if err != nil { LOG.Fatal("创建请求出错:%v", err) } - req.Header.Set("Authorization", "Bearer "+gToken) + req.Header.Set("Authorization", "Bearer "+gProtocol.Token) // 配置WebSocket连接升级器 dialer := websocket.DefaultDialer // 使用升级器建立WebSocket连接 diff --git a/typed/typed.go b/typed/typed.go index 698cc04..929ed8c 100644 --- a/typed/typed.go +++ b/typed/typed.go @@ -1,17 +1,17 @@ package typed type CoreConfigInfo struct { - CoreName string `json:"core_name"` - Protocols []Protocol `json:"protocols"` - WebUIPort uint16 `json:"webui_port"` - PasswordHash string `json:"password_hash"` - ServiceName string `json:"service_name"` + CoreName string `json:"core_name"` + Protocol Protocol `json:"protocol"` + WebUIPort uint16 `json:"webui_port"` + PasswordHash string `json:"password_hash"` + ServiceName string `json:"service_name"` } type Protocol struct { - ProtocolName string `json:"protocol_name"` - ProtocolPlatform string `json:"protocol_platform"` - ProtocolAddr string `json:"protocol_addr"` - Token string `json:"token"` - Enable bool `json:"enable"` + Name string `json:"protocol_name"` + Platform string `json:"protocol_platform"` + Addr string `json:"protocol_addr"` + Token string `json:"token"` + Enable bool `json:"enable"` } diff --git a/utils.go b/utils.go index f0ed031..f9b6384 100644 --- a/utils.go +++ b/utils.go @@ -87,16 +87,16 @@ func checkAndUpdateConfig(configPath string) error { var coreConfig typed.CoreConfigInfo var defaultProtocol typed.Protocol - defaultProtocol.ProtocolName = "EXAMPLE" - defaultProtocol.ProtocolPlatform = "在这里输入协议平台" - defaultProtocol.ProtocolAddr = "在这里输入协议地址,如'ws://127.0.0.1:8080'" + defaultProtocol.Name = "EXAMPLE" + defaultProtocol.Platform = "在这里输入协议平台" + defaultProtocol.Addr = "在这里输入协议地址,如'ws://127.0.0.1:8080'" defaultProtocol.Token = "在这里输入协议的Token" defaultProtocol.Enable = true var defaultConfig typed.CoreConfigInfo defaultConfig.CoreName = "windCore" defaultConfig.WebUIPort = 3211 - defaultConfig.Protocols = []typed.Protocol{defaultProtocol} + defaultConfig.Protocol = defaultProtocol defaultConfig.ServiceName = "wind" // 读取配置文件 file, err := os.Open(configPath) @@ -120,11 +120,8 @@ func checkAndUpdateConfig(configPath string) error { } // 检查并更新配置 - //if coreConfig.ProtocolAddr == "" { - // coreConfig.ProtocolAddr = defaultConfig.ProtocolAddr - //} - if coreConfig.Protocols == nil || len(coreConfig.Protocols) == 0 { - coreConfig.Protocols = defaultConfig.Protocols + if coreConfig.Protocol == (typed.Protocol{}) { + coreConfig.Protocol = defaultConfig.Protocol } if coreConfig.WebUIPort == 0 { coreConfig.WebUIPort = defaultConfig.WebUIPort @@ -311,44 +308,30 @@ func startProtocol() { LOG.Fatal("连接协议时,解析配置文件 ./data/core.json 失败: %v", err) } LOG.Info("正在启动WebSocket链接程序...") - protocolNum := 0 - breakNum := 0 - UnenableProtocolNum := 0 - for _, protocol := range config.Protocols { - protocolName := protocol.ProtocolName - if protocolName == "EXAMPLE" { - continue - } - if protocolName == "" { - LOG.Warn("连接协议 %s 时,协议名称为空,跳过该协议", protocolName) - breakNum++ - continue - } - //获取协议地址 - protocolAddr := protocol.ProtocolAddr - if protocolAddr == "" { - LOG.Warn("连接协议 %s 时,协议地址为空,跳过该协议", protocolName) - breakNum++ - continue - } - if protocol.Enable == false { - LOG.Warn("连接协议 %s 时,协议已禁用,跳过该协议", protocolName) - UnenableProtocolNum++ - continue - } - //获取token - token := protocol.Token - // 启动 WebSocket 处理程序 - go func() { - err := core.WebSocketHandler(protocolAddr, token) - if err != nil { - LOG.Error("连接协议时,启动 WebSocket 处理程序失败: %v", err) - } - }() - protocolNum++ + protocol := config.Protocol + if protocol.Name == "EXAMPLE" { + LOG.Warn("未找到协议配置信息") + return + } + if protocol.Name == "" { + LOG.Warn("连接协议 %s 时,协议名称为空", protocol.Name) + return + } + //获取协议地址 + protocolAddr := protocol.Addr + if protocolAddr == "" { + LOG.Warn("连接协议 %s 时,协议地址为空", protocol.Name) + return + } + if protocol.Enable == false { + LOG.Warn("连接协议 %s 时,协议已禁用", protocol.Name) + return + } + // 启动 WebSocket 处理程序 + err = core.WebSocketHandler(protocol) + if err != nil { + LOG.Error("连接协议时 %s,启动 WebSocket 处理程序失败: %v", protocol.Name, err) } - LOG.Info(" %d 个协议服务启动完成, %d 个协议服务已禁用, %d 个协议服务因为配置错误被跳过。", protocolNum, UnenableProtocolNum, breakNum) - select {} } func ReloadApps() { From 944fadc6881b13e0024103ad1015f504e549a622 Mon Sep 17 00:00:00 2001 From: Sheyiyuan <2125107118@qq.com> Date: Sun, 2 Mar 2025 11:31:59 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86readme=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 1ab02b5..c697bf4 100644 --- a/readme.md +++ b/readme.md @@ -14,8 +14,8 @@ TODO: - ✅ 文件初始化 - ✅ 事件处理 - ✅ 数据库交互 -- ❌ 插件系统 -- ❌ 用户系统 +- ✅ 插件系统 +- ✅ 用户系统 - ❌ web ui - ❌ 文档编写 @@ -30,14 +30,19 @@ WIND(全称:WIND is not dice)是一个基于 Go 语言开发的bot框架 ## 1. goja - **库名称**:goja - **仓库地址**:[https://github.com/dop251/goja](https://github.com/dop251/goja) -- **用途说明**:goja 作为一款强大的 JavaScript 解释器,在本项目中承担了处理动态的 JavaScript 脚本逻辑,为项目提供了灵活的脚本扩展能力,使得我们能够在 Go 项目中嵌入 JavaScript 代码来实现一些特定的业务规则处理等功能。它极大地丰富了项目的功能和灵活性,让我们能够更高效地开发出具有特色的功能模块。 +- **用途说明**:goja 作为一款强大的 JavaScript 解释器,在本项目中承担了处理动态的 JavaScript 脚本逻辑,为项目提供了灵活的脚本扩展能力,使得我们能够在项目中实现js插件的功能。它极大地丰富了项目的功能和灵活性,让跨平台的插件开发变得更加容易。 ## 2. gocron - **库名称**:gocron - **仓库地址**:[https://github.com/go-co-op/gocron](https://github.com/go-co-op/gocron) -- **用途说明**:gocron 是一个出色的任务调度库。在本项目里,它被用于[详细的任务调度应用场景,比如定期执行数据同步任务、定时清理临时文件或缓存数据等],确保了项目中的各种定时任务能够精准、可靠地执行。其简洁易用的 API 设计大大降低了我们实现复杂任务调度逻辑的难度,为项目的稳定运行提供了有力保障。 +- **用途说明**:gocron 是一个出色的任务调度库。在本项目里,它被用作定时任务的调度器,确保了项目中的各种定时任务能够精准、可靠地执行。其简洁易用的 API 设计大大降低了我们实现复杂任务调度逻辑的难度,为项目的稳定运行提供了有力保障。 -非常感谢 `goja` 和 `gocron` 项目团队的开源贡献,使得我们的项目开发能够借助这些优秀的工具快速推进,为用户带来更好的体验。 +## 3. hertz +- **库名称**:hertz +- **仓库地址**:[https://github.com/albertwidi/hertz](https://github.com/albertwidi/hertz) +- **用途说明**:hertz 是一个基于 Go 语言开发的高性能 HTTP 路由器。在本项目中,它被用作项目的 HTTP 服务器,为项目提供了快速、高效的 HTTP 请求处理能力。让我们能够灵活地对 HTTP 请求进行处理。 + +非常感谢以上项目团队的开源贡献,使得我们的项目开发能够借助这些优秀的工具快速推进,为用户带来更好的体验。 --- 后面没有了,开发者很懒,什么都没写。 \ No newline at end of file From c63f4c2dd8e8cce500687887fbce463c7d837349 Mon Sep 17 00:00:00 2001 From: Sheyiyuan <2125107118@qq.com> Date: Sun, 2 Mar 2025 11:34:50 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86readme=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index c697bf4..830b353 100644 --- a/readme.md +++ b/readme.md @@ -39,7 +39,7 @@ WIND(全称:WIND is not dice)是一个基于 Go 语言开发的bot框架 ## 3. hertz - **库名称**:hertz -- **仓库地址**:[https://github.com/albertwidi/hertz](https://github.com/albertwidi/hertz) +- **仓库地址**:[https://github.com/cloudwego/hertz](https://github.com/cloudwego/hertz) - **用途说明**:hertz 是一个基于 Go 语言开发的高性能 HTTP 路由器。在本项目中,它被用作项目的 HTTP 服务器,为项目提供了快速、高效的 HTTP 请求处理能力。让我们能够灵活地对 HTTP 请求进行处理。 非常感谢以上项目团队的开源贡献,使得我们的项目开发能够借助这些优秀的工具快速推进,为用户带来更好的体验。 From 8a49ded455275ad016bc17c0801df2d69c8dbeca Mon Sep 17 00:00:00 2001 From: Thun_Ann <2865813065@qq.com> Date: Mon, 3 Mar 2025 14:13:48 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E5=B0=86=E6=95=B0=E6=8D=AE=E5=BA=93api?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=88=B0js=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/api.go | 103 +++++++++++++++++++++++++++++++++++++- core/app_admin_windows.go | 1 + utils.go | 6 +-- wba/wind.go | 30 +++++------ 4 files changed, 121 insertions(+), 19 deletions(-) diff --git a/core/api.go b/core/api.go index 2420bde..6ba454b 100644 --- a/core/api.go +++ b/core/api.go @@ -818,7 +818,108 @@ func (a *apiInfo) Log(content string, args ...interface{}) { } //database模块 -//数据库部分允许字符串变量的读写操作,允许获取配置项操作 +// //数据库部分允许字符串变量的读写操作,允许获取配置项操作 +// func (ai *AppInfo) VarSet(dataMap string, unit string, id string, key string, value string) { +// if ai.dbHandler != nil { +// ai.dbHandler.Set(ai.Name, dataMap, unit, id, key, value) +// } +// } + +// // VarGet 获取变量 +// func (ai *AppInfo) VarGet(dataMap string, unit string, id string, key string) (string, bool) { +// if ai.dbHandler != nil { +// res, ok := ai.dbHandler.Get(ai.Name, dataMap, unit, id, key, false) +// if !ok { +// return "", false +// } +// resStr, ok := res.(string) +// if !ok { +// return "", false +// } +// return resStr, true +// } +// return "", false +// } + +// // GetIntConfig 获取整数配置 +// func (ai *AppInfo) GetIntConfig(dataMap string, key string) (int64, bool) { +// if ai.dbHandler != nil { +// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "number", key, true) +// if !ok { +// return 0, false +// } +// resInt, ok := res.(int64) +// if !ok { +// return 0, false +// } +// return resInt, true +// } +// return 0, false +// } + +// // GetStringConfig 获取字符串配置 +// func (ai *AppInfo) GetStringConfig(dataMap string, key string) (string, bool) { +// if ai.dbHandler != nil { +// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "string", key, true) +// if !ok { +// return "", false +// } +// resStr, ok := res.(string) +// if !ok { +// return "", false +// } +// return resStr, true +// } +// return "", false +// } + +// // GetFloatConfig 获取浮点数配置 +// func (ai *AppInfo) GetFloatConfig(dataMap string, key string) (float64, bool) { +// if ai.dbHandler != nil { +// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "float", key, true) +// if !ok { +// return 0, false +// } +// resFloat, ok := res.(float64) +// if !ok { +// return 0, false +// } +// return resFloat, true +// } +// return 0, false +// } + +// // GetIntSliceConfig 获取整数切片配置 +// func (ai *AppInfo) GetIntSliceConfig(dataMap string, key string) ([]int64, bool) { +// if ai.dbHandler != nil { +// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "number_slice", key, true) +// if !ok { +// return nil, false +// } +// resSlice, ok := res.([]int64) +// if !ok { +// return nil, false +// } +// return resSlice, true +// } +// return nil, false +// } + +// // GetStringSliceConfig 获取字符串切片配置 +// func (ai *AppInfo) GetStringSliceConfig(dataMap string, key string) ([]string, bool) { +// if ai.dbHandler != nil { +// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "string_slice", key, true) +// if !ok { +// return nil, false +// } +// resSlice, ok := res.([]string) +// if !ok { +// return nil, false +// } +// return resSlice, true +// } +// return nil, false +// } // 文件管理模块 //TODO: 文件管理模块待实现 diff --git a/core/app_admin_windows.go b/core/app_admin_windows.go index 258d0db..97687e1 100644 --- a/core/app_admin_windows.go +++ b/core/app_admin_windows.go @@ -11,6 +11,7 @@ import ( "path/filepath" "syscall" "unsafe" + "github.com/dop251/goja" ) var CmdMap = make(map[string]wba.Cmd) diff --git a/utils.go b/utils.go index f0ed031..66d59cf 100644 --- a/utils.go +++ b/utils.go @@ -362,7 +362,7 @@ func startDatabase() { time.Sleep(time.Second * 1) // 读写测试 // for i := 0; i < 10; i++ { - // data, ok := database.Get("user", "test", "test"+fmt.Sprintf("%d", i)) + // data, ok := database.Get("go", "go", "user", "test", "test"+fmt.Sprintf("%d", i), false) // if !ok { // LOG.Error("Failed to get data from database") // continue @@ -372,12 +372,12 @@ func startDatabase() { // } // time.Sleep(time.Second * 1) // for i := 0; i < 10; i++ { - // database.Set("user", "test", "test"+fmt.Sprintf("%d", i), "test"+fmt.Sprintf("%d", 1000+i)) + // database.Set("go", "go", "user", "test", "test"+fmt.Sprintf("%d", i), "test"+fmt.Sprintf("%d", 1000+i)) // time.Sleep(time.Second * 1) // } // time.Sleep(time.Second * 1) // for i := 0; i < 10; i++ { - // data, ok := database.Get("user", "test", "test"+fmt.Sprintf("%d", i)) + // data, ok := database.Get("go", "go", "user", "test", "test"+fmt.Sprintf("%d", i), false) // if !ok { // LOG.Error("Failed to get data from database") // continue diff --git a/wba/wind.go b/wba/wind.go index cdfab18..0904d56 100644 --- a/wba/wind.go +++ b/wba/wind.go @@ -287,7 +287,7 @@ type AppInfo struct { MetaEventHandler func(msg MetaEventInfo) ScheduledTasks map[string]ScheduledTaskInfo API map[string]interface{} - dbHandler DataBaseHandler + DbHandler DataBaseHandler } func (ai AppInfo) Get() AppInfo { @@ -312,15 +312,15 @@ func (ai *AppInfo) AddScheduledTask(task ScheduledTaskInfo) { } func (ai *AppInfo) VarSet(dataMap string, unit string, id string, key string, value string) { - if ai.dbHandler != nil { - ai.dbHandler.Set(ai.Name, dataMap, unit, id, key, value) + if ai.DbHandler != nil { + ai.DbHandler.Set(ai.Name, dataMap, unit, id, key, value) } } // VarGet 获取变量 func (ai *AppInfo) VarGet(dataMap string, unit string, id string, key string) (string, bool) { - if ai.dbHandler != nil { - res, ok := ai.dbHandler.Get(ai.Name, dataMap, unit, id, key, false) + if ai.DbHandler != nil { + res, ok := ai.DbHandler.Get(ai.Name, dataMap, unit, id, key, false) if !ok { return "", false } @@ -335,8 +335,8 @@ func (ai *AppInfo) VarGet(dataMap string, unit string, id string, key string) (s // GetIntConfig 获取整数配置 func (ai *AppInfo) GetIntConfig(dataMap string, key string) (int64, bool) { - if ai.dbHandler != nil { - res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "number", key, true) + if ai.DbHandler != nil { + res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "number", key, true) if !ok { return 0, false } @@ -351,8 +351,8 @@ func (ai *AppInfo) GetIntConfig(dataMap string, key string) (int64, bool) { // GetStringConfig 获取字符串配置 func (ai *AppInfo) GetStringConfig(dataMap string, key string) (string, bool) { - if ai.dbHandler != nil { - res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "string", key, true) + if ai.DbHandler != nil { + res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "string", key, true) if !ok { return "", false } @@ -367,8 +367,8 @@ func (ai *AppInfo) GetStringConfig(dataMap string, key string) (string, bool) { // GetFloatConfig 获取浮点数配置 func (ai *AppInfo) GetFloatConfig(dataMap string, key string) (float64, bool) { - if ai.dbHandler != nil { - res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "float", key, true) + if ai.DbHandler != nil { + res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "float", key, true) if !ok { return 0, false } @@ -383,8 +383,8 @@ func (ai *AppInfo) GetFloatConfig(dataMap string, key string) (float64, bool) { // GetIntSliceConfig 获取整数切片配置 func (ai *AppInfo) GetIntSliceConfig(dataMap string, key string) ([]int64, bool) { - if ai.dbHandler != nil { - res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "number_slice", key, true) + if ai.DbHandler != nil { + res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "number_slice", key, true) if !ok { return nil, false } @@ -399,8 +399,8 @@ func (ai *AppInfo) GetIntSliceConfig(dataMap string, key string) ([]int64, bool) // GetStringSliceConfig 获取字符串切片配置 func (ai *AppInfo) GetStringSliceConfig(dataMap string, key string) ([]string, bool) { - if ai.dbHandler != nil { - res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "string_slice", key, true) + if ai.DbHandler != nil { + res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "string_slice", key, true) if !ok { return nil, false } From 5a5c3a4c48b8a7874afbde18daade086a304b6ab Mon Sep 17 00:00:00 2001 From: Sheyiyuan <2125107118@qq.com> Date: Mon, 3 Mar 2025 14:20:09 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=8A=A0=E8=BD=BD=E7=AE=A1=E7=90=86,=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E4=BA=86=E9=83=A8=E5=88=86=E6=8F=92=E4=BB=B6=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/app_admin.go | 32 +++++++++++++++++++++++++++----- core/app_core.go | 8 ++++---- core/events_handler.go | 27 ++++++++++++++++----------- typed/typed.go | 7 +++++++ wba/wind.go | 18 ++++++++++-------- 5 files changed, 64 insertions(+), 28 deletions(-) diff --git a/core/app_admin.go b/core/app_admin.go index a02b4a2..6a9bea1 100644 --- a/core/app_admin.go +++ b/core/app_admin.go @@ -2,15 +2,21 @@ package core import ( "ProjectWIND/LOG" + "ProjectWIND/typed" "ProjectWIND/wba" "github.com/dop251/goja" "os" "path/filepath" + "strings" ) -var CmdMap = make(map[string]wba.Cmd) +var CmdMap = make([]map[string]wba.Cmd, 4) +var AppMap = make(map[typed.AppKey]wba.AppInfo) func ReloadApps() (total int, success int) { + // 清空AppMap和CmdMap + CmdMap = make([]map[string]wba.Cmd, 4) + AppMap = make(map[typed.AppKey]wba.AppInfo) appsDir := "./data/app/" appFiles, err := os.ReadDir(appsDir) total = 0 @@ -25,7 +31,7 @@ func ReloadApps() (total int, success int) { total += totalDelta success += successDelta } - CmdMap = mergeMaps(CmdMap, AppCore.CmdMap) + CmdMap[0] = AppCore.CmdMap return total, success } @@ -55,8 +61,6 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i wsp := runtime.NewObject() _ = runtime.Set("wba", wbaObj) _ = wbaObj.Set("NewApp", wba.NewApp) - _ = wbaObj.Set("NewCmd", wba.NewCmd) - _ = wbaObj.Set("NewScheduledTask", wba.NewScheduledTask) _ = wbaObj.Set("WithName", wba.WithName) _ = wbaObj.Set("WithAuthor", wba.WithAuthor) _ = wbaObj.Set("WithVersion", wba.WithVersion) @@ -163,8 +167,10 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i return 1, 0 } + AppMap[typed.AppKey{AppName: appInfo.Name, AppType: appInfo.AppType, AppVersion: appInfo.Version, AppLevel: checkAppLevel(appInfo)}] = appInfo + cmdIndex := AppTypeToInt(appInfo.AppType) // 合并命令 - CmdMap = mergeMaps(CmdMap, appInfo.CmdMap) + CmdMap[cmdIndex] = mergeMaps(CmdMap[cmdIndex], appInfo.CmdMap) // 注册定时任务 for _, task := range appInfo.ScheduledTasks { @@ -188,3 +194,19 @@ func mergeMaps(map1, map2 map[string]wba.Cmd) map[string]wba.Cmd { } return map3 } + +func AppTypeToInt(appType string) int32 { + appType = strings.ToLower(appType) + switch appType { + case "system": + return 1 + case "rule": + return 2 + default: + return 3 + } +} + +func checkAppLevel(appInfo wba.AppInfo) int32 { + return 0 +} diff --git a/core/app_core.go b/core/app_core.go index bf2a114..2409f18 100644 --- a/core/app_core.go +++ b/core/app_core.go @@ -21,7 +21,7 @@ func (app *AppInfo) Run(cmd string, args []string, msg wba.MessageEventInfo) err if !ok { return errors.New("cmd not found") } - app.CmdMap[cmd].SOLVE(args, msg) + app.CmdMap[cmd].Solve(args, msg) return nil } @@ -35,9 +35,9 @@ func (app *AppInfo) GetCmd() map[string]wba.Cmd { func NewCmd(name string, help string, solve func(args []string, msg wba.MessageEventInfo)) wba.Cmd { return wba.Cmd{ - NAME: name, - DESC: help, - SOLVE: solve, + Name: name, + Desc: help, + Solve: solve, } } diff --git a/core/events_handler.go b/core/events_handler.go index 66c701b..37b721b 100644 --- a/core/events_handler.go +++ b/core/events_handler.go @@ -16,13 +16,16 @@ func HandleMessage(msgJson []byte) { } // 处理消息 LOG.Info("收到消息:(来自:%v-%v:%v-%v)%v", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname, msg.RawMessage) - //如果消息文本内容为bot,发送框架信息。 cmd, args := CmdSplit(msg) - _, ok := CmdMap[cmd] - if ok { - LOG.Debug("执行命令:%v %v", cmd, args) - CmdMap[cmd].SOLVE(args, msg) + for _, cmdList := range CmdMap { + _, ok := cmdList[cmd] + if ok { + LOG.Debug("执行命令:%v %v", cmd, args) + cmdList[cmd].Solve(args, msg) + break + } } + // TODO: 处理消息内容 } @@ -62,15 +65,17 @@ func CmdSplit(msg wba.MessageEventInfo) (string, []string) { return "", []string{} } } - //检查有无application.CmdList中的命令前缀 + //检查有无application.CmdMap中的命令前缀 for _, prefix := range cmdPrefix { if strings.HasPrefix(text, prefix) { text = strings.TrimPrefix(text, prefix) - for cmd := range CmdMap { - if strings.HasPrefix(text, cmd) { - text = strings.TrimPrefix(text, cmd) - text = strings.TrimPrefix(text, " ") - return cmd, strings.Split(text, " ") + for cmdList := range CmdMap { + for cmd := range CmdMap[cmdList] { + if strings.HasPrefix(text, cmd) { + text = strings.TrimPrefix(text, cmd) + text = strings.TrimPrefix(text, " ") + return cmd, strings.Split(text, " ") + } } } } diff --git a/typed/typed.go b/typed/typed.go index 929ed8c..0f621d7 100644 --- a/typed/typed.go +++ b/typed/typed.go @@ -15,3 +15,10 @@ type Protocol struct { Token string `json:"token"` Enable bool `json:"enable"` } + +type AppKey struct { + AppName string `json:"app_name"` + AppType string `json:"app_type"` + AppLevel int32 `json:"app_level"` + AppVersion string `json:"app_version"` +} diff --git a/wba/wind.go b/wba/wind.go index cdfab18..0ffb8ba 100644 --- a/wba/wind.go +++ b/wba/wind.go @@ -483,15 +483,16 @@ func NewApp(opts ...AppInfoOption) AppInfo { return Ext } -func NewCmd(name string, description string, solve func(args []string, msg MessageEventInfo)) Cmd { +func (ai *AppInfo) NewCmd(name string, description string, solve func(args []string, msg MessageEventInfo)) Cmd { return Cmd{ - NAME: name, - DESC: description, - SOLVE: solve, + Name: name, + Desc: description, + Solve: solve, + Rule: ai.Rule, } } -func NewScheduledTask(name string, description string, cron string, task func()) ScheduledTaskInfo { +func (ai *AppInfo) NewScheduledTask(name string, description string, cron string, task func()) ScheduledTaskInfo { return ScheduledTaskInfo{ Name: name, Desc: description, @@ -501,9 +502,10 @@ func NewScheduledTask(name string, description string, cron string, task func()) } type Cmd struct { - NAME string - DESC string - SOLVE func(args []string, msg MessageEventInfo) + Name string + Desc string + Solve func(args []string, msg MessageEventInfo) + Rule string } type MessageEventInfo struct { From 0a3a260eda69dfd860f25c3c6776d0f458d22370 Mon Sep 17 00:00:00 2001 From: Thun_Ann <2865813065@qq.com> Date: Mon, 3 Mar 2025 14:21:54 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=B0=86=E6=95=B0=E6=8D=AE=E5=BA=93api?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=88=B0js=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/api.go | 219 +++++++++++++++----------- core/app_admin_unix.go | 24 +++ core/app_admin_windows.go | 24 +++ core/app_core.go | 4 + database/database.go | 10 -- database/datamap.wdb | 1 - database/数据库0.1 使用文档.md | 40 ----- utils.go | 25 --- wba/wind.go | 191 ++++++++++------------ 9 files changed, 260 insertions(+), 278 deletions(-) delete mode 100644 database/datamap.wdb delete mode 100644 database/数据库0.1 使用文档.md diff --git a/core/api.go b/core/api.go index 6ba454b..3b1e3d9 100644 --- a/core/api.go +++ b/core/api.go @@ -2,6 +2,7 @@ package core import ( "ProjectWIND/LOG" + "ProjectWIND/database" "ProjectWIND/wba" "crypto/rand" "fmt" @@ -818,108 +819,133 @@ func (a *apiInfo) Log(content string, args ...interface{}) { } //database模块 -// //数据库部分允许字符串变量的读写操作,允许获取配置项操作 -// func (ai *AppInfo) VarSet(dataMap string, unit string, id string, key string, value string) { -// if ai.dbHandler != nil { -// ai.dbHandler.Set(ai.Name, dataMap, unit, id, key, value) -// } -// } +// //数据库部分允许字符串变量的读写操作,允许读取配置项操作 -// // VarGet 获取变量 -// func (ai *AppInfo) VarGet(dataMap string, unit string, id string, key string) (string, bool) { -// if ai.dbHandler != nil { -// res, ok := ai.dbHandler.Get(ai.Name, dataMap, unit, id, key, false) -// if !ok { -// return "", false -// } -// resStr, ok := res.(string) -// if !ok { -// return "", false -// } -// return resStr, true -// } -// return "", false -// } +type databaseInfo struct {} -// // GetIntConfig 获取整数配置 -// func (ai *AppInfo) GetIntConfig(dataMap string, key string) (int64, bool) { -// if ai.dbHandler != nil { -// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "number", key, true) -// if !ok { -// return 0, false -// } -// resInt, ok := res.(int64) -// if !ok { -// return 0, false -// } -// return resInt, true -// } -// return 0, false -// } +func (dbi *databaseInfo) varSet(app wba.AppInfo, datamap string, unit string, id string, key string, value string) { + database.Set(app.Name, datamap, unit, id, key, value) +} -// // GetStringConfig 获取字符串配置 -// func (ai *AppInfo) GetStringConfig(dataMap string, key string) (string, bool) { -// if ai.dbHandler != nil { -// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "string", key, true) -// if !ok { -// return "", false -// } -// resStr, ok := res.(string) -// if !ok { -// return "", false -// } -// return resStr, true -// } -// return "", false -// } +func (dbi *databaseInfo) SetUserVariable(app wba.AppInfo, id string, key string, value string) { + dbi.varSet(app, app.Name, "user", id, key, value) +} -// // GetFloatConfig 获取浮点数配置 -// func (ai *AppInfo) GetFloatConfig(dataMap string, key string) (float64, bool) { -// if ai.dbHandler != nil { -// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "float", key, true) -// if !ok { -// return 0, false -// } -// resFloat, ok := res.(float64) -// if !ok { -// return 0, false -// } -// return resFloat, true -// } -// return 0, false -// } +func (dbi *databaseInfo) SetGroupVariable(app wba.AppInfo, id string, key string, value string) { + dbi.varSet(app, app.Name, "group", id, key, value) +} -// // GetIntSliceConfig 获取整数切片配置 -// func (ai *AppInfo) GetIntSliceConfig(dataMap string, key string) ([]int64, bool) { -// if ai.dbHandler != nil { -// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "number_slice", key, true) -// if !ok { -// return nil, false -// } -// resSlice, ok := res.([]int64) -// if !ok { -// return nil, false -// } -// return resSlice, true -// } -// return nil, false -// } +func (dbi *databaseInfo) SetGlobalVariable(app wba.AppInfo, id string, key string, value string) { + dbi.varSet(app, app.Name, "global", id, key, value) +} -// // GetStringSliceConfig 获取字符串切片配置 -// func (ai *AppInfo) GetStringSliceConfig(dataMap string, key string) ([]string, bool) { -// if ai.dbHandler != nil { -// res, ok := ai.dbHandler.Get(ai.Name, dataMap, "config", "string_slice", key, true) -// if !ok { -// return nil, false -// } -// resSlice, ok := res.([]string) -// if !ok { -// return nil, false -// } -// return resSlice, true -// } -// return nil, false -// } +func (dbi *databaseInfo) SetOutUserVariable(app wba.AppInfo, datamap string, id string, key string, value string) { + dbi.varSet(app, datamap, "user", id, key, value) +} + +func (dbi *databaseInfo) SetOutGroupVariable(app wba.AppInfo, datamap string, id string, key string, value string) { + dbi.varSet(app, datamap, "group", id, key, value) +} + +func (dbi *databaseInfo) SetOutGlobalVariable(app wba.AppInfo, datamap string, id string, key string, value string) { + dbi.varSet(app, datamap, "global", id, key, value) +} + +func (dbi *databaseInfo) varGet(app wba.AppInfo, datamap string, unit string, id string, key string) (string, bool) { + res, ok := database.Get(app.Name, datamap, unit, id, key, false) + if !ok { + return "", false + } + resStr, ok := res.(string) + if !ok { + return "", false + } + return resStr, true +} + +func (dbi *databaseInfo) GetUserVariable(app wba.AppInfo, id string, key string) (string, bool) { + return dbi.varGet(app, app.Name, "user", id, key) +} + +func (dbi *databaseInfo) GetGroupVariable(app wba.AppInfo, id string, key string) (string, bool) { + return dbi.varGet(app, app.Name, "group", id, key) +} + +func (dbi *databaseInfo) GetGlobalVariable(app wba.AppInfo, id string, key string) (string, bool) { + return dbi.varGet(app, app.Name, "global", id, key) +} + +func (dbi *databaseInfo) GetOutUserVariable(app wba.AppInfo, datamap string, id string, key string) (string, bool) { + return dbi.varGet(app, datamap, "user", id, key) +} + +func (dbi *databaseInfo) GetOutGroupVariable(app wba.AppInfo, datamap string, id string, key string) (string, bool) { + return dbi.varGet(app, datamap, "group", id, key) +} + +func (dbi *databaseInfo) GetOutGlobalVariable(app wba.AppInfo, datamap string, id string, key string) (string, bool) { + return dbi.varGet(app, datamap, "global", id, key) +} + +func (dbi *databaseInfo) GetIntConfig(app wba.AppInfo, datamap string, key string) (int64, bool) { + res, ok := database.Get(app.Name, datamap, "config", "number", key, true) + if !ok { + return 0, false + } + resInt, ok := res.(int64) + if !ok { + return 0, false + } + return resInt, true +} + +func (dbi *databaseInfo) GetStringConfig(app wba.AppInfo, datamap string, key string) (string, bool) { + res, ok := database.Get(app.Name, datamap, "config", "string", key, true) + if !ok { + return "", false + } + resStr, ok := res.(string) + if !ok { + return "", false + } + return resStr, true +} + +func (dbi *databaseInfo) GetFloatConfig(app wba.AppInfo, datamap string, key string) (float64, bool) { + res, ok := database.Get(app.Name, datamap, "config", "float", key, true) + if !ok { + return 0, false + } + resFloat, ok := res.(float64) + if !ok { + return 0, false + } + return resFloat, true +} + +func (dbi *databaseInfo) GetIntSliceConfig(app wba.AppInfo, datamap string, key string) ([]int64, bool) { + res, ok := database.Get(app.Name, datamap, "config", "number_slice", key, true) + if !ok { + return nil, false + } + resSlice, ok := res.([]int64) + if !ok { + return nil, false + } + return resSlice, true +} + +func (dbi *databaseInfo) GetStringSliceConfig(app wba.AppInfo, datamap string, key string) ([]string, bool) { + res, ok := database.Get(app.Name, datamap, "config", "string_slice", key, true) + if !ok { + return nil, false + } + resSlice, ok := res.([]string) + if !ok { + return nil, false + } + return resSlice, true +} // 文件管理模块 //TODO: 文件管理模块待实现 @@ -930,6 +956,7 @@ func (a *apiInfo) Log(content string, args ...interface{}) { //核心信息调用模块 var AppApi apiInfo +var DatabaseApi databaseInfo func GenerateUUID() (string, error) { uuid := make([]byte, 16) diff --git a/core/app_admin_unix.go b/core/app_admin_unix.go index d7bd4fd..b154ba6 100644 --- a/core/app_admin_unix.go +++ b/core/app_admin_unix.go @@ -58,6 +58,11 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i LOG.Error("初始化应用 %s 失败: %v", pluginPath, err) } + err = app.InitWSD(&DatabaseApi) + if err != nil { + LOG.Error("初始化应用 %s 数据库失败: %v", pluginPath, err) + } + CmdMap = mergeMaps(CmdMap, app.Get().CmdMap) ScheduledTasks := app.Get().ScheduledTasks for _, task := range ScheduledTasks { @@ -84,6 +89,7 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i // 创建JS可用的wbaObj对象 wbaObj := runtime.NewObject() wsp := runtime.NewObject() + wsd := runtime.NewObject() _ = runtime.Set("wba", wbaObj) _ = wbaObj.Set("NewApp", wba.NewApp) _ = wbaObj.Set("NewCmd", wba.NewCmd) @@ -97,6 +103,7 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i _ = wbaObj.Set("WithAppType", wba.WithAppType) _ = wbaObj.Set("WithRule", wba.WithRule) _ = wbaObj.Set("WSP", wsp) + _ = wbaObj.Set("WSD", wsd) _ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg) _ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg) _ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg) @@ -139,6 +146,23 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i _ = wsp.Set("CleanCache", AppApi.CleanCache) _ = wsp.Set("GetLoginInfo", AppApi.LogWith) _ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo) + _ = wsd.Set("SetUserVariable", DatabaseApi.SetUserVariable) + _ = wsd.Set("SetGroupVariable", DatabaseApi.SetGroupVariable) + _ = wsd.Set("SetGlobalVariable", DatabaseApi.SetGlobalVariable) + _ = wsd.Set("SetOutUserVariable", DatabaseApi.SetOutUserVariable) + _ = wsd.Set("SetOutGroupVariable", DatabaseApi.SetOutGroupVariable) + _ = wsd.Set("SetOutGlobalVariable", DatabaseApi.SetOutGlobalVariable) + _ = wsd.Set("GetUserVariable", DatabaseApi.GetUserVariable) + _ = wsd.Set("GetGroupVariable", DatabaseApi.GetGroupVariable) + _ = wsd.Set("GetGlobalVariable", DatabaseApi.GetGlobalVariable) + _ = wsd.Set("GetOutUserVariable", DatabaseApi.GetOutUserVariable) + _ = wsd.Set("GetOutGroupVariable", DatabaseApi.GetOutGroupVariable) + _ = wsd.Set("GetOutGlobalVariable", DatabaseApi.GetOutGlobalVariable) + _ = wsd.Set("GetIntConfig", DatabaseApi.GetIntConfig) + _ = wsd.Set("GetFloatConfig", DatabaseApi.GetFloatConfig) + _ = wsd.Set("GetStringConfig", DatabaseApi.GetStringConfig) + _ = wsd.Set("GetIntSliceConfig", DatabaseApi.GetIntSliceConfig) + _ = wsd.Set("GetStringSliceConfig", DatabaseApi.GetStringSliceConfig) // 获取AppInit函数 appInitVal := runtime.Get("AppInit") diff --git a/core/app_admin_windows.go b/core/app_admin_windows.go index 97687e1..e501027 100644 --- a/core/app_admin_windows.go +++ b/core/app_admin_windows.go @@ -72,6 +72,11 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i LOG.Error("初始化应用 %s 失败: %v", pluginPath, err) } + err = app.InitWSD(&DatabaseApi) + if err != nil { + LOG.Error("初始化应用 %s 数据库失败: %v", pluginPath, err) + } + CmdMap = mergeMaps(CmdMap, app.Get().CmdMap) LOG.Info("应用 %s 加载成功", pluginPath) return 1, 1 @@ -95,6 +100,7 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i // 创建JS可用的wbaObj对象 wbaObj := runtime.NewObject() wsp := runtime.NewObject() + wsd := runtime.NewObject() _ = runtime.Set("wba", wbaObj) _ = wbaObj.Set("NewApp", wba.NewApp) _ = wbaObj.Set("NewCmd", wba.NewCmd) @@ -108,6 +114,7 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i _ = wbaObj.Set("WithAppType", wba.WithAppType) _ = wbaObj.Set("WithRule", wba.WithRule) _ = wbaObj.Set("WSP", wsp) + _ = wbaObj.Set("WSD", wsd) _ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg) _ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg) _ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg) @@ -150,6 +157,23 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i _ = wsp.Set("CleanCache", AppApi.CleanCache) _ = wsp.Set("GetLoginInfo", AppApi.LogWith) _ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo) + _ = wsd.Set("SetUserVariable", DatabaseApi.SetUserVariable) + _ = wsd.Set("SetGroupVariable", DatabaseApi.SetGroupVariable) + _ = wsd.Set("SetGlobalVariable", DatabaseApi.SetGlobalVariable) + _ = wsd.Set("SetOutUserVariable", DatabaseApi.SetOutUserVariable) + _ = wsd.Set("SetOutGroupVariable", DatabaseApi.SetOutGroupVariable) + _ = wsd.Set("SetOutGlobalVariable", DatabaseApi.SetOutGlobalVariable) + _ = wsd.Set("GetUserVariable", DatabaseApi.GetUserVariable) + _ = wsd.Set("GetGroupVariable", DatabaseApi.GetGroupVariable) + _ = wsd.Set("GetGlobalVariable", DatabaseApi.GetGlobalVariable) + _ = wsd.Set("GetOutUserVariable", DatabaseApi.GetOutUserVariable) + _ = wsd.Set("GetOutGroupVariable", DatabaseApi.GetOutGroupVariable) + _ = wsd.Set("GetOutGlobalVariable", DatabaseApi.GetOutGlobalVariable) + _ = wsd.Set("GetIntConfig", DatabaseApi.GetIntConfig) + _ = wsd.Set("GetFloatConfig", DatabaseApi.GetFloatConfig) + _ = wsd.Set("GetStringConfig", DatabaseApi.GetStringConfig) + _ = wsd.Set("GetIntSliceConfig", DatabaseApi.GetIntSliceConfig) + _ = wsd.Set("GetStringSliceConfig", DatabaseApi.GetStringSliceConfig) // 获取AppInit函数 appInitVal := runtime.Get("AppInit") diff --git a/core/app_core.go b/core/app_core.go index bf2a114..402a7db 100644 --- a/core/app_core.go +++ b/core/app_core.go @@ -29,6 +29,10 @@ func (app *AppInfo) Init(Api wba.WindStandardProtocolAPI) error { return nil } +func (app *AppInfo) InitWSD(Api wba.WindStandardDataBaseAPI) error { + return nil +} + func (app *AppInfo) GetCmd() map[string]wba.Cmd { return app.CmdMap } diff --git a/database/database.go b/database/database.go index 468cee8..8a86e79 100644 --- a/database/database.go +++ b/database/database.go @@ -538,16 +538,6 @@ func Set(appName string, datamap string, unit string, id string, key string, val dataSet(appName, unit, id, key, value, true) } -type DatabaseHandlerImpl struct{} - -func (dbh *DatabaseHandlerImpl) Set(appName string, datamap string, unit string, id string, key string, value interface{}) { - Set(appName, datamap, unit, id, key, value) -} - -func (dbh *DatabaseHandlerImpl) Get(appName string, datamap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) { - return Get(appName, datamap, unit, id, key, isGettingConfig) -} - // func VarSet(app wba.AppInfo, datamap string, unit string, id string, key string, value string) { // Set(app.Name, datamap, unit, id, key, value) // } diff --git a/database/datamap.wdb b/database/datamap.wdb deleted file mode 100644 index 049d915..0000000 --- a/database/datamap.wdb +++ /dev/null @@ -1 +0,0 @@ -{"Id":"datamap","Users":{},"Groups":{},"Global":{}} \ No newline at end of file diff --git a/database/数据库0.1 使用文档.md b/database/数据库0.1 使用文档.md deleted file mode 100644 index 9a0e865..0000000 --- a/database/数据库0.1 使用文档.md +++ /dev/null @@ -1,40 +0,0 @@ -```go -func Start() //启动默认数据库 -``` - -该函数用于启动数据库,加载数据,启动自动存储 - -Tips:需要异步启动数据库,否则进程会被阻塞 - -Tips:需要在启动数据库后等待其初始化,建议使用time.Sleep()函数等待至少1秒 - -```go -func Get(database *database, category string, id string, key string) (string,bool) //获取变量,示例用法:// database.Get("user", "1001", "age") 表示查询db数据库中id为1001的用户个人变量age -``` - -该函数用于查询设定的变量 - -——category部分可以填入"user","group","global",分别表示个人变量,群变量,全局变量 - -——id为用户id或群id,全局变量使用时,id可以理解为命名空间 - -——key为要查询的变量名 - -返回值类型为string,bool,第一个返回值为查询到的变量,第二个返回值表示是否返回成功 - -```go -func Set(category string, id string, key string, value string) //修改变量,示例用法: -// database.Set("user", "1001", "age", "18") 表示将db数据库中id为1001的用户个人变量age设置为"18" -// 注意:变量目前只支持string类型,如果需要储存数据或对象,请将它们转化为string类型再进行储存 -// 该数据库的所有变量将会存放在/data/database/datamap.txt中,请不要乱动这个文件 -``` - -该函数用于新建或修改变量 - -——category部分可以填入"user","group","global",分别表示个人变量,群变量,全局变量 - -——id为用户id或群id,全局变量使用时,id可以理解为命名空间 - -——key为要修改的变量名 - -——value为要修改的变量值 diff --git a/utils.go b/utils.go index 66d59cf..1a99737 100644 --- a/utils.go +++ b/utils.go @@ -360,30 +360,5 @@ func ReloadApps() { func startDatabase() { go database.Start() time.Sleep(time.Second * 1) - // 读写测试 - // for i := 0; i < 10; i++ { - // data, ok := database.Get("go", "go", "user", "test", "test"+fmt.Sprintf("%d", i), false) - // if !ok { - // LOG.Error("Failed to get data from database") - // continue - // } - // LOG.Info("Get data from database: %v", data) - // time.Sleep(time.Second * 1) - // } - // time.Sleep(time.Second * 1) - // for i := 0; i < 10; i++ { - // database.Set("go", "go", "user", "test", "test"+fmt.Sprintf("%d", i), "test"+fmt.Sprintf("%d", 1000+i)) - // time.Sleep(time.Second * 1) - // } - // time.Sleep(time.Second * 1) - // for i := 0; i < 10; i++ { - // data, ok := database.Get("go", "go", "user", "test", "test"+fmt.Sprintf("%d", i), false) - // if !ok { - // LOG.Error("Failed to get data from database") - // continue - // } - // LOG.Info("Get data from database: %v", data) - // time.Sleep(time.Second * 1) - // } select {} } diff --git a/wba/wind.go b/wba/wind.go index 0904d56..d6d58a0 100644 --- a/wba/wind.go +++ b/wba/wind.go @@ -7,6 +7,7 @@ import ( type APP interface { Get() AppInfo Init(api WindStandardProtocolAPI) error + InitWSD(api WindStandardDataBaseAPI) error } // WindStandardProtocolAPI Wind标准协议API,提供了onebot11标准中的API接口。 @@ -265,9 +266,84 @@ type WindStandardProtocolAPI interface { Log(log string, args ...interface{}) } -type DataBaseHandler interface { - Set(appName string, dataMap string, unit string, id string, key string, value interface{}) - Get(appName string, dataMap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) +type WindStandardDataBaseAPI interface { + // SetUserVariable 设置用户变量 + // SetGroupVariable 设置群组变量 + // SetGlobalVariable 设置全局变量 + // SetOutUserVarialbe 设置其他数据库中的用户变量(需要权限) + // SetOutGroupVarialbe 设置其他数据库中的群组变量(需要权限) + // SetOutGlobalVarialbe 设置其他数据库中的全局变量(需要权限) + // 参数: + // - app: 应用信息。 + // - id: 数据单元 ID。 + // - key: 变量名称。 + // - value: 变量值。 + // - datamap: 数据表名称。 + SetUserVariable(app AppInfo, id string, key string, value string) + SetGroupVariable(app AppInfo, id string, key string, value string) + SetGlobalVariable(app AppInfo, id string, key string, value string) + SetOutUserVariable(app AppInfo, datamap string, id string, key string, value string) + SetOutGroupVariable(app AppInfo, datamap string, id string, key string, value string) + SetOutGlobalVariable(app AppInfo, datamap string, id string, key string, value string) + + // GetUserVariable 获取用户变量 + // GetGroupVariable 获取群组变量 + // GetGlobalVariable 获取全局变量 + // GetOutUserVariable 获取其他数据库中的用户变量(需要权限) + // GetOutGroupVariable 获取其他数据库中的群组变量(需要权限) + // GetOutGlobalVariable 获取其他数据库中的全局变量(需要权限) + // 参数: + // - app: 应用信息。 + // - id: 数据单元 ID。 + // - key: 变量名称。 + // - datamap:数据表名称。 + // 返回: 变量值,是否存在。 + GetUserVariable(app AppInfo, id string, key string) (string, bool) + GetGroupVariable(app AppInfo, id string, key string) (string, bool) + GetGlobalVariable(app AppInfo, id string, key string) (string, bool) + GetOutUserVariable(app AppInfo, datamap string, id string, key string) (string, bool) + GetOutGroupVariable(app AppInfo, datamap string, id string, key string) (string, bool) + GetOutGlobalVariable(app AppInfo, datamap string, id string, key string) (string, bool) + + // GetIntConfig 获取指定数据单元的整数型配置。 + // 参数: + // - app: 应用信息。 + // - datamap: 数据单元名称。 + // - key: 配置名称。 + // 返回: 配置值,是否存在。 + GetIntConfig(app AppInfo, datamap string, key string) (int64, bool) + + // GetStringConfig 获取指定数据单元的字符串型配置。 + // 参数: + // - app: 应用信息。 + // - datamap: 数据单元名称。 + // - key: 配置名称。 + // 返回: 配置值,是否存在。 + GetStringConfig(app AppInfo, datamap string, key string) (string, bool) + + // GetFloatConfig 获取指定数据单元的浮点型配置。 + // 参数: + // - app: 应用信息。 + // - datamap: 数据单元名称。 + // - key: 配置名称。 + // 返回: 配置值,是否存在。 + GetFloatConfig(app AppInfo, datamap string, key string) (float64, bool) + + // GetIntSliceConfig 获取指定数据单元的整数型切片配置。 + // 参数: + // - app: 应用信息。 + // - datamap: 数据单元名称。 + // - key: 配置名称。 + // 返回: 配置值,是否存在。 + GetIntSliceConfig(app AppInfo, datamap string, key string) ([]int64, bool) + + // GetStringSliceConfig 获取指定数据单元的字符串型切片配置。 + // 参数: + // - app: 应用信息。 + // - datamap: 数据单元名称。 + // - key: 配置名称。 + // 返回: 配置值,是否存在。 + GetStringSliceConfig(app AppInfo, datamap string, key string) ([]string, bool) } type AppInfo struct { @@ -287,7 +363,6 @@ type AppInfo struct { MetaEventHandler func(msg MetaEventInfo) ScheduledTasks map[string]ScheduledTaskInfo API map[string]interface{} - DbHandler DataBaseHandler } func (ai AppInfo) Get() AppInfo { @@ -299,6 +374,11 @@ func (ai *AppInfo) Init(api WindStandardProtocolAPI) error { return nil } +func (ai *AppInfo) InitWSD(api WindStandardDataBaseAPI) error { + WSD = api + return nil +} + func (ai *AppInfo) AddCmd(name string, cmd Cmd) { ai.CmdMap[name] = cmd } @@ -311,108 +391,6 @@ func (ai *AppInfo) AddScheduledTask(task ScheduledTaskInfo) { ai.ScheduledTasks[task.Name] = task } -func (ai *AppInfo) VarSet(dataMap string, unit string, id string, key string, value string) { - if ai.DbHandler != nil { - ai.DbHandler.Set(ai.Name, dataMap, unit, id, key, value) - } -} - -// VarGet 获取变量 -func (ai *AppInfo) VarGet(dataMap string, unit string, id string, key string) (string, bool) { - if ai.DbHandler != nil { - res, ok := ai.DbHandler.Get(ai.Name, dataMap, unit, id, key, false) - if !ok { - return "", false - } - resStr, ok := res.(string) - if !ok { - return "", false - } - return resStr, true - } - return "", false -} - -// GetIntConfig 获取整数配置 -func (ai *AppInfo) GetIntConfig(dataMap string, key string) (int64, bool) { - if ai.DbHandler != nil { - res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "number", key, true) - if !ok { - return 0, false - } - resInt, ok := res.(int64) - if !ok { - return 0, false - } - return resInt, true - } - return 0, false -} - -// GetStringConfig 获取字符串配置 -func (ai *AppInfo) GetStringConfig(dataMap string, key string) (string, bool) { - if ai.DbHandler != nil { - res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "string", key, true) - if !ok { - return "", false - } - resStr, ok := res.(string) - if !ok { - return "", false - } - return resStr, true - } - return "", false -} - -// GetFloatConfig 获取浮点数配置 -func (ai *AppInfo) GetFloatConfig(dataMap string, key string) (float64, bool) { - if ai.DbHandler != nil { - res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "float", key, true) - if !ok { - return 0, false - } - resFloat, ok := res.(float64) - if !ok { - return 0, false - } - return resFloat, true - } - return 0, false -} - -// GetIntSliceConfig 获取整数切片配置 -func (ai *AppInfo) GetIntSliceConfig(dataMap string, key string) ([]int64, bool) { - if ai.DbHandler != nil { - res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "number_slice", key, true) - if !ok { - return nil, false - } - resSlice, ok := res.([]int64) - if !ok { - return nil, false - } - return resSlice, true - } - return nil, false -} - -// GetStringSliceConfig 获取字符串切片配置 -func (ai *AppInfo) GetStringSliceConfig(dataMap string, key string) ([]string, bool) { - if ai.DbHandler != nil { - res, ok := ai.DbHandler.Get(ai.Name, dataMap, "config", "string_slice", key, true) - if !ok { - return nil, false - } - resSlice, ok := res.([]string) - if !ok { - return nil, false - } - return resSlice, true - } - return nil, false -} - type AppInfoOption func(ei *AppInfo) func WithName(name string) AppInfoOption { @@ -745,3 +723,4 @@ type ScheduledTaskInfo struct { } var WSP WindStandardProtocolAPI +var WSD WindStandardDataBaseAPI From cdc0316c523db161b458de6efcaf60d93a91ab7c Mon Sep 17 00:00:00 2001 From: Thun_Ann <2865813065@qq.com> Date: Mon, 3 Mar 2025 14:38:17 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=BA=86=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=B8=A6=E6=9D=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/app_admin_windows.go | 256 -------------------------------------- 1 file changed, 256 deletions(-) delete mode 100644 core/app_admin_windows.go diff --git a/core/app_admin_windows.go b/core/app_admin_windows.go deleted file mode 100644 index e501027..0000000 --- a/core/app_admin_windows.go +++ /dev/null @@ -1,256 +0,0 @@ -//go:build windows -// +build windows - -package core - -import ( - "ProjectWIND/LOG" - "ProjectWIND/wba" - "fmt" - "os" - "path/filepath" - "syscall" - "unsafe" - "github.com/dop251/goja" -) - -var CmdMap = make(map[string]wba.Cmd) - -func ReloadApps() (total int, success int) { - appsDir := "./data/app/" - appFiles, err := os.ReadDir(appsDir) - total = 0 - success = 0 - if err != nil { - LOG.Error("加载应用所在目录失败:%v", err) - return - } - - for _, file := range appFiles { - totalDelta, successDelta := reloadAPP(file, appsDir) - total += totalDelta - success += successDelta - } - CmdMap = mergeMaps(CmdMap, AppCore.CmdMap) - return total, success -} - -func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta int) { - if file.IsDir() { - return 0, 0 - } - ext := filepath.Ext(file.Name()) - if ext == ".dll" { - pluginPath := filepath.Join(appsDir, file.Name()) - lib, err := syscall.LoadLibrary(pluginPath) - if err != nil { - LOG.Error("加载应用 %s 失败: %v", pluginPath, err) - return 1, 0 - } - defer func(handle syscall.Handle) { - err := syscall.FreeLibrary(handle) - if err != nil { - LOG.Error("释放应用 %s 时发生错误: %v", pluginPath, err) - } - }(lib) - - // 获取函数地址 - sym, err := syscall.GetProcAddress(lib, "AppInit") - if err != nil { - fmt.Println("找不到应用 %s 提供的 AppInit 接口: %v", err) - return 1, 0 - } - - // 定义函数类型 - AppInitPtr := (*func() wba.AppInfo)(unsafe.Pointer(&sym)) - AppInit := *AppInitPtr - - app := AppInit() - - err = app.Init(&AppApi) - if err != nil { - LOG.Error("初始化应用 %s 失败: %v", pluginPath, err) - } - - err = app.InitWSD(&DatabaseApi) - if err != nil { - LOG.Error("初始化应用 %s 数据库失败: %v", pluginPath, err) - } - - CmdMap = mergeMaps(CmdMap, app.Get().CmdMap) - LOG.Info("应用 %s 加载成功", pluginPath) - return 1, 1 - - } - if ext == ".js" { - pluginPath := filepath.Join(appsDir, file.Name()) - jsCode, err := os.ReadFile(pluginPath) - if err != nil { - LOG.Error("读取应用 %s 时发生错误: %v", pluginPath, err) - return 1, 0 - } - - runtime := goja.New() - _, err = runtime.RunString(string(jsCode)) - if err != nil { - LOG.Error("执行应用 %s 失败: %v", pluginPath, err) - return 1, 0 - } - - // 创建JS可用的wbaObj对象 - wbaObj := runtime.NewObject() - wsp := runtime.NewObject() - wsd := runtime.NewObject() - _ = runtime.Set("wba", wbaObj) - _ = wbaObj.Set("NewApp", wba.NewApp) - _ = wbaObj.Set("NewCmd", wba.NewCmd) - _ = wbaObj.Set("NewScheduledTask", wba.NewScheduledTask) - _ = wbaObj.Set("WithName", wba.WithName) - _ = wbaObj.Set("WithAuthor", wba.WithAuthor) - _ = wbaObj.Set("WithVersion", wba.WithVersion) - _ = wbaObj.Set("WithDescription", wba.WithDescription) - _ = wbaObj.Set("WithWebUrl", wba.WithWebUrl) - _ = wbaObj.Set("WithLicense", wba.WithLicense) - _ = wbaObj.Set("WithAppType", wba.WithAppType) - _ = wbaObj.Set("WithRule", wba.WithRule) - _ = wbaObj.Set("WSP", wsp) - _ = wbaObj.Set("WSD", wsd) - _ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg) - _ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg) - _ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg) - _ = wsp.Set("SendMsg", AppApi.SendMsg) - _ = wsp.Set("SendPrivateMsg", AppApi.SendPrivateMsg) - _ = wsp.Set("SendGroupMsg", AppApi.SendGroupMsg) - _ = wsp.Set("UnsafelyDeleteMsg", AppApi.UnsafelyDeleteMsg) - _ = wsp.Set("DeleteMsg", AppApi.DeleteMsg) - _ = wsp.Set("SendLike", AppApi.SendLike) - _ = wsp.Set("SetGroupKick", AppApi.SetGroupKick) - _ = wsp.Set("SetGroupBan", AppApi.SetGroupBan) - _ = wsp.Set("SetGroupWholeBan", AppApi.SetGroupWholeBan) - _ = wsp.Set("SetGroupAdmin", AppApi.SetGroupAdmin) - _ = wsp.Set("SetGroupLeave", AppApi.SetGroupLeave) - _ = wsp.Set("SetGroupCard", AppApi.SetGroupCard) - _ = wsp.Set("SetGroupName", AppApi.SetGroupName) - _ = wsp.Set("SetGroupSpecialTitle", AppApi.SetGroupSpecialTitle) - _ = wsp.Set("SetFriendAddRequest", AppApi.SetFriendAddRequest) - _ = wsp.Set("SetGroupAddRequest", AppApi.SetGroupAddRequest) - _ = wsp.Set("GetLoginInfo", AppApi.GetLoginInfo) - _ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo) - _ = wsp.Set("GetMsg", AppApi.GetMsg) - _ = wsp.Set("GetGroupInfo", AppApi.GetGroupInfo) - _ = wsp.Set("GetForwardMsg", AppApi.GetForwardMsg) - _ = wsp.Set("GetStrangerInfo", AppApi.GetStrangerInfo) - _ = wsp.Set("GetGroupList", AppApi.GetGroupList) - _ = wsp.Set("GetGroupMemberList", AppApi.GetGroupMemberList) - _ = wsp.Set("GetFriendList", AppApi.GetFriendList) - _ = wsp.Set("GetGroupMemberInfo", AppApi.GetGroupMemberInfo) - _ = wsp.Set("GetGroupHonorInfo", AppApi.GetGroupHonorInfo) - _ = wsp.Set("GetStatus", AppApi.GetStatus) - _ = wsp.Set("GetCookies", AppApi.GetCookies) - _ = wsp.Set("GetCSRFToken", AppApi.GetCSRFToken) - _ = wsp.Set("GetCredentials", AppApi.GetCredentials) - _ = wsp.Set("GetImage", AppApi.GetImage) - _ = wsp.Set("GetRecord", AppApi.GetRecord) - _ = wsp.Set("CanSendImage", AppApi.CanSendImage) - _ = wsp.Set("CanSendRecord", AppApi.CanSendRecord) - _ = wsp.Set("SetRestart", AppApi.SetRestart) - _ = wsp.Set("CleanCache", AppApi.CleanCache) - _ = wsp.Set("GetLoginInfo", AppApi.LogWith) - _ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo) - _ = wsd.Set("SetUserVariable", DatabaseApi.SetUserVariable) - _ = wsd.Set("SetGroupVariable", DatabaseApi.SetGroupVariable) - _ = wsd.Set("SetGlobalVariable", DatabaseApi.SetGlobalVariable) - _ = wsd.Set("SetOutUserVariable", DatabaseApi.SetOutUserVariable) - _ = wsd.Set("SetOutGroupVariable", DatabaseApi.SetOutGroupVariable) - _ = wsd.Set("SetOutGlobalVariable", DatabaseApi.SetOutGlobalVariable) - _ = wsd.Set("GetUserVariable", DatabaseApi.GetUserVariable) - _ = wsd.Set("GetGroupVariable", DatabaseApi.GetGroupVariable) - _ = wsd.Set("GetGlobalVariable", DatabaseApi.GetGlobalVariable) - _ = wsd.Set("GetOutUserVariable", DatabaseApi.GetOutUserVariable) - _ = wsd.Set("GetOutGroupVariable", DatabaseApi.GetOutGroupVariable) - _ = wsd.Set("GetOutGlobalVariable", DatabaseApi.GetOutGlobalVariable) - _ = wsd.Set("GetIntConfig", DatabaseApi.GetIntConfig) - _ = wsd.Set("GetFloatConfig", DatabaseApi.GetFloatConfig) - _ = wsd.Set("GetStringConfig", DatabaseApi.GetStringConfig) - _ = wsd.Set("GetIntSliceConfig", DatabaseApi.GetIntSliceConfig) - _ = wsd.Set("GetStringSliceConfig", DatabaseApi.GetStringSliceConfig) - - // 获取AppInit函数 - appInitVal := runtime.Get("AppInit") - if appInitVal == nil || goja.IsUndefined(appInitVal) { - LOG.Error("应用 %s 缺少AppInit函数", pluginPath) - return 1, 0 - } - appInitFunc, ok := goja.AssertFunction(appInitVal) - if !ok { - LOG.Error("应用 %s 的AppInit不是有效函数", pluginPath) - return 1, 0 - } - - // 调用AppInit获取应用实例 - jsApp, err := appInitFunc(goja.Undefined()) - if err != nil { - LOG.Error("初始化应用实例失败: %v", err) - return 1, 0 - } - - // 调用Init方法 - initVal := jsApp.ToObject(runtime).Get("Init") - initFunc, ok := goja.AssertFunction(initVal) - if !ok { - LOG.Error("应用 %s 缺少有效的Init方法", pluginPath) - return 1, 0 - } - - _, err = initFunc(wbaObj) - if err != nil { - LOG.Trace("应用初始化失败: %v", err) - return 1, 0 - } - - // 调用Get方法 - getVal := jsApp.ToObject(runtime).Get("Get") - getFunc, ok := goja.AssertFunction(getVal) - if !ok { - LOG.Error("应用 %s 缺少有效的Get方法", pluginPath) - return 1, 0 - } - - appInfoVal, err := getFunc(jsApp) - if err != nil { - LOG.Error("获取应用信息失败: %v", err) - return 1, 0 - } - - // 转换应用信息 - var appInfo wba.AppInfo - if err := runtime.ExportTo(appInfoVal, &appInfo); err != nil { - LOG.Error("应用信息转换失败: %v", err) - return 1, 0 - } - - // 合并命令 - CmdMap = mergeMaps(CmdMap, appInfo.CmdMap) - - // 注册定时任务 - for _, task := range appInfo.ScheduledTasks { - RegisterCron(appInfo.Name, task) - } - - LOG.Info("JS应用 %s 加载成功", pluginPath) - return 1, 1 - } - return 0, 0 -} - -func mergeMaps(map1, map2 map[string]wba.Cmd) map[string]wba.Cmd { - // 合并map1和map2到map3中 - map3 := make(map[string]wba.Cmd) - for key, value := range map1 { - map3[key] = value - } - for key, value := range map2 { - map3[key] = value - } - return map3 -} From 56599142988566e8450600c7fa982a0c6a58183f Mon Sep 17 00:00:00 2001 From: Sheyiyuan <2125107118@qq.com> Date: Mon, 3 Mar 2025 15:37:59 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=88=86=E6=94=AFSheyiyu?= =?UTF-8?q?anDev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/app_admin.go | 4 ++-- typed/typed.go | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/core/app_admin.go b/core/app_admin.go index e4ae3da..fbe99d8 100644 --- a/core/app_admin.go +++ b/core/app_admin.go @@ -70,8 +70,8 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i _ = wbaObj.Set("WithLicense", wba.WithLicense) _ = wbaObj.Set("WithAppType", wba.WithAppType) _ = wbaObj.Set("WithRule", wba.WithRule) - _ = wbaObj.Set("WSP", wsp) - _ = wbaObj.Set("WSD", wsd) + _ = wbaObj.Set("wsp", wsp) + _ = wbaObj.Set("wsd", wsd) _ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg) _ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg) _ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg) diff --git a/typed/typed.go b/typed/typed.go index 0f621d7..2dce859 100644 --- a/typed/typed.go +++ b/typed/typed.go @@ -22,3 +22,13 @@ type AppKey struct { AppLevel int32 `json:"app_level"` AppVersion string `json:"app_version"` } + +type SessionWorkSpace struct { + SessionId string `json:"session_id"` + SessionType string `json:"session_type"` + Rule string `json:"rule"` + Enable bool `json:"enable"` + AppEnable map[AppKey]bool `json:"app_enable"` + CmdEnable map[string]bool `json:"cmd_enable"` + WorkLevel int32 `json:"work_level"` +}