feat:初版

This commit is contained in:
2025-12-03 15:48:44 +08:00
commit b4df26f61d
199 changed files with 23434 additions and 0 deletions

694
docs/API文档.md Normal file
View 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 调用频率不宜过高,避免风控

View 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 管理界面
- 数据统计功能

View 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. 编写使用文档

View 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
View 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. 查看项目文档

View 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
View 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
View 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
View 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 层