优化api业务逻辑

This commit is contained in:
Sheyiyuan 2024-12-07 17:16:44 +08:00
parent 4f6a994205
commit 86ea3fc544
15 changed files with 675 additions and 375 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
/scripts /scripts
/ProjectWIND /ProjectWIND
/data /data
**/.DS_Store **/.DS_Store
/app_demo/

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GoMixedReceiverTypes" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@ -12,12 +12,12 @@ func DEBUG(text string, msg ...interface{}) {
func INFO(text string, msg ...interface{}) { func INFO(text string, msg ...interface{}) {
msgText := fmt.Sprintf(text, msg...) msgText := fmt.Sprintf(text, msg...)
log.Println("[INFO] ", msgText) log.Println("[INFO] ", msgText)
} }
func WARN(text string, msg ...interface{}) { func WARN(text string, msg ...interface{}) {
msgText := fmt.Sprintf(text, msg...) msgText := fmt.Sprintf(text, msg...)
log.Println("[WARN] ", msgText) log.Println("[WARN] ", msgText)
} }
func ERROR(text string, msg ...interface{}) { func ERROR(text string, msg ...interface{}) {

View File

@ -1,26 +1,31 @@
package core package core
import ( import (
"ProjectWIND/typed" "ProjectWIND/LOG"
"ProjectWIND/wba"
"crypto/rand"
"encoding/json" "encoding/json"
"errors" "fmt"
) )
type apiInfo struct{}
/* /*
关于API的说明 关于API的说明
1.所有API请求按照OneBot11标准使用JSON格式进行数据交换api命名为由原文档中蛇形命名法改为双驼峰命名法 1.所有API请求按照OneBot11标准使用JSON格式进行数据交换api命名为由原文档中蛇形命名法改为双驼峰命名法
2.无响应的API请求使用ws协议处理有响应的API请求使用http协议处理 2.无响应的API请求使用ws协议处理有响应的API需添加echo字段
3.wind会从配置文件中读取API请求的url请确保正确填写 3.wind会从配置文件中读取API请求的url请确保正确填写
*/ */
//1.无响应API,使用ws协议处理 //1.无响应API,使用ws协议处理
func SendMsg(msg typed.MessageEventInfo, message string, autoEscape bool) error { // SendMsg 发送消息(自动判断消息类型)
func (a *apiInfo) SendMsg(msg wba.MessageEventInfo, message string, autoEscape bool) {
// 构建发送消息的JSON数据 // 构建发送消息的JSON数据
var messageData typed.APIRequestInfo var messageData wba.APIRequestInfo
messageType := msg.MessageType messageType := msg.MessageType
@ -38,202 +43,260 @@ func SendMsg(msg typed.MessageEventInfo, message string, autoEscape bool) error
} }
default: default:
{ {
return errors.New("invalid type") LOG.ERROR("发送消息(SendMsg)时,消息类型错误: %v", messageType)
} }
} }
messageData.Params.Message = message messageData.Params.Message = message
messageData.Params.AutoEscape = autoEscape messageData.Params.AutoEscape = autoEscape
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("发送消息时构建JSON数据失败: %v", err)
return
} }
// 发送消息 // 发送消息
err = wsAPI(messageJson) err = wsAPI(messageJson)
return err if err != nil {
LOG.ERROR("发送消息时,发送失败: %v", err)
return
}
LOG.INFO("发送消息(SendMsg)(至:%v-%v:%v-%v):%v", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname, message)
return
} }
func SendPrivateMsg(msg typed.MessageEventInfo, message string, autoEscape bool) error { // SendPrivateMsg 发送私聊消息
func (a *apiInfo) SendPrivateMsg(msg wba.MessageEventInfo, message string, autoEscape bool) {
// 构建发送消息的JSON数据 // 构建发送消息的JSON数据
var messageData typed.APIRequestInfo var messageData wba.APIRequestInfo
messageData.Action = "send_private_msg" messageData.Action = "send_private_msg"
messageData.Params.UserId = msg.UserId messageData.Params.UserId = msg.UserId
messageData.Params.Message = message messageData.Params.Message = message
messageData.Params.AutoEscape = autoEscape messageData.Params.AutoEscape = autoEscape
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("发送消息(SendPrivateMsg)时构建JSON数据失败: %v", err)
return
} }
// 发送消息 // 发送消息
err = wsAPI(messageJson) err = wsAPI(messageJson)
return err if err != nil {
LOG.ERROR("发送消息(SendPrivateMsg)时,发送失败: %v", err)
return
}
LOG.INFO("发送消息(SendPrivateMsg)(至:%v-%v:%v-%v):%v", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname, message)
return
} }
func SendGroupMsg(msg typed.MessageEventInfo, message string, autoEscape bool) error { // SendGroupMsg 发送群消息
func (a *apiInfo) SendGroupMsg(msg wba.MessageEventInfo, message string, autoEscape bool) {
// 构建发送消息的JSON数据 // 构建发送消息的JSON数据
var messageData typed.APIRequestInfo var messageData wba.APIRequestInfo
messageData.Action = "send_group_msg" messageData.Action = "send_group_msg"
messageData.Params.GroupId = msg.GroupId messageData.Params.GroupId = msg.GroupId
messageData.Params.Message = message messageData.Params.Message = message
messageData.Params.AutoEscape = autoEscape messageData.Params.AutoEscape = autoEscape
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("发送消息(SendGroupMsg)时构建JSON数据失败: %v", err)
return
} }
// 发送消息 // 发送消息
err = wsAPI(messageJson) err = wsAPI(messageJson)
return err if err != nil {
LOG.ERROR("发送消息(SendGroupMsg)时,发送失败: %v", err)
return
}
LOG.INFO("发送消息(SendGroupMsg)(至:%v-%v:%v-%v):%v", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname, message)
return
} }
func DeleteMsg(msg typed.MessageEventInfo, msgId int64) error { // DeleteMsg 撤回消息
func (a *apiInfo) DeleteMsg(msg wba.MessageEventInfo) {
// 构建删除消息的JSON数据 // 构建删除消息的JSON数据
var messageData typed.APIRequestInfo var messageData wba.APIRequestInfo
messageData.Action = "delete_msg" messageData.Action = "delete_msg"
messageData.Params.MessageId = msg.MessageId messageData.Params.MessageId = msg.MessageId
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("撤回消息(DeleteMsg)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return err if err != nil {
LOG.ERROR("撤回消息(DeleteMsg)时,发送失败: %v", err)
return
}
LOG.INFO("撤回消息(DeleteMsg):[id:%v]%v", msg.MessageId, msg.RawMessage)
return
} }
func sendLike(userId int64, times int) error { // SendLike 发送赞
func (a *apiInfo) SendLike(userId int64, times int) {
// 构建发送赞的JSON数据 // 构建发送赞的JSON数据
var messageData typed.APIRequestInfo var messageData wba.APIRequestInfo
messageData.Action = "send_like" messageData.Action = "send_like"
messageData.Params.UserId = userId messageData.Params.UserId = userId
messageData.Params.Times = times messageData.Params.Times = times
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("发送赞(SendLike)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("发送赞(SendLike)时,发送失败: %v", err)
return
}
LOG.INFO("发送赞(SendLike)(至:%v):%v", userId, times)
return
} }
func setGroupKick(groupId int64, userId int64, rejectAddRequest bool) error { // SetGroupKick 将指定用户移出群聊(需要群主或管理员权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupKick(groupId int64, userId int64, rejectAddRequest bool) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_kick" messageData.Action = "set_group_kick"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.UserId = userId messageData.Params.UserId = userId
messageData.Params.RejectAddRequest = rejectAddRequest messageData.Params.RejectAddRequest = rejectAddRequest
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("移出群聊(SetGroupKick)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("移出群聊(SetGroupKick)时,发送失败: %v", err)
return
}
LOG.INFO("移出群聊(SetGroupKick)(从:%v-%v):%v", groupId, userId, rejectAddRequest)
return
} }
func setGroupBan(groupId int64, userId int64, duration int32) error { // SetGroupBan 将指定用户禁言(需要群主或管理员权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupBan(groupId int64, userId int64, duration int32) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_ban" messageData.Action = "set_group_ban"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.UserId = userId messageData.Params.UserId = userId
messageData.Params.Duration = duration messageData.Params.Duration = duration
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("禁言群成员(SetGroupBan)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil
}
func setGroupAnonymousBan(groupId int64, flag string, duration int32) error {
var messageData typed.APIRequestInfo
messageData.Action = "set_group_anonymous_ban"
messageData.Params.GroupId = groupId
messageData.Params.Flag = flag
messageData.Params.Duration = duration
messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("禁言群成员(SetGroupBan)时,执行失败: %v", err)
return
} }
err = wsAPI(messageJson) LOG.INFO("禁言群成员(SetGroupBan)(在:%v-%v):%v", groupId, userId, duration)
return nil return
} }
func setGroupWholeBan(groupId int64, enable bool) error { // SetGroupWholeBan 设置全员禁言(需要群主或管理员权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupWholeBan(groupId int64, enable bool) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_whole_ban" messageData.Action = "set_group_whole_ban"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.Enable = enable messageData.Params.Enable = enable
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("设置全员禁言(SetGroupWholeBan)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("设置全员禁言(SetGroupWholeBan)时,执行失败: %v", err)
return
}
LOG.INFO("设置全员禁言(SetGroupWholeBan)(在:%v):%v", groupId, enable)
return
} }
func setGroupAdmin(groupId int64, userId int64, enable bool) error { // SetGroupAdmin 设置群管理员(需要群主权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupAdmin(groupId int64, userId int64, enable bool) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_admin" messageData.Action = "set_group_admin"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.UserId = userId messageData.Params.UserId = userId
messageData.Params.Enable = enable messageData.Params.Enable = enable
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("设置群管理员(SetGroupAdmin)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil
}
func setGroupAnonymous(groupId int64, enable bool) error {
var messageData typed.APIRequestInfo
messageData.Action = "set_group_anonymous"
messageData.Params.GroupId = groupId
messageData.Params.Enable = enable
messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("设置群管理员(SetGroupAdmin)时,执行失败: %v", err)
return
} }
err = wsAPI(messageJson) LOG.INFO("设置群管理员(SetGroupAdmin)(在:%v-%v):%v", groupId, userId, enable)
return nil return
} }
func setGroupCard(groupId int64, userId int64, card string) error { // SetGroupCard 设置群名片(需要群主或管理员权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupCard(groupId int64, userId int64, card string) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_card" messageData.Action = "set_group_card"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.UserId = userId messageData.Params.UserId = userId
messageData.Params.Card = card messageData.Params.Card = card
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("设置群名片(SetGroupCard)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("设置群名片(SetGroupCard)时,执行失败: %v", err)
return
}
LOG.INFO("设置群名片(SetGroupCard)(在:%v-%v):%v", groupId, userId, card)
return
} }
func setGroupName(groupId int64, groupName string) error { // SetGroupName 设置群名称(可能需要群主或管理员权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupName(groupId int64, groupName string) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_name" messageData.Action = "set_group_name"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.GroupName = groupName messageData.Params.GroupName = groupName
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("设置群名称(SetGroupName)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("设置群名称(SetGroupName)时,执行失败: %v", err)
return
}
LOG.INFO("设置群名称(SetGroupName)(在:%v):%v", groupId, groupName)
return
} }
func setGroupLeave(groupId int64, isDismiss bool) error { // SetGroupLeave 退出群聊
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupLeave(groupId int64, isDismiss bool) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_leave" messageData.Action = "set_group_leave"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.IsDismiss = isDismiss messageData.Params.IsDismiss = isDismiss
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("退出群聊(SetGroupLeave)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("退出群聊(SetGroupLeave)时,执行失败: %v", err)
return
}
LOG.INFO("退出群聊(SetGroupLeave)(在:%v):%v", groupId, isDismiss)
return
} }
func setGroupSpecialTitle(groupId int64, userId int64, specialTitle string, duration int32) error { // SetGroupSpecialTitle 设置群专属头衔(需要群主权限)
var messageData typed.APIRequestInfo func (a *apiInfo) SetGroupSpecialTitle(groupId int64, userId int64, specialTitle string, duration int32) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_special_title" messageData.Action = "set_group_special_title"
messageData.Params.GroupId = groupId messageData.Params.GroupId = groupId
messageData.Params.UserId = userId messageData.Params.UserId = userId
@ -241,46 +304,76 @@ func setGroupSpecialTitle(groupId int64, userId int64, specialTitle string, dura
messageData.Params.Duration = duration messageData.Params.Duration = duration
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("设置群特殊头衔(SetGroupSpecialTitle)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("设置群特殊头衔(SetGroupSpecialTitle)时,执行失败: %v", err)
return
}
LOG.INFO("设置群特殊头衔(SetGroupSpecialTitle)(在:%v-%v):%v-%v", groupId, userId, specialTitle, duration)
return
} }
func setFriendAddRequest(flag string, approve bool, remark string) error { // SetFriendAddRequest 处理加好友请求
var messageData typed.APIRequestInfo func (a *apiInfo) SetFriendAddRequest(flag string, approve bool, remark string) {
var messageData wba.APIRequestInfo
messageData.Action = "set_friend_add_request" messageData.Action = "set_friend_add_request"
messageData.Params.Flag = flag messageData.Params.Flag = flag
messageData.Params.Approve = approve messageData.Params.Approve = approve
messageData.Params.Remark = remark messageData.Params.Remark = remark
messageJson, err := json.Marshal(messageData) messageJson, err := json.Marshal(messageData)
if err != nil { if err != nil {
return err LOG.ERROR("处理加好友请求(SetFriendAddRequest)时构建JSON数据失败: %v", err)
return
} }
err = wsAPI(messageJson) err = wsAPI(messageJson)
return nil if err != nil {
LOG.ERROR("处理加好友请求(SetFriendAddRequest)时,执行失败: %v", err)
return
}
LOG.INFO("处理加好友请求(SetFriendAddRequest)(在:%v):%v-%v-%v", flag, approve, remark)
return
}
// SetGroupAddRequest 处理加群请求/邀请
func (a *apiInfo) SetGroupAddRequest(flag string, subType string, approve bool, reason string) {
var messageData wba.APIRequestInfo
messageData.Action = "set_group_add_request"
messageData.Params.Flag = flag
messageData.Params.SubType = subType
messageData.Params.Approve = approve
messageData.Params.Reason = reason
messageJson, err := json.Marshal(messageData)
if err != nil {
LOG.ERROR("处理加群请求/邀请(SetGroupAddRequest)时构建JSON数据失败: %v", err)
return
}
err = wsAPI(messageJson)
if err != nil {
LOG.ERROR("处理加群请求/邀请(SetGroupAddRequest)时,执行失败: %v", err)
return
}
LOG.INFO("处理加群请求/邀请(SetGroupAddRequest)(在:%v-%v-%v):%v", flag, subType, approve, reason)
return
} }
// 2.有响应API使用http协议处理 // 2.有响应API使用http协议处理
func GetMsg(messageId int32) (typed.MessageEventInfo, error) {
// 构建获取消息的JSON数据 var AppApi apiInfo
var requestData typed.ParamsInfo
var msg typed.MessageEventInfo func GenerateUUID() (string, error) {
action := "get_msg" uuid := make([]byte, 16)
requestData.MessageId = messageId _, err := rand.Read(uuid)
body, err := json.Marshal(requestData)
if err != nil { if err != nil {
return typed.MessageEventInfo{}, err return "", err
} }
// 发送请求
_, response, err := httpAPI("POST", action, body) // 设置UUID版本号版本4将第6字节的高4位设置为0100
if err != nil { uuid[6] = (uuid[6] & 0x0F) | 0x40
return typed.MessageEventInfo{}, err // 设置UUID变体RFC 4122规范定义的变体将第8字节的高4位设置为10
} uuid[8] = (uuid[8] & 0x3F) | 0x80
// 解析响应
err = json.Unmarshal(response, &msg) return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
if err != nil {
return typed.MessageEventInfo{}, err
}
return msg, nil
} }

