forked from ProjectWIND/ProjectWIND
优化api业务逻辑
This commit is contained in:
parent
4f6a994205
commit
86ea3fc544
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
||||
/ProjectWIND
|
||||
/data
|
||||
**/.DS_Store
|
||||
/app_demo/
|
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal 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>
|
295
core/api.go
295
core/api.go
@ -1,26 +1,31 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"ProjectWIND/typed"
|
||||
"ProjectWIND/LOG"
|
||||
"ProjectWIND/wba"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type apiInfo struct{}
|
||||
|
||||
/*
|
||||
关于API的说明:
|
||||
|
||||
1.所有API请求按照OneBot11标准,使用JSON格式进行数据交换。api命名为由原文档中蛇形命名法改为双驼峰命名法。
|
||||
|
||||
2.无响应的API请求使用ws协议处理,有响应的API请求使用http协议处理。
|
||||
2.无响应的API请求使用ws协议处理,有响应的API需添加echo字段。
|
||||
|
||||
3.wind会从配置文件中读取API请求的url,请确保正确填写。
|
||||
*/
|
||||
|
||||
//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数据
|
||||
var messageData typed.APIRequestInfo
|
||||
var messageData wba.APIRequestInfo
|
||||
|
||||
messageType := msg.MessageType
|
||||
|
||||
@ -38,202 +43,260 @@ func SendMsg(msg typed.MessageEventInfo, message string, autoEscape bool) error
|
||||
}
|
||||
default:
|
||||
{
|
||||
return errors.New("invalid type")
|
||||
LOG.ERROR("发送消息(SendMsg)时,消息类型错误: %v", messageType)
|
||||
}
|
||||
}
|
||||
messageData.Params.Message = message
|
||||
messageData.Params.AutoEscape = autoEscape
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("发送消息时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
// 发送消息
|
||||
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数据
|
||||
var messageData typed.APIRequestInfo
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "send_private_msg"
|
||||
messageData.Params.UserId = msg.UserId
|
||||
messageData.Params.Message = message
|
||||
messageData.Params.AutoEscape = autoEscape
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("发送消息(SendPrivateMsg)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
// 发送消息
|
||||
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数据
|
||||
var messageData typed.APIRequestInfo
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "send_group_msg"
|
||||
messageData.Params.GroupId = msg.GroupId
|
||||
messageData.Params.Message = message
|
||||
messageData.Params.AutoEscape = autoEscape
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("发送消息(SendGroupMsg)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
// 发送消息
|
||||
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数据
|
||||
var messageData typed.APIRequestInfo
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "delete_msg"
|
||||
messageData.Params.MessageId = msg.MessageId
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("撤回消息(DeleteMsg)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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数据
|
||||
var messageData typed.APIRequestInfo
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "send_like"
|
||||
messageData.Params.UserId = userId
|
||||
messageData.Params.Times = times
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("发送赞(SendLike)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupKick 将指定用户移出群聊(需要群主或管理员权限)
|
||||
func (a *apiInfo) SetGroupKick(groupId int64, userId int64, rejectAddRequest bool) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_kick"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.UserId = userId
|
||||
messageData.Params.RejectAddRequest = rejectAddRequest
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("移出群聊(SetGroupKick)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupBan 将指定用户禁言(需要群主或管理员权限)
|
||||
func (a *apiInfo) SetGroupBan(groupId int64, userId int64, duration int32) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_ban"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.UserId = userId
|
||||
messageData.Params.Duration = duration
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("禁言群成员(SetGroupBan)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
LOG.ERROR("禁言群成员(SetGroupBan)时,执行失败: %v", err)
|
||||
return
|
||||
}
|
||||
err = wsAPI(messageJson)
|
||||
return nil
|
||||
LOG.INFO("禁言群成员(SetGroupBan)(在:%v-%v):%v", groupId, userId, duration)
|
||||
return
|
||||
}
|
||||
|
||||
func setGroupWholeBan(groupId int64, enable bool) error {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupWholeBan 设置全员禁言(需要群主或管理员权限)
|
||||
func (a *apiInfo) SetGroupWholeBan(groupId int64, enable bool) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_whole_ban"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.Enable = enable
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("设置全员禁言(SetGroupWholeBan)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupAdmin 设置群管理员(需要群主权限)
|
||||
func (a *apiInfo) SetGroupAdmin(groupId int64, userId int64, enable bool) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_admin"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.UserId = userId
|
||||
messageData.Params.Enable = enable
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("设置群管理员(SetGroupAdmin)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
LOG.ERROR("设置群管理员(SetGroupAdmin)时,执行失败: %v", err)
|
||||
return
|
||||
}
|
||||
err = wsAPI(messageJson)
|
||||
return nil
|
||||
LOG.INFO("设置群管理员(SetGroupAdmin)(在:%v-%v):%v", groupId, userId, enable)
|
||||
return
|
||||
}
|
||||
|
||||
func setGroupCard(groupId int64, userId int64, card string) error {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupCard 设置群名片(需要群主或管理员权限)
|
||||
func (a *apiInfo) SetGroupCard(groupId int64, userId int64, card string) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_card"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.UserId = userId
|
||||
messageData.Params.Card = card
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("设置群名片(SetGroupCard)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupName 设置群名称(可能需要群主或管理员权限)
|
||||
func (a *apiInfo) SetGroupName(groupId int64, groupName string) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_name"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.GroupName = groupName
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("设置群名称(SetGroupName)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupLeave 退出群聊
|
||||
func (a *apiInfo) SetGroupLeave(groupId int64, isDismiss bool) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_leave"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.IsDismiss = isDismiss
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("退出群聊(SetGroupLeave)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetGroupSpecialTitle 设置群专属头衔(需要群主权限)
|
||||
func (a *apiInfo) SetGroupSpecialTitle(groupId int64, userId int64, specialTitle string, duration int32) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_group_special_title"
|
||||
messageData.Params.GroupId = groupId
|
||||
messageData.Params.UserId = userId
|
||||
@ -241,46 +304,76 @@ func setGroupSpecialTitle(groupId int64, userId int64, specialTitle string, dura
|
||||
messageData.Params.Duration = duration
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("设置群特殊头衔(SetGroupSpecialTitle)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
var messageData typed.APIRequestInfo
|
||||
// SetFriendAddRequest 处理加好友请求
|
||||
func (a *apiInfo) SetFriendAddRequest(flag string, approve bool, remark string) {
|
||||
var messageData wba.APIRequestInfo
|
||||
messageData.Action = "set_friend_add_request"
|
||||
messageData.Params.Flag = flag
|
||||
messageData.Params.Approve = approve
|
||||
messageData.Params.Remark = remark
|
||||
messageJson, err := json.Marshal(messageData)
|
||||
if err != nil {
|
||||
return err
|
||||
LOG.ERROR("处理加好友请求(SetFriendAddRequest)时,构建JSON数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
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协议处理
|
||||
func GetMsg(messageId int32) (typed.MessageEventInfo, error) {
|
||||
// 构建获取消息的JSON数据
|
||||
var requestData typed.ParamsInfo
|
||||
var msg typed.MessageEventInfo
|
||||
action := "get_msg"
|
||||
requestData.MessageId = messageId
|
||||
body, err := json.Marshal(requestData)
|
||||
|
||||
var AppApi apiInfo
|
||||
|
||||
func GenerateUUID() (string, error) {
|
||||
uuid := make([]byte, 16)
|
||||
_, err := rand.Read(uuid)
|
||||
if err != nil {
|
||||
return typed.MessageEventInfo{}, err
|
||||
return "", err
|
||||
}
|
||||
// 发送请求
|
||||
_, response, err := httpAPI("POST", action, body)
|
||||
if err != nil {
|
||||
return typed.MessageEventInfo{}, err
|
||||
}
|
||||
// 解析响应
|
||||
err = json.Unmarshal(response, &msg)
|
||||
if err != nil {
|
||||
return typed.MessageEventInfo{}, err
|
||||
}
|
||||
return msg, nil
|
||||
|
||||
// 设置UUID版本号(版本4),将第6字节的高4位设置为0100
|
||||
uuid[6] = (uuid[6] & 0x0F) | 0x40
|
||||
// 设置UUID变体(RFC 4122规范定义的变体),将第8字节的高4位设置为10
|
||||
uuid[8] = (uuid[8] & 0x3F) | 0x80
|
||||
|
||||
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
|
||||
}
|
||||
|
@ -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
81
core/app_admin.go
Normal 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
55
core/app_core.go
Normal 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)
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
@ -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
|
||||
},
|
||||
}
|
@ -2,14 +2,14 @@ package core
|
||||
|
||||
import (
|
||||
"ProjectWIND/LOG"
|
||||
"ProjectWIND/typed"
|
||||
"ProjectWIND/wba"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func HandleMessage(msgJson []byte) {
|
||||
var msg typed.MessageEventInfo
|
||||
var msg wba.MessageEventInfo
|
||||
err := json.Unmarshal(msgJson, &msg)
|
||||
if err != nil {
|
||||
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)
|
||||
//如果消息文本内容为bot,发送框架信息。
|
||||
cmd, args := CmdSplit(msg)
|
||||
_, ok := CmdList[cmd]
|
||||
_, ok := CmdMap[cmd]
|
||||
if ok {
|
||||
err = CmdList[cmd].Run(cmd, args, msg)
|
||||
if err != nil {
|
||||
LOG.ERROR("消息发送失败: %v", err)
|
||||
}
|
||||
LOG.DEBUG("执行命令:%v %v", cmd, args)
|
||||
CmdMap[cmd].SOLVE(args, msg)
|
||||
}
|
||||
// TODO: 处理消息内容
|
||||
}
|
||||
|
||||
func HandleNotice(msgJson []byte) {
|
||||
var notice typed.NoticeEventInfo
|
||||
var notice wba.NoticeEventInfo
|
||||
err := json.Unmarshal(msgJson, ¬ice)
|
||||
if err != nil {
|
||||
LOG.ERROR("Unmarshalling notice: %v", err)
|
||||
@ -38,7 +36,7 @@ func HandleNotice(msgJson []byte) {
|
||||
}
|
||||
|
||||
func HandleRequest(msgJson []byte) {
|
||||
var request typed.NoticeEventInfo
|
||||
var request wba.NoticeEventInfo
|
||||
err := json.Unmarshal(msgJson, &request)
|
||||
if err != nil {
|
||||
LOG.ERROR("Unmarshalling request: %v", err)
|
||||
@ -47,7 +45,7 @@ func HandleRequest(msgJson []byte) {
|
||||
}
|
||||
|
||||
func HandleMetaEvent(msgJson []byte) {
|
||||
var meta typed.NoticeEventInfo
|
||||
var meta wba.NoticeEventInfo
|
||||
err := json.Unmarshal(msgJson, &meta)
|
||||
if err != nil {
|
||||
LOG.ERROR("Unmarshalling meta: %v", err)
|
||||
@ -55,7 +53,7 @@ func HandleMetaEvent(msgJson []byte) {
|
||||
// TODO: 处理元事件
|
||||
}
|
||||
|
||||
func CmdSplit(msg typed.MessageEventInfo) (string, []string) {
|
||||
func CmdSplit(msg wba.MessageEventInfo) (string, []string) {
|
||||
text := msg.RawMessage
|
||||
if strings.HasPrefix(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 {
|
||||
if strings.HasPrefix(text, prefix) {
|
||||
text = strings.TrimPrefix(text, prefix)
|
||||
for cmd := range CmdList {
|
||||
for cmd := range CmdMap {
|
||||
if strings.HasPrefix(text, cmd) {
|
||||
text = strings.TrimPrefix(text, cmd)
|
||||
text = strings.TrimPrefix(text, " ")
|
||||
return cmd, strings.Split(text, " ")
|
||||
}
|
||||
}
|
||||
@ -79,7 +78,7 @@ func CmdSplit(msg typed.MessageEventInfo) (string, []string) {
|
||||
return "", []string{}
|
||||
}
|
||||
|
||||
func statusCheck(msg typed.MessageEventInfo) bool {
|
||||
func statusCheck(msg wba.MessageEventInfo) bool {
|
||||
//TODO: 检查当前组群工作状态
|
||||
return false
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
var gProtocolAddr string
|
||||
|
||||
// WebSocketHandler 接收WebSocket连接处的消息并处理
|
||||
func WebSocketHandler(protocolAddr string) error {
|
||||
func WebSocketHandler(protocolAddr string, token string) error {
|
||||
// 保存全局变量
|
||||
gProtocolAddr = protocolAddr
|
||||
// 解析连接URL
|
||||
@ -25,10 +25,18 @@ func WebSocketHandler(protocolAddr string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
// 创建一个带有自定义头的HTTP请求
|
||||
req, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
LOG.ERROR("Dial error: %v", err)
|
||||
return err
|
||||
LOG.FATAL("创建请求出错:%v", 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) {
|
||||
err := conn.Close()
|
||||
@ -107,8 +115,8 @@ func processMessage(messageType int, message []byte) {
|
||||
}
|
||||
default:
|
||||
{
|
||||
// 打印接收到的消息
|
||||
LOG.WARN("Received unknown event: %s", message)
|
||||
// 此处为api请求响应数据,通过channel返回给调用者
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
main.go
2
main.go
@ -39,8 +39,8 @@ func main() {
|
||||
}
|
||||
if cmdArgs[0] == "-p" || cmdArgs[0] == "--protocol" {
|
||||
// 连接到协议端
|
||||
startProtocol()
|
||||
go AutoSave()
|
||||
startProtocol()
|
||||
return
|
||||
}
|
||||
fmt.Println("Invalid command.")
|
||||
|
@ -12,7 +12,7 @@ TODO:
|
||||
- ✅ 协议端通信
|
||||
- ✅ 日志输出
|
||||
- ✅ 文件初始化
|
||||
- ❌ 事件处理
|
||||
- ✅ 事件处理
|
||||
- ❌ 数据库交互
|
||||
- ❌ 插件系统
|
||||
- ❌ 用户系统
|
||||
|
157
typed/typed.go
157
typed/typed.go
@ -3,163 +3,8 @@ package typed
|
||||
type CoreConfigInfo struct {
|
||||
CoreName string `json:"core_name"`
|
||||
ProtocolAddr string `json:"protocol_addr"`
|
||||
Token string `json:"token"`
|
||||
WebUIPort uint16 `json:"webui_port"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
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
|
||||
}
|
||||
|
22
utils.go
22
utils.go
@ -15,7 +15,7 @@ import (
|
||||
|
||||
func initCore() string {
|
||||
// 初始化日志记录器
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||
log.SetFlags(log.Ldate | log.Ltime)
|
||||
log.SetPrefix("[WIND] ")
|
||||
|
||||
LOG.INFO("正在初始化WIND配置文件...")
|
||||
@ -128,6 +128,9 @@ func checkAndUpdateConfig(configPath string) error {
|
||||
if coreConfig.PasswordHash == "" {
|
||||
coreConfig.PasswordHash = ""
|
||||
}
|
||||
if coreConfig.Token == "" {
|
||||
coreConfig.Token = ""
|
||||
}
|
||||
|
||||
formattedJSON, err := json.MarshalIndent(coreConfig, "", " ")
|
||||
if err != nil {
|
||||
@ -193,7 +196,7 @@ func startWebUI() {
|
||||
//初始化
|
||||
logFile := initCore()
|
||||
// 设置日志输出到文件
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||
log.SetFlags(log.Ldate | log.Ltime)
|
||||
log.SetPrefix("[WIND] ")
|
||||
// 打开日志文件
|
||||
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
@ -220,7 +223,7 @@ func registerService() {
|
||||
//初始化
|
||||
logFile := initCore()
|
||||
// 设置日志输出到文件
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||
log.SetFlags(log.Ldate | log.Ltime)
|
||||
log.SetPrefix("[WIND] ")
|
||||
// 打开日志文件
|
||||
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
@ -242,7 +245,7 @@ func startProtocol() {
|
||||
//初始化
|
||||
logFile := initCore()
|
||||
// 设置日志输出到文件
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||
log.SetFlags(log.Ldate | log.Ltime)
|
||||
log.SetPrefix("[WIND] ")
|
||||
// 打开日志文件
|
||||
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
@ -257,6 +260,7 @@ func startProtocol() {
|
||||
}(file)
|
||||
// 设置日志输出到文件
|
||||
log.SetOutput(io.MultiWriter(os.Stdout, file))
|
||||
ReloadApps()
|
||||
//从配置文件中读取配置信息
|
||||
LOG.INFO("正在启动WIND协议服务...")
|
||||
var config typed.CoreConfigInfo
|
||||
@ -278,10 +282,12 @@ func startProtocol() {
|
||||
}
|
||||
//获取协议地址
|
||||
protocolAddr := config.ProtocolAddr
|
||||
//获取token
|
||||
token := config.Token
|
||||
//链接协议
|
||||
// 启动 WebSocket 处理程序
|
||||
LOG.INFO("正在启动WebSocket链接程序...")
|
||||
err = core.WebSocketHandler(protocolAddr)
|
||||
err = core.WebSocketHandler(protocolAddr, token)
|
||||
if err != nil {
|
||||
// 如果发生错误,记录错误并退出程序
|
||||
LOG.FATAL("Failed to start WebSocket link program: %v", err)
|
||||
@ -296,3 +302,9 @@ func AutoSave() {
|
||||
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
289
wba/wind.go
Normal 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
|
Loading…
x
Reference in New Issue
Block a user