feat: 初始化多机器人服务端项目框架
基于Go语言构建多机器人服务端框架,包含配置管理、事件总线、依赖注入等核心模块 添加项目基础结构、README、gitignore和初始代码实现
This commit is contained in:
107
internal/protocol/action.go
Normal file
107
internal/protocol/action.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package protocol
|
||||
|
||||
// Action 动作接口
|
||||
// 参考OneBot12协议,定义统一的动作操作接口
|
||||
type Action interface {
|
||||
// GetType 获取动作类型
|
||||
GetType() ActionType
|
||||
// GetParams 获取动作参数
|
||||
GetParams() map[string]interface{}
|
||||
// Execute 执行动作
|
||||
Execute(ctx interface{}) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ActionType 动作类型
|
||||
type ActionType string
|
||||
|
||||
const (
|
||||
// 消息相关动作
|
||||
ActionTypeSendPrivateMessage ActionType = "send_private_message"
|
||||
ActionTypeSendGroupMessage ActionType = "send_group_message"
|
||||
ActionTypeDeleteMessage ActionType = "delete_message"
|
||||
|
||||
// 用户相关动作
|
||||
ActionTypeGetUserInfo ActionType = "get_user_info"
|
||||
ActionTypeGetFriendList ActionType = "get_friend_list"
|
||||
ActionTypeGetGroupInfo ActionType = "get_group_info"
|
||||
ActionTypeGetGroupMemberList ActionType = "get_group_member_list"
|
||||
|
||||
// 群组相关动作
|
||||
ActionTypeSetGroupKick ActionType = "set_group_kick"
|
||||
ActionTypeSetGroupBan ActionType = "set_group_ban"
|
||||
ActionTypeSetGroupAdmin ActionType = "set_group_admin"
|
||||
ActionTypeSetGroupWholeBan ActionType = "set_group_whole_ban"
|
||||
|
||||
// 其他动作
|
||||
ActionTypeGetStatus ActionType = "get_status"
|
||||
ActionTypeGetVersion ActionType = "get_version"
|
||||
)
|
||||
|
||||
// BaseAction 基础动作结构
|
||||
type BaseAction struct {
|
||||
Type ActionType `json:"type"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
}
|
||||
|
||||
// GetType 获取动作类型
|
||||
func (a *BaseAction) GetType() ActionType {
|
||||
return a.Type
|
||||
}
|
||||
|
||||
// GetParams 获取动作参数
|
||||
func (a *BaseAction) GetParams() map[string]interface{} {
|
||||
return a.Params
|
||||
}
|
||||
|
||||
// Execute 执行动作(需子类实现)
|
||||
func (a *BaseAction) Execute(ctx interface{}) (map[string]interface{}, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
// SendPrivateMessageAction 发送私聊消息动作
|
||||
type SendPrivateMessageAction struct {
|
||||
BaseAction
|
||||
UserID string `json:"user_id"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// SendGroupMessageAction 发送群聊消息动作
|
||||
type SendGroupMessageAction struct {
|
||||
BaseAction
|
||||
GroupID string `json:"group_id"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// DeleteMessageAction 删除消息动作
|
||||
type DeleteMessageAction struct {
|
||||
BaseAction
|
||||
MessageID string `json:"message_id"`
|
||||
}
|
||||
|
||||
// GetUserInfoAction 获取用户信息动作
|
||||
type GetUserInfoAction struct {
|
||||
BaseAction
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetGroupInfoAction 获取群信息动作
|
||||
type GetGroupInfoAction struct {
|
||||
BaseAction
|
||||
GroupID string `json:"group_id"`
|
||||
}
|
||||
|
||||
// 错误定义
|
||||
var (
|
||||
ErrNotImplemented = &ProtocolError{Code: 10001, Message: "action not implemented"}
|
||||
ErrInvalidParams = &ProtocolError{Code: 10002, Message: "invalid parameters"}
|
||||
)
|
||||
|
||||
// ProtocolError 协议错误
|
||||
type ProtocolError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e *ProtocolError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
206
internal/protocol/bot.go
Normal file
206
internal/protocol/bot.go
Normal file
@@ -0,0 +1,206 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// BaseBotInstance 机器人实例基类
|
||||
type BaseBotInstance struct {
|
||||
id string
|
||||
protocol Protocol
|
||||
status BotStatus
|
||||
logger *zap.Logger
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewBaseBotInstance 创建机器人实例基类
|
||||
func NewBaseBotInstance(id string, protocol Protocol, logger *zap.Logger) *BaseBotInstance {
|
||||
return &BaseBotInstance{
|
||||
id: id,
|
||||
protocol: protocol,
|
||||
status: BotStatusStopped,
|
||||
logger: logger.With(zap.String("bot_id", id)),
|
||||
}
|
||||
}
|
||||
|
||||
// GetID 获取实例ID
|
||||
func (b *BaseBotInstance) GetID() string {
|
||||
return b.id
|
||||
}
|
||||
|
||||
// Name 获取协议名称
|
||||
func (b *BaseBotInstance) Name() string {
|
||||
return b.protocol.Name()
|
||||
}
|
||||
|
||||
// Version 获取协议版本
|
||||
func (b *BaseBotInstance) Version() string {
|
||||
return b.protocol.Version()
|
||||
}
|
||||
|
||||
// Connect 建立连接
|
||||
func (b *BaseBotInstance) Connect(ctx context.Context) error {
|
||||
b.mu.Lock()
|
||||
b.status = BotStatusStarting
|
||||
b.mu.Unlock()
|
||||
|
||||
if err := b.protocol.Connect(ctx); err != nil {
|
||||
b.mu.Lock()
|
||||
b.status = BotStatusError
|
||||
b.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
b.mu.Lock()
|
||||
b.status = BotStatusRunning
|
||||
b.mu.Unlock()
|
||||
|
||||
b.logger.Info("Bot instance connected")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Disconnect 断开连接
|
||||
func (b *BaseBotInstance) Disconnect(ctx context.Context) error {
|
||||
b.mu.Lock()
|
||||
b.status = BotStatusStopping
|
||||
b.mu.Unlock()
|
||||
|
||||
if err := b.protocol.Disconnect(ctx); err != nil {
|
||||
b.mu.Lock()
|
||||
b.status = BotStatusError
|
||||
b.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
b.mu.Lock()
|
||||
b.status = BotStatusStopped
|
||||
b.mu.Unlock()
|
||||
|
||||
b.logger.Info("Bot instance disconnected")
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsConnected 检查连接状态
|
||||
func (b *BaseBotInstance) IsConnected() bool {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return b.status == BotStatusRunning
|
||||
}
|
||||
|
||||
// SendAction 发送动作
|
||||
func (b *BaseBotInstance) SendAction(ctx context.Context, action Action) (map[string]interface{}, error) {
|
||||
return b.protocol.SendAction(ctx, action)
|
||||
}
|
||||
|
||||
// HandleEvent 处理事件
|
||||
func (b *BaseBotInstance) HandleEvent(ctx context.Context, event Event) error {
|
||||
return b.protocol.HandleEvent(ctx, event)
|
||||
}
|
||||
|
||||
// GetSelfID 获取机器人自身ID
|
||||
func (b *BaseBotInstance) GetSelfID() string {
|
||||
return b.protocol.GetSelfID()
|
||||
}
|
||||
|
||||
// Start 启动实例
|
||||
func (b *BaseBotInstance) Start(ctx context.Context) error {
|
||||
return b.Connect(ctx)
|
||||
}
|
||||
|
||||
// Stop 停止实例
|
||||
func (b *BaseBotInstance) Stop(ctx context.Context) error {
|
||||
return b.Disconnect(ctx)
|
||||
}
|
||||
|
||||
// GetStatus 获取实例状态
|
||||
func (b *BaseBotInstance) GetStatus() BotStatus {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return b.status
|
||||
}
|
||||
|
||||
// BotManager 机器人管理器
|
||||
type BotManager struct {
|
||||
bots map[string]BotInstance
|
||||
logger *zap.Logger
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewBotManager 创建机器人管理器
|
||||
func NewBotManager(logger *zap.Logger) *BotManager {
|
||||
return &BotManager{
|
||||
bots: make(map[string]BotInstance),
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// Add 添加机器人实例
|
||||
func (bm *BotManager) Add(bot BotInstance) {
|
||||
bm.mu.Lock()
|
||||
defer bm.mu.Unlock()
|
||||
bm.bots[bot.GetID()] = bot
|
||||
bm.logger.Info("Bot added", zap.String("bot_id", bot.GetID()))
|
||||
}
|
||||
|
||||
// Remove 移除机器人实例
|
||||
func (bm *BotManager) Remove(id string) {
|
||||
bm.mu.Lock()
|
||||
defer bm.mu.Unlock()
|
||||
if bot, ok := bm.bots[id]; ok {
|
||||
bot.Stop(context.Background())
|
||||
delete(bm.bots, id)
|
||||
bm.logger.Info("Bot removed", zap.String("bot_id", id))
|
||||
}
|
||||
}
|
||||
|
||||
// Get 获取机器人实例
|
||||
func (bm *BotManager) Get(id string) (BotInstance, bool) {
|
||||
bm.mu.RLock()
|
||||
defer bm.mu.RUnlock()
|
||||
bot, ok := bm.bots[id]
|
||||
return bot, ok
|
||||
}
|
||||
|
||||
// GetAll 获取所有机器人实例
|
||||
func (bm *BotManager) GetAll() []BotInstance {
|
||||
bm.mu.RLock()
|
||||
defer bm.mu.RUnlock()
|
||||
bots := make([]BotInstance, 0, len(bm.bots))
|
||||
for _, bot := range bm.bots {
|
||||
bots = append(bots, bot)
|
||||
}
|
||||
return bots
|
||||
}
|
||||
|
||||
// StartAll 启动所有机器人
|
||||
func (bm *BotManager) StartAll(ctx context.Context) error {
|
||||
bm.mu.RLock()
|
||||
defer bm.mu.RUnlock()
|
||||
|
||||
for _, bot := range bm.bots {
|
||||
if err := bot.Start(ctx); err != nil {
|
||||
bm.logger.Error("Failed to start bot",
|
||||
zap.String("bot_id", bot.GetID()),
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopAll 停止所有机器人
|
||||
func (bm *BotManager) StopAll(ctx context.Context) error {
|
||||
bm.mu.RLock()
|
||||
defer bm.mu.RUnlock()
|
||||
|
||||
for _, bot := range bm.bots {
|
||||
if err := bot.Stop(ctx); err != nil {
|
||||
bm.logger.Error("Failed to stop bot",
|
||||
zap.String("bot_id", bot.GetID()),
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
105
internal/protocol/event.go
Normal file
105
internal/protocol/event.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package protocol
|
||||
|
||||
import "time"
|
||||
|
||||
// EventType 事件类型
|
||||
type EventType string
|
||||
|
||||
const (
|
||||
// 事件类型常量
|
||||
EventTypeMessage EventType = "message"
|
||||
EventTypeNotice EventType = "notice"
|
||||
EventTypeRequest EventType = "request"
|
||||
EventTypeMeta EventType = "meta"
|
||||
EventTypeMessageSent EventType = "message_sent"
|
||||
EventTypeNoticeSent EventType = "notice_sent"
|
||||
EventTypeRequestSent EventType = "request_sent"
|
||||
)
|
||||
|
||||
// Event 通用事件接口
|
||||
// 参考OneBot12协议设计,提供统一的事件抽象
|
||||
type Event interface {
|
||||
// GetType 获取事件类型
|
||||
GetType() EventType
|
||||
// GetDetailType 获取详细类型
|
||||
GetDetailType() string
|
||||
// GetSubType 获取子类型
|
||||
GetSubType() string
|
||||
// GetTimestamp 获取时间戳
|
||||
GetTimestamp() time.Time
|
||||
// GetSelfID 获取机器人自身ID
|
||||
GetSelfID() string
|
||||
// GetData 获取事件数据
|
||||
GetData() map[string]interface{}
|
||||
}
|
||||
|
||||
// BaseEvent 基础事件结构
|
||||
type BaseEvent struct {
|
||||
Type EventType `json:"type"`
|
||||
DetailType string `json:"detail_type"`
|
||||
SubType string `json:"sub_type,omitempty"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
SelfID string `json:"self_id"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// GetType 获取事件类型
|
||||
func (e *BaseEvent) GetType() EventType {
|
||||
return e.Type
|
||||
}
|
||||
|
||||
// GetDetailType 获取详细类型
|
||||
func (e *BaseEvent) GetDetailType() string {
|
||||
return e.DetailType
|
||||
}
|
||||
|
||||
// GetSubType 获取子类型
|
||||
func (e *BaseEvent) GetSubType() string {
|
||||
return e.SubType
|
||||
}
|
||||
|
||||
// GetTimestamp 获取时间戳
|
||||
func (e *BaseEvent) GetTimestamp() time.Time {
|
||||
return time.Unix(e.Timestamp, 0)
|
||||
}
|
||||
|
||||
// GetSelfID 获取机器人自身ID
|
||||
func (e *BaseEvent) GetSelfID() string {
|
||||
return e.SelfID
|
||||
}
|
||||
|
||||
// GetData 获取事件数据
|
||||
func (e *BaseEvent) GetData() map[string]interface{} {
|
||||
return e.Data
|
||||
}
|
||||
|
||||
// MessageEvent 消息事件
|
||||
type MessageEvent struct {
|
||||
BaseEvent
|
||||
MessageID string `json:"message_id"`
|
||||
Message string `json:"message"`
|
||||
AltText string `json:"alt_text,omitempty"`
|
||||
}
|
||||
|
||||
// NoticeEvent 通知事件
|
||||
type NoticeEvent struct {
|
||||
BaseEvent
|
||||
GroupID string `json:"group_id,omitempty"`
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
Operator string `json:"operator,omitempty"`
|
||||
}
|
||||
|
||||
// RequestEvent 请求事件
|
||||
type RequestEvent struct {
|
||||
BaseEvent
|
||||
RequestID string `json:"request_id"`
|
||||
UserID string `json:"user_id"`
|
||||
Comment string `json:"comment"`
|
||||
Flag string `json:"flag"`
|
||||
}
|
||||
|
||||
// MetaEvent 元事件
|
||||
type MetaEvent struct {
|
||||
BaseEvent
|
||||
Status string `json:"status"`
|
||||
}
|
||||
77
internal/protocol/interface.go
Normal file
77
internal/protocol/interface.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Protocol 通用协议接口
|
||||
// 参考OneBot12协议核心设计理念,定义统一的机器人协议接口
|
||||
type Protocol interface {
|
||||
// Name 获取协议名称
|
||||
Name() string
|
||||
// Version 获取协议版本
|
||||
Version() string
|
||||
// Connect 建立连接
|
||||
Connect(ctx context.Context) error
|
||||
// Disconnect 断开连接
|
||||
Disconnect(ctx context.Context) error
|
||||
// IsConnected 检查连接状态
|
||||
IsConnected() bool
|
||||
// SendAction 发送动作
|
||||
SendAction(ctx context.Context, action Action) (map[string]interface{}, error)
|
||||
// HandleEvent 处理事件
|
||||
HandleEvent(ctx context.Context, event Event) error
|
||||
// GetSelfID 获取机器人自身ID
|
||||
GetSelfID() string
|
||||
}
|
||||
|
||||
// Adapter 协议适配器接口
|
||||
// 实现具体协议的接入逻辑
|
||||
type Adapter interface {
|
||||
Protocol
|
||||
// ParseMessage 解析原始消息为Event
|
||||
ParseMessage(raw []byte) (Event, error)
|
||||
// SerializeAction 序列化Action为协议格式
|
||||
SerializeAction(action Action) ([]byte, error)
|
||||
}
|
||||
|
||||
// BotInstance 机器人实例接口
|
||||
// 管理单个机器人实例的生命周期
|
||||
type BotInstance interface {
|
||||
Protocol
|
||||
// GetID 获取实例ID
|
||||
GetID() string
|
||||
// Start 启动实例
|
||||
Start(ctx context.Context) error
|
||||
// Stop 停止实例
|
||||
Stop(ctx context.Context) error
|
||||
// GetStatus 获取实例状态
|
||||
GetStatus() BotStatus
|
||||
}
|
||||
|
||||
// BotStatus 机器人状态
|
||||
type BotStatus string
|
||||
|
||||
const (
|
||||
BotStatusStarting BotStatus = "starting"
|
||||
BotStatusRunning BotStatus = "running"
|
||||
BotStatusStopping BotStatus = "stopping"
|
||||
BotStatusStopped BotStatus = "stopped"
|
||||
BotStatusError BotStatus = "error"
|
||||
)
|
||||
|
||||
// EventHandler 事件处理器接口
|
||||
type EventHandler interface {
|
||||
// Handle 处理事件
|
||||
Handle(ctx context.Context, event Event) error
|
||||
// Priority 获取处理器优先级(数值越小优先级越高)
|
||||
Priority() int
|
||||
// Match 判断是否匹配事件
|
||||
Match(event Event) bool
|
||||
}
|
||||
|
||||
// Middleware 中间件接口
|
||||
type Middleware interface {
|
||||
// Process 处理事件
|
||||
Process(ctx context.Context, event Event, next func(ctx context.Context, event Event) error) error
|
||||
}
|
||||
Reference in New Issue
Block a user