View File

@ -1,58 +0,0 @@
package core
import (
"ProjectWIND/LOG"
"os"
"path/filepath"
"plugin"
)
func reloadApps() {
appsDir := "./data/app/"
appFiles, err := os.ReadDir(appsDir)
total := 0
success := 0
if err != nil {
LOG.ERROR("Error reading apps directory:%v", err)
return
}
for _, file := range appFiles {
totalDelta, successDelta := reloadAPP(file, appsDir)
total += totalDelta
success += successDelta
}
}
func reloadAPP(file os.DirEntry, appsDir string) (totalDelta int, successDelta int) {
if file.IsDir() {
return 0, 0
}
ext := filepath.Ext(file.Name())
if ext == ".so" || (ext == ".dll" && os.PathSeparator == '\\') {
pluginPath := filepath.Join(appsDir, file.Name())
p, err := plugin.Open(pluginPath)
if err != nil {
LOG.ERROR("Error opening app %s: %v\n", pluginPath, err)
return 1, 0
}
initSymbol, err := p.Lookup("init")
if err != nil {
LOG.ERROR("Error finding init function in app %s: %v\n", pluginPath, err)
return 1, 0
}
initFunc, ok := initSymbol.(func())
if !ok {
LOG.ERROR("init symbol in app %s is not a function\n", pluginPath)
return 1, 0
}
initFunc()
LOG.INFO("App %s initialized successfully\n", pluginPath)
return 1, 1
}
return 0, 0
}

