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() {