feat:初版
This commit is contained in:
694
docs/API文档.md
Normal file
694
docs/API文档.md
Normal file
@@ -0,0 +1,694 @@
|
||||
# WechatHookBot API 文档
|
||||
|
||||
## WechatHookClient API 参考
|
||||
|
||||
基于个微大客户版 Hook API 封装的 Python 客户端。
|
||||
|
||||
## 消息发送
|
||||
|
||||
### send_text - 发送文本消息
|
||||
|
||||
```python
|
||||
await client.send_text(to_wxid: str, content: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid(个人或群聊)
|
||||
- `content`: 文本内容
|
||||
|
||||
**返回:** 是否发送成功
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_text("wxid_xxx", "你好,世界")
|
||||
await client.send_text("123@chatroom", "群聊消息")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_image - 发送图片
|
||||
|
||||
```python
|
||||
await client.send_image(to_wxid: str, image_path: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `image_path`: 图片文件路径
|
||||
|
||||
**支持格式:** jpg, png, gif
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_image("wxid_xxx", "D:/images/photo.jpg")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_file - 发送文件
|
||||
|
||||
```python
|
||||
await client.send_file(to_wxid: str, file_path: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `file_path`: 文件路径
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_file("wxid_xxx", "D:/documents/report.pdf")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_video - 发送视频
|
||||
|
||||
```python
|
||||
await client.send_video(to_wxid: str, video_path: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `video_path`: 视频文件路径
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_video("wxid_xxx", "D:/videos/demo.mp4")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_card - 发送名片
|
||||
|
||||
```python
|
||||
await client.send_card(to_wxid: str, card_wxid: str, card_nickname: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `card_wxid`: 名片的 wxid
|
||||
- `card_nickname`: 名片昵称
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_card("wxid_xxx", "wxid_yyy", "张三")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_location - 发送位置
|
||||
|
||||
```python
|
||||
await client.send_location(
|
||||
to_wxid: str,
|
||||
latitude: float,
|
||||
longitude: float,
|
||||
title: str,
|
||||
address: str
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `latitude`: 纬度
|
||||
- `longitude`: 经度
|
||||
- `title`: 位置标题
|
||||
- `address`: 详细地址
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_location(
|
||||
"wxid_xxx",
|
||||
39.9042,
|
||||
116.4074,
|
||||
"天安门",
|
||||
"北京市东城区"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_link - 发送链接
|
||||
|
||||
```python
|
||||
await client.send_link(
|
||||
to_wxid: str,
|
||||
title: str,
|
||||
desc: str,
|
||||
url: str,
|
||||
thumb_url: str = ""
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `title`: 链接标题
|
||||
- `desc`: 链接描述
|
||||
- `url`: 链接地址
|
||||
- `thumb_url`: 缩略图 URL(可选)
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_link(
|
||||
"wxid_xxx",
|
||||
"新闻标题",
|
||||
"新闻摘要",
|
||||
"https://example.com/news",
|
||||
"https://example.com/thumb.jpg"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_miniapp - 发送小程序
|
||||
|
||||
```python
|
||||
await client.send_miniapp(
|
||||
to_wxid: str,
|
||||
appid: str,
|
||||
title: str,
|
||||
page_path: str,
|
||||
thumb_url: str = ""
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `to_wxid`: 接收者 wxid
|
||||
- `appid`: 小程序 appid
|
||||
- `title`: 小程序标题
|
||||
- `page_path`: 小程序页面路径
|
||||
- `thumb_url`: 缩略图 URL(可选)
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.send_miniapp(
|
||||
"wxid_xxx",
|
||||
"wx1234567890",
|
||||
"小程序标题",
|
||||
"pages/index/index"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### send_at_message - 发送群聊@消息
|
||||
|
||||
```python
|
||||
await client.send_at_message(
|
||||
chatroom_id: str,
|
||||
content: str,
|
||||
at_list: list[str]
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
- `content`: 消息内容
|
||||
- `at_list`: 要@的 wxid 列表
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
# @指定用户
|
||||
await client.send_at_message(
|
||||
"123@chatroom",
|
||||
"大家好",
|
||||
["wxid_aaa", "wxid_bbb"]
|
||||
)
|
||||
|
||||
# @所有人
|
||||
await client.send_at_message(
|
||||
"123@chatroom",
|
||||
"重要通知",
|
||||
["notify@all"]
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### revoke_message - 撤回消息
|
||||
|
||||
```python
|
||||
await client.revoke_message(msg_id: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `msg_id`: 消息 ID
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.revoke_message("1234567890")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 好友管理
|
||||
|
||||
### get_friend_list - 获取好友列表
|
||||
|
||||
```python
|
||||
await client.get_friend_list() -> list[dict]
|
||||
```
|
||||
|
||||
**返回:** 好友列表
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
friends = await client.get_friend_list()
|
||||
for friend in friends:
|
||||
print(friend["wxid"], friend["nickname"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### get_friend_info - 获取好友信息
|
||||
|
||||
```python
|
||||
await client.get_friend_info(wxid: str) -> dict
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `wxid`: 好友 wxid
|
||||
|
||||
**返回:** 好友详细信息
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
info = await client.get_friend_info("wxid_xxx")
|
||||
print(info["nickname"], info["remark"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### search_user - 搜索用户
|
||||
|
||||
```python
|
||||
await client.search_user(keyword: str) -> dict
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `keyword`: 搜索关键词(wxid、手机号、微信号)
|
||||
|
||||
**返回:** 用户信息
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
result = await client.search_user("wxid_xxx")
|
||||
if result:
|
||||
print(result["nickname"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### add_friend - 添加好友
|
||||
|
||||
```python
|
||||
await client.add_friend(
|
||||
wxid: str,
|
||||
verify_msg: str = "",
|
||||
scene: int = 3
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `wxid`: 要添加的 wxid
|
||||
- `verify_msg`: 验证消息
|
||||
- `scene`: 添加场景(3=搜索,15=名片)
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.add_friend("wxid_xxx", "你好,我是...")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### accept_friend - 同意好友请求
|
||||
|
||||
```python
|
||||
await client.accept_friend(v3: str, v4: str, scene: int) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `v3`: 好友请求的 v3 参数
|
||||
- `v4`: 好友请求的 v4 参数
|
||||
- `scene`: 场景值
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
# 从好友请求消息中获取参数
|
||||
await client.accept_friend(v3, v4, scene)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### delete_friend - 删除好友
|
||||
|
||||
```python
|
||||
await client.delete_friend(wxid: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `wxid`: 要删除的好友 wxid
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.delete_friend("wxid_xxx")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### set_friend_remark - 修改好友备注
|
||||
|
||||
```python
|
||||
await client.set_friend_remark(wxid: str, remark: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `wxid`: 好友 wxid
|
||||
- `remark`: 新备注
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.set_friend_remark("wxid_xxx", "张三")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### check_friend_status - 检测好友状态
|
||||
|
||||
```python
|
||||
await client.check_friend_status(wxid: str) -> dict
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `wxid`: 好友 wxid
|
||||
|
||||
**返回:** 好友状态信息
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
status = await client.check_friend_status("wxid_xxx")
|
||||
print(status["is_friend"]) # 是否是好友
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 群聊管理
|
||||
|
||||
### get_chatroom_list - 获取群聊列表
|
||||
|
||||
```python
|
||||
await client.get_chatroom_list() -> list[dict]
|
||||
```
|
||||
|
||||
**返回:** 群聊列表
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
chatrooms = await client.get_chatroom_list()
|
||||
for room in chatrooms:
|
||||
print(room["chatroom_id"], room["name"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### get_chatroom_members - 获取群成员
|
||||
|
||||
```python
|
||||
await client.get_chatroom_members(chatroom_id: str) -> list[dict]
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
|
||||
**返回:** 群成员列表
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
members = await client.get_chatroom_members("123@chatroom")
|
||||
for member in members:
|
||||
print(member["wxid"], member["nickname"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### get_chatroom_info - 获取群信息
|
||||
|
||||
```python
|
||||
await client.get_chatroom_info(chatroom_id: str) -> dict
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
|
||||
**返回:** 群聊详细信息
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
info = await client.get_chatroom_info("123@chatroom")
|
||||
print(info["name"], info["member_count"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### create_chatroom - 创建群聊
|
||||
|
||||
```python
|
||||
await client.create_chatroom(member_list: list[str]) -> str
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `member_list`: 成员 wxid 列表(至少2人)
|
||||
|
||||
**返回:** 新群聊的 chatroom_id
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
chatroom_id = await client.create_chatroom(["wxid_aaa", "wxid_bbb"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### invite_to_chatroom - 邀请进群
|
||||
|
||||
```python
|
||||
await client.invite_to_chatroom(
|
||||
chatroom_id: str,
|
||||
wxid_list: list[str]
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
- `wxid_list`: 要邀请的 wxid 列表
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.invite_to_chatroom("123@chatroom", ["wxid_xxx", "wxid_yyy"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### remove_chatroom_member - 踢出群成员
|
||||
|
||||
```python
|
||||
await client.remove_chatroom_member(
|
||||
chatroom_id: str,
|
||||
wxid_list: list[str]
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
- `wxid_list`: 要踢出的 wxid 列表
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.remove_chatroom_member("123@chatroom", ["wxid_xxx"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### quit_chatroom - 退出群聊
|
||||
|
||||
```python
|
||||
await client.quit_chatroom(chatroom_id: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.quit_chatroom("123@chatroom")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### set_chatroom_name - 修改群名称
|
||||
|
||||
```python
|
||||
await client.set_chatroom_name(chatroom_id: str, name: str) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
- `name`: 新群名称
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.set_chatroom_name("123@chatroom", "新群名")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### set_chatroom_announcement - 修改群公告
|
||||
|
||||
```python
|
||||
await client.set_chatroom_announcement(
|
||||
chatroom_id: str,
|
||||
announcement: str
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
- `announcement`: 群公告内容
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.set_chatroom_announcement("123@chatroom", "群公告内容")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### set_my_chatroom_nickname - 修改我的群昵称
|
||||
|
||||
```python
|
||||
await client.set_my_chatroom_nickname(
|
||||
chatroom_id: str,
|
||||
nickname: str
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `chatroom_id`: 群聊 ID
|
||||
- `nickname`: 新昵称
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.set_my_chatroom_nickname("123@chatroom", "我的群昵称")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 登录信息
|
||||
|
||||
### get_login_info - 获取当前登录信息
|
||||
|
||||
```python
|
||||
await client.get_login_info() -> dict
|
||||
```
|
||||
|
||||
**返回:** 登录账号信息
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
info = await client.get_login_info()
|
||||
print(info["wxid"], info["nickname"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CDN 功能
|
||||
|
||||
### cdn_upload - CDN 上传
|
||||
|
||||
```python
|
||||
await client.cdn_upload(file_path: str) -> dict
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `file_path`: 文件路径
|
||||
|
||||
**返回:** CDN 信息(包含 aes_key, file_id 等)
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
cdn_info = await client.cdn_upload("D:/files/image.jpg")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### cdn_download - CDN 下载
|
||||
|
||||
```python
|
||||
await client.cdn_download(
|
||||
aes_key: str,
|
||||
file_id: str,
|
||||
save_path: str
|
||||
) -> bool
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `aes_key`: AES 密钥
|
||||
- `file_id`: 文件 ID
|
||||
- `save_path`: 保存路径
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
await client.cdn_download(aes_key, file_id, "D:/downloads/file.jpg")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 企业微信
|
||||
|
||||
### get_work_chatroom_list - 获取企业群列表
|
||||
|
||||
```python
|
||||
await client.get_work_chatroom_list() -> list[dict]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### get_work_friend_list - 获取企业好友列表
|
||||
|
||||
```python
|
||||
await client.get_work_friend_list() -> list[dict]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### get_work_chatroom_members - 获取企业群成员
|
||||
|
||||
```python
|
||||
await client.get_work_chatroom_members(chatroom_id: str) -> list[dict]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
所有 API 调用失败时会抛出异常或返回 False/None,建议使用 try-except 处理:
|
||||
|
||||
```python
|
||||
try:
|
||||
result = await client.send_text("wxid_xxx", "消息")
|
||||
if result:
|
||||
logger.info("发送成功")
|
||||
else:
|
||||
logger.error("发送失败")
|
||||
except Exception as e:
|
||||
logger.error(f"发送异常: {e}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 所有 API 都是异步函数,必须使用 `await` 调用
|
||||
2. wxid 格式:个人为 `wxid_xxx`,群聊为 `xxx@chatroom`
|
||||
3. 文件路径建议使用绝对路径
|
||||
4. 部分 API 需要特定权限(如群主才能踢人)
|
||||
5. API 调用频率不宜过高,避免风控
|
||||
84
docs/MemoryBank/01-项目概述.md
Normal file
84
docs/MemoryBank/01-项目概述.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# WechatHookBot 项目概述
|
||||
|
||||
## 项目信息
|
||||
|
||||
- **项目名称**: WechatHookBot
|
||||
- **版本**: v1.0.0
|
||||
- **创建时间**: 2025-11-12
|
||||
- **项目类型**: 微信机器人框架
|
||||
- **技术栈**: Python 3.11 (32位), asyncio, ctypes
|
||||
|
||||
## 项目简介
|
||||
|
||||
基于个微大客户版 Hook API 的微信机器人框架,通过 DLL 注入方式实现微信消息的接收和发送。
|
||||
|
||||
## 核心特性
|
||||
|
||||
1. **DLL Hook 技术**
|
||||
- 使用 Loader.dll 和 Helper.dll 注入微信进程
|
||||
- 通过 Socket 回调接收消息
|
||||
- 支持微信版本: 2.84.18.17
|
||||
|
||||
2. **插件系统**
|
||||
- 基于事件驱动的插件架构
|
||||
- 支持热重载(无需重启)
|
||||
- 装饰器风格的事件处理
|
||||
- 插件启用/禁用管理
|
||||
|
||||
3. **消息处理**
|
||||
- 支持文本、图片、视频、文件等多种消息类型
|
||||
- 群聊和私聊消息处理
|
||||
- 消息过滤(白名单/黑名单)
|
||||
- @消息识别
|
||||
|
||||
4. **AI 集成**
|
||||
- 支持自定义 AI API
|
||||
- 可切换人设(通过 txt 文件)
|
||||
- 多种触发模式(全部/提及/@/关键词)
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
WechatHookBot/
|
||||
├── bot.py # 主入口
|
||||
├── main_config.toml # 主配置文件
|
||||
├── requirements.txt # 依赖列表
|
||||
├── libs/ # DLL 文件
|
||||
│ ├── Loader.dll
|
||||
│ └── Helper.dll
|
||||
├── WechatHook/ # Hook API 封装
|
||||
│ ├── loader.py # DLL 加载器
|
||||
│ ├── client.py # API 客户端
|
||||
│ ├── callbacks.py # 回调处理
|
||||
│ └── message_types.py # 消息类型定义
|
||||
├── utils/ # 工具模块
|
||||
│ ├── hookbot.py # 机器人核心
|
||||
│ ├── plugin_manager.py # 插件管理器
|
||||
│ ├── event_manager.py # 事件管理器
|
||||
│ └── decorators.py # 装饰器
|
||||
├── plugins/ # 插件目录
|
||||
│ ├── AIChat/ # AI 聊天插件
|
||||
│ ├── ManagePlugin/ # 插件管理插件
|
||||
│ └── ExamplePlugin/ # 示例插件
|
||||
└── docs/ # 文档目录
|
||||
└── MemoryBank/ # 内存银行
|
||||
```
|
||||
|
||||
## 当前状态
|
||||
|
||||
✅ **已完成**:
|
||||
- DLL Hook 集成
|
||||
- 消息接收和发送
|
||||
- 插件系统框架
|
||||
- AI 聊天插件
|
||||
- 插件管理功能
|
||||
- 热重载支持
|
||||
|
||||
🚧 **进行中**:
|
||||
- 测试和调试
|
||||
- 文档完善
|
||||
|
||||
📋 **待开发**:
|
||||
- 更多插件功能
|
||||
- Web 管理界面
|
||||
- 数据统计功能
|
||||
137
docs/MemoryBank/02-开发日志.md
Normal file
137
docs/MemoryBank/02-开发日志.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# 开发日志
|
||||
|
||||
## 2025-11-12
|
||||
|
||||
### 项目初始化
|
||||
- ✅ 创建 WechatHookBot 项目结构
|
||||
- ✅ 从 XYBot 复制 utils 和 database 模块
|
||||
- ✅ 设计技术架构文档
|
||||
|
||||
### Hook API 集成
|
||||
- ✅ 封装 NoveLoader (Loader.dll)
|
||||
- ✅ 封装 WechatHookClient (API 客户端)
|
||||
- ✅ 实现消息类型映射和格式转换
|
||||
- ✅ 实现回调处理机制
|
||||
|
||||
### 启动调试
|
||||
**问题**: 回调未触发,无法接收消息
|
||||
- ❌ 尝试1: 调整回调注册顺序 - 失败
|
||||
- ❌ 尝试2: 修改事件循环处理 - 失败
|
||||
- ✅ 解决: 添加共享内存创建 (`create_shared_memory`)
|
||||
- 关键发现: DLL 需要共享内存进行通信
|
||||
- 参考官方 Demo 第 357-365 行
|
||||
|
||||
**问题**: Socket 客户端 ID 混淆
|
||||
- ❌ 使用进程 ID 发送消息 - 失败
|
||||
- ✅ 解决: 区分进程 ID 和 Socket 客户端 ID
|
||||
- `InjectWeChat` 返回进程 ID
|
||||
- 回调中的 `client_id` 是 Socket ID (通常为 1)
|
||||
|
||||
**问题**: 登录信息获取失败
|
||||
- ❌ 使用 type=11028 - 错误
|
||||
- ✅ 解决: 实际类型是 type=11025
|
||||
- 登录信息在注入后自动推送
|
||||
- 包含 wxid, nickname, account, avatar 等字段
|
||||
|
||||
**问题**: 消息类型映射错误
|
||||
- ❌ 使用 10001-10013 - 错误
|
||||
- ✅ 解决: 实际类型是 11046-11061
|
||||
- 文本消息: 11046
|
||||
- 图片消息: 11047
|
||||
- 其他类型依次递增
|
||||
|
||||
**问题**: 群聊消息处理失败
|
||||
- ❌ 使用 `from_wxid` 判断群聊 - 错误
|
||||
- ✅ 解决: 使用 `room_wxid` 字段判断
|
||||
- 群聊消息: `room_wxid` 不为空
|
||||
- 私聊消息: `room_wxid` 为空
|
||||
- 消息内容字段: `msg` (不是 `content`)
|
||||
|
||||
### 插件开发
|
||||
|
||||
#### AIChat 插件
|
||||
- ✅ 支持自定义 API 配置
|
||||
- ✅ 支持人设切换 (txt 文件)
|
||||
- ✅ 三种触发模式: all/mention/keyword
|
||||
- ✅ 群聊/私聊分别控制
|
||||
|
||||
**问题**: 插件配置未加载
|
||||
- ❌ 使用 `on_load` 方法 - 失败
|
||||
- ✅ 解决: 使用 `async_init` 方法
|
||||
- 插件基类只支持 `async_init`
|
||||
- `on_enable` 用于定时任务注册
|
||||
|
||||
#### ManagePlugin 插件
|
||||
- ✅ 插件列表查看
|
||||
- ✅ 热重载功能
|
||||
- ✅ 启用/禁用插件
|
||||
- ✅ 权限控制(管理员)
|
||||
|
||||
**命令列表**:
|
||||
- `/插件列表` - 查看所有插件状态
|
||||
- `/重载插件 <名称>` - 热重载指定插件
|
||||
- `/启用插件 <名称>` - 启用插件
|
||||
- `/禁用插件 <名称>` - 禁用插件
|
||||
|
||||
### 依赖管理
|
||||
**最终依赖**:
|
||||
```
|
||||
loguru==0.7.3
|
||||
APScheduler==3.11.0
|
||||
aiohttp==3.9.1
|
||||
```
|
||||
|
||||
**移除的依赖**:
|
||||
- SQLAlchemy (需要 C++ 编译)
|
||||
- eventlet (msgspec 不支持 32 位)
|
||||
- Flask (不需要 WebUI)
|
||||
|
||||
### 关键技术点
|
||||
|
||||
1. **共享内存创建**
|
||||
```python
|
||||
def create_shared_memory():
|
||||
kernel32 = ctypes.WinDLL('kernel32')
|
||||
file_handle = kernel32.CreateFileMappingA(-1, None, 4, 0, 33,
|
||||
"windows_shell_global__".encode('utf-8'))
|
||||
data_address = kernel32.MapViewOfFile(file_handle, 983071, 0, 0, 0)
|
||||
key = "3101b223dca7715b0154924f0eeeee20".encode('utf-8')
|
||||
kernel32.RtlMoveMemory(data_address, key, len(key))
|
||||
```
|
||||
|
||||
2. **异步回调处理**
|
||||
```python
|
||||
# 在回调线程中使用事件循环
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
self.hookbot.process_message(msg_type, data),
|
||||
self.event_loop
|
||||
)
|
||||
```
|
||||
|
||||
3. **消息格式转换**
|
||||
```python
|
||||
# 群聊判断
|
||||
room_wxid = data.get("room_wxid", "")
|
||||
if room_wxid:
|
||||
message["IsGroup"] = True
|
||||
message["FromWxid"] = room_wxid
|
||||
message["SenderWxid"] = data.get("from_wxid", "")
|
||||
```
|
||||
|
||||
### 测试结果
|
||||
|
||||
✅ **成功测试**:
|
||||
- 机器人启动和注入
|
||||
- 登录信息获取
|
||||
- 私聊消息接收
|
||||
- 群聊消息接收
|
||||
- ping-pong 测试
|
||||
- 插件管理命令
|
||||
- AI 聊天功能
|
||||
|
||||
### 下一步计划
|
||||
|
||||
1. 完善插件功能
|
||||
2. 添加更多消息类型支持
|
||||
3. 优化错误处理
|
||||
4. 编写使用文档
|
||||
234
docs/MemoryBank/03-技术要点.md
Normal file
234
docs/MemoryBank/03-技术要点.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# 技术要点
|
||||
|
||||
## 核心架构
|
||||
|
||||
### 1. DLL Hook 机制
|
||||
|
||||
**工作流程**:
|
||||
```
|
||||
1. 加载 Loader.dll
|
||||
2. 创建共享内存 (关键!)
|
||||
3. 注册 Socket 回调
|
||||
4. 调用 InjectWeChat 注入 Helper.dll
|
||||
5. 等待 Socket 连接回调
|
||||
6. 使用 Socket Client ID 发送 API 请求
|
||||
```
|
||||
|
||||
**关键代码**:
|
||||
```python
|
||||
# 共享内存创建 (必须在 Loader 之前)
|
||||
create_shared_memory()
|
||||
|
||||
# 注册回调
|
||||
add_callback_handler(self)
|
||||
loader = NoveLoader(loader_dll)
|
||||
|
||||
# 注入微信
|
||||
process_id = loader.InjectWeChat(helper_dll)
|
||||
|
||||
# 等待 Socket 连接
|
||||
# socket_client_id 从回调中获取 (通常为 1)
|
||||
|
||||
# 使用 Socket ID 发送请求
|
||||
client = WechatHookClient(loader, socket_client_id)
|
||||
```
|
||||
|
||||
### 2. 消息类型映射
|
||||
|
||||
**实际测试的消息类型**:
|
||||
```python
|
||||
MT_DEBUG_LOG = 11024 # 调试日志
|
||||
MT_USER_LOGIN = 11025 # 用户登录 (自动推送)
|
||||
MT_TEXT = 11046 # 文本消息
|
||||
MT_IMAGE = 11047 # 图片消息
|
||||
MT_VOICE = 11048 # 语音消息
|
||||
MT_VIDEO = 11049 # 视频消息
|
||||
MT_EMOJI = 11050 # 表情消息
|
||||
MT_LOCATION = 11051 # 位置消息
|
||||
MT_LINK = 11052 # 链接消息
|
||||
MT_FILE = 11053 # 文件消息
|
||||
MT_MINIAPP = 11054 # 小程序消息
|
||||
MT_CARD = 11055 # 名片消息
|
||||
MT_FRIEND_REQUEST = 11056 # 好友请求
|
||||
MT_REVOKE = 11057 # 撤回消息
|
||||
MT_SYSTEM = 11058 # 系统消息
|
||||
```
|
||||
|
||||
### 3. 消息数据结构
|
||||
|
||||
**文本消息** (type=11046):
|
||||
```json
|
||||
{
|
||||
"at_user_list": [],
|
||||
"from_wxid": "wxid_xxx",
|
||||
"is_pc": 0,
|
||||
"msg": "消息内容",
|
||||
"msgid": "123456789",
|
||||
"room_wxid": "",
|
||||
"timestamp": 1762940000,
|
||||
"to_wxid": "wxid_yyy",
|
||||
"wx_type": 1
|
||||
}
|
||||
```
|
||||
|
||||
**登录信息** (type=11025):
|
||||
```json
|
||||
{
|
||||
"account": "账号",
|
||||
"avatar": "http://...",
|
||||
"device_id": "设备ID",
|
||||
"nickname": "昵称",
|
||||
"phone": "手机号",
|
||||
"wxid": "wxid_xxx",
|
||||
"wx_user_dir": "C:\\..."
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 群聊消息判断
|
||||
|
||||
**关键字段**:
|
||||
- `room_wxid`: 群聊 ID,私聊时为空
|
||||
- `from_wxid`: 发送者 wxid
|
||||
- `to_wxid`: 接收者 (群聊时是群 ID)
|
||||
|
||||
**判断逻辑**:
|
||||
```python
|
||||
room_wxid = data.get("room_wxid", "")
|
||||
if room_wxid:
|
||||
# 群聊消息
|
||||
message["IsGroup"] = True
|
||||
message["FromWxid"] = room_wxid
|
||||
message["SenderWxid"] = data.get("from_wxid", "")
|
||||
else:
|
||||
# 私聊消息
|
||||
message["IsGroup"] = False
|
||||
message["FromWxid"] = data.get("from_wxid", "")
|
||||
```
|
||||
|
||||
### 5. 异步回调处理
|
||||
|
||||
**问题**: 回调在同步线程中执行,但需要调用异步方法
|
||||
|
||||
**解决方案**:
|
||||
```python
|
||||
# 在初始化时保存事件循环
|
||||
self.event_loop = asyncio.get_event_loop()
|
||||
|
||||
# 在回调中使用
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
self.hookbot.process_message(msg_type, data),
|
||||
self.event_loop
|
||||
)
|
||||
```
|
||||
|
||||
### 6. 插件系统
|
||||
|
||||
**插件生命周期**:
|
||||
```python
|
||||
class MyPlugin(PluginBase):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# 初始化成员变量
|
||||
|
||||
async def async_init(self):
|
||||
# 异步初始化 (加载配置等)
|
||||
pass
|
||||
|
||||
async def on_enable(self, bot=None):
|
||||
# 启用时调用 (注册定时任务)
|
||||
pass
|
||||
|
||||
async def on_disable(self):
|
||||
# 禁用时调用 (清理资源)
|
||||
pass
|
||||
```
|
||||
|
||||
**事件处理**:
|
||||
```python
|
||||
@on_text_message()
|
||||
async def handle_message(self, bot, message: dict):
|
||||
content = message.get("Content", "")
|
||||
from_wxid = message.get("FromWxid", "")
|
||||
|
||||
# 处理消息
|
||||
await bot.send_text(from_wxid, "回复内容")
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 为什么必须使用 32 位 Python?
|
||||
**A**: Loader.dll 和 Helper.dll 是 32 位编译的,只能在 32 位 Python 中加载。
|
||||
|
||||
### Q2: 为什么需要共享内存?
|
||||
**A**: DLL 之间通过共享内存进行通信,必须在加载 Loader.dll 之前创建。
|
||||
|
||||
### Q3: 为什么 Socket Client ID 和进程 ID 不同?
|
||||
**A**:
|
||||
- `InjectWeChat` 返回的是微信进程 ID
|
||||
- 回调中的 `client_id` 是 Socket 连接 ID (从 1 开始)
|
||||
- 发送 API 请求时使用 Socket ID
|
||||
|
||||
### Q4: 如何判断是群聊还是私聊?
|
||||
**A**: 检查 `room_wxid` 字段,不为空则是群聊。
|
||||
|
||||
### Q5: 插件配置为什么没有加载?
|
||||
**A**: 使用 `async_init` 方法而不是 `on_load`。
|
||||
|
||||
### Q6: 如何热重载插件?
|
||||
**A**: 发送 `/重载插件 插件名` 命令。
|
||||
|
||||
### Q7: 为什么收不到消息?
|
||||
**A**: 检查以下几点:
|
||||
1. 共享内存是否创建成功
|
||||
2. Socket 客户端是否连接
|
||||
3. 消息类型是否在 MESSAGE_TYPE_MAP 中
|
||||
4. 消息是否被过滤 (白名单/黑名单)
|
||||
|
||||
### Q8: 如何添加新的消息类型?
|
||||
**A**:
|
||||
1. 在 `message_types.py` 中添加常量
|
||||
2. 在 `MESSAGE_TYPE_MAP` 中添加映射
|
||||
3. 在 `normalize_message` 中处理特殊字段
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 1. 消息处理
|
||||
- 使用 `asyncio.run_coroutine_threadsafe` 避免阻塞回调线程
|
||||
- 深拷贝消息数据避免并发问题
|
||||
|
||||
### 2. 插件管理
|
||||
- 按优先级排序事件处理器
|
||||
- 支持插件返回 False 中断处理链
|
||||
|
||||
### 3. 错误处理
|
||||
- 每个处理器独立 try-except
|
||||
- 一个插件出错不影响其他插件
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 1. 查看回调数据
|
||||
```python
|
||||
logger.info(f"[回调] 收到消息: type={msg_type}, data={msg_data}")
|
||||
```
|
||||
|
||||
### 2. 查看消息处理
|
||||
```python
|
||||
logger.info(f"收到消息: type={event_type}, from={from_wxid}, content={content}")
|
||||
```
|
||||
|
||||
### 3. 查看插件加载
|
||||
```python
|
||||
logger.info(f"插件 {plugin_name} 已加载")
|
||||
```
|
||||
|
||||
### 4. 使用调试日志
|
||||
```python
|
||||
logger.debug(f"详细信息: {variable}")
|
||||
```
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
1. **API 密钥**: 不要将 API 密钥提交到版本控制
|
||||
2. **管理员权限**: 只有管理员可以执行插件管理命令
|
||||
3. **消息过滤**: 使用白名单/黑名单控制消息处理
|
||||
4. **错误处理**: 捕获所有异常避免崩溃
|
||||
200
docs/快速开始.md
Normal file
200
docs/快速开始.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# 快速开始
|
||||
|
||||
## 环境准备
|
||||
|
||||
### 1. 系统要求
|
||||
|
||||
- ✅ Windows 系统(Win10/Win11)
|
||||
- ✅ Python 3.x **32位版本**(重要!)
|
||||
- ✅ 微信客户端已安装并登录
|
||||
|
||||
### 2. 检查 Python 版本
|
||||
|
||||
```bash
|
||||
python --version
|
||||
# 应显示 Python 3.x.x
|
||||
|
||||
# 检查是否为 32位
|
||||
python -c "import sys; print(sys.maxsize > 2**32)"
|
||||
# 应显示 False(表示 32位)
|
||||
```
|
||||
|
||||
如果是 64位 Python,需要下载安装 32位版本:
|
||||
https://www.python.org/downloads/
|
||||
|
||||
## 安装步骤
|
||||
|
||||
### 1. 克隆或下载项目
|
||||
|
||||
```bash
|
||||
cd D:\project\shrobot
|
||||
# 项目已在 WechatHookBot 目录
|
||||
```
|
||||
|
||||
### 2. 安装依赖
|
||||
|
||||
```bash
|
||||
cd WechatHookBot
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 3. 准备 DLL 文件
|
||||
|
||||
将个微大客户版的 DLL 文件放到 `libs/` 目录:
|
||||
|
||||
```
|
||||
WechatHookBot/
|
||||
libs/
|
||||
Loader.dll
|
||||
Helper.dll
|
||||
```
|
||||
|
||||
### 4. 配置文件
|
||||
|
||||
复制配置模板并修改:
|
||||
|
||||
```bash
|
||||
# main_config.toml 已存在,修改以下内容:
|
||||
```
|
||||
|
||||
```toml
|
||||
[Bot]
|
||||
admins = ["your_wxid"] # 改为你的 wxid
|
||||
```
|
||||
|
||||
## 运行
|
||||
|
||||
### 方式一:简单启动(无 WebUI)
|
||||
|
||||
```bash
|
||||
python bot.py
|
||||
```
|
||||
|
||||
### 方式二:完整启动(带 WebUI)
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
然后访问:http://localhost:9999
|
||||
|
||||
默认账号:admin / admin123
|
||||
|
||||
## 第一次运行
|
||||
|
||||
1. **启动微信**:确保微信客户端已登录
|
||||
2. **运行程序**:执行 `python bot.py`
|
||||
3. **观察日志**:查看是否成功注入微信
|
||||
4. **测试消息**:给机器人发送消息测试
|
||||
|
||||
## 测试插件
|
||||
|
||||
### 创建测试插件
|
||||
|
||||
在 `plugins/` 目录创建 `TestPlugin/` 文件夹:
|
||||
|
||||
```
|
||||
plugins/
|
||||
TestPlugin/
|
||||
__init__.py # 空文件
|
||||
main.py
|
||||
```
|
||||
|
||||
`main.py` 内容:
|
||||
|
||||
```python
|
||||
from utils.plugin_base import PluginBase
|
||||
from utils.decorators import *
|
||||
from WechatHook import WechatHookClient
|
||||
from loguru import logger
|
||||
|
||||
class TestPlugin(PluginBase):
|
||||
description = "测试插件"
|
||||
author = "Your Name"
|
||||
version = "1.0.0"
|
||||
|
||||
@on_text_message
|
||||
async def handle_text(self, client: WechatHookClient, message: dict):
|
||||
content = message.get("Content", "")
|
||||
from_wxid = message.get("FromWxid", "")
|
||||
|
||||
if content == "ping":
|
||||
await client.send_text(from_wxid, "pong")
|
||||
logger.info("收到 ping,回复 pong")
|
||||
```
|
||||
|
||||
重启程序,给机器人发送 "ping",应该会收到 "pong" 回复。
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 1. DLL 注入失败
|
||||
|
||||
**现象:** 提示 "注入微信失败"
|
||||
|
||||
**解决:**
|
||||
- 确认使用 32位 Python
|
||||
- 确认微信已登录
|
||||
- 关闭杀毒软件或添加信任
|
||||
- 以管理员身份运行
|
||||
|
||||
### 2. 找不到 DLL 文件
|
||||
|
||||
**现象:** "Loader DLL 文件不存在"
|
||||
|
||||
**解决:**
|
||||
- 检查 `libs/` 目录是否有 DLL 文件
|
||||
- 检查 `main_config.toml` 中的路径配置
|
||||
|
||||
### 3. 收不到消息
|
||||
|
||||
**现象:** 程序运行正常但收不到消息
|
||||
|
||||
**解决:**
|
||||
- 检查是否启用了白名单/黑名单过滤
|
||||
- 查看日志是否有错误信息
|
||||
- 确认插件已正确加载
|
||||
|
||||
### 4. 发送消息失败
|
||||
|
||||
**现象:** 调用 send_text 返回 False
|
||||
|
||||
**解决:**
|
||||
- 检查 wxid 是否正确
|
||||
- 检查是否是好友/群成员
|
||||
- 查看日志中的详细错误信息
|
||||
|
||||
## 获取 wxid
|
||||
|
||||
### 方法一:通过日志
|
||||
|
||||
运行程序后,给机器人发送消息,在日志中可以看到:
|
||||
|
||||
```
|
||||
收到消息: FromWxid=wxid_xxx, Content=...
|
||||
```
|
||||
|
||||
### 方法二:通过 API
|
||||
|
||||
创建临时插件打印所有消息:
|
||||
|
||||
```python
|
||||
@on_text_message
|
||||
async def handle_text(self, client, message):
|
||||
logger.info(f"消息详情: {message}")
|
||||
```
|
||||
|
||||
## 下一步
|
||||
|
||||
- 📖 阅读 [插件开发指南](插件开发.md)
|
||||
- 🏗️ 了解 [架构设计](架构设计.md)
|
||||
- 📚 查看 [API 文档](API文档.md)
|
||||
- 🔌 开发自己的插件
|
||||
|
||||
## 获取帮助
|
||||
|
||||
如遇到问题,请:
|
||||
|
||||
1. 查看日志文件 `logs/hookbot.log`
|
||||
2. 检查配置文件是否正确
|
||||
3. 确认环境要求是否满足
|
||||
4. 查看项目文档
|
||||
90
docs/控制台卡顿优化方案.md
Normal file
90
docs/控制台卡顿优化方案.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# WechatHookBot 控制台卡顿优化方案
|
||||
|
||||
## 问题判断
|
||||
- 控制台卡顿主要来源于高频日志输出、消息处理缺乏背压、插件耗时任务并发过高、异步调度开销叠加。
|
||||
- 项目当前在回调入口与路由层大量打印日志,并为每条消息创建异步任务,易导致 I/O 堆积与事件循环压力。
|
||||
- 关键日志位置:
|
||||
- 控制台与文件日志初始化:`WechatHookBot/bot.py:236-249`
|
||||
- 回调层日志:`WechatHookBot/bot.py:49-78`
|
||||
- 路由层日志:`WechatHookBot/utils/hookbot.py:80-123`
|
||||
|
||||
## 优化方案
|
||||
|
||||
### 日志优化
|
||||
- 将控制台日志级别降至 `WARNING` 或禁用控制台,仅保留文件日志;关闭 `colorize` 降低 Windows 终端渲染开销(参考 `WechatHookBot/bot.py:236-241`)。
|
||||
- 合并重复日志为一条结构化日志,减少每消息的 `debug/info` 输出;对系统与群成员变动事件保留必要日志,其余按采样输出(参考 `WechatHookBot/bot.py:49-78`、`WechatHookBot/utils/hookbot.py:80-123`)。
|
||||
- 使用异步日志队列/缓冲写入降低主流程的 I/O 开销;缩短文件日志保留周期与大小(参考 `WechatHookBot/bot.py:242-249`)。
|
||||
|
||||
### 背压与队列
|
||||
- 在接收回调引入有界 `asyncio.Queue(maxsize=...)`:`on_receive` 只负责快速入队,不对每条消息直接 `run_coroutine_threadsafe`(参考 `WechatHookBot/bot.py:68-78`)。
|
||||
- 由独立消费者协程从队列拉取并串行或受限并行处理;队列满时采用以下策略之一:
|
||||
- 丢弃最旧消息(防止饥饿)
|
||||
- 采样处理(降低负载)
|
||||
- 降级处理(仅计数、不分发事件)
|
||||
- 为高频消息类型设置优先级;在高水位时先处理高优先级(系统通知等),低优先级直接丢弃或延后。
|
||||
|
||||
### 并发与耗时任务
|
||||
- 使用 `asyncio.Semaphore(n)` 限制插件执行并发度,避免大量并行 I/O 或 CPU 任务压垮事件循环(事件分发位置:`WechatHookBot/utils/hookbot.py:126-132`)。
|
||||
- 为插件任务设置超时与熔断:单条消息处理超过阈值自动取消或降级;对连续失败触发短期熔断减少系统压力。
|
||||
|
||||
### 过滤策略
|
||||
- 启用/加强 `ignore-mode`:在群聊压力大时切换为 `Whitelist` 仅处理白名单来源;或用 `Blacklist` 屏蔽噪声(读取配置位置:`WechatHookBot/utils/hookbot.py:33-50`,过滤逻辑:`WechatHookBot/utils/hookbot.py:160-171`)。
|
||||
- 对非关键消息类型(除 `11058` 系统通知)在高负载状态下动态降级为统计计数,不逐条分发。
|
||||
|
||||
### 定时任务与调度
|
||||
- APScheduler 设置:
|
||||
- `coalesce=True` 合并触发
|
||||
- `max_instances=1` 防止并发堆积
|
||||
- 合理 `misfire_grace_time`
|
||||
- 将 APScheduler 相关日志降至 `WARNING`,避免定时任务导致控制台刷屏(启动点:`WechatHookBot/bot.py:185-187`)。
|
||||
|
||||
### 运行习惯与配置
|
||||
- 长期运行时仅启用文件日志或在初始化阶段保留控制台输出,稳定后自动关闭控制台 Sink。
|
||||
- 将日志采样率、队列容量、并发上限、忽略模式等参数放入 `main_config.toml`,支持运行期按需调整(配置读取:`WechatHookBot/utils/hookbot.py:33-50`)。
|
||||
|
||||
## 实施优先级
|
||||
1. 低风险配置级
|
||||
- 降低或关闭控制台日志、压低日志级别、关闭彩色输出、减少路由层细粒度日志。
|
||||
2. 架构级
|
||||
- 引入有界消息队列与单/多消费者;设置并发上限与任务超时;高水位时对低优先级消息降级或采样。
|
||||
3. 策略级
|
||||
- 启用白名单模式;扩充过滤类型;对高频事件采用采样与聚合日志。
|
||||
|
||||
## 验证要点
|
||||
- CPU 与终端响应度显著改善,`logs/hookbot.log` 保持必要信息且写入量合理。
|
||||
- 峰值时队列长度稳定在上限附近但不无限增长,平均处理时延可控。
|
||||
- 插件执行受限在设定并发与超时范围内,无明显阻塞主循环。
|
||||
|
||||
## 可配置建议示例(不直接改代码)
|
||||
```toml
|
||||
# main_config.toml 中建议新增
|
||||
[Performance]
|
||||
log_console_enabled = false # 禁用控制台日志
|
||||
log_level_file = "INFO" # 文件日志级别
|
||||
log_colorize = false # 关闭彩色输出
|
||||
log_sampling_rate = 0.1 # 日志采样比例(10%)
|
||||
|
||||
[Queue]
|
||||
max_size = 1000 # 消息队列容量
|
||||
overflow_strategy = "drop_oldest" # 溢出策略:丢弃最旧/采样/degrade
|
||||
|
||||
[Concurrency]
|
||||
plugin_max_concurrency = 8 # 插件并发上限
|
||||
plugin_task_timeout_seconds = 5 # 单任务超时
|
||||
|
||||
[Filter]
|
||||
ignore_mode = "Whitelist" # None/Whitelist/Blacklist
|
||||
whitelist = ["room_wxid_xxx", "wxid_xxx"]
|
||||
blacklist = []
|
||||
|
||||
[Scheduler]
|
||||
coalesce = true
|
||||
max_instances = 1
|
||||
misfire_grace_time = 30
|
||||
```
|
||||
|
||||
## 关联文件位置(便于落地)
|
||||
- 控制台与文件日志初始化:`WechatHookBot/bot.py:236-249`
|
||||
- 回调注册与消息接收:`WechatHookBot/bot.py:42-83`
|
||||
- 事件分发与过滤:`WechatHookBot/utils/hookbot.py:68-132`、`WechatHookBot/utils/hookbot.py:133-172`
|
||||
- 定时任务启动:`WechatHookBot/bot.py:185-187`
|
||||
465
docs/插件开发.md
Normal file
465
docs/插件开发.md
Normal file
@@ -0,0 +1,465 @@
|
||||
# WechatHookBot 插件开发指南
|
||||
|
||||
## 插件系统
|
||||
|
||||
WechatHookBot 的插件系统完全兼容 XYBotV2,所有 XYBot 插件可以直接使用。
|
||||
|
||||
## 插件结构
|
||||
|
||||
```
|
||||
plugins/
|
||||
PluginName/
|
||||
__init__.py # 可选,可为空
|
||||
main.py # 必需,包含插件类
|
||||
config.toml # 可选,插件配置
|
||||
README.md # 可选,插件说明
|
||||
```
|
||||
|
||||
## 基本插件模板
|
||||
|
||||
```python
|
||||
from utils.plugin_base import PluginBase
|
||||
from utils.decorators import *
|
||||
from WechatHook import WechatHookClient
|
||||
|
||||
class MyPlugin(PluginBase):
|
||||
description = "插件描述"
|
||||
author = "作者名"
|
||||
version = "1.0.0"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# 同步初始化
|
||||
self.data = {}
|
||||
|
||||
async def async_init(self):
|
||||
# 异步初始化
|
||||
pass
|
||||
|
||||
@on_text_message(priority=50)
|
||||
async def handle_text(self, client: WechatHookClient, message: dict):
|
||||
"""处理文本消息"""
|
||||
content = message.get("Content", "")
|
||||
from_wxid = message.get("FromWxid", "")
|
||||
|
||||
if content == "你好":
|
||||
await client.send_text(from_wxid, "你好!我是机器人")
|
||||
return False # 阻止后续处理
|
||||
|
||||
return True # 继续执行后续处理器
|
||||
```
|
||||
|
||||
## 事件装饰器
|
||||
|
||||
### 消息事件
|
||||
|
||||
| 装饰器 | 触发条件 | 参数 |
|
||||
|--------|----------|------|
|
||||
| `@on_text_message` | 文本消息 | priority (0-99) |
|
||||
| `@on_image_message` | 图片消息 | priority |
|
||||
| `@on_voice_message` | 语音消息 | priority |
|
||||
| `@on_video_message` | 视频消息 | priority |
|
||||
| `@on_file_message` | 文件消息 | priority |
|
||||
| `@on_at_message` | @消息 | priority |
|
||||
| `@on_quote_message` | 引用消息 | priority |
|
||||
| `@on_card_message` | 名片消息 | priority |
|
||||
| `@on_location_message` | 位置消息 | priority |
|
||||
| `@on_link_message` | 链接消息 | priority |
|
||||
| `@on_miniapp_message` | 小程序消息 | priority |
|
||||
| `@on_emoji_message` | 表情消息 | priority |
|
||||
| `@on_revoke_message` | 撤回消息 | priority |
|
||||
| `@on_friend_request` | 好友请求 | priority |
|
||||
|
||||
### 优先级机制
|
||||
|
||||
- 优先级范围:0-99
|
||||
- 数值越大,优先级越高
|
||||
- 默认优先级:50
|
||||
- 按优先级从高到低执行
|
||||
|
||||
```python
|
||||
@on_text_message(priority=80) # 高优先级
|
||||
async def handle_important(self, client, message):
|
||||
pass
|
||||
|
||||
@on_text_message(priority=20) # 低优先级
|
||||
async def handle_normal(self, client, message):
|
||||
pass
|
||||
```
|
||||
|
||||
### 阻塞机制
|
||||
|
||||
- 返回 `False`:阻止后续处理器执行
|
||||
- 返回 `True` 或不返回:继续执行
|
||||
|
||||
```python
|
||||
@on_text_message
|
||||
async def handle_sensitive(self, client, message):
|
||||
if "敏感词" in message["Content"]:
|
||||
await client.send_text(message["FromWxid"], "检测到敏感内容")
|
||||
return False # 阻止后续执行
|
||||
return True # 继续执行
|
||||
```
|
||||
|
||||
## 定时任务
|
||||
|
||||
### interval - 间隔触发
|
||||
|
||||
```python
|
||||
@schedule('interval', seconds=30)
|
||||
async def periodic_task(self, client: WechatHookClient):
|
||||
"""每30秒执行一次"""
|
||||
pass
|
||||
|
||||
@schedule('interval', minutes=5)
|
||||
async def five_minutes_task(self, client: WechatHookClient):
|
||||
"""每5分钟执行一次"""
|
||||
pass
|
||||
```
|
||||
|
||||
### cron - 定时触发
|
||||
|
||||
```python
|
||||
@schedule('cron', hour=8, minute=30)
|
||||
async def morning_task(self, client: WechatHookClient):
|
||||
"""每天早上8:30执行"""
|
||||
await client.send_text("wxid_xxx", "早安!")
|
||||
|
||||
@schedule('cron', day_of_week='mon-fri', hour='9-17')
|
||||
async def work_time_task(self, client: WechatHookClient):
|
||||
"""工作日9-17点每小时执行"""
|
||||
pass
|
||||
```
|
||||
|
||||
### date - 指定时间触发
|
||||
|
||||
```python
|
||||
@schedule('date', run_date='2024-12-31 23:59:59')
|
||||
async def new_year_task(self, client: WechatHookClient):
|
||||
"""在指定时间执行一次"""
|
||||
pass
|
||||
```
|
||||
|
||||
## 消息对象结构
|
||||
|
||||
### 文本消息
|
||||
|
||||
```python
|
||||
{
|
||||
"FromWxid": "wxid_xxx", # 发送者 wxid
|
||||
"ToWxid": "wxid_yyy", # 接收者 wxid
|
||||
"Content": "消息内容", # 文本内容
|
||||
"MsgType": 1, # 消息类型
|
||||
"IsGroup": False, # 是否群聊
|
||||
"SenderWxid": "wxid_xxx", # 实际发送者(群聊时不同)
|
||||
"CreateTime": 1234567890, # 创建时间戳
|
||||
}
|
||||
```
|
||||
|
||||
### 群聊消息
|
||||
|
||||
```python
|
||||
{
|
||||
"FromWxid": "123@chatroom", # 群聊 ID
|
||||
"ToWxid": "wxid_bot", # 机器人 wxid
|
||||
"Content": "消息内容",
|
||||
"IsGroup": True, # 是否群聊
|
||||
"SenderWxid": "wxid_xxx", # 实际发送者
|
||||
"Ats": ["wxid_bot"], # 被@的用户列表
|
||||
}
|
||||
```
|
||||
|
||||
### 图片消息
|
||||
|
||||
```python
|
||||
{
|
||||
"FromWxid": "wxid_xxx",
|
||||
"Content": "base64_image_data", # 图片 base64 数据
|
||||
"MsgType": 3,
|
||||
"ImagePath": "/path/to/image", # 图片路径(如果有)
|
||||
}
|
||||
```
|
||||
|
||||
## WechatHookClient API
|
||||
|
||||
### 发送消息
|
||||
|
||||
```python
|
||||
# 发送文本
|
||||
await client.send_text(wxid, "消息内容")
|
||||
|
||||
# 发送图片
|
||||
await client.send_image(wxid, "/path/to/image.jpg")
|
||||
|
||||
# 发送文件
|
||||
await client.send_file(wxid, "/path/to/file.pdf")
|
||||
|
||||
# 发送视频
|
||||
await client.send_video(wxid, "/path/to/video.mp4")
|
||||
|
||||
# 发送名片
|
||||
await client.send_card(wxid, card_wxid, card_nickname)
|
||||
|
||||
# 发送位置
|
||||
await client.send_location(wxid, lat, lng, title, address)
|
||||
|
||||
# 发送链接
|
||||
await client.send_link(wxid, title, desc, url, thumb_url)
|
||||
|
||||
# 发送小程序
|
||||
await client.send_miniapp(wxid, appid, title, page_path, thumb_url)
|
||||
|
||||
# 群聊@消息
|
||||
await client.send_at_message(chatroom_id, content, at_list)
|
||||
|
||||
# 撤回消息
|
||||
await client.revoke_message(msg_id)
|
||||
```
|
||||
|
||||
### 好友管理
|
||||
|
||||
```python
|
||||
# 获取好友列表
|
||||
friends = await client.get_friend_list()
|
||||
|
||||
# 获取好友信息
|
||||
info = await client.get_friend_info(wxid)
|
||||
|
||||
# 搜索用户
|
||||
result = await client.search_user(keyword)
|
||||
|
||||
# 添加好友
|
||||
await client.add_friend(wxid, verify_msg)
|
||||
|
||||
# 同意好友请求
|
||||
await client.accept_friend(v3, v4, scene)
|
||||
|
||||
# 删除好友
|
||||
await client.delete_friend(wxid)
|
||||
|
||||
# 修改备注
|
||||
await client.set_friend_remark(wxid, remark)
|
||||
|
||||
# 检测好友状态
|
||||
status = await client.check_friend_status(wxid)
|
||||
```
|
||||
|
||||
### 群聊管理
|
||||
|
||||
```python
|
||||
# 获取群聊列表
|
||||
chatrooms = await client.get_chatroom_list()
|
||||
|
||||
# 获取群成员
|
||||
members = await client.get_chatroom_members(chatroom_id)
|
||||
|
||||
# 获取群信息
|
||||
info = await client.get_chatroom_info(chatroom_id)
|
||||
|
||||
# 创建群聊
|
||||
chatroom_id = await client.create_chatroom(member_list)
|
||||
|
||||
# 邀请进群
|
||||
await client.invite_to_chatroom(chatroom_id, wxid_list)
|
||||
|
||||
# 踢出群成员
|
||||
await client.remove_chatroom_member(chatroom_id, wxid_list)
|
||||
|
||||
# 退出群聊
|
||||
await client.quit_chatroom(chatroom_id)
|
||||
|
||||
# 修改群名称
|
||||
await client.set_chatroom_name(chatroom_id, name)
|
||||
|
||||
# 修改群公告
|
||||
await client.set_chatroom_announcement(chatroom_id, announcement)
|
||||
|
||||
# 修改我的群昵称
|
||||
await client.set_my_chatroom_nickname(chatroom_id, nickname)
|
||||
```
|
||||
|
||||
## 数据库使用
|
||||
|
||||
### KeyvalDB - 键值存储
|
||||
|
||||
```python
|
||||
from database.keyvalDB import KeyvalDB
|
||||
|
||||
keyval_db = KeyvalDB()
|
||||
|
||||
# 设置值
|
||||
await keyval_db.set("key", "value")
|
||||
|
||||
# 获取值
|
||||
value = await keyval_db.get("key")
|
||||
|
||||
# 删除值
|
||||
await keyval_db.delete("key")
|
||||
```
|
||||
|
||||
### XYBotDB - 业务数据
|
||||
|
||||
```python
|
||||
from database.XYBotDB import XYBotDB
|
||||
|
||||
db = XYBotDB()
|
||||
|
||||
# 使用 SQLAlchemy 操作数据库
|
||||
# 参考 XYBot 的数据库使用方式
|
||||
```
|
||||
|
||||
## 配置文件
|
||||
|
||||
### 插件配置 (config.toml)
|
||||
|
||||
```toml
|
||||
[basic]
|
||||
enable = true
|
||||
|
||||
[settings]
|
||||
api_key = "your_api_key"
|
||||
timeout = 30
|
||||
```
|
||||
|
||||
### 读取配置
|
||||
|
||||
```python
|
||||
import tomllib
|
||||
import os
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.toml")
|
||||
with open(config_path, "rb") as f:
|
||||
config = tomllib.load(f)
|
||||
|
||||
self.enable = config.get("basic", {}).get("enable", False)
|
||||
self.api_key = config.get("settings", {}).get("api_key", "")
|
||||
```
|
||||
|
||||
## 日志系统
|
||||
|
||||
使用 loguru 记录日志:
|
||||
|
||||
```python
|
||||
from loguru import logger
|
||||
|
||||
# 不同级别的日志
|
||||
logger.debug("调试信息")
|
||||
logger.info("普通信息")
|
||||
logger.success("成功信息")
|
||||
logger.warning("警告信息")
|
||||
logger.error("错误信息")
|
||||
|
||||
# 带参数的日志
|
||||
logger.info("收到消息: {}", message)
|
||||
```
|
||||
|
||||
## 异步编程
|
||||
|
||||
所有插件函数必须是异步函数:
|
||||
|
||||
```python
|
||||
# ✅ 正确
|
||||
@on_text_message
|
||||
async def handle_text(self, client, message):
|
||||
await client.send_text(...)
|
||||
|
||||
# ❌ 错误
|
||||
@on_text_message
|
||||
def handle_text(self, client, message): # 缺少 async
|
||||
client.send_text(...) # 缺少 await
|
||||
```
|
||||
|
||||
### 使用阻塞函数
|
||||
|
||||
如需使用阻塞函数,使用 `asyncio.run_in_executor`:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
@on_text_message
|
||||
async def handle_text(self, client, message):
|
||||
# 在线程池中运行阻塞函数
|
||||
result = await asyncio.to_thread(blocking_function, arg1, arg2)
|
||||
```
|
||||
|
||||
## 完整示例
|
||||
|
||||
```python
|
||||
from utils.plugin_base import PluginBase
|
||||
from utils.decorators import *
|
||||
from WechatHook import WechatHookClient
|
||||
from loguru import logger
|
||||
import tomllib
|
||||
import os
|
||||
|
||||
class ExamplePlugin(PluginBase):
|
||||
description = "示例插件"
|
||||
author = "Your Name"
|
||||
version = "1.0.0"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# 读取配置
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.toml")
|
||||
with open(config_path, "rb") as f:
|
||||
config = tomllib.load(f)
|
||||
|
||||
self.enable = config.get("basic", {}).get("enable", False)
|
||||
self.keyword = config.get("settings", {}).get("keyword", "你好")
|
||||
|
||||
async def async_init(self):
|
||||
logger.info("ExamplePlugin 初始化完成")
|
||||
|
||||
@on_text_message(priority=50)
|
||||
async def handle_text(self, client: WechatHookClient, message: dict):
|
||||
if not self.enable:
|
||||
return
|
||||
|
||||
content = message.get("Content", "")
|
||||
from_wxid = message.get("FromWxid", "")
|
||||
|
||||
if self.keyword in content:
|
||||
await client.send_text(from_wxid, f"你说了关键词:{self.keyword}")
|
||||
logger.info(f"触发关键词回复: {from_wxid}")
|
||||
|
||||
@on_at_message(priority=60)
|
||||
async def handle_at(self, client: WechatHookClient, message: dict):
|
||||
if not self.enable:
|
||||
return
|
||||
|
||||
content = message.get("Content", "")
|
||||
from_wxid = message.get("FromWxid", "")
|
||||
|
||||
await client.send_text(from_wxid, "你@了我!")
|
||||
|
||||
@schedule('cron', hour=9, minute=0)
|
||||
async def morning_greeting(self, client: WechatHookClient):
|
||||
if not self.enable:
|
||||
return
|
||||
|
||||
# 每天早上9点发送问候
|
||||
await client.send_text("wxid_xxx", "早安!新的一天开始了")
|
||||
```
|
||||
|
||||
## 插件管理
|
||||
|
||||
### 禁用插件
|
||||
|
||||
在 `main_config.toml` 中添加:
|
||||
|
||||
```toml
|
||||
[Bot]
|
||||
disabled-plugins = ["ExamplePlugin", "AnotherPlugin"]
|
||||
```
|
||||
|
||||
### 删除插件
|
||||
|
||||
直接删除 `plugins/` 下对应的文件夹
|
||||
|
||||
### 热重载
|
||||
|
||||
通过 WebUI 或 ManagePlugin 插件实现热重载
|
||||
253
docs/架构设计.md
Normal file
253
docs/架构设计.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# WechatHookBot 架构设计
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 四层架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第四层:WebUI 层(可选) │
|
||||
│ Flask + SocketIO + Bootstrap │
|
||||
│ - 插件管理、消息监控、配置管理 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↕
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第三层:插件层(完全复用 XYBot) │
|
||||
│ PluginManager → PluginBase → 具体插件 │
|
||||
│ 装饰器:@on_text_message, @on_image_message, @schedule │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↕
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第二层:Bot 核心层 │
|
||||
│ HookBot - 消息预处理、路由、类型映射 │
|
||||
│ EventManager - 事件分发、优先级、阻塞机制 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↕
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第一层:WechatHook 层 │
|
||||
│ WechatHookClient - API 封装 │
|
||||
│ NoveLoader - DLL 调用 │
|
||||
│ 回调处理器 - Socket 回调 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↕
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 底层:DLL 层 │
|
||||
│ Loader.dll ←→ Helper.dll (注入微信进程) ←→ 微信客户端 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 消息流转
|
||||
|
||||
### 接收消息流程
|
||||
|
||||
```
|
||||
微信消息
|
||||
→ Helper.dll (注入微信进程)
|
||||
→ Socket 回调
|
||||
→ on_recv_callback(client_id, msg_type, data)
|
||||
→ HookBot.process_message()
|
||||
→ 消息类型映射 (type → event)
|
||||
→ EventManager.emit(event_type, client, message)
|
||||
→ 插件事件处理器(按优先级执行)
|
||||
```
|
||||
|
||||
### 发送消息流程
|
||||
|
||||
```
|
||||
插件调用
|
||||
→ client.send_text(wxid, content)
|
||||
→ WechatHookClient 封装
|
||||
→ 构造 JSON payload {"type": 11036, "data": {...}}
|
||||
→ NoveLoader.SendWeChatData()
|
||||
→ Loader.dll
|
||||
→ Helper.dll
|
||||
→ 微信发送
|
||||
```
|
||||
|
||||
## 核心模块
|
||||
|
||||
### 1. WechatHook 层
|
||||
|
||||
**NoveLoader** - DLL 函数封装
|
||||
```python
|
||||
class NoveLoader:
|
||||
- InitWeChatSocket() # 初始化回调
|
||||
- InjectWeChat() # 注入微信
|
||||
- SendWeChatData() # 发送数据
|
||||
- DestroyWeChat() # 销毁连接
|
||||
```
|
||||
|
||||
**WechatHookClient** - API 封装
|
||||
```python
|
||||
class WechatHookClient:
|
||||
- send_text() # 发送文本
|
||||
- send_image() # 发送图片
|
||||
- send_file() # 发送文件
|
||||
- get_friend_list() # 获取好友列表
|
||||
- get_chatroom_list() # 获取群聊列表
|
||||
- add_friend() # 添加好友
|
||||
# ... 更多 API
|
||||
```
|
||||
|
||||
### 2. Bot 核心层
|
||||
|
||||
**HookBot** - 消息处理核心
|
||||
```python
|
||||
class HookBot:
|
||||
- process_message() # 处理消息
|
||||
- _normalize_message() # 统一消息格式
|
||||
- _filter_message() # 白名单/黑名单过滤
|
||||
```
|
||||
|
||||
**EventManager** - 事件管理(复用 XYBot)
|
||||
```python
|
||||
class EventManager:
|
||||
- bind_instance() # 绑定插件实例
|
||||
- emit() # 触发事件
|
||||
- unbind_instance() # 解绑实例
|
||||
```
|
||||
|
||||
### 3. 插件层
|
||||
|
||||
**PluginBase** - 插件基类(复用 XYBot)
|
||||
```python
|
||||
class PluginBase:
|
||||
description: str
|
||||
author: str
|
||||
version: str
|
||||
|
||||
async def on_enable() # 启用时调用
|
||||
async def on_disable() # 禁用时调用
|
||||
async def async_init() # 异步初始化
|
||||
```
|
||||
|
||||
**装饰器系统**(复用 XYBot)
|
||||
- `@on_text_message` - 文本消息
|
||||
- `@on_image_message` - 图片消息
|
||||
- `@on_voice_message` - 语音消息
|
||||
- `@on_at_message` - @消息
|
||||
- `@schedule` - 定时任务
|
||||
|
||||
## 消息类型映射
|
||||
|
||||
从个微 API 的 type 值映射到内部事件类型:
|
||||
|
||||
```python
|
||||
MESSAGE_TYPE_MAP = {
|
||||
# 需要根据实际 API 文档补充
|
||||
10001: "text_message",
|
||||
10002: "image_message",
|
||||
10003: "voice_message",
|
||||
10004: "video_message",
|
||||
10005: "file_message",
|
||||
10006: "card_message",
|
||||
10007: "location_message",
|
||||
10008: "link_message",
|
||||
10009: "miniapp_message",
|
||||
10010: "emoji_message",
|
||||
10011: "revoke_message",
|
||||
10012: "system_message",
|
||||
10013: "friend_request",
|
||||
# 群聊通知
|
||||
10020: "chatroom_member_add",
|
||||
10021: "chatroom_member_remove",
|
||||
}
|
||||
```
|
||||
|
||||
## 数据库设计
|
||||
|
||||
复用 XYBot 的数据库架构:
|
||||
|
||||
### XYBotDB (SQLite)
|
||||
- 用户表 - 用户信息、积分
|
||||
- 签到表 - 签到记录
|
||||
- 其他业务表
|
||||
|
||||
### MessageDB (SQLite + aiosqlite)
|
||||
- 消息记录表(可选)
|
||||
|
||||
### KeyvalDB (SQLite + aiosqlite)
|
||||
- 键值存储表
|
||||
- 用于配置、状态管理
|
||||
|
||||
## 配置系统
|
||||
|
||||
### main_config.toml
|
||||
|
||||
```toml
|
||||
[WechatHook]
|
||||
loader-dll = "libs/Loader.dll"
|
||||
helper-dll = "libs/Helper.dll"
|
||||
|
||||
[Bot]
|
||||
version = "v1.0.0"
|
||||
admins = ["admin_wxid"]
|
||||
disabled-plugins = []
|
||||
timezone = "Asia/Shanghai"
|
||||
|
||||
# 消息过滤
|
||||
ignore-mode = "None" # None/Whitelist/Blacklist
|
||||
whitelist = []
|
||||
blacklist = []
|
||||
|
||||
[Database]
|
||||
xybot-db = "sqlite:///database/hookbot.db"
|
||||
message-db = "sqlite+aiosqlite:///database/message.db"
|
||||
keyval-db = "sqlite+aiosqlite:///database/keyval.db"
|
||||
|
||||
[WebUI]
|
||||
admin-username = "admin"
|
||||
admin-password = "admin123"
|
||||
session-timeout = 30
|
||||
```
|
||||
|
||||
## 与 XYBot 的对比
|
||||
|
||||
| 特性 | XYBot | WechatHookBot |
|
||||
|------|-------|---------------|
|
||||
| 底层技术 | 协议实现 | DLL Hook |
|
||||
| 登录方式 | 二维码/唤醒 | 无需登录 |
|
||||
| 依赖 | Redis | 无 |
|
||||
| 消息接收 | sync_message 轮询 | Socket 回调 |
|
||||
| 插件系统 | ✅ | ✅ 完全兼容 |
|
||||
| 风控风险 | 中 | 高 |
|
||||
| 多开支持 | 需多实例 | 原生支持 |
|
||||
| Python 版本 | 3.11 | 3.x (32位) |
|
||||
|
||||
## 优势
|
||||
|
||||
1. **架构更简单**:无需 Redis,减少依赖
|
||||
2. **无需登录**:Hook 已登录微信,省去登录流程
|
||||
3. **实时性更好**:Socket 回调,无需轮询
|
||||
4. **代码复用**:80% 代码可复用 XYBot
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **32位限制**:DLL 是 32位,必须使用 32位 Python
|
||||
2. **风控风险**:Hook 方式风控风险较高
|
||||
3. **依赖微信**:必须有微信客户端在运行
|
||||
4. **杀软拦截**:DLL 可能被杀毒软件拦截
|
||||
|
||||
## 开发路线
|
||||
|
||||
### 第一阶段:基础框架
|
||||
- [ ] WechatHook 层实现
|
||||
- [ ] HookBot 核心类
|
||||
- [ ] 消息类型映射
|
||||
- [ ] 基础 API 封装
|
||||
|
||||
### 第二阶段:插件系统
|
||||
- [ ] 复用 XYBot 插件系统
|
||||
- [ ] 适配消息格式
|
||||
- [ ] 测试插件兼容性
|
||||
|
||||
### 第三阶段:完善功能
|
||||
- [ ] 数据库集成
|
||||
- [ ] 配置系统
|
||||
- [ ] 日志系统
|
||||
- [ ] 错误处理
|
||||
|
||||
### 第四阶段:WebUI(可选)
|
||||
- [ ] 复用 XYBot WebUI
|
||||
- [ ] 适配 Hook API
|
||||
- [ ] 实时监控界面
|
||||
236
docs/项目概览.md
Normal file
236
docs/项目概览.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# WechatHookBot 项目概览
|
||||
|
||||
## 📁 当前项目结构
|
||||
|
||||
```
|
||||
WechatHookBot/
|
||||
├── docs/ # 📚 文档目录
|
||||
│ ├── 项目概览.md # 本文件
|
||||
│ ├── 快速开始.md # 安装和运行指南
|
||||
│ ├── 架构设计.md # 技术架构文档
|
||||
│ ├── 插件开发.md # 插件开发指南
|
||||
│ └── API文档.md # API 接口文档
|
||||
├── main_config.toml # ⚙️ 主配置文件
|
||||
├── requirements.txt # 📦 Python 依赖
|
||||
├── .gitignore # 🚫 Git 忽略文件
|
||||
└── README.md # 📖 项目说明
|
||||
```
|
||||
|
||||
## 📋 已完成的工作
|
||||
|
||||
### ✅ 文档系统
|
||||
- [x] README.md - 项目介绍和快速开始
|
||||
- [x] 架构设计.md - 完整的技术架构设计
|
||||
- [x] 插件开发.md - 详细的插件开发指南
|
||||
- [x] API文档.md - 完整的 API 接口文档
|
||||
- [x] 快速开始.md - 安装和运行教程
|
||||
- [x] 项目概览.md - 项目总览(本文件)
|
||||
|
||||
### ✅ 配置文件
|
||||
- [x] main_config.toml - 主配置文件模板
|
||||
- [x] requirements.txt - Python 依赖列表
|
||||
- [x] .gitignore - Git 忽略规则
|
||||
|
||||
## 🚧 待开发模块
|
||||
|
||||
### 第一阶段:核心框架(优先级:高)
|
||||
|
||||
```
|
||||
WechatHook/ # Hook 层实现
|
||||
├── __init__.py
|
||||
├── loader.py # NoveLoader DLL 封装
|
||||
├── client.py # WechatHookClient API 封装
|
||||
├── message_types.py # 消息类型映射
|
||||
└── callbacks.py # 回调处理器
|
||||
```
|
||||
|
||||
**任务清单:**
|
||||
- [ ] 实现 NoveLoader 类(基于 python_demo.py)
|
||||
- [ ] 实现 WechatHookClient 类(封装所有 API)
|
||||
- [ ] 定义消息类型映射表
|
||||
- [ ] 实现回调处理系统
|
||||
|
||||
### 第二阶段:Bot 核心(优先级:高)
|
||||
|
||||
```
|
||||
utils/ # 工具类(复用 XYBot)
|
||||
├── __init__.py
|
||||
├── plugin_base.py # ✅ 从 XYBot 复制
|
||||
├── plugin_manager.py # ✅ 从 XYBot 复制
|
||||
├── event_manager.py # ✅ 从 XYBot 复制
|
||||
├── decorators.py # ✅ 从 XYBot 复制
|
||||
├── singleton.py # ✅ 从 XYBot 复制
|
||||
└── hookbot.py # ⚠️ 新实现(类似 xybot.py)
|
||||
|
||||
bot.py # 主入口(简化版)
|
||||
```
|
||||
|
||||
**任务清单:**
|
||||
- [ ] 从 XYBot 复制 utils/ 下的文件
|
||||
- [ ] 实现 HookBot 类(消息处理核心)
|
||||
- [ ] 实现 bot.py 主入口
|
||||
- [ ] 适配消息格式(统一为 XYBot 格式)
|
||||
|
||||
### 第三阶段:数据库(优先级:中)
|
||||
|
||||
```
|
||||
database/ # 数据库(复用 XYBot)
|
||||
├── __init__.py
|
||||
├── XYBotDB.py # ✅ 从 XYBot 复制
|
||||
├── keyvalDB.py # ✅ 从 XYBot 复制
|
||||
└── messsagDB.py # ✅ 从 XYBot 复制
|
||||
```
|
||||
|
||||
**任务清单:**
|
||||
- [ ] 从 XYBot 复制数据库文件
|
||||
- [ ] 修改数据库名称(xybot.db → hookbot.db)
|
||||
- [ ] 测试数据库功能
|
||||
|
||||
### 第四阶段:插件系统(优先级:中)
|
||||
|
||||
```
|
||||
plugins/ # 插件目录
|
||||
├── ExamplePlugin/ # 示例插件
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── config.toml
|
||||
└── Menu/ # 菜单插件(从 XYBot 移植)
|
||||
├── __init__.py
|
||||
├── main.py
|
||||
└── config.toml
|
||||
```
|
||||
|
||||
**任务清单:**
|
||||
- [ ] 创建 ExamplePlugin 示例插件
|
||||
- [ ] 从 XYBot 移植 Menu 插件
|
||||
- [ ] 测试插件兼容性
|
||||
- [ ] 根据需要移植更多插件
|
||||
|
||||
### 第五阶段:WebUI(优先级:低,可选)
|
||||
|
||||
```
|
||||
WebUI/ # Web 管理界面(复用 XYBot)
|
||||
├── __init__.py
|
||||
├── config.py
|
||||
├── routes/ # 路由
|
||||
├── services/ # 服务层
|
||||
├── templates/ # 模板
|
||||
└── static/ # 静态资源
|
||||
|
||||
app.py # WebUI 入口
|
||||
```
|
||||
|
||||
**任务清单:**
|
||||
- [ ] 从 XYBot 复制 WebUI 代码
|
||||
- [ ] 适配 WechatHook API
|
||||
- [ ] 实现 app.py 入口
|
||||
- [ ] 测试 WebUI 功能
|
||||
|
||||
### 第六阶段:辅助功能(优先级:低)
|
||||
|
||||
```
|
||||
libs/ # DLL 文件目录
|
||||
├── Loader.dll # 从个微大客户版复制
|
||||
└── Helper.dll # 从个微大客户版复制
|
||||
|
||||
logs/ # 日志目录(自动创建)
|
||||
resources/ # 资源目录(自动创建)
|
||||
```
|
||||
|
||||
**任务清单:**
|
||||
- [ ] 准备 DLL 文件
|
||||
- [ ] 实现日志系统
|
||||
- [ ] 实现资源管理
|
||||
|
||||
## 📊 开发进度
|
||||
|
||||
| 阶段 | 模块 | 状态 | 进度 |
|
||||
|------|------|------|------|
|
||||
| 0 | 文档系统 | ✅ 完成 | 100% |
|
||||
| 1 | WechatHook 层 | 🚧 待开发 | 0% |
|
||||
| 2 | Bot 核心层 | 🚧 待开发 | 0% |
|
||||
| 3 | 数据库 | 🚧 待开发 | 0% |
|
||||
| 4 | 插件系统 | 🚧 待开发 | 0% |
|
||||
| 5 | WebUI | 🚧 待开发 | 0% |
|
||||
| 6 | 辅助功能 | 🚧 待开发 | 0% |
|
||||
|
||||
**总体进度:** 15% (文档完成)
|
||||
|
||||
## 🎯 下一步行动
|
||||
|
||||
### 立即开始(推荐顺序)
|
||||
|
||||
1. **准备 DLL 文件**
|
||||
- 从个微大客户版复制 `Loader.dll` 和 `Helper.dll` 到 `libs/` 目录
|
||||
|
||||
2. **实现 WechatHook 层**
|
||||
- 参考 `个微大客户版/python4.1.2.17Demo/python_demo.py`
|
||||
- 实现 `WechatHook/loader.py`(NoveLoader 类)
|
||||
- 实现 `WechatHook/client.py`(WechatHookClient 类)
|
||||
|
||||
3. **复用 XYBot 代码**
|
||||
- 复制 `XYBotV2/utils/` 到 `WechatHookBot/utils/`
|
||||
- 复制 `XYBotV2/database/` 到 `WechatHookBot/database/`
|
||||
|
||||
4. **实现 Bot 核心**
|
||||
- 参考 `XYBotV2/utils/xybot.py` 实现 `utils/hookbot.py`
|
||||
- 实现 `bot.py` 主入口
|
||||
|
||||
5. **测试基础功能**
|
||||
- 创建简单的测试插件
|
||||
- 测试消息收发
|
||||
- 验证插件系统
|
||||
|
||||
## 📚 参考资料
|
||||
|
||||
### 内部文档
|
||||
- [快速开始](快速开始.md) - 环境准备和安装
|
||||
- [架构设计](架构设计.md) - 技术架构详解
|
||||
- [插件开发](插件开发.md) - 插件开发指南
|
||||
- [API文档](API文档.md) - API 接口参考
|
||||
|
||||
### 参考项目
|
||||
- `XYBotV2/` - 插件系统、事件管理、数据库
|
||||
- `个微大客户版/python4.1.2.17Demo/python_demo.py` - DLL 调用示例
|
||||
- `个微大客户版/API/` - API 接口文档
|
||||
|
||||
## 💡 开发建议
|
||||
|
||||
### 代码复用策略
|
||||
- ✅ **完全复用**:utils/(插件系统、事件管理、装饰器)
|
||||
- ✅ **完全复用**:database/(数据库层)
|
||||
- ⚠️ **参考实现**:hookbot.py(参考 xybot.py,但需适配)
|
||||
- 🆕 **全新实现**:WechatHook/(Hook 层封装)
|
||||
|
||||
### 开发优先级
|
||||
1. **核心功能优先**:先实现消息收发和插件系统
|
||||
2. **逐步完善**:基础功能稳定后再添加 WebUI
|
||||
3. **测试驱动**:每个模块完成后立即测试
|
||||
|
||||
### 注意事项
|
||||
- 使用 32位 Python 开发和测试
|
||||
- 保持与 XYBot 插件的兼容性
|
||||
- 注意消息格式的统一转换
|
||||
- 做好错误处理和日志记录
|
||||
|
||||
## 🔗 相关链接
|
||||
|
||||
- **XYBotV2 项目**:`D:\project\shrobot\XYBotV2\`
|
||||
- **个微大客户版**:`D:\project\shrobot\个微大客户版\`
|
||||
- **当前项目**:`D:\project\shrobot\WechatHookBot\`
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### 2025-01-XX
|
||||
- ✅ 创建项目目录结构
|
||||
- ✅ 完成所有文档编写
|
||||
- ✅ 创建配置文件模板
|
||||
- 🚧 准备开始代码实现
|
||||
|
||||
---
|
||||
|
||||
**项目状态:** 🚧 文档完成,代码开发中
|
||||
|
||||
**预计完成时间:** 2-3 天(基础框架)
|
||||
|
||||
**当前任务:** 实现 WechatHook 层
|
||||
Reference in New Issue
Block a user