Compare commits

...

2 Commits

Author SHA1 Message Date
fec78bc3e9 Merge pull request 'update: app_type' (#10) from SheyiyuanDev into dev
Reviewed-on: #10
2025-05-14 17:07:27 +08:00
Sheyiyuan
d38d1f2c68 update: app_type 2025-05-14 16:43:17 +08:00
9 changed files with 159 additions and 184 deletions

4
.gitignore vendored
View File

@ -3,4 +3,6 @@ data/
**/.DS_Store
.idea/
.vscode/
ProjectWIND
ProjectWIND
ProjectWIND.exe
*/*abandoned*

View File

@ -9,7 +9,22 @@ import (
"runtime"
)
var logLevel = 2
func SetLogLevel(level int) {
if level < 0 {
level = 0
}
if level > 5 {
level = 5
}
logLevel = level
}
func Trace(text string, msg ...interface{}) {
if logLevel > 0 {
return
}
var pc uintptr
var file string
var line int
@ -27,25 +42,40 @@ func Trace(text string, msg ...interface{}) {
}
func Debug(text string, msg ...interface{}) {
if logLevel > 1 {
return
}
log.Printf("[Debug] %s\n", fmt.Sprintf(text, msg...))
}
func Info(text string, msg ...interface{}) {
if logLevel > 2 {
return
}
msgText := fmt.Sprintf(text, msg...)
log.Println("[Info] ", msgText)
}
func Notice(text string, msg ...interface{}) {
if logLevel > 3 {
return
}
msgText := fmt.Sprintf(text, msg...)
log.Println("[Notice]", msgText)
}
func Warn(text string, msg ...interface{}) {
if logLevel > 4 {
return
}
msgText := fmt.Sprintf(text, msg...)
log.Println("[Warn] ", msgText)
}
func Error(text string, msg ...interface{}) {
if logLevel > 5 {
return
}
msgText := fmt.Sprintf(text, msg...)
log.Println("[Error] ", msgText)
}

View File

@ -3,13 +3,42 @@ package core
import (
"ProjectWIND/LOG"
"ProjectWIND/wba"
"fmt"
"github.com/dop251/goja"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
)
var runtimePool = sync.Pool{
New: func() interface{} {
rt := goja.New()
rt.SetFieldNameMapper(CamelCaseFieldNameMapper{})
_ = rt.Set("console", map[string]interface{}{
"log": func(v ...interface{}) {
LOG.Info("JS log: %v", v...)
},
"error": func(v ...interface{}) {
LOG.Error("JS error: %v", v...)
},
})
// 创建JS可用的wbaObj对象
windObj := rt.NewObject()
_ = rt.Set("wind", windObj)
_ = windObj.Set("newApp", wba.NewApp)
_ = windObj.Set("withName", wba.WithSelector)
_ = windObj.Set("withDescription", wba.WithDescription)
_ = windObj.Set("withWebUrl", wba.WithWebUrl)
_ = windObj.Set("withLicense", wba.WithLicense)
_ = rt.Set("wsp", ProtocolApi)
_ = rt.Set("wsd", DatabaseApi)
_ = rt.Set("wst", ToolsApi)
return rt
},
}
type CamelCaseFieldNameMapper struct{}
func (CamelCaseFieldNameMapper) FieldName(_ reflect.Type, f reflect.StructField) string {
@ -76,16 +105,12 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
return 1, 0
}
runtime := goja.New()
runtime.SetFieldNameMapper(CamelCaseFieldNameMapper{})
runtime.Set("console", map[string]interface{}{
"log": func(v ...interface{}) {
LOG.Info("JS log: %v", v...)
},
"error": func(v ...interface{}) {
LOG.Error("JS error: %v", v...)
},
})
runtime := runtimePool.Get().(*goja.Runtime)
defer runtimePool.Put(runtime)
// 重置runtime状态
runtime.ClearInterrupt()
runtime.SetRandSource(nil)
// 添加错误捕获
safeRun := func(fn func() error) {
@ -105,150 +130,37 @@ func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta i
return err
})
// 创建JS可用的wbaObj对象
wbaObj := runtime.NewObject()
//wsp := runtime.NewObject()
//wsd := runtime.NewObject()
//wst := runtime.NewObject()
_ = runtime.Set("wba", wbaObj)
_ = wbaObj.Set("newApp", wba.NewApp)
_ = wbaObj.Set("withName", wba.WithSelector)
_ = wbaObj.Set("withDescription", wba.WithDescription)
_ = wbaObj.Set("withWebUrl", wba.WithWebUrl)
_ = wbaObj.Set("withLicense", wba.WithLicense)
_ = wbaObj.Set("wsp", ProtocolApi)
_ = wbaObj.Set("wsd", DatabaseApi)
_ = wbaObj.Set("wst", ToolsApi)
//_ = wbaObj.Set("wsp", wsp)
//_ = wbaObj.Set("wsd", wsd)
//_ = wbaObj.Set("wst", wst)
////WSP注册
//_ = wsp.Set("unsafelySendMsg", ProtocolApi.UnsafelySendMsg)
//_ = wsp.Set("unsafelySendPrivateMsg", ProtocolApi.UnsafelySendPrivateMsg)
//_ = wsp.Set("unsafelySendGroupMsg", ProtocolApi.UnsafelySendGroupMsg)
//_ = wsp.Set("sendMsg", ProtocolApi.SendMsg)
//_ = wsp.Set("sendPrivateMsg", ProtocolApi.SendPrivateMsg)
//_ = wsp.Set("sendGroupMsg", ProtocolApi.SendGroupMsg)
//_ = wsp.Set("unsafelyDeleteMsg", ProtocolApi.UnsafelyDeleteMsg)
//_ = wsp.Set("deleteMsg", ProtocolApi.DeleteMsg)
//_ = wsp.Set("sendLike", ProtocolApi.SendLike)
//_ = wsp.Set("setGroupKick", ProtocolApi.SetGroupKick)
//_ = wsp.Set("setGroupBan", ProtocolApi.SetGroupBan)
//_ = wsp.Set("setGroupWholeBan", ProtocolApi.SetGroupWholeBan)
//_ = wsp.Set("setGroupAdmin", ProtocolApi.SetGroupAdmin)
//_ = wsp.Set("setGroupLeave", ProtocolApi.SetGroupLeave)
//_ = wsp.Set("setGroupCard", ProtocolApi.SetGroupCard)
//_ = wsp.Set("setGroupName", ProtocolApi.SetGroupName)
//_ = wsp.Set("setGroupSpecialTitle", ProtocolApi.SetGroupSpecialTitle)
//_ = wsp.Set("setFriendAddRequest", ProtocolApi.SetFriendAddRequest)
//_ = wsp.Set("setGroupAddRequest", ProtocolApi.SetGroupAddRequest)
//_ = wsp.Set("getLoginInfo", ProtocolApi.GetLoginInfo)
//_ = wsp.Set("getVersionInfo", ProtocolApi.GetVersionInfo)
//_ = wsp.Set("getMsg", ProtocolApi.GetMsg)
//_ = wsp.Set("getGroupInfo", ProtocolApi.GetGroupInfo)
//_ = wsp.Set("getForwardMsg", ProtocolApi.GetForwardMsg)
//_ = wsp.Set("getStrangerInfo", ProtocolApi.GetStrangerInfo)
//_ = wsp.Set("getGroupList", ProtocolApi.GetGroupList)
//_ = wsp.Set("getGroupMemberList", ProtocolApi.GetGroupMemberList)
//_ = wsp.Set("getFriendList", ProtocolApi.GetFriendList)
//_ = wsp.Set("getGroupMemberInfo", ProtocolApi.GetGroupMemberInfo)
//_ = wsp.Set("getGroupHonorInfo", ProtocolApi.GetGroupHonorInfo)
//_ = wsp.Set("getStatus", ProtocolApi.GetStatus)
//_ = wsp.Set("getCookies", ProtocolApi.GetCookies)
//_ = wsp.Set("getCSRFToken", ProtocolApi.GetCSRFToken)
//_ = wsp.Set("getCredentials", ProtocolApi.GetCredentials)
//_ = wsp.Set("getImage", ProtocolApi.GetImage)
//_ = wsp.Set("getRecord", ProtocolApi.GetRecord)
//_ = wsp.Set("canSendImage", ProtocolApi.CanSendImage)
//_ = wsp.Set("canSendRecord", ProtocolApi.CanSendRecord)
//_ = wsp.Set("cetRestart", ProtocolApi.SetRestart)
//_ = wsp.Set("cleanCache", ProtocolApi.CleanCache)
//_ = wsp.Set("getVersionInfo", ProtocolApi.GetVersionInfo)
////WST注册
//_ = wst.Set("logWith", ToolsApi.LogWith)
//_ = wst.Set("log", ToolsApi.Log)
//_ = wst.Set("msgMarshal", ToolsApi.MsgUnmarshal)
////WSD注册
//_ = wsd.Set("setUserVariable", DatabaseApi.SetUserVariable)
//_ = wsd.Set("setGroupVariable", DatabaseApi.SetGroupVariable)
//_ = wsd.Set("setOutUserVariable", DatabaseApi.SetOutUserVariable)
//_ = wsd.Set("setOutGroupVariable", DatabaseApi.SetOutGroupVariable)
//_ = wsd.Set("unsafelySetUserVariable", DatabaseApi.UnsafelySetUserVariable)
//_ = wsd.Set("unsafelySetGroupVariable", DatabaseApi.UnsafelySetGroupVariable)
//_ = wsd.Set("unsafelySetGlobalVariable", DatabaseApi.UnsafelySetGlobalVariable)
//_ = wsd.Set("unsafelySetOutUserVariable", DatabaseApi.UnsafelySetOutUserVariable)
//_ = wsd.Set("unsafelySetOutGroupVariable", DatabaseApi.UnsafelySetOutGroupVariable)
//_ = wsd.Set("unsafelySetOutGlobalVariable", DatabaseApi.UnsafelySetOutGlobalVariable)
//_ = wsd.Set("getUserVariable", DatabaseApi.GetUserVariable)
//_ = wsd.Set("getGroupVariable", DatabaseApi.GetGroupVariable)
//_ = wsd.Set("getOutUserVariable", DatabaseApi.GetOutUserVariable)
//_ = wsd.Set("getOutGroupVariable", DatabaseApi.GetOutGroupVariable)
//_ = wsd.Set("unsafelyGetUserVariable", DatabaseApi.UnsafelyGetUserVariable)
//_ = wsd.Set("unsafelyGetGroupVariable", DatabaseApi.UnsafelyGetGroupVariable)
//_ = wsd.Set("unsafelyGetGlobalVariable", DatabaseApi.UnsafelyGetGlobalVariable)
//_ = wsd.Set("unsafelyGetOutUserVariable", DatabaseApi.UnsafelyGetOutUserVariable)
//_ = wsd.Set("unsafelyGetOutGroupVariable", DatabaseApi.UnsafelyGetOutGroupVariable)
//_ = wsd.Set("unsafelyGetOutGlobalVariable", DatabaseApi.UnsafelyGetOutGlobalVariable)
//_ = 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)
//_ = wsd.Set("unsafelyCreatePublicDatamap", DatabaseApi.UnsafelyCreatePublicDatamap)
// 获取app对象
var jsApp goja.Value
func() {
defer func() {
if r := recover(); r != nil {
LOG.Error("获取app对象时发生panic: %v", r)
}
}()
jsApp = runtime.Get("app")
}()
// 获取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)
if jsApp == nil || goja.IsUndefined(jsApp) {
LOG.Error("应用 %s 缺少app对象", 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方法 %#v", pluginPath, initFunc)
// 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(jsApp, &appInfo); err != nil {
err = func() (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("应用信息转换时发生panic: %v", r)
}
}()
return runtime.ExportTo(jsApp, &appInfo)
}()
if err != nil {
LOG.Error("应用信息转换失败: %v", err)
return 1, 0
}
// 初始化map字段
if appInfo.CmdMap == nil {
appInfo.CmdMap = make(map[string]wba.Cmd)

View File

@ -29,22 +29,25 @@ func (app *AppInfo) GetCmd() map[string]wba.Cmd {
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), appKey wba.AppKey) wba.Cmd {
return wba.Cmd{
Name: name,
Desc: help,
Solve: solve,
Name: name,
Desc: help,
Solve: solve,
AppKey: appKey,
}
}
var AppKeyOfCore = wba.AppKey{
Name: "core",
Level: 0,
Version: "1.0.0",
Selector: "core",
Option: "core",
}
var AppCore = AppInfo{
AppKey: wba.AppKey{
Name: "core",
Level: 0,
Version: "1.0.0",
Selector: "core",
Option: "core",
},
AppKey: AppKeyOfCore,
CmdMap: CmdListInfo{
"bot": NewCmd(
"bot",
@ -53,6 +56,7 @@ var AppCore = AppInfo{
ProtocolApi.SendMsg(msg, "WIND 0.1.0", false)
LOG.Info("发送核心版本信息:(至:%v-%v:%v-%v)", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname)
},
AppKeyOfCore,
),
"help": NewCmd(
"help",
@ -61,6 +65,7 @@ var AppCore = AppInfo{
ProtocolApi.SendMsg(msg, "帮助信息", false)
LOG.Info("发送帮助信息:(至:%v-%v:%v-%v)", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname)
},
AppKeyOfCore,
),
},
}

View File

@ -45,4 +45,10 @@ type Cmmand struct {
App AppKey
Solve func(*wba.Context)
}
```
```
## 原理说明
在每次接收指令时,核心会从核心表中的配置数据根据当前工作会话获取相关配置,若为空时,使用默认配置。
配置会设置每个选择器的选项及其子元素的禁用状态。也就是说所有指令集将以默认开启的状态被加载。

31
note/design_user_sys.md Normal file
View File

@ -0,0 +1,31 @@
# 用户系统设计
## 文件目录架构
```
wd:data
├── public
│ ├── app
│ │ ├── app1.js
│ │ └── app2.js
│ ├── images
│ │ ├── image1.jpg
│ │ └── image2.jpg
│ ├── files
│ │ ├── file1.txt
│ │ └── file2.txt
│ └── aduio
│ ├── audio1.mp3
│ └── audio2.wav
├── database
│ └── root.db
├── log
│ └── WIND_CORE_20250426114514.log
├── home
│ ├── user A
│ │ ├── coc
│ └── user B
│ ├── dnd
├── config
```

View File

@ -32,7 +32,7 @@ TODO:
- [ ] 配置文件
- [ ] 插件管理
- [x] 基础事件处理
- [ ] 指令管理
- [x] 指令管理
- [ ] 定时任务管理
- [ ] API管理
- [ ] web ui

View File

@ -1,7 +1,5 @@
package typed
import "ProjectWIND/wba"
type CoreConfigInfo struct {
CoreName string `json:"core_name"`
Protocol Protocol `json:"protocol"`
@ -17,12 +15,3 @@ type Protocol struct {
Token string `json:"token"`
Enable bool `json:"enable"`
}
type SessionWorkSpace struct {
SessionId string `json:"session_id"`
Rule string `json:"rule"`
Enable bool `json:"enable"`
AppEnable map[wba.AppKey]bool `json:"app_enable"`
CmdEnable map[string]bool `json:"cmd_enable"`
WorkLevel int32 `json:"work_level"`
}

View File

@ -93,23 +93,23 @@ func NewApp(name string, version string, author string, opts ...AppInfoOption) A
for _, opt := range opts {
opt(&Ext)
}
// 添加JS风格方法
Ext.API = map[string]interface{}{
toCamelCase("NewCmd"): Ext.NewCmd,
toCamelCase("AddCmd"): Ext.AddCmd,
toCamelCase("NewScheduledTask"): Ext.NewScheduledTask,
toCamelCase("AddScheduledTask"): Ext.AddScheduledTask,
}
return Ext
}
func (ai *AppInfo) 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,
// AppKey: ai.AppKey,
// }
//}
func (ai *AppInfo) NewCmd() Cmd {
return Cmd{
Name: name,
Desc: description,
Solve: solve,
Name: "",
Desc: "",
Solve: nil,
AppKey: ai.AppKey,
}
}