81
core/app_admin.go Normal file
View File

@ -0,0 +1,81 @@
package core
import (
"ProjectWIND/LOG"
"ProjectWIND/wba"
"os"
"path/filepath"
"plugin"
)
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("Error reading apps directory:%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 == ".so" || (ext == ".dll" && os.PathSeparator == '\\') {
pluginPath := filepath.Join(appsDir, file.Name())
p, err := plugin.Open(pluginPath)
if err != nil {
LOG.ERROR("Error opening app %s: %v\n", pluginPath, err)
return 1, 0
}
initSymbol, err := p.Lookup("Application")
if err != nil {
LOG.ERROR("Error finding interface Application in app %s: %v", pluginPath, err)
return 1, 0
}
app, ok := initSymbol.(wba.APP)
if !ok {
LOG.ERROR("init symbol in app %s is not a right type", pluginPath)
return 1, 0
}
err = app.Init(&AppApi)
if err != nil {
LOG.ERROR("Error initializing app %s: %v", pluginPath, err)
}
//CmdMap = mergeMaps(CmdMap, app.Get())
LOG.INFO("App %s initialized successfully", 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
}

55
core/app_core.go Normal file
View File

@ -0,0 +1,55 @@
package core
import (
"ProjectWIND/LOG"
"ProjectWIND/wba"
"errors"
)
type CmdListInfo map[string]wba.Cmd
type AppInfo struct {
CmdMap map[string]wba.Cmd
}
func (app AppInfo) Get() AppInfo {
return app
}
func (app *AppInfo) Run(cmd string, args []string, msg wba.MessageEventInfo) error {
_, ok := app.CmdMap[cmd]
if !ok {
return errors.New("cmd not found")
}
app.CmdMap[cmd].SOLVE(args, msg)
return nil
}
func (app *AppInfo) Init(Api wba.WindAPI) error {
return nil
}
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 {
return wba.Cmd{
NAME: name,
DESC: help,
SOLVE: solve,
}
}
var AppCore = AppInfo{
CmdMap: CmdListInfo{
"bot": NewCmd(
"bot",
"显示WIND版本信息",
func(args []string, msg wba.MessageEventInfo) {
AppApi.SendMsg(msg, "WIND 0.1.0", false)
LOG.INFO("发送核心版本信息:(至:%v-%v:%v-%v)", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname)
},
),
},
}

View File

@ -1,31 +0,0 @@
package core
import (
"ProjectWIND/LOG"
"ProjectWIND/typed"
)
var CmdList = map[string]typed.ExtInfo{
"bot": ExtCore,
"help": ExtCore,
}
var ExtCore = typed.ExtInfo{
Run: func(cmd string, args []string, msg typed.MessageEventInfo) error {
if cmd == "help" {
err := SendMsg(msg, "假装有帮助信息", false)
LOG.INFO("发送核心帮助信息:(至:%v-%v:%v-%v)", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname)
if err != nil {
return err
}
}
if cmd == "bot" {
err := SendMsg(msg, "WIND 0.1.0", false)
LOG.INFO("发送核心版本信息:(至:%v-%v:%v-%v)", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname)
if err != nil {
return err
}
}
return nil
},
}

View File

@ -2,14 +2,14 @@ package core
import ( import (
"ProjectWIND/LOG" "ProjectWIND/LOG"
"ProjectWIND/typed" "ProjectWIND/wba"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
) )
func HandleMessage(msgJson []byte) { func HandleMessage(msgJson []byte) {
var msg typed.MessageEventInfo var msg wba.MessageEventInfo
err := json.Unmarshal(msgJson, &msg) err := json.Unmarshal(msgJson, &msg)
if err != nil { if err != nil {
LOG.ERROR("Unmarshalling message: %v", err) LOG.ERROR("Unmarshalling message: %v", err)
@ -18,18 +18,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发送框架信息。 //如果消息文本内容为bot发送框架信息。
cmd, args := CmdSplit(msg) cmd, args := CmdSplit(msg)
_, ok := CmdList[cmd] _, ok := CmdMap[cmd]
if ok { if ok {
err = CmdList[cmd].Run(cmd, args, msg) LOG.DEBUG("执行命令:%v %v", cmd, args)
if err != nil { CmdMap[cmd].SOLVE(args, msg)
LOG.ERROR("消息发送失败: %v", err)
}
} }
// TODO: 处理消息内容 // TODO: 处理消息内容
} }
func HandleNotice(msgJson []byte) { func HandleNotice(msgJson []byte) {
var notice typed.NoticeEventInfo var notice wba.NoticeEventInfo
err := json.Unmarshal(msgJson, &notice) err := json.Unmarshal(msgJson, &notice)
if err != nil { if err != nil {
LOG.ERROR("Unmarshalling notice: %v", err) LOG.ERROR("Unmarshalling notice: %v", err)
@ -38,7 +36,7 @@ func HandleNotice(msgJson []byte) {
} }
func HandleRequest(msgJson []byte) { func HandleRequest(msgJson []byte) {
var request typed.NoticeEventInfo var request wba.NoticeEventInfo
err := json.Unmarshal(msgJson, &request) err := json.Unmarshal(msgJson, &request)
if err != nil { if err != nil {
LOG.ERROR("Unmarshalling request: %v", err) LOG.ERROR("Unmarshalling request: %v", err)
@ -47,7 +45,7 @@ func HandleRequest(msgJson []byte) {
} }
func HandleMetaEvent(msgJson []byte) { func HandleMetaEvent(msgJson []byte) {
var meta typed.NoticeEventInfo var meta wba.NoticeEventInfo
err := json.Unmarshal(msgJson, &meta) err := json.Unmarshal(msgJson, &meta)
if err != nil { if err != nil {
LOG.ERROR("Unmarshalling meta: %v", err) LOG.ERROR("Unmarshalling meta: %v", err)
@ -55,7 +53,7 @@ func HandleMetaEvent(msgJson []byte) {
// TODO: 处理元事件 // TODO: 处理元事件
} }
func CmdSplit(msg typed.MessageEventInfo) (string, []string) { func CmdSplit(msg wba.MessageEventInfo) (string, []string) {
text := msg.RawMessage text := msg.RawMessage
if strings.HasPrefix(text, fmt.Sprintf("[CQ:at,qq=%d]", msg.SelfId)) { if strings.HasPrefix(text, fmt.Sprintf("[CQ:at,qq=%d]", msg.SelfId)) {
text = strings.TrimPrefix(text, fmt.Sprintf("[CQ:at,qq=%d]", msg.SelfId)) text = strings.TrimPrefix(text, fmt.Sprintf("[CQ:at,qq=%d]", msg.SelfId))
@ -68,9 +66,10 @@ func CmdSplit(msg typed.MessageEventInfo) (string, []string) {
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 CmdList { for cmd := range CmdMap {
if strings.HasPrefix(text, cmd) { if strings.HasPrefix(text, cmd) {
text = strings.TrimPrefix(text, cmd) text = strings.TrimPrefix(text, cmd)
text = strings.TrimPrefix(text, " ")
return cmd, strings.Split(text, " ") return cmd, strings.Split(text, " ")
} }
} }
@ -79,7 +78,7 @@ func CmdSplit(msg typed.MessageEventInfo) (string, []string) {
return "", []string{} return "", []string{}
} }
func statusCheck(msg typed.MessageEventInfo) bool { func statusCheck(msg wba.MessageEventInfo) bool {
//TODO: 检查当前组群工作状态 //TODO: 检查当前组群工作状态
return false return false
} }

View File

@ -15,7 +15,7 @@ import (
var gProtocolAddr string var gProtocolAddr string
// WebSocketHandler 接收WebSocket连接处的消息并处理 // WebSocketHandler 接收WebSocket连接处的消息并处理
func WebSocketHandler(protocolAddr string) error { func WebSocketHandler(protocolAddr string, token string) error {
// 保存全局变量 // 保存全局变量
gProtocolAddr = protocolAddr gProtocolAddr = protocolAddr
// 解析连接URL // 解析连接URL
@ -25,10 +25,18 @@ func WebSocketHandler(protocolAddr string) error {
return err return err
} }
conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil) // 创建一个带有自定义头的HTTP请求
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil { if err != nil {
LOG.ERROR("Dial error: %v", err) LOG.FATAL("创建请求出错:%v", err)
return err }
req.Header.Set("Authorization", "Bearer "+token)
// 配置WebSocket连接升级器
dialer := websocket.DefaultDialer
// 使用升级器建立WebSocket连接
conn, _, err := dialer.Dial(req.URL.String(), req.Header)
if err != nil {
LOG.FATAL("建立WebSocket连接出错:%v", err)
} }
defer func(conn *websocket.Conn) { defer func(conn *websocket.Conn) {
err := conn.Close() err := conn.Close()
@ -107,8 +115,8 @@ func processMessage(messageType int, message []byte) {
} }
default: default:
{ {
// 打印接收到的消息 // 此处为api请求响应数据通过channel返回给调用者
LOG.WARN("Received unknown event: %s", message) return
} }
} }
} }

View File

@ -39,8 +39,8 @@ func main() {
} }
if cmdArgs[0] == "-p" || cmdArgs[0] == "--protocol" { if cmdArgs[0] == "-p" || cmdArgs[0] == "--protocol" {
// 连接到协议端 // 连接到协议端
startProtocol()
go AutoSave() go AutoSave()
startProtocol()
return return
} }
fmt.Println("Invalid command.") fmt.Println("Invalid command.")

View File

@ -12,7 +12,7 @@ TODO:
- ✅ 协议端通信 - ✅ 协议端通信
- ✅ 日志输出 - ✅ 日志输出
- ✅ 文件初始化 - ✅ 文件初始化
- 事件处理 - 事件处理
- ❌ 数据库交互 - ❌ 数据库交互
- ❌ 插件系统 - ❌ 插件系统
- ❌ 用户系统 - ❌ 用户系统

View File

@ -3,163 +3,8 @@ package typed
type CoreConfigInfo struct { type CoreConfigInfo struct {
CoreName string `json:"core_name"` CoreName string `json:"core_name"`
ProtocolAddr string `json:"protocol_addr"` ProtocolAddr string `json:"protocol_addr"`
Token string `json:"token"`
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 MessageEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
MessageType string `json:"message_type,omitempty"`
SubType string `json:"sub_type,omitempty"`
MessageId int32 `json:"message_id,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
UserId int64 `json:"user_id,omitempty"`
Anonymous AnonymousInfo `json:"anonymous"`
Message []MessageInfo `json:"message,omitempty"`
RawMessage string `json:"raw_message,omitempty"`
Font int32 `json:"font,omitempty"`
Sender SenderInfo `json:"sender"`
}
type NoticeEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
NoticeType string `json:"notice_type,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
UserId int64 `json:"user_id,omitempty"`
File FileInfo `json:"file,omitempty"`
SubType string `json:"sub_type,omitempty"`
OperatorId int64 `json:"operator_id,omitempty"`
Duration int64 `json:"duration,omitempty"`
MessageId int64 `json:"message,omitempty"`
TargetId int64 `json:"target_id,omitempty"`
HonorType string `json:"honor_type,omitempty"`
}
type RequestEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
RequestType string `json:"request_type,omitempty"`
SubType string `json:"sub_type,omitempty"`
UserId int64 `json:"user_id,omitempty"`
Comment string `json:"comment,omitempty"`
Flag string `json:"flag,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
}
type MetaEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
MetaEventType string `json:"meta_event_type,omitempty"`
SubType string `json:"sub_type,omitempty"`
Status string `json:"status,omitempty"`
Interval int64 `json:"interval,omitempty"`
}
type FileInfo struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Size int64 `json:"size,omitempty"`
Busid int64 `json:"bucket,omitempty"`
}
type SenderInfo struct {
UserId int64 `json:"user_id,omitempty"`
Nickname string `json:"nickname,omitempty"`
Card string `json:"card,omitempty"`
Sex string `json:"sex,omitempty"`
Age int32 `json:"age,omitempty"`
Area string `json:"area,omitempty"`
Level string `json:"level,omitempty"`
Role string `json:"role,omitempty"`
Title string `json:"title,omitempty"`
}
type AnonymousInfo struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Flag string `json:"flag,omitempty"`
}
type MessageInfo struct {
Type string `json:"type,omitempty"`
Data MessageDataInfo `json:"data"`
}
type MessageDataInfo struct {
Type string `json:"type,omitempty"`
Text string `json:"text,omitempty"`
Id string `json:"id,omitempty"`
File string `json:"file,omitempty"`
Url string `json:"url,omitempty"`
Magic string `json:"magic,omitempty"`
Qq string `json:"qq,omitempty"`
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
Image string `json:"image,omitempty"`
Audio string `json:"audio,omitempty"`
Lat string `json:"lat,omitempty"`
Lon string `json:"lon,omitempty"`
Data string `json:"data,omitempty"`
}
type APIRequestInfo struct {
Action string `json:"action,omitempty"`
Params ParamsInfo `json:"params"`
Echo string `json:"echo,omitempty"`
}
type ParamsInfo struct {
Message string `json:"message,omitempty"`
UserId int64 `json:"user_id,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
AutoEscape bool `json:"auto_escape,omitempty"`
MessageId int32 `json:"message_id,omitempty"`
Id string `json:"id,omitempty"`
RejectAddRequest bool `json:"reject_add_request,omitempty"`
Duration int32 `json:"duration,omitempty"`
Enable bool `json:"enable,omitempty"`
Card string `json:"card,omitempty"`
GroupName string `json:"group_name,omitempty"`
IsDismiss bool `json:"is_dismiss,omitempty"`
SpecialTitle string `json:"special_title,omitempty"`
Flag string `json:"flag,omitempty"`
Approve bool `json:"approve,omitempty"`
Remark string `json:"remark,omitempty"`
Type string `json:"type,omitempty"`
SubType string `json:"sub_type,omitempty"`
Reason string `json:"reason,omitempty"`
NoCache bool `json:"no_cache,omitempty"`
File string `json:"file,omitempty"`
Times int `json:"times,omitempty"`
}
type ExtInfo struct {
Inform func() extInformation
Run func(cmd string, args []string, msg MessageEventInfo) error
Init func() error
CmdList func() []string
}
func (e *ExtInfo) SetInform(name string, version string, author string) {
inform := extInformation{
Name: name,
Version: version,
Author: author,
}
e.Inform = func() extInformation {
return inform
}
}
type extInformation struct {
Name string
Version string
Author string
}

View File

@ -15,7 +15,7 @@ import (
func initCore() string { func initCore() string {
// 初始化日志记录器 // 初始化日志记录器
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.SetFlags(log.Ldate | log.Ltime)
log.SetPrefix("[WIND] ") log.SetPrefix("[WIND] ")
LOG.INFO("正在初始化WIND配置文件...") LOG.INFO("正在初始化WIND配置文件...")
@ -128,6 +128,9 @@ func checkAndUpdateConfig(configPath string) error {
if coreConfig.PasswordHash == "" { if coreConfig.PasswordHash == "" {
coreConfig.PasswordHash = "" coreConfig.PasswordHash = ""
} }
if coreConfig.Token == "" {
coreConfig.Token = ""
}
formattedJSON, err := json.MarshalIndent(coreConfig, "", " ") formattedJSON, err := json.MarshalIndent(coreConfig, "", " ")
if err != nil { if err != nil {
@ -193,7 +196,7 @@ func startWebUI() {
//初始化 //初始化
logFile := initCore() logFile := initCore()
// 设置日志输出到文件 // 设置日志输出到文件
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.SetFlags(log.Ldate | log.Ltime)
log.SetPrefix("[WIND] ") log.SetPrefix("[WIND] ")
// 打开日志文件 // 打开日志文件
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
@ -220,7 +223,7 @@ func registerService() {
//初始化 //初始化
logFile := initCore() logFile := initCore()
// 设置日志输出到文件 // 设置日志输出到文件
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.SetFlags(log.Ldate | log.Ltime)
log.SetPrefix("[WIND] ") log.SetPrefix("[WIND] ")
// 打开日志文件 // 打开日志文件
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
@ -242,7 +245,7 @@ func startProtocol() {
//初始化 //初始化
logFile := initCore() logFile := initCore()
// 设置日志输出到文件 // 设置日志输出到文件
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.SetFlags(log.Ldate | log.Ltime)
log.SetPrefix("[WIND] ") log.SetPrefix("[WIND] ")
// 打开日志文件 // 打开日志文件
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
@ -257,6 +260,7 @@ func startProtocol() {
}(file) }(file)
// 设置日志输出到文件 // 设置日志输出到文件
log.SetOutput(io.MultiWriter(os.Stdout, file)) log.SetOutput(io.MultiWriter(os.Stdout, file))
ReloadApps()
//从配置文件中读取配置信息 //从配置文件中读取配置信息
LOG.INFO("正在启动WIND协议服务...") LOG.INFO("正在启动WIND协议服务...")
var config typed.CoreConfigInfo var config typed.CoreConfigInfo
@ -278,10 +282,12 @@ func startProtocol() {
} }
//获取协议地址 //获取协议地址
protocolAddr := config.ProtocolAddr protocolAddr := config.ProtocolAddr
//获取token
token := config.Token
//链接协议 //链接协议
// 启动 WebSocket 处理程序 // 启动 WebSocket 处理程序
LOG.INFO("正在启动WebSocket链接程序...") LOG.INFO("正在启动WebSocket链接程序...")
err = core.WebSocketHandler(protocolAddr) err = core.WebSocketHandler(protocolAddr, token)
if err != nil { if err != nil {
// 如果发生错误,记录错误并退出程序 // 如果发生错误,记录错误并退出程序
LOG.FATAL("Failed to start WebSocket link program: %v", err) LOG.FATAL("Failed to start WebSocket link program: %v", err)
@ -296,3 +302,9 @@ func AutoSave() {
time.Sleep(time.Second * 60) time.Sleep(time.Second * 60)
} }
} }
func ReloadApps() {
LOG.INFO("正在重新加载应用...")
total, success := core.ReloadApps()
LOG.INFO("应用重新加载完成,共加载%d个应用成功加载%d个应用。", total, success)
}

289
wba/wind.go Normal file
View File

@ -0,0 +1,289 @@
package wba
import (
"errors"
"fmt"
)
type APP interface {
Get() AppInfo
Run(cmd string, args []string, msg MessageEventInfo) error
Init(api WindAPI) error
}
type WindAPI interface {
SendMsg(msg MessageEventInfo, message string, autoEscape bool)
SendPrivateMsg(msg MessageEventInfo, message string, autoEscape bool)
SendGroupMsg(msg MessageEventInfo, message string, autoEscape bool)
DeleteMsg(msg MessageEventInfo)
SendLike(userId int64, times int)
SetGroupKick(groupId int64, userId int64, rejectAddRequest bool)
SetGroupBan(groupId int64, userId int64, duration int32)
SetGroupWholeBan(groupId int64, enable bool)
SetGroupAdmin(groupId int64, userId int64, enable bool)
SetGroupLeave(groupId int64, isDismiss bool)
SetGroupCard(groupId int64, userId int64, card string)
SetGroupName(groupId int64, groupName string)
SetGroupSpecialTitle(groupId int64, userId int64, specialTitle string, duration int32)
SetFriendAddRequest(flag string, approve bool, remark string)
SetGroupAddRequest(flag string, subType string, approve bool, reason string)
}
type AppInfo struct {
name string
version string
author string
description string
namespace string
webUrl string
license string
appType string
rule string
CmdMap map[string]Cmd
}
func (ei AppInfo) Get() AppInfo {
return ei
}
func (ei *AppInfo) Run(cmd string, args []string, msg MessageEventInfo) error {
_, ok := ei.CmdMap[cmd]
if !ok {
return errors.New("cmd not found")
}
ei.CmdMap[cmd].SOLVE(args, msg)
return nil
}
func (ei *AppInfo) Init(api WindAPI) error {
Wind = api
return nil
}
func (ei *AppInfo) AddCmd(name string, cmd Cmd) error {
ei.CmdMap[name] = cmd
return nil
}
type AppInfoOption func(ei *AppInfo)
func WithName(name string) AppInfoOption {
return func(ei *AppInfo) {
ei.name = name
}
}
func WithVersion(version string) AppInfoOption {
return func(ei *AppInfo) {
ei.version = version
}
}
func WithAuthor(author string) AppInfoOption {
return func(ei *AppInfo) {
ei.author = author
}
}
func WithDescription(description string) AppInfoOption {
return func(ei *AppInfo) {
ei.description = description
}
}
func WithNamespace(namespace string) AppInfoOption {
return func(ei *AppInfo) {
ei.namespace = namespace
}
}
func WithWebUrl(webUrl string) AppInfoOption {
return func(ei *AppInfo) {
ei.webUrl = webUrl
}
}
func WithLicense(license string) AppInfoOption {
return func(ei *AppInfo) {
ei.license = license
}
}
func WithAppType(appType string) AppInfoOption {
return func(ei *AppInfo) {
ei.appType = appType
}
}
func WithRule(rule string) AppInfoOption {
return func(ei *AppInfo) {
ei.rule = fmt.Sprintf("rule_%s", rule)
}
}
func NewApp(opts ...AppInfoOption) AppInfo {
Ext := AppInfo{
name: "Wind",
version: "v1.0.0",
author: "Wind",
description: "A simple and easy-to-use bot framework",
namespace: "wind",
webUrl: "https://github.com/Sheyiyuan/wind_app_model",
license: "MIT",
appType: "fun",
rule: "none",
CmdMap: make(map[string]Cmd),
}
for _, opt := range opts {
opt(&Ext)
}
return Ext
}
func NewCmd(name string, description string, solve func(args []string, msg MessageEventInfo)) Cmd {
return Cmd{
NAME: name,
DESC: description,
SOLVE: solve,
}
}
type Cmd struct {
NAME string
DESC string
SOLVE func(args []string, msg MessageEventInfo)
}
type MessageEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
MessageType string `json:"message_type,omitempty"`
SubType string `json:"sub_type,omitempty"`
MessageId int32 `json:"message_id,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
UserId int64 `json:"user_id,omitempty"`
Anonymous AnonymousInfo `json:"anonymous"`
Message []MessageInfo `json:"message,omitempty"`
RawMessage string `json:"raw_message,omitempty"`
Font int32 `json:"font,omitempty"`
Sender SenderInfo `json:"sender"`
}
type NoticeEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
NoticeType string `json:"notice_type,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
UserId int64 `json:"user_id,omitempty"`
File FileInfo `json:"file,omitempty"`
SubType string `json:"sub_type,omitempty"`
OperatorId int64 `json:"operator_id,omitempty"`
Duration int64 `json:"duration,omitempty"`
MessageId int64 `json:"message,omitempty"`
TargetId int64 `json:"target_id,omitempty"`
HonorType string `json:"honor_type,omitempty"`
}
type RequestEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
RequestType string `json:"request_type,omitempty"`
SubType string `json:"sub_type,omitempty"`
UserId int64 `json:"user_id,omitempty"`
Comment string `json:"comment,omitempty"`
Flag string `json:"flag,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
}
type MetaEventInfo struct {
Time int64 `json:"time,omitempty"`
SelfId int64 `json:"self_id,omitempty"`
PostType string `json:"post_type,omitempty"`
MetaEventType string `json:"meta_event_type,omitempty"`
SubType string `json:"sub_type,omitempty"`
Status string `json:"status,omitempty"`
Interval int64 `json:"interval,omitempty"`
}
type FileInfo struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Size int64 `json:"size,omitempty"`
Busid int64 `json:"bucket,omitempty"`
}
type SenderInfo struct {
UserId int64 `json:"user_id,omitempty"`
Nickname string `json:"nickname,omitempty"`
Card string `json:"card,omitempty"`
Sex string `json:"sex,omitempty"`
Age int32 `json:"age,omitempty"`
Area string `json:"area,omitempty"`
Level string `json:"level,omitempty"`
Role string `json:"role,omitempty"`
Title string `json:"title,omitempty"`
}
type AnonymousInfo struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Flag string `json:"flag,omitempty"`
}
type MessageInfo struct {
Type string `json:"type,omitempty"`
Data MessageDataInfo `json:"data"`
}
type MessageDataInfo struct {
Type string `json:"type,omitempty"`
Text string `json:"text,omitempty"`
Id string `json:"id,omitempty"`
File string `json:"file,omitempty"`
Url string `json:"url,omitempty"`
Magic string `json:"magic,omitempty"`
Qq string `json:"qq,omitempty"`
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
Image string `json:"image,omitempty"`
Audio string `json:"audio,omitempty"`
Lat string `json:"lat,omitempty"`
Lon string `json:"lon,omitempty"`
Data string `json:"data,omitempty"`
}
type ParamsInfo struct {
Message string `json:"message,omitempty"`
UserId int64 `json:"user_id,omitempty"`
GroupId int64 `json:"group_id,omitempty"`
AutoEscape bool `json:"auto_escape,omitempty"`
MessageId int32 `json:"message_id,omitempty"`
Id string `json:"id,omitempty"`
RejectAddRequest bool `json:"reject_add_request,omitempty"`
Duration int32 `json:"duration,omitempty"`
Enable bool `json:"enable,omitempty"`
Card string `json:"card,omitempty"`
GroupName string `json:"group_name,omitempty"`
IsDismiss bool `json:"is_dismiss,omitempty"`
SpecialTitle string `json:"special_title,omitempty"`
Flag string `json:"flag,omitempty"`
Approve bool `json:"approve,omitempty"`
Remark string `json:"remark,omitempty"`
Type string `json:"type,omitempty"`
SubType string `json:"sub_type,omitempty"`
Reason string `json:"reason,omitempty"`
NoCache bool `json:"no_cache,omitempty"`
File string `json:"file,omitempty"`
Times int `json:"times,omitempty"`
}
type APIRequestInfo struct {
Action string `json:"action,omitempty"`
Params ParamsInfo `json:"params"`
Echo string `json:"echo,omitempty"`
}
var Wind WindAPI