Merge remote-tracking branch 'origin/dev' into bhc
This commit is contained in:
commit
4cc3808ab8
130
core/api.go
130
core/api.go
@ -2,6 +2,7 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"ProjectWIND/LOG"
|
"ProjectWIND/LOG"
|
||||||
|
"ProjectWIND/database"
|
||||||
"ProjectWIND/wba"
|
"ProjectWIND/wba"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -818,7 +819,133 @@ func (a *apiInfo) Log(content string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//database模块
|
//database模块
|
||||||
//数据库部分允许字符串变量的读写操作,允许获取配置项操作
|
// //数据库部分允许字符串变量的读写操作,允许读取配置项操作
|
||||||
|
|
||||||
|
type databaseInfo struct {}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dbi *databaseInfo) SetUserVariable(app wba.AppInfo, id string, key string, value string) {
|
||||||
|
dbi.varSet(app, app.Name, "user", id, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dbi *databaseInfo) SetGroupVariable(app wba.AppInfo, id string, key string, value string) {
|
||||||
|
dbi.varSet(app, app.Name, "group", id, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dbi *databaseInfo) SetGlobalVariable(app wba.AppInfo, id string, key string, value string) {
|
||||||
|
dbi.varSet(app, app.Name, "global", id, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
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: 文件管理模块待实现
|
//TODO: 文件管理模块待实现
|
||||||
@ -829,6 +956,7 @@ func (a *apiInfo) Log(content string, args ...interface{}) {
|
|||||||
//核心信息调用模块
|
//核心信息调用模块
|
||||||
|
|
||||||
var AppApi apiInfo
|
var AppApi apiInfo
|
||||||
|
var DatabaseApi databaseInfo
|
||||||
|
|
||||||
func GenerateUUID() (string, error) {
|
func GenerateUUID() (string, error) {
|
||||||
uuid := make([]byte, 16)
|
uuid := make([]byte, 16)
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
//go:build linux || darwin
|
|
||||||
// +build linux darwin
|
|
||||||
|
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ProjectWIND/LOG"
|
"ProjectWIND/LOG"
|
||||||
|
"ProjectWIND/typed"
|
||||||
"ProjectWIND/wba"
|
"ProjectWIND/wba"
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"plugin"
|
"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) {
|
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/"
|
appsDir := "./data/app/"
|
||||||
appFiles, err := os.ReadDir(appsDir)
|
appFiles, err := os.ReadDir(appsDir)
|
||||||
total = 0
|
total = 0
|
||||||
@ -29,7 +31,7 @@ func ReloadApps() (total int, success int) {
|
|||||||
total += totalDelta
|
total += totalDelta
|
||||||
success += successDelta
|
success += successDelta
|
||||||
}
|
}
|
||||||
CmdMap = mergeMaps(CmdMap, AppCore.CmdMap)
|
CmdMap[0] = AppCore.CmdMap
|
||||||
return total, success
|
return total, success
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,33 +41,6 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext := filepath.Ext(file.Name())
|
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" {
|
if ext == ".js" {
|
||||||
pluginPath := filepath.Join(appsDir, file.Name())
|
pluginPath := filepath.Join(appsDir, file.Name())
|
||||||
jsCode, err := os.ReadFile(pluginPath)
|
jsCode, err := os.ReadFile(pluginPath)
|
||||||
@ -84,10 +59,9 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
|
|||||||
// 创建JS可用的wbaObj对象
|
// 创建JS可用的wbaObj对象
|
||||||
wbaObj := runtime.NewObject()
|
wbaObj := runtime.NewObject()
|
||||||
wsp := runtime.NewObject()
|
wsp := runtime.NewObject()
|
||||||
|
wsd := runtime.NewObject()
|
||||||
_ = runtime.Set("wba", wbaObj)
|
_ = runtime.Set("wba", wbaObj)
|
||||||
_ = wbaObj.Set("NewApp", wba.NewApp)
|
_ = wbaObj.Set("NewApp", wba.NewApp)
|
||||||
_ = wbaObj.Set("NewCmd", wba.NewCmd)
|
|
||||||
_ = wbaObj.Set("NewScheduledTask", wba.NewScheduledTask)
|
|
||||||
_ = wbaObj.Set("WithName", wba.WithName)
|
_ = wbaObj.Set("WithName", wba.WithName)
|
||||||
_ = wbaObj.Set("WithAuthor", wba.WithAuthor)
|
_ = wbaObj.Set("WithAuthor", wba.WithAuthor)
|
||||||
_ = wbaObj.Set("WithVersion", wba.WithVersion)
|
_ = wbaObj.Set("WithVersion", wba.WithVersion)
|
||||||
@ -96,7 +70,8 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
|
|||||||
_ = wbaObj.Set("WithLicense", wba.WithLicense)
|
_ = wbaObj.Set("WithLicense", wba.WithLicense)
|
||||||
_ = wbaObj.Set("WithAppType", wba.WithAppType)
|
_ = wbaObj.Set("WithAppType", wba.WithAppType)
|
||||||
_ = wbaObj.Set("WithRule", wba.WithRule)
|
_ = wbaObj.Set("WithRule", wba.WithRule)
|
||||||
_ = wbaObj.Set("WSP", wsp)
|
_ = wbaObj.Set("wsp", wsp)
|
||||||
|
_ = wbaObj.Set("wsd", wsd)
|
||||||
_ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg)
|
_ = wsp.Set("UnsafelySendMsg", AppApi.UnsafelySendMsg)
|
||||||
_ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg)
|
_ = wsp.Set("UnsafelySendPrivateMsg", AppApi.UnsafelySendPrivateMsg)
|
||||||
_ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg)
|
_ = wsp.Set("UnsafelySendGroupMsg", AppApi.UnsafelySendGroupMsg)
|
||||||
@ -139,6 +114,23 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
|
|||||||
_ = wsp.Set("CleanCache", AppApi.CleanCache)
|
_ = wsp.Set("CleanCache", AppApi.CleanCache)
|
||||||
_ = wsp.Set("GetLoginInfo", AppApi.LogWith)
|
_ = wsp.Set("GetLoginInfo", AppApi.LogWith)
|
||||||
_ = wsp.Set("GetVersionInfo", AppApi.GetVersionInfo)
|
_ = 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函数
|
// 获取AppInit函数
|
||||||
appInitVal := runtime.Get("AppInit")
|
appInitVal := runtime.Get("AppInit")
|
||||||
@ -194,8 +186,10 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
|
|||||||
return 1, 0
|
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 {
|
for _, task := range appInfo.ScheduledTasks {
|
||||||
@ -219,3 +213,19 @@ func mergeMaps(map1, map2 map[string]wba.Cmd) map[string]wba.Cmd {
|
|||||||
}
|
}
|
||||||
return map3
|
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
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
|
@ -21,7 +21,7 @@ func (app *AppInfo) Run(cmd string, args []string, msg wba.MessageEventInfo) err
|
|||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("cmd not found")
|
return errors.New("cmd not found")
|
||||||
}
|
}
|
||||||
app.CmdMap[cmd].SOLVE(args, msg)
|
app.CmdMap[cmd].Solve(args, msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,15 +29,19 @@ func (app *AppInfo) Init(Api wba.WindStandardProtocolAPI) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *AppInfo) InitWSD(Api wba.WindStandardDataBaseAPI) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (app *AppInfo) GetCmd() map[string]wba.Cmd {
|
func (app *AppInfo) GetCmd() map[string]wba.Cmd {
|
||||||
return app.CmdMap
|
return app.CmdMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmd(name string, help string, solve func(args []string, msg wba.MessageEventInfo)) wba.Cmd {
|
func NewCmd(name string, help string, solve func(args []string, msg wba.MessageEventInfo)) wba.Cmd {
|
||||||
return wba.Cmd{
|
return wba.Cmd{
|
||||||
NAME: name,
|
Name: name,
|
||||||
DESC: help,
|
Desc: help,
|
||||||
SOLVE: solve,
|
Solve: solve,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
LOG.Info("收到消息:(来自:%v-%v:%v-%v)%v", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname, msg.RawMessage)
|
||||||
//如果消息文本内容为bot,发送框架信息。
|
|
||||||
cmd, args := CmdSplit(msg)
|
cmd, args := CmdSplit(msg)
|
||||||
_, ok := CmdMap[cmd]
|
for _, cmdList := range CmdMap {
|
||||||
if ok {
|
_, ok := cmdList[cmd]
|
||||||
LOG.Debug("执行命令:%v %v", cmd, args)
|
if ok {
|
||||||
CmdMap[cmd].SOLVE(args, msg)
|
LOG.Debug("执行命令:%v %v", cmd, args)
|
||||||
|
cmdList[cmd].Solve(args, msg)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 处理消息内容
|
// TODO: 处理消息内容
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,15 +65,17 @@ func CmdSplit(msg wba.MessageEventInfo) (string, []string) {
|
|||||||
return "", []string{}
|
return "", []string{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//检查有无application.CmdList中的命令前缀
|
//检查有无application.CmdMap中的命令前缀
|
||||||
for _, prefix := range cmdPrefix {
|
for _, prefix := range cmdPrefix {
|
||||||
if strings.HasPrefix(text, prefix) {
|
if strings.HasPrefix(text, prefix) {
|
||||||
text = strings.TrimPrefix(text, prefix)
|
text = strings.TrimPrefix(text, prefix)
|
||||||
for cmd := range CmdMap {
|
for cmdList := range CmdMap {
|
||||||
if strings.HasPrefix(text, cmd) {
|
for cmd := range CmdMap[cmdList] {
|
||||||
text = strings.TrimPrefix(text, cmd)
|
if strings.HasPrefix(text, cmd) {
|
||||||
text = strings.TrimPrefix(text, " ")
|
text = strings.TrimPrefix(text, cmd)
|
||||||
return cmd, strings.Split(text, " ")
|
text = strings.TrimPrefix(text, " ")
|
||||||
|
return cmd, strings.Split(text, " ")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"ProjectWIND/LOG"
|
"ProjectWIND/LOG"
|
||||||
|
"ProjectWIND/typed"
|
||||||
"ProjectWIND/wba"
|
"ProjectWIND/wba"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -10,16 +11,14 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gProtocolAddr string
|
var gProtocol typed.Protocol
|
||||||
var gToken string
|
|
||||||
|
|
||||||
// WebSocketHandler 接收WebSocket连接处的消息并处理
|
// WebSocketHandler 接收WebSocket连接处的消息并处理
|
||||||
func WebSocketHandler(protocolAddr string, token string) error {
|
func WebSocketHandler(protocol typed.Protocol) error {
|
||||||
// 保存全局变量
|
// 保存全局变量
|
||||||
gProtocolAddr = protocolAddr
|
gProtocol = protocol
|
||||||
gToken = token
|
|
||||||
// 解析连接URL
|
// 解析连接URL
|
||||||
u, err := url.Parse(protocolAddr)
|
u, err := url.Parse(protocol.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LOG.Error("Parse URL error: %v", err)
|
LOG.Error("Parse URL error: %v", err)
|
||||||
return err
|
return err
|
||||||
@ -30,7 +29,7 @@ func WebSocketHandler(protocolAddr string, token string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
LOG.Fatal("创建请求出错:%v", err)
|
LOG.Fatal("创建请求出错:%v", err)
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+token)
|
req.Header.Set("Authorization", "Bearer "+protocol.Token)
|
||||||
// 配置WebSocket连接升级器
|
// 配置WebSocket连接升级器
|
||||||
dialer := websocket.DefaultDialer
|
dialer := websocket.DefaultDialer
|
||||||
// 使用升级器建立WebSocket连接
|
// 使用升级器建立WebSocket连接
|
||||||
@ -126,7 +125,7 @@ func wsAPI(body wba.APIRequestInfo) (Response wba.APIResponseInfo, err error) {
|
|||||||
return wba.APIResponseInfo{}, err
|
return wba.APIResponseInfo{}, err
|
||||||
}
|
}
|
||||||
// 解析连接URL
|
// 解析连接URL
|
||||||
u, err := url.Parse(gProtocolAddr)
|
u, err := url.Parse(gProtocol.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LOG.Error("Parse URL error: %v", err)
|
LOG.Error("Parse URL error: %v", err)
|
||||||
return wba.APIResponseInfo{}, err
|
return wba.APIResponseInfo{}, err
|
||||||
@ -136,7 +135,7 @@ func wsAPI(body wba.APIRequestInfo) (Response wba.APIResponseInfo, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
LOG.Fatal("创建请求出错:%v", err)
|
LOG.Fatal("创建请求出错:%v", err)
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+gToken)
|
req.Header.Set("Authorization", "Bearer "+gProtocol.Token)
|
||||||
// 配置WebSocket连接升级器
|
// 配置WebSocket连接升级器
|
||||||
dialer := websocket.DefaultDialer
|
dialer := websocket.DefaultDialer
|
||||||
// 使用升级器建立WebSocket连接
|
// 使用升级器建立WebSocket连接
|
||||||
|
@ -560,16 +560,6 @@ func Set(appName string, datamap string, unit string, id string, key string, val
|
|||||||
dataSet(appName, unit, id, key, value, true, false)
|
dataSet(appName, unit, id, key, value, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
// func VarSet(app wba.AppInfo, datamap string, unit string, id string, key string, value string) {
|
||||||
// Set(app.Name, datamap, unit, id, key, value)
|
// Set(app.Name, datamap, unit, id, key, value)
|
||||||
// }
|
// }
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{"Id":"datamap","Users":{},"Groups":{},"Global":{}}
|
|
@ -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为要修改的变量值
|
|
15
readme.md
15
readme.md
@ -14,8 +14,8 @@ TODO:
|
|||||||
- ✅ 文件初始化
|
- ✅ 文件初始化
|
||||||
- ✅ 事件处理
|
- ✅ 事件处理
|
||||||
- ✅ 数据库交互
|
- ✅ 数据库交互
|
||||||
- ❌ 插件系统
|
- ✅ 插件系统
|
||||||
- ❌ 用户系统
|
- ✅ 用户系统
|
||||||
- ❌ web ui
|
- ❌ web ui
|
||||||
- ❌ 文档编写
|
- ❌ 文档编写
|
||||||
|
|
||||||
@ -30,14 +30,19 @@ WIND(全称:WIND is not dice)是一个基于 Go 语言开发的bot框架
|
|||||||
## 1. goja
|
## 1. goja
|
||||||
- **库名称**:goja
|
- **库名称**:goja
|
||||||
- **仓库地址**:[https://github.com/dop251/goja](https://github.com/dop251/goja)
|
- **仓库地址**:[https://github.com/dop251/goja](https://github.com/dop251/goja)
|
||||||
- **用途说明**:goja 作为一款强大的 JavaScript 解释器,在本项目中承担了处理动态的 JavaScript 脚本逻辑,为项目提供了灵活的脚本扩展能力,使得我们能够在 Go 项目中嵌入 JavaScript 代码来实现一些特定的业务规则处理等功能。它极大地丰富了项目的功能和灵活性,让我们能够更高效地开发出具有特色的功能模块。
|
- **用途说明**:goja 作为一款强大的 JavaScript 解释器,在本项目中承担了处理动态的 JavaScript 脚本逻辑,为项目提供了灵活的脚本扩展能力,使得我们能够在项目中实现js插件的功能。它极大地丰富了项目的功能和灵活性,让跨平台的插件开发变得更加容易。
|
||||||
|
|
||||||
## 2. gocron
|
## 2. gocron
|
||||||
- **库名称**:gocron
|
- **库名称**:gocron
|
||||||
- **仓库地址**:[https://github.com/go-co-op/gocron](https://github.com/go-co-op/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/cloudwego/hertz](https://github.com/cloudwego/hertz)
|
||||||
|
- **用途说明**:hertz 是一个基于 Go 语言开发的高性能 HTTP 路由器。在本项目中,它被用作项目的 HTTP 服务器,为项目提供了快速、高效的 HTTP 请求处理能力。让我们能够灵活地对 HTTP 请求进行处理。
|
||||||
|
|
||||||
|
非常感谢以上项目团队的开源贡献,使得我们的项目开发能够借助这些优秀的工具快速推进,为用户带来更好的体验。
|
||||||
|
|
||||||
---
|
---
|
||||||
后面没有了,开发者很懒,什么都没写。
|
后面没有了,开发者很懒,什么都没写。
|
@ -1,17 +1,34 @@
|
|||||||
package typed
|
package typed
|
||||||
|
|
||||||
type CoreConfigInfo struct {
|
type CoreConfigInfo struct {
|
||||||
CoreName string `json:"core_name"`
|
CoreName string `json:"core_name"`
|
||||||
Protocols []Protocol `json:"protocols"`
|
Protocol Protocol `json:"protocol"`
|
||||||
WebUIPort uint16 `json:"webui_port"`
|
WebUIPort uint16 `json:"webui_port"`
|
||||||
PasswordHash string `json:"password_hash"`
|
PasswordHash string `json:"password_hash"`
|
||||||
ServiceName string `json:"service_name"`
|
ServiceName string `json:"service_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
ProtocolName string `json:"protocol_name"`
|
Name string `json:"protocol_name"`
|
||||||
ProtocolPlatform string `json:"protocol_platform"`
|
Platform string `json:"protocol_platform"`
|
||||||
ProtocolAddr string `json:"protocol_addr"`
|
Addr string `json:"protocol_addr"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Enable bool `json:"enable"`
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
}
|
}
|
||||||
|
100
utils.go
100
utils.go
@ -87,16 +87,16 @@ func checkAndUpdateConfig(configPath string) error {
|
|||||||
var coreConfig typed.CoreConfigInfo
|
var coreConfig typed.CoreConfigInfo
|
||||||
|
|
||||||
var defaultProtocol typed.Protocol
|
var defaultProtocol typed.Protocol
|
||||||
defaultProtocol.ProtocolName = "EXAMPLE"
|
defaultProtocol.Name = "EXAMPLE"
|
||||||
defaultProtocol.ProtocolPlatform = "在这里输入协议平台"
|
defaultProtocol.Platform = "在这里输入协议平台"
|
||||||
defaultProtocol.ProtocolAddr = "在这里输入协议地址,如'ws://127.0.0.1:8080'"
|
defaultProtocol.Addr = "在这里输入协议地址,如'ws://127.0.0.1:8080'"
|
||||||
defaultProtocol.Token = "在这里输入协议的Token"
|
defaultProtocol.Token = "在这里输入协议的Token"
|
||||||
defaultProtocol.Enable = true
|
defaultProtocol.Enable = true
|
||||||
|
|
||||||
var defaultConfig typed.CoreConfigInfo
|
var defaultConfig typed.CoreConfigInfo
|
||||||
defaultConfig.CoreName = "windCore"
|
defaultConfig.CoreName = "windCore"
|
||||||
defaultConfig.WebUIPort = 3211
|
defaultConfig.WebUIPort = 3211
|
||||||
defaultConfig.Protocols = []typed.Protocol{defaultProtocol}
|
defaultConfig.Protocol = defaultProtocol
|
||||||
defaultConfig.ServiceName = "wind"
|
defaultConfig.ServiceName = "wind"
|
||||||
// 读取配置文件
|
// 读取配置文件
|
||||||
file, err := os.Open(configPath)
|
file, err := os.Open(configPath)
|
||||||
@ -120,11 +120,8 @@ func checkAndUpdateConfig(configPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查并更新配置
|
// 检查并更新配置
|
||||||
//if coreConfig.ProtocolAddr == "" {
|
if coreConfig.Protocol == (typed.Protocol{}) {
|
||||||
// coreConfig.ProtocolAddr = defaultConfig.ProtocolAddr
|
coreConfig.Protocol = defaultConfig.Protocol
|
||||||
//}
|
|
||||||
if coreConfig.Protocols == nil || len(coreConfig.Protocols) == 0 {
|
|
||||||
coreConfig.Protocols = defaultConfig.Protocols
|
|
||||||
}
|
}
|
||||||
if coreConfig.WebUIPort == 0 {
|
if coreConfig.WebUIPort == 0 {
|
||||||
coreConfig.WebUIPort = defaultConfig.WebUIPort
|
coreConfig.WebUIPort = defaultConfig.WebUIPort
|
||||||
@ -311,44 +308,30 @@ func startProtocol() {
|
|||||||
LOG.Fatal("连接协议时,解析配置文件 ./data/core.json 失败: %v", err)
|
LOG.Fatal("连接协议时,解析配置文件 ./data/core.json 失败: %v", err)
|
||||||
}
|
}
|
||||||
LOG.Info("正在启动WebSocket链接程序...")
|
LOG.Info("正在启动WebSocket链接程序...")
|
||||||
protocolNum := 0
|
protocol := config.Protocol
|
||||||
breakNum := 0
|
if protocol.Name == "EXAMPLE" {
|
||||||
UnenableProtocolNum := 0
|
LOG.Warn("未找到协议配置信息")
|
||||||
for _, protocol := range config.Protocols {
|
return
|
||||||
protocolName := protocol.ProtocolName
|
}
|
||||||
if protocolName == "EXAMPLE" {
|
if protocol.Name == "" {
|
||||||
continue
|
LOG.Warn("连接协议 %s 时,协议名称为空", protocol.Name)
|
||||||
}
|
return
|
||||||
if protocolName == "" {
|
}
|
||||||
LOG.Warn("连接协议 %s 时,协议名称为空,跳过该协议", protocolName)
|
//获取协议地址
|
||||||
breakNum++
|
protocolAddr := protocol.Addr
|
||||||
continue
|
if protocolAddr == "" {
|
||||||
}
|
LOG.Warn("连接协议 %s 时,协议地址为空", protocol.Name)
|
||||||
//获取协议地址
|
return
|
||||||
protocolAddr := protocol.ProtocolAddr
|
}
|
||||||
if protocolAddr == "" {
|
if protocol.Enable == false {
|
||||||
LOG.Warn("连接协议 %s 时,协议地址为空,跳过该协议", protocolName)
|
LOG.Warn("连接协议 %s 时,协议已禁用", protocol.Name)
|
||||||
breakNum++
|
return
|
||||||
continue
|
}
|
||||||
}
|
// 启动 WebSocket 处理程序
|
||||||
if protocol.Enable == false {
|
err = core.WebSocketHandler(protocol)
|
||||||
LOG.Warn("连接协议 %s 时,协议已禁用,跳过该协议", protocolName)
|
if err != nil {
|
||||||
UnenableProtocolNum++
|
LOG.Error("连接协议时 %s,启动 WebSocket 处理程序失败: %v", protocol.Name, err)
|
||||||
continue
|
|
||||||
}
|
|
||||||
//获取token
|
|
||||||
token := protocol.Token
|
|
||||||
// 启动 WebSocket 处理程序
|
|
||||||
go func() {
|
|
||||||
err := core.WebSocketHandler(protocolAddr, token)
|
|
||||||
if err != nil {
|
|
||||||
LOG.Error("连接协议时,启动 WebSocket 处理程序失败: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
protocolNum++
|
|
||||||
}
|
}
|
||||||
LOG.Info(" %d 个协议服务启动完成, %d 个协议服务已禁用, %d 个协议服务因为配置错误被跳过。", protocolNum, UnenableProtocolNum, breakNum)
|
|
||||||
select {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReloadApps() {
|
func ReloadApps() {
|
||||||
@ -360,30 +343,5 @@ func ReloadApps() {
|
|||||||
func startDatabase() {
|
func startDatabase() {
|
||||||
go database.Start()
|
go database.Start()
|
||||||
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))
|
|
||||||
// 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("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))
|
|
||||||
// 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 {}
|
select {}
|
||||||
}
|
}
|
||||||
|
209
wba/wind.go
209
wba/wind.go
@ -7,6 +7,7 @@ import (
|
|||||||
type APP interface {
|
type APP interface {
|
||||||
Get() AppInfo
|
Get() AppInfo
|
||||||
Init(api WindStandardProtocolAPI) error
|
Init(api WindStandardProtocolAPI) error
|
||||||
|
InitWSD(api WindStandardDataBaseAPI) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// WindStandardProtocolAPI Wind标准协议API,提供了onebot11标准中的API接口。
|
// WindStandardProtocolAPI Wind标准协议API,提供了onebot11标准中的API接口。
|
||||||
@ -265,9 +266,84 @@ type WindStandardProtocolAPI interface {
|
|||||||
Log(log string, args ...interface{})
|
Log(log string, args ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataBaseHandler interface {
|
type WindStandardDataBaseAPI interface {
|
||||||
Set(appName string, dataMap string, unit string, id string, key string, value interface{})
|
// SetUserVariable 设置用户变量
|
||||||
Get(appName string, dataMap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool)
|
// 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 {
|
type AppInfo struct {
|
||||||
@ -287,7 +363,6 @@ type AppInfo struct {
|
|||||||
MetaEventHandler func(msg MetaEventInfo)
|
MetaEventHandler func(msg MetaEventInfo)
|
||||||
ScheduledTasks map[string]ScheduledTaskInfo
|
ScheduledTasks map[string]ScheduledTaskInfo
|
||||||
API map[string]interface{}
|
API map[string]interface{}
|
||||||
dbHandler DataBaseHandler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ai AppInfo) Get() AppInfo {
|
func (ai AppInfo) Get() AppInfo {
|
||||||
@ -299,6 +374,11 @@ func (ai *AppInfo) Init(api WindStandardProtocolAPI) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ai *AppInfo) InitWSD(api WindStandardDataBaseAPI) error {
|
||||||
|
WSD = api
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ai *AppInfo) AddCmd(name string, cmd Cmd) {
|
func (ai *AppInfo) AddCmd(name string, cmd Cmd) {
|
||||||
ai.CmdMap[name] = cmd
|
ai.CmdMap[name] = cmd
|
||||||
}
|
}
|
||||||
@ -311,108 +391,6 @@ func (ai *AppInfo) AddScheduledTask(task ScheduledTaskInfo) {
|
|||||||
ai.ScheduledTasks[task.Name] = task
|
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)
|
type AppInfoOption func(ei *AppInfo)
|
||||||
|
|
||||||
func WithName(name string) AppInfoOption {
|
func WithName(name string) AppInfoOption {
|
||||||
@ -483,15 +461,16 @@ func NewApp(opts ...AppInfoOption) AppInfo {
|
|||||||
return Ext
|
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{
|
return Cmd{
|
||||||
NAME: name,
|
Name: name,
|
||||||
DESC: description,
|
Desc: description,
|
||||||
SOLVE: solve,
|
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{
|
return ScheduledTaskInfo{
|
||||||
Name: name,
|
Name: name,
|
||||||
Desc: description,
|
Desc: description,
|
||||||
@ -501,9 +480,10 @@ func NewScheduledTask(name string, description string, cron string, task func())
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Cmd struct {
|
type Cmd struct {
|
||||||
NAME string
|
Name string
|
||||||
DESC string
|
Desc string
|
||||||
SOLVE func(args []string, msg MessageEventInfo)
|
Solve func(args []string, msg MessageEventInfo)
|
||||||
|
Rule string
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageEventInfo struct {
|
type MessageEventInfo struct {
|
||||||
@ -745,3 +725,4 @@ type ScheduledTaskInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var WSP WindStandardProtocolAPI
|
var WSP WindStandardProtocolAPI
|
||||||
|
var WSD WindStandardDataBaseAPI
|
||||||
|
Loading…
x
Reference in New Issue
Block a user