322 lines
8.9 KiB
Go
322 lines
8.9 KiB
Go
|
|
package milky
|
||
|
|
|
||
|
|
import (
|
||
|
|
"cellbot/internal/engine"
|
||
|
|
"cellbot/internal/protocol"
|
||
|
|
"cellbot/pkg/net"
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
|
||
|
|
"go.uber.org/zap"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Bot Milky Bot 实例
|
||
|
|
type Bot struct {
|
||
|
|
id string
|
||
|
|
adapter *Adapter
|
||
|
|
logger *zap.Logger
|
||
|
|
status protocol.BotStatus
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewBot 创建 Milky Bot 实例
|
||
|
|
func NewBot(id string, config *Config, eventBus *engine.EventBus, wsManager *net.WebSocketManager, logger *zap.Logger) *Bot {
|
||
|
|
adapter := NewAdapter(config, id, eventBus, wsManager, logger)
|
||
|
|
|
||
|
|
return &Bot{
|
||
|
|
id: id,
|
||
|
|
adapter: adapter,
|
||
|
|
logger: logger.Named("milky-bot").With(zap.String("bot_id", id)),
|
||
|
|
status: protocol.BotStatusStopped,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetID 获取机器人 ID
|
||
|
|
func (b *Bot) GetID() string {
|
||
|
|
return b.id
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetProtocol 获取协议名称
|
||
|
|
func (b *Bot) GetProtocol() string {
|
||
|
|
return "milky"
|
||
|
|
}
|
||
|
|
|
||
|
|
// Name 获取协议名称
|
||
|
|
func (b *Bot) Name() string {
|
||
|
|
return "milky"
|
||
|
|
}
|
||
|
|
|
||
|
|
// Version 获取协议版本
|
||
|
|
func (b *Bot) Version() string {
|
||
|
|
return "1.0"
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetSelfID 获取机器人自身ID
|
||
|
|
func (b *Bot) GetSelfID() string {
|
||
|
|
return b.id
|
||
|
|
}
|
||
|
|
|
||
|
|
// Start 启动实例
|
||
|
|
func (b *Bot) Start(ctx context.Context) error {
|
||
|
|
return b.Connect(ctx)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Stop 停止实例
|
||
|
|
func (b *Bot) Stop(ctx context.Context) error {
|
||
|
|
return b.Disconnect(ctx)
|
||
|
|
}
|
||
|
|
|
||
|
|
// HandleEvent 处理事件
|
||
|
|
func (b *Bot) HandleEvent(ctx context.Context, event protocol.Event) error {
|
||
|
|
// Milky 适配器通过事件总线自动处理事件
|
||
|
|
// 这里不需要额外处理
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetStatus 获取状态
|
||
|
|
func (b *Bot) GetStatus() protocol.BotStatus {
|
||
|
|
return b.status
|
||
|
|
}
|
||
|
|
|
||
|
|
// Connect 连接
|
||
|
|
func (b *Bot) Connect(ctx context.Context) error {
|
||
|
|
b.logger.Info("Connecting Milky bot")
|
||
|
|
|
||
|
|
if err := b.adapter.Connect(ctx); err != nil {
|
||
|
|
b.status = protocol.BotStatusError
|
||
|
|
return fmt.Errorf("failed to connect: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
b.status = protocol.BotStatusRunning
|
||
|
|
b.logger.Info("Milky bot connected")
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Disconnect 断开连接
|
||
|
|
func (b *Bot) Disconnect(ctx context.Context) error {
|
||
|
|
b.logger.Info("Disconnecting Milky bot")
|
||
|
|
|
||
|
|
if err := b.adapter.Disconnect(); err != nil {
|
||
|
|
return fmt.Errorf("failed to disconnect: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
b.status = protocol.BotStatusStopped
|
||
|
|
b.logger.Info("Milky bot disconnected")
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// SendAction 发送动作
|
||
|
|
func (b *Bot) SendAction(ctx context.Context, action protocol.Action) (map[string]interface{}, error) {
|
||
|
|
if b.status != protocol.BotStatusRunning {
|
||
|
|
return nil, fmt.Errorf("bot is not running")
|
||
|
|
}
|
||
|
|
|
||
|
|
return b.adapter.SendAction(ctx, action)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetAdapter 获取适配器
|
||
|
|
func (b *Bot) GetAdapter() *Adapter {
|
||
|
|
return b.adapter
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetInfo 获取机器人信息
|
||
|
|
func (b *Bot) GetInfo() map[string]interface{} {
|
||
|
|
return map[string]interface{}{
|
||
|
|
"id": b.id,
|
||
|
|
"protocol": "milky",
|
||
|
|
"status": b.status,
|
||
|
|
"stats": b.adapter.GetStats(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsConnected 是否已连接
|
||
|
|
func (b *Bot) IsConnected() bool {
|
||
|
|
return b.status == protocol.BotStatusRunning && b.adapter.IsConnected()
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetStatus 设置状态
|
||
|
|
func (b *Bot) SetStatus(status protocol.BotStatus) {
|
||
|
|
b.status = status
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Milky 特定的 API 方法
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
// SendPrivateMessage 发送私聊消息
|
||
|
|
func (b *Bot) SendPrivateMessage(ctx context.Context, userID int64, segments []OutgoingSegment) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"user_id": userID,
|
||
|
|
"segments": segments,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "send_private_message", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// SendGroupMessage 发送群消息
|
||
|
|
func (b *Bot) SendGroupMessage(ctx context.Context, groupID int64, segments []OutgoingSegment) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"segments": segments,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "send_group_message", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// SendTempMessage 发送临时消息
|
||
|
|
func (b *Bot) SendTempMessage(ctx context.Context, groupID, userID int64, segments []OutgoingSegment) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"user_id": userID,
|
||
|
|
"segments": segments,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "send_temp_message", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// RecallMessage 撤回消息
|
||
|
|
func (b *Bot) RecallMessage(ctx context.Context, messageScene string, peerID, messageSeq int64) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"message_scene": messageScene,
|
||
|
|
"peer_id": peerID,
|
||
|
|
"message_seq": messageSeq,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "recall_message", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFriendList 获取好友列表
|
||
|
|
func (b *Bot) GetFriendList(ctx context.Context) (*APIResponse, error) {
|
||
|
|
return b.adapter.CallAPI(ctx, "get_friend_list", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetGroupList 获取群列表
|
||
|
|
func (b *Bot) GetGroupList(ctx context.Context) (*APIResponse, error) {
|
||
|
|
return b.adapter.CallAPI(ctx, "get_group_list", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetGroupMemberList 获取群成员列表
|
||
|
|
func (b *Bot) GetGroupMemberList(ctx context.Context, groupID int64) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "get_group_member_list", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetGroupMemberInfo 获取群成员信息
|
||
|
|
func (b *Bot) GetGroupMemberInfo(ctx context.Context, groupID, userID int64) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"user_id": userID,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "get_group_member_info", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetGroupAdmin 设置群管理员
|
||
|
|
func (b *Bot) SetGroupAdmin(ctx context.Context, groupID, userID int64, isSet bool) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"user_id": userID,
|
||
|
|
"is_set": isSet,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "set_group_admin", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetGroupCard 设置群名片
|
||
|
|
func (b *Bot) SetGroupCard(ctx context.Context, groupID, userID int64, card string) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"user_id": userID,
|
||
|
|
"card": card,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "set_group_card", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetGroupName 设置群名
|
||
|
|
func (b *Bot) SetGroupName(ctx context.Context, groupID int64, groupName string) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"group_name": groupName,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "set_group_name", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// KickGroupMember 踢出群成员
|
||
|
|
func (b *Bot) KickGroupMember(ctx context.Context, groupID, userID int64, rejectAddRequest bool) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"user_id": userID,
|
||
|
|
"reject_add_request": rejectAddRequest,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "kick_group_member", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// MuteGroupMember 禁言群成员
|
||
|
|
func (b *Bot) MuteGroupMember(ctx context.Context, groupID, userID int64, duration int32) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"user_id": userID,
|
||
|
|
"duration": duration,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "mute_group_member", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// MuteGroupWhole 全体禁言
|
||
|
|
func (b *Bot) MuteGroupWhole(ctx context.Context, groupID int64, isMute bool) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"is_mute": isMute,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "mute_group_whole", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// LeaveGroup 退出群
|
||
|
|
func (b *Bot) LeaveGroup(ctx context.Context, groupID int64) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "leave_group", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// HandleFriendRequest 处理好友请求
|
||
|
|
func (b *Bot) HandleFriendRequest(ctx context.Context, initiatorUID string, accept bool) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"initiator_uid": initiatorUID,
|
||
|
|
"accept": accept,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "handle_friend_request", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// HandleGroupJoinRequest 处理入群申请
|
||
|
|
func (b *Bot) HandleGroupJoinRequest(ctx context.Context, groupID, notificationSeq int64, accept bool, rejectReason string) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"notification_seq": notificationSeq,
|
||
|
|
"accept": accept,
|
||
|
|
"reject_reason": rejectReason,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "handle_group_join_request", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// HandleGroupInvitation 处理群邀请
|
||
|
|
func (b *Bot) HandleGroupInvitation(ctx context.Context, groupID, invitationSeq int64, accept bool) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"group_id": groupID,
|
||
|
|
"invitation_seq": invitationSeq,
|
||
|
|
"accept": accept,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "handle_group_invitation", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// UploadFile 上传文件
|
||
|
|
func (b *Bot) UploadFile(ctx context.Context, fileType, filePath string) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"file_type": fileType,
|
||
|
|
"file_path": filePath,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "upload_file", params)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFile 获取文件
|
||
|
|
func (b *Bot) GetFile(ctx context.Context, fileID string) (*APIResponse, error) {
|
||
|
|
params := map[string]interface{}{
|
||
|
|
"file_id": fileID,
|
||
|
|
}
|
||
|
|
return b.adapter.CallAPI(ctx, "get_file", params)
|
||
|
|
}
|