You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
7.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

## 一、整体设计
```mermaid
flowchart TB
subgraph Platforms [外部平台]
FS[飞书]
DT[钉钉]
WC[企业微信(开发中)]
TG[Telegram开发中]
More[更多平台...]
end
subgraph BotModule [bot/ 模块]
WH[Webhook Server]
Adapters[平台适配器]
Dispatcher[命令分发器]
Commands[命令处理器]
end
subgraph Core [现有核心模块]
AS[AnalysisService]
MA[MarketAnalyzer]
NS[NotificationService]
end
FS -->|POST /bot/feishu| WH
DT -->|POST /bot/dingtalk| WH
WC -->|POST /bot/wecom| WH
TG -->|POST /bot/telegram| WH
WH --> Adapters
Adapters -->|统一消息格式| Dispatcher
Dispatcher --> Commands
Commands --> AS
Commands --> MA
Commands --> NS
```
## 二、目录结构
在项目根目录新建 `bot/` 目录:
```
bot/
├── __init__.py # 模块入口,导出主要类
├── models.py # 统一的消息/响应模型
├── dispatcher.py # 命令分发器(核心)
├── commands/ # 命令处理器
│ ├── __init__.py
│ ├── base.py # 命令抽象基类
│ ├── analyze.py # /analyze 股票分析
│ ├── market.py # /market 大盘复盘
│ ├── help.py # /help 帮助信息
│ └── status.py # /status 系统状态
└── platforms/ # 平台适配器
├── __init__.py
├── base.py # 平台抽象基类
├── feishu.py # 飞书机器人
├── dingtalk.py # 钉钉机器人
├── dingtalk_stream.py # 钉钉机器人Stream
├── wecom.py # 企业微信机器人 (开发中)
└── telegram.py # Telegram 机器人 (开发中)
```
## 三、核心抽象设计
### 3.1 统一消息模型 (`bot/models.py`)
```python
@dataclass
class BotMessage:
"""统一的机器人消息模型"""
platform: str # 平台标识: feishu/dingtalk/wecom/telegram
user_id: str # 发送者 ID
user_name: str # 发送者名称
chat_id: str # 会话 ID群聊或私聊
chat_type: str # 会话类型: group/private
content: str # 消息文本内容
raw_data: Dict # 原始请求数据(平台特定)
timestamp: datetime # 消息时间
mentioned: bool = False # 是否@了机器人
@dataclass
class BotResponse:
"""统一的机器人响应模型"""
text: str # 回复文本
markdown: bool = False # 是否为 Markdown
at_user: bool = True # 是否@发送者
```
### 3.2 平台适配器基类 (`bot/platforms/base.py`)
```python
class BotPlatform(ABC):
"""平台适配器抽象基类"""
@property
@abstractmethod
def platform_name(self) -> str:
"""平台标识名称"""
pass
@abstractmethod
def verify_request(self, headers: Dict, body: bytes) -> bool:
"""验证请求签名(安全校验)"""
pass
@abstractmethod
def parse_message(self, data: Dict) -> Optional[BotMessage]:
"""解析平台消息为统一格式"""
pass
@abstractmethod
def format_response(self, response: BotResponse) -> Dict:
"""将统一响应转换为平台格式"""
pass
```
### 3.3 命令基类 (`bot/commands/base.py`)
```python
class BotCommand(ABC):
"""命令处理器抽象基类"""
@property
@abstractmethod
def name(self) -> str:
"""命令名称 (如 'analyze')"""
pass
@property
@abstractmethod
def aliases(self) -> List[str]:
"""命令别名 (如 ['a', '分析'])"""
pass
@property
@abstractmethod
def description(self) -> str:
"""命令描述"""
pass
@property
@abstractmethod
def usage(self) -> str:
"""使用说明"""
pass
@abstractmethod
async def execute(self, message: BotMessage, args: List[str]) -> BotResponse:
"""执行命令"""
pass
```
### 3.4 命令分发器 (`bot/dispatcher.py`)
```python
class CommandDispatcher:
"""命令分发器 - 单例模式"""
def __init__(self):
self._commands: Dict[str, BotCommand] = {}
self._aliases: Dict[str, str] = {}
def register(self, command: BotCommand) -> None:
"""注册命令"""
self._commands[command.name] = command
for alias in command.aliases:
self._aliases[alias] = command.name
def dispatch(self, message: BotMessage) -> BotResponse:
"""分发消息到对应命令"""
# 1. 解析命令和参数
# 2. 查找命令处理器
# 3. 执行并返回响应
```
## 四、已支持的命令
| 命令 | 别名 | 说明 | 示例 |
|------|------|------|------|
| /analyze | /a, 分析 | 分析指定股票 | `/analyze 600519` |
| /market | /m, 大盘 | 大盘复盘 | `/market` |
| /batch | /b, 批量 | 批量分析自选股 | `/batch` |
| /help | /h, 帮助 | 显示帮助信息 | `/help` |
| /status | /s, 状态 | 系统状态 | `/status` |
## 五、Webhook 路由
在 [api/v1/router.py](../api/v1/router.py) 中注册路由:
```python
# Webhook 路由
/bot/feishu # POST - 飞书事件回调
/bot/dingtalk # POST - 钉钉事件回调
/bot/wecom # POST - 企业微信事件回调 (开发中)
/bot/telegram # POST - Telegram 更新回调 (开发中)
```
## 配置
在 [config.py](../config.py) 中新增机器人配置:
```python
# === 机器人配置 ===
bot_enabled: bool = False # 是否启用机器人
bot_command_prefix: str = "/" # 命令前缀
# 飞书机器人(事件订阅)
feishu_app_id: str # 已有
feishu_app_secret: str # 已有
feishu_verification_token: str # 新增:事件校验 Token
feishu_encrypt_key: str # 新增:加密密钥
# 钉钉机器人(应用)
dingtalk_app_key: str # 新增
dingtalk_app_secret: str # 新增
# 企业微信机器人(开发中)
wecom_token: str # 新增:回调 Token
wecom_encoding_aes_key: str # 新增EncodingAESKey
# Telegram 机器人(开发中)
telegram_bot_token: str # 已有
telegram_webhook_secret: str # 新增Webhook 密钥
```
## 扩展说明
### 怎样新增一个通知平台
1.`bot/platforms/` 创建新文件
2. 继承 `BotPlatform` 基类
3. 实现 `verify_request`, `parse_message`, `format_response`
4. 在路由中注册 Webhook 端点
### 怎样新增新增命令
1.`bot/commands/` 创建新文件
2. 继承 `BotCommand` 基类
3. 实现 `execute` 方法
4. 在分发器中注册命令
## 安全相关配置
- 支持命令频率限制(防刷)
- 敏感操作(如批量分析)可设置权限白名单
在 [config.py](../config.py) 中新增机器人安全配置:
```python
bot_rate_limit_requests: int = 10 # 频率限制:窗口内最大请求数
bot_rate_limit_window: int = 60 # 频率限制:窗口时间(秒)
bot_admin_users: List[str] = field(default_factory=list) # 管理员用户 ID 列表,限制敏感操作
```