add:新增文档变更
This commit is contained in:
@@ -128,146 +128,21 @@ action_require = [
|
|||||||
associated_types = ["text", "emoji", "image"]
|
associated_types = ["text", "emoji", "image"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. 新API导入必须项
|
### 4. 执行方法必须项
|
||||||
|
|
||||||
使用新插件系统时,必须导入所需的API模块:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 导入新API模块
|
|
||||||
from src.plugin_system.apis import generator_api, send_api, emoji_api
|
|
||||||
|
|
||||||
# 如果需要使用其他API
|
|
||||||
from src.plugin_system.apis import llm_api, database_api, message_api
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 动作记录必须项
|
|
||||||
|
|
||||||
每个 Action 在执行完成后,**必须**使用 `store_action_info` 记录动作信息:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
# ... 执行动作的代码 ...
|
"""
|
||||||
|
执行Action的主要逻辑
|
||||||
|
|
||||||
if success:
|
Returns:
|
||||||
# 存储动作信息 - 使用新API格式
|
Tuple[bool, str]: (是否成功, 执行结果描述)
|
||||||
await self.store_action_info(
|
"""
|
||||||
action_build_into_prompt=True, # 让麦麦知道这个动作
|
# 执行动作的代码
|
||||||
action_prompt_display=f"执行了xxx动作,参数:{param}", # 动作描述
|
success = True
|
||||||
action_done=True, # 动作是否完成
|
message = "动作执行成功"
|
||||||
)
|
|
||||||
return True, "动作执行成功"
|
|
||||||
```
|
|
||||||
|
|
||||||
> ⚠️ **重要提示**:新API格式中不再需要手动传递 `thinking_id` 等参数,BaseAction会自动处理。
|
return success, message
|
||||||
|
|
||||||
## 🚀 新API使用指南
|
|
||||||
|
|
||||||
### 📨 消息发送API
|
|
||||||
|
|
||||||
新的消息发送API更加简洁,自动处理群聊/私聊逻辑:
|
|
||||||
|
|
||||||
```python
|
|
||||||
class MessageAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 发送文本消息 - 自动判断群聊/私聊
|
|
||||||
await self.send_text("Hello World!")
|
|
||||||
|
|
||||||
# 发送表情包
|
|
||||||
emoji_base64 = await emoji_api.get_by_description("开心")
|
|
||||||
if emoji_base64:
|
|
||||||
await self.send_emoji(emoji_base64)
|
|
||||||
|
|
||||||
# 发送图片
|
|
||||||
await self.send_image(image_base64)
|
|
||||||
|
|
||||||
# 发送自定义类型消息
|
|
||||||
await self.send_custom("video", video_data, typing=True)
|
|
||||||
|
|
||||||
return True, "消息发送完成"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🤖 智能生成API (replyer_1)
|
|
||||||
|
|
||||||
使用replyer_1生成个性化内容:
|
|
||||||
|
|
||||||
```python
|
|
||||||
class SmartReplyAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 构建生成参数
|
|
||||||
reply_data = {
|
|
||||||
"text": "请生成一个友好的回复",
|
|
||||||
"style": "casual",
|
|
||||||
"topic": "日常聊天",
|
|
||||||
"replyer_name": "replyer_1" # 指定使用replyer_1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 使用generator_api生成回复
|
|
||||||
success, reply_set = await generator_api.generate_reply(
|
|
||||||
chat_stream=self.chat_stream,
|
|
||||||
action_data=reply_data,
|
|
||||||
platform=self.platform,
|
|
||||||
chat_id=self.chat_id,
|
|
||||||
is_group=self.is_group
|
|
||||||
)
|
|
||||||
|
|
||||||
if success and reply_set:
|
|
||||||
# 提取并发送文本回复
|
|
||||||
for reply_type, reply_content in reply_set:
|
|
||||||
if reply_type == "text":
|
|
||||||
await self.send_text(reply_content)
|
|
||||||
elif reply_type == "emoji":
|
|
||||||
await self.send_emoji(reply_content)
|
|
||||||
|
|
||||||
# 记录动作
|
|
||||||
await self.store_action_info(
|
|
||||||
action_build_into_prompt=True,
|
|
||||||
action_prompt_display=f"使用replyer_1生成了智能回复",
|
|
||||||
action_done=True
|
|
||||||
)
|
|
||||||
|
|
||||||
return True, "智能回复生成成功"
|
|
||||||
else:
|
|
||||||
return False, "回复生成失败"
|
|
||||||
```
|
|
||||||
|
|
||||||
### ⚙️ 配置访问API
|
|
||||||
|
|
||||||
使用便捷的配置访问方法:
|
|
||||||
|
|
||||||
```python
|
|
||||||
class ConfigurableAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 获取插件配置 - 支持嵌套键访问
|
|
||||||
enable_feature = self.get_config("features.enable_smart_mode", False)
|
|
||||||
max_length = self.get_config("limits.max_text_length", 200)
|
|
||||||
style = self.get_config("behavior.response_style", "friendly")
|
|
||||||
|
|
||||||
if enable_feature:
|
|
||||||
# 启用高级功能
|
|
||||||
pass
|
|
||||||
|
|
||||||
return True, "配置获取成功"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 📊 数据库API
|
|
||||||
|
|
||||||
使用新的数据库API存储和查询数据:
|
|
||||||
|
|
||||||
```python
|
|
||||||
class DataAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 使用database_api
|
|
||||||
from src.plugin_system.apis import database_api
|
|
||||||
|
|
||||||
# 存储数据
|
|
||||||
await database_api.store_action_info(
|
|
||||||
chat_stream=self.chat_stream,
|
|
||||||
action_name=self.action_name,
|
|
||||||
action_data=self.action_data,
|
|
||||||
# ... 其他参数
|
|
||||||
)
|
|
||||||
|
|
||||||
return True, "数据存储完成"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔧 激活类型详解
|
## 🔧 激活类型详解
|
||||||
@@ -286,28 +161,8 @@ class GreetingAction(BaseAction):
|
|||||||
keyword_case_sensitive = False # 不区分大小写
|
keyword_case_sensitive = False # 不区分大小写
|
||||||
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
# 可选:使用replyer_1生成个性化问候
|
# 执行问候逻辑
|
||||||
if self.get_config("greeting.use_smart_reply", False):
|
return True, "发送了问候"
|
||||||
greeting_data = {
|
|
||||||
"text": "生成一个友好的问候语",
|
|
||||||
"replyer_name": "replyer_1"
|
|
||||||
}
|
|
||||||
|
|
||||||
success, reply_set = await generator_api.generate_reply(
|
|
||||||
chat_stream=self.chat_stream,
|
|
||||||
action_data=greeting_data
|
|
||||||
)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
for reply_type, content in reply_set:
|
|
||||||
if reply_type == "text":
|
|
||||||
await self.send_text(content)
|
|
||||||
break
|
|
||||||
return True, "发送智能问候"
|
|
||||||
|
|
||||||
# 传统问候方式
|
|
||||||
await self.send_text("你好!很高兴见到你!")
|
|
||||||
return True, "发送问候"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### LLM_JUDGE激活
|
### LLM_JUDGE激活
|
||||||
@@ -330,26 +185,8 @@ class HelpAction(BaseAction):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
# 使用replyer_1生成帮助内容
|
# 执行帮助逻辑
|
||||||
help_data = {
|
|
||||||
"text": "用户需要帮助,请提供适当的帮助信息",
|
|
||||||
"help_type": self.action_data.get("help_type", "general"),
|
|
||||||
"replyer_name": "replyer_1"
|
|
||||||
}
|
|
||||||
|
|
||||||
success, reply_set = await generator_api.generate_reply(
|
|
||||||
chat_stream=self.chat_stream,
|
|
||||||
action_data=help_data
|
|
||||||
)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
for reply_type, content in reply_set:
|
|
||||||
if reply_type == "text":
|
|
||||||
await self.send_text(content)
|
|
||||||
return True, "提供了帮助"
|
return True, "提供了帮助"
|
||||||
else:
|
|
||||||
await self.send_text("我来帮助你!有什么问题吗?")
|
|
||||||
return True, "提供了默认帮助"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### RANDOM激活
|
### RANDOM激活
|
||||||
@@ -365,11 +202,181 @@ class SurpriseAction(BaseAction):
|
|||||||
random_activation_probability = 0.1 # 10%概率激活
|
random_activation_probability = 0.1 # 10%概率激活
|
||||||
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
import random
|
# 执行惊喜动作
|
||||||
|
return True, "发送了惊喜内容"
|
||||||
surprises = ["🎉", "✨", "🌟", "💝", "🎈"]
|
|
||||||
selected = random.choice(surprises)
|
|
||||||
|
|
||||||
await self.send_emoji(selected)
|
|
||||||
return True, f"发送了惊喜表情: {selected}"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### ALWAYS激活
|
||||||
|
|
||||||
|
永远激活,常用于核心功能:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class CoreAction(BaseAction):
|
||||||
|
focus_activation_type = ActionActivationType.ALWAYS
|
||||||
|
normal_activation_type = ActionActivationType.ALWAYS
|
||||||
|
|
||||||
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
|
# 执行核心功能
|
||||||
|
return True, "执行了核心功能"
|
||||||
|
```
|
||||||
|
|
||||||
|
### NEVER激活
|
||||||
|
|
||||||
|
从不激活,用于临时禁用:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class DisabledAction(BaseAction):
|
||||||
|
focus_activation_type = ActionActivationType.NEVER
|
||||||
|
normal_activation_type = ActionActivationType.NEVER
|
||||||
|
|
||||||
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
|
# 这个方法不会被调用
|
||||||
|
return False, "已禁用"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 BaseAction内置属性和方法
|
||||||
|
|
||||||
|
### 内置属性
|
||||||
|
|
||||||
|
```python
|
||||||
|
class MyAction(BaseAction):
|
||||||
|
def __init__(self):
|
||||||
|
# 消息相关属性
|
||||||
|
self.message # 当前消息对象
|
||||||
|
self.chat_stream # 聊天流对象
|
||||||
|
self.user_id # 用户ID
|
||||||
|
self.user_nickname # 用户昵称
|
||||||
|
self.platform # 平台类型 (qq, telegram等)
|
||||||
|
self.chat_id # 聊天ID
|
||||||
|
self.is_group # 是否群聊
|
||||||
|
|
||||||
|
# Action相关属性
|
||||||
|
self.action_data # Action执行时的数据
|
||||||
|
self.thinking_id # 思考ID
|
||||||
|
self.matched_groups # 匹配到的组(如果有正则匹配)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 内置方法
|
||||||
|
|
||||||
|
```python
|
||||||
|
class MyAction(BaseAction):
|
||||||
|
# 配置相关
|
||||||
|
def get_config(self, key: str, default=None):
|
||||||
|
"""获取配置值"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 消息发送相关
|
||||||
|
async def send_text(self, text: str):
|
||||||
|
"""发送文本消息"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def send_emoji(self, emoji_base64: str):
|
||||||
|
"""发送表情包"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def send_image(self, image_base64: str):
|
||||||
|
"""发送图片"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 动作记录相关
|
||||||
|
async def store_action_info(self, **kwargs):
|
||||||
|
"""记录动作信息"""
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 完整Action示例
|
||||||
|
|
||||||
|
```python
|
||||||
|
from src.plugin_system import BaseAction, ActionActivationType, ChatMode
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
class ExampleAction(BaseAction):
|
||||||
|
"""示例Action - 展示完整的Action结构"""
|
||||||
|
|
||||||
|
# === 激活控制 ===
|
||||||
|
focus_activation_type = ActionActivationType.LLM_JUDGE
|
||||||
|
normal_activation_type = ActionActivationType.KEYWORD
|
||||||
|
mode_enable = ChatMode.ALL
|
||||||
|
parallel_action = False
|
||||||
|
|
||||||
|
# 关键词激活配置
|
||||||
|
activation_keywords = ["示例", "测试", "example"]
|
||||||
|
keyword_case_sensitive = False
|
||||||
|
|
||||||
|
# LLM判断提示词
|
||||||
|
llm_judge_prompt = "当用户需要示例或测试功能时激活"
|
||||||
|
|
||||||
|
# 随机激活概率(如果使用RANDOM类型)
|
||||||
|
random_activation_probability = 0.2
|
||||||
|
|
||||||
|
# === 基本信息 ===
|
||||||
|
action_name = "example_action"
|
||||||
|
action_description = "这是一个示例Action,用于演示Action的完整结构"
|
||||||
|
|
||||||
|
# === 功能定义 ===
|
||||||
|
action_parameters = {
|
||||||
|
"content": "要处理的内容",
|
||||||
|
"type": "处理类型",
|
||||||
|
"options": "可选配置"
|
||||||
|
}
|
||||||
|
|
||||||
|
action_require = [
|
||||||
|
"用户需要示例功能时使用",
|
||||||
|
"适合用于测试和演示",
|
||||||
|
"不要在正式对话中频繁使用"
|
||||||
|
]
|
||||||
|
|
||||||
|
associated_types = ["text", "emoji"]
|
||||||
|
|
||||||
|
async def execute(self) -> Tuple[bool, str]:
|
||||||
|
"""执行示例Action"""
|
||||||
|
try:
|
||||||
|
# 获取Action参数
|
||||||
|
content = self.action_data.get("content", "默认内容")
|
||||||
|
action_type = self.action_data.get("type", "default")
|
||||||
|
|
||||||
|
# 获取配置
|
||||||
|
enable_feature = self.get_config("example.enable_advanced", False)
|
||||||
|
max_length = self.get_config("example.max_length", 100)
|
||||||
|
|
||||||
|
# 执行具体逻辑
|
||||||
|
if action_type == "greeting":
|
||||||
|
await self.send_text(f"你好!这是示例内容:{content}")
|
||||||
|
elif action_type == "info":
|
||||||
|
await self.send_text(f"信息:{content[:max_length]}")
|
||||||
|
else:
|
||||||
|
await self.send_text("执行了示例Action")
|
||||||
|
|
||||||
|
# 记录动作信息
|
||||||
|
await self.store_action_info(
|
||||||
|
action_build_into_prompt=True,
|
||||||
|
action_prompt_display=f"执行了示例动作:{action_type}",
|
||||||
|
action_done=True
|
||||||
|
)
|
||||||
|
|
||||||
|
return True, f"示例Action执行成功,类型:{action_type}"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"执行失败:{str(e)}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 最佳实践
|
||||||
|
|
||||||
|
### 1. Action设计原则
|
||||||
|
|
||||||
|
- **单一职责**:每个Action只负责一个明确的功能
|
||||||
|
- **智能激活**:合理选择激活类型,避免过度激活
|
||||||
|
- **清晰描述**:提供准确的`action_require`帮助LLM决策
|
||||||
|
- **错误处理**:妥善处理执行过程中的异常情况
|
||||||
|
|
||||||
|
### 2. 性能优化
|
||||||
|
|
||||||
|
- **激活控制**:使用合适的激活类型减少不必要的LLM调用
|
||||||
|
- **并行执行**:谨慎设置`parallel_action`,避免冲突
|
||||||
|
- **资源管理**:及时释放占用的资源
|
||||||
|
|
||||||
|
### 3. 调试技巧
|
||||||
|
|
||||||
|
- **日志记录**:在关键位置添加日志
|
||||||
|
- **参数验证**:检查`action_data`的有效性
|
||||||
|
- **配置测试**:测试不同配置下的行为
|
||||||
|
|||||||
@@ -1,398 +1,311 @@
|
|||||||
# 📡 消息API
|
# 消息API
|
||||||
|
|
||||||
## 📖 概述
|
> 消息API提供了强大的消息查询、计数和格式化功能,让你轻松处理聊天消息数据。
|
||||||
|
|
||||||
消息API提供了发送各种类型消息的接口,支持文本、表情、图片等多种消息类型。新版API格式更加简洁直观,自动处理群聊/私聊判断。
|
## 导入方式
|
||||||
|
|
||||||
## 🔄 基础消息发送
|
|
||||||
|
|
||||||
### 发送文本消息
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# 新API格式 - 自动判断群聊/私聊
|
from src.plugin_system.apis import message_api
|
||||||
await self.send_text("这是一条文本消息")
|
|
||||||
|
|
||||||
# 发送多行文本
|
|
||||||
message = """
|
|
||||||
这是第一行
|
|
||||||
这是第二行
|
|
||||||
这是第三行
|
|
||||||
"""
|
|
||||||
await self.send_text(message.strip())
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 发送表情消息
|
## 功能概述
|
||||||
|
|
||||||
|
消息API主要提供三大类功能:
|
||||||
|
- **消息查询** - 按时间、聊天、用户等条件查询消息
|
||||||
|
- **消息计数** - 统计新消息数量
|
||||||
|
- **消息格式化** - 将消息转换为可读格式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 消息查询API
|
||||||
|
|
||||||
|
### 按时间查询消息
|
||||||
|
|
||||||
|
#### `get_messages_by_time(start_time, end_time, limit=0, limit_mode="latest")`
|
||||||
|
|
||||||
|
获取指定时间范围内的消息
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `start_time` (float): 开始时间戳
|
||||||
|
- `end_time` (float): 结束时间戳
|
||||||
|
- `limit` (int): 限制返回消息数量,0为不限制
|
||||||
|
- `limit_mode` (str): 限制模式,`"earliest"`获取最早记录,`"latest"`获取最新记录
|
||||||
|
|
||||||
|
**返回:** `List[Dict[str, Any]]` - 消息列表
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
# 新API格式 - 发送表情
|
import time
|
||||||
await self.send_emoji("😊")
|
|
||||||
await self.send_emoji("🎉")
|
# 获取最近24小时的消息
|
||||||
await self.send_emoji("👋")
|
now = time.time()
|
||||||
|
yesterday = now - 24 * 3600
|
||||||
|
messages = message_api.get_messages_by_time(yesterday, now, limit=50)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 发送特定类型消息
|
### 按聊天查询消息
|
||||||
|
|
||||||
|
#### `get_messages_by_time_in_chat(chat_id, start_time, end_time, limit=0, limit_mode="latest")`
|
||||||
|
|
||||||
|
获取指定聊天中指定时间范围内的消息
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `chat_id` (str): 聊天ID
|
||||||
|
- 其他参数同上
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
# 发送图片
|
# 获取某个群聊最近的100条消息
|
||||||
await self.send_type("image", "https://example.com/image.jpg")
|
messages = message_api.get_messages_by_time_in_chat(
|
||||||
|
chat_id="123456789",
|
||||||
# 发送音频
|
start_time=yesterday,
|
||||||
await self.send_type("audio", "audio_file_path")
|
end_time=now,
|
||||||
|
limit=100
|
||||||
# 发送视频
|
|
||||||
await self.send_type("video", "video_file_path")
|
|
||||||
|
|
||||||
# 发送文件
|
|
||||||
await self.send_type("file", "file_path")
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎯 跨目标消息发送
|
|
||||||
|
|
||||||
### 使用send_api模块发送消息
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 导入send_api
|
|
||||||
from src.plugin_system.apis import send_api
|
|
||||||
|
|
||||||
# 向指定群聊发送文本消息
|
|
||||||
success = await send_api.text_to_group(
|
|
||||||
text="这是发送到群聊的消息",
|
|
||||||
group_id="123456789",
|
|
||||||
platform="qq"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 向指定用户发送私聊消息
|
|
||||||
success = await send_api.text_to_user(
|
|
||||||
text="这是私聊消息",
|
|
||||||
user_id="987654321",
|
|
||||||
platform="qq"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 向指定群聊发送表情
|
|
||||||
success = await send_api.emoji_to_group(
|
|
||||||
emoji="😊",
|
|
||||||
group_id="123456789",
|
|
||||||
platform="qq"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 向指定用户发送表情
|
|
||||||
success = await send_api.emoji_to_user(
|
|
||||||
emoji="🎉",
|
|
||||||
user_id="987654321",
|
|
||||||
platform="qq"
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 通用目标消息发送
|
#### `get_messages_by_time_in_chat_inclusive(chat_id, start_time, end_time, limit=0, limit_mode="latest")`
|
||||||
|
|
||||||
|
获取指定聊天中指定时间范围内的消息(包含边界时间点)
|
||||||
|
|
||||||
|
与 `get_messages_by_time_in_chat` 类似,但包含边界时间戳的消息。
|
||||||
|
|
||||||
|
#### `get_recent_messages(chat_id, hours=24.0, limit=100, limit_mode="latest")`
|
||||||
|
|
||||||
|
获取指定聊天中最近一段时间的消息(便捷方法)
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `chat_id` (str): 聊天ID
|
||||||
|
- `hours` (float): 最近多少小时,默认24小时
|
||||||
|
- `limit` (int): 限制返回消息数量,默认100条
|
||||||
|
- `limit_mode` (str): 限制模式
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
# 向任意目标发送任意类型消息
|
# 获取最近6小时的消息
|
||||||
success = await send_api.message_to_target(
|
recent_messages = message_api.get_recent_messages(
|
||||||
message_type="text", # 消息类型
|
chat_id="123456789",
|
||||||
content="消息内容", # 消息内容
|
hours=6.0,
|
||||||
platform="qq", # 平台
|
limit=50
|
||||||
target_id="123456789", # 目标ID
|
|
||||||
is_group=True, # 是否为群聊
|
|
||||||
display_message="显示消息" # 可选:显示消息
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📨 消息类型支持
|
### 按用户查询消息
|
||||||
|
|
||||||
### 支持的消息类型
|
#### `get_messages_by_time_in_chat_for_users(chat_id, start_time, end_time, person_ids, limit=0, limit_mode="latest")`
|
||||||
|
|
||||||
| 类型 | 说明 | 新API方法 | send_api方法 |
|
获取指定聊天中指定用户在指定时间范围内的消息
|
||||||
|-----|------|----------|-------------|
|
|
||||||
| `text` | 普通文本消息 | `await self.send_text()` | `await send_api.text_to_group()` |
|
|
||||||
| `emoji` | 表情消息 | `await self.send_emoji()` | `await send_api.emoji_to_group()` |
|
|
||||||
| `image` | 图片消息 | `await self.send_type("image", url)` | `await send_api.message_to_target()` |
|
|
||||||
| `audio` | 音频消息 | `await self.send_type("audio", path)` | `await send_api.message_to_target()` |
|
|
||||||
| `video` | 视频消息 | `await self.send_type("video", path)` | `await send_api.message_to_target()` |
|
|
||||||
| `file` | 文件消息 | `await self.send_type("file", path)` | `await send_api.message_to_target()` |
|
|
||||||
|
|
||||||
### 新API格式示例
|
**参数:**
|
||||||
|
- `chat_id` (str): 聊天ID
|
||||||
|
- `start_time` (float): 开始时间戳
|
||||||
|
- `end_time` (float): 结束时间戳
|
||||||
|
- `person_ids` (list): 用户ID列表
|
||||||
|
- `limit` (int): 限制返回消息数量
|
||||||
|
- `limit_mode` (str): 限制模式
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
class ExampleAction(BaseAction):
|
# 获取特定用户的消息
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
user_messages = message_api.get_messages_by_time_in_chat_for_users(
|
||||||
# 文本消息 - 最常用
|
chat_id="123456789",
|
||||||
await self.send_text("普通文本消息")
|
start_time=yesterday,
|
||||||
|
end_time=now,
|
||||||
# 表情消息 - 直接方法
|
person_ids=["user1", "user2"]
|
||||||
await self.send_emoji("🎉")
|
)
|
||||||
|
|
||||||
# 图片消息
|
|
||||||
await self.send_type("image", "/path/to/image.jpg")
|
|
||||||
|
|
||||||
# 音频消息
|
|
||||||
await self.send_type("audio", "/path/to/audio.mp3")
|
|
||||||
|
|
||||||
# 文件消息
|
|
||||||
await self.send_type("file", "/path/to/document.pdf")
|
|
||||||
|
|
||||||
return True, "发送了多种类型的消息"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔍 消息信息获取
|
#### `get_messages_by_time_for_users(start_time, end_time, person_ids, limit=0, limit_mode="latest")`
|
||||||
|
|
||||||
### 获取当前消息信息
|
获取指定用户在所有聊天中指定时间范围内的消息
|
||||||
|
|
||||||
|
### 其他查询方法
|
||||||
|
|
||||||
|
#### `get_random_chat_messages(start_time, end_time, limit=0, limit_mode="latest")`
|
||||||
|
|
||||||
|
随机选择一个聊天,返回该聊天在指定时间范围内的消息
|
||||||
|
|
||||||
|
#### `get_messages_before_time(timestamp, limit=0)`
|
||||||
|
|
||||||
|
获取指定时间戳之前的消息
|
||||||
|
|
||||||
|
#### `get_messages_before_time_in_chat(chat_id, timestamp, limit=0)`
|
||||||
|
|
||||||
|
获取指定聊天中指定时间戳之前的消息
|
||||||
|
|
||||||
|
#### `get_messages_before_time_for_users(timestamp, person_ids, limit=0)`
|
||||||
|
|
||||||
|
获取指定用户在指定时间戳之前的消息
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 消息计数API
|
||||||
|
|
||||||
|
### `count_new_messages(chat_id, start_time=0.0, end_time=None)`
|
||||||
|
|
||||||
|
计算指定聊天中从开始时间到结束时间的新消息数量
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `chat_id` (str): 聊天ID
|
||||||
|
- `start_time` (float): 开始时间戳
|
||||||
|
- `end_time` (float): 结束时间戳,如果为None则使用当前时间
|
||||||
|
|
||||||
|
**返回:** `int` - 新消息数量
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
# 新API格式 - 直接属性访问
|
# 计算最近1小时的新消息数
|
||||||
class ExampleCommand(BaseCommand):
|
import time
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
now = time.time()
|
||||||
# 用户信息
|
hour_ago = now - 3600
|
||||||
user_id = self.user_id
|
new_count = message_api.count_new_messages("123456789", hour_ago, now)
|
||||||
user_nickname = self.user_nickname
|
print(f"最近1小时有{new_count}条新消息")
|
||||||
|
|
||||||
# 聊天信息
|
|
||||||
is_group_chat = self.is_group
|
|
||||||
chat_id = self.chat_id
|
|
||||||
platform = self.platform
|
|
||||||
|
|
||||||
# 消息内容
|
|
||||||
message_text = self.message.processed_plain_text
|
|
||||||
|
|
||||||
# 构建信息显示
|
|
||||||
info = f"""
|
|
||||||
👤 用户: {user_nickname}({user_id})
|
|
||||||
💬 类型: {'群聊' if is_group_chat else '私聊'}
|
|
||||||
📱 平台: {platform}
|
|
||||||
📝 内容: {message_text}
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
await self.send_text(info)
|
|
||||||
return True, "显示了消息信息"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 获取群聊信息(如果适用)
|
### `count_new_messages_for_users(chat_id, start_time, end_time, person_ids)`
|
||||||
|
|
||||||
|
计算指定聊天中指定用户从开始时间到结束时间的新消息数量
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 消息格式化API
|
||||||
|
|
||||||
|
### `build_readable_messages_to_str(messages, **options)`
|
||||||
|
|
||||||
|
将消息列表构建成可读的字符串
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `messages` (List[Dict[str, Any]]): 消息列表
|
||||||
|
- `replace_bot_name` (bool): 是否将机器人的名称替换为"你",默认True
|
||||||
|
- `merge_messages` (bool): 是否合并连续消息,默认False
|
||||||
|
- `timestamp_mode` (str): 时间戳显示模式,`"relative"`或`"absolute"`,默认`"relative"`
|
||||||
|
- `read_mark` (float): 已读标记时间戳,用于分割已读和未读消息,默认0.0
|
||||||
|
- `truncate` (bool): 是否截断长消息,默认False
|
||||||
|
- `show_actions` (bool): 是否显示动作记录,默认False
|
||||||
|
|
||||||
|
**返回:** `str` - 格式化后的可读字符串
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
# 在Action或Command中检查群聊信息
|
# 获取消息并格式化为可读文本
|
||||||
if self.is_group:
|
messages = message_api.get_recent_messages("123456789", hours=2)
|
||||||
group_info = self.message.message_info.group_info
|
readable_text = message_api.build_readable_messages_to_str(
|
||||||
if group_info:
|
messages,
|
||||||
group_id = group_info.group_id
|
replace_bot_name=True,
|
||||||
group_name = getattr(group_info, 'group_name', '未知群聊')
|
merge_messages=True,
|
||||||
|
timestamp_mode="relative"
|
||||||
await self.send_text(f"当前群聊: {group_name}({group_id})")
|
)
|
||||||
else:
|
print(readable_text)
|
||||||
await self.send_text("当前是私聊对话")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🌐 平台支持
|
### `build_readable_messages_with_details(messages, **options)` 异步
|
||||||
|
|
||||||
### 支持的平台
|
将消息列表构建成可读的字符串,并返回详细信息
|
||||||
|
|
||||||
| 平台 | 标识 | 说明 |
|
**参数:** 与 `build_readable_messages_to_str` 类似,但不包含 `read_mark` 和 `show_actions`
|
||||||
|-----|------|------|
|
|
||||||
| QQ | `qq` | QQ聊天平台 |
|
|
||||||
| 微信 | `wechat` | 微信聊天平台 |
|
|
||||||
| Discord | `discord` | Discord聊天平台 |
|
|
||||||
|
|
||||||
### 平台适配示例
|
**返回:** `Tuple[str, List[Tuple[float, str, str]]]` - 格式化字符串和详细信息元组列表(时间戳, 昵称, 内容)
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
class PlatformAdaptiveAction(BaseAction):
|
# 异步获取详细格式化信息
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
readable_text, details = await message_api.build_readable_messages_with_details(
|
||||||
# 获取当前平台
|
messages,
|
||||||
current_platform = self.platform
|
timestamp_mode="absolute"
|
||||||
|
)
|
||||||
|
|
||||||
# 根据平台调整消息格式
|
for timestamp, nickname, content in details:
|
||||||
if current_platform == "qq":
|
print(f"{timestamp}: {nickname} 说: {content}")
|
||||||
await self.send_text("[QQ] 这是QQ平台的消息")
|
|
||||||
await self.send_emoji("🐧") # QQ企鹅表情
|
|
||||||
elif current_platform == "wechat":
|
|
||||||
await self.send_text("【微信】这是微信平台的消息")
|
|
||||||
await self.send_emoji("💬") # 微信气泡表情
|
|
||||||
elif current_platform == "discord":
|
|
||||||
await self.send_text("**Discord** 这是Discord平台的消息")
|
|
||||||
await self.send_emoji("🎮") # Discord游戏表情
|
|
||||||
else:
|
|
||||||
await self.send_text(f"未知平台: {current_platform}")
|
|
||||||
|
|
||||||
return True, f"发送了{current_platform}平台适配消息"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🎨 消息格式化和高级功能
|
### `get_person_ids_from_messages(messages)` 异步
|
||||||
|
|
||||||
### 长消息分割
|
从消息列表中提取不重复的用户ID列表
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `messages` (List[Dict[str, Any]]): 消息列表
|
||||||
|
|
||||||
|
**返回:** `List[str]` - 用户ID列表
|
||||||
|
|
||||||
|
**示例:**
|
||||||
```python
|
```python
|
||||||
# 自动处理长消息分割
|
# 获取参与对话的所有用户ID
|
||||||
long_message = "这是一条很长的消息..." * 100
|
messages = message_api.get_recent_messages("123456789")
|
||||||
|
person_ids = await message_api.get_person_ids_from_messages(messages)
|
||||||
# 新API会自动处理长消息分割
|
print(f"参与对话的用户: {person_ids}")
|
||||||
await self.send_text(long_message)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 消息模板和格式化
|
---
|
||||||
|
|
||||||
|
## 完整使用示例
|
||||||
|
|
||||||
|
### 场景1:统计活跃度
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class TemplateMessageAction(BaseAction):
|
import time
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
from src.plugin_system.apis import message_api
|
||||||
# 使用配置中的消息模板
|
|
||||||
template = self.get_config("messages.greeting_template", "你好 {username}!")
|
|
||||||
|
|
||||||
# 格式化消息
|
async def analyze_chat_activity(chat_id: str):
|
||||||
formatted_message = template.format(
|
"""分析聊天活跃度"""
|
||||||
username=self.user_nickname,
|
now = time.time()
|
||||||
time=datetime.now().strftime("%H:%M"),
|
day_ago = now - 24 * 3600
|
||||||
platform=self.platform
|
|
||||||
|
# 获取最近24小时的消息
|
||||||
|
messages = message_api.get_recent_messages(chat_id, hours=24)
|
||||||
|
|
||||||
|
# 统计消息数量
|
||||||
|
total_count = len(messages)
|
||||||
|
|
||||||
|
# 获取参与用户
|
||||||
|
person_ids = await message_api.get_person_ids_from_messages(messages)
|
||||||
|
|
||||||
|
# 格式化消息内容
|
||||||
|
readable_text = message_api.build_readable_messages_to_str(
|
||||||
|
messages[-10:], # 最后10条消息
|
||||||
|
merge_messages=True,
|
||||||
|
timestamp_mode="relative"
|
||||||
)
|
)
|
||||||
|
|
||||||
await self.send_text(formatted_message)
|
return {
|
||||||
|
"total_messages": total_count,
|
||||||
# 根据配置决定是否发送表情
|
"active_users": len(person_ids),
|
||||||
if self.get_config("messages.include_emoji", True):
|
"recent_chat": readable_text
|
||||||
await self.send_emoji("😊")
|
}
|
||||||
|
|
||||||
return True, "发送了模板化消息"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 条件消息发送
|
### 场景2:查看特定用户的历史消息
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class ConditionalMessageAction(BaseAction):
|
def get_user_history(chat_id: str, user_id: str, days: int = 7):
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
"""获取用户最近N天的消息历史"""
|
||||||
# 根据用户类型发送不同消息
|
now = time.time()
|
||||||
if self.is_group:
|
start_time = now - days * 24 * 3600
|
||||||
await self.send_text(f"群聊消息 - 当前群成员: @{self.user_nickname}")
|
|
||||||
else:
|
|
||||||
await self.send_text(f"私聊消息 - 你好 {self.user_nickname}!")
|
|
||||||
|
|
||||||
# 根据时间发送不同表情
|
# 获取特定用户的消息
|
||||||
from datetime import datetime
|
user_messages = message_api.get_messages_by_time_in_chat_for_users(
|
||||||
hour = datetime.now().hour
|
chat_id=chat_id,
|
||||||
|
start_time=start_time,
|
||||||
|
end_time=now,
|
||||||
|
person_ids=[user_id],
|
||||||
|
limit=100
|
||||||
|
)
|
||||||
|
|
||||||
if 6 <= hour < 12:
|
# 格式化为可读文本
|
||||||
await self.send_emoji("🌅") # 早上
|
readable_history = message_api.build_readable_messages_to_str(
|
||||||
elif 12 <= hour < 18:
|
user_messages,
|
||||||
await self.send_emoji("☀️") # 下午
|
replace_bot_name=False,
|
||||||
else:
|
timestamp_mode="absolute"
|
||||||
await self.send_emoji("🌙") # 晚上
|
)
|
||||||
|
|
||||||
return True, "发送了条件化消息"
|
return readable_history
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🛠️ 高级消息发送功能
|
---
|
||||||
|
|
||||||
### 批量消息发送
|
## 注意事项
|
||||||
|
|
||||||
```python
|
1. **时间戳格式**:所有时间参数都使用Unix时间戳(float类型)
|
||||||
class BatchMessageAction(BaseAction):
|
2. **异步函数**:`build_readable_messages_with_details` 和 `get_person_ids_from_messages` 是异步函数,需要使用 `await`
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
3. **性能考虑**:查询大量消息时建议设置合理的 `limit` 参数
|
||||||
messages = [
|
4. **消息格式**:返回的消息是字典格式,包含时间戳、发送者、内容等信息
|
||||||
("text", "第一条消息"),
|
5. **用户ID**:`person_ids` 参数接受字符串列表,用于筛选特定用户的消息
|
||||||
("emoji", "🎉"),
|
|
||||||
("text", "第二条消息"),
|
|
||||||
("emoji", "✨")
|
|
||||||
]
|
|
||||||
|
|
||||||
for msg_type, content in messages:
|
|
||||||
if msg_type == "text":
|
|
||||||
await self.send_text(content)
|
|
||||||
elif msg_type == "emoji":
|
|
||||||
await self.send_emoji(content)
|
|
||||||
|
|
||||||
# 可选:添加延迟避免消息发送过快
|
|
||||||
import asyncio
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
|
|
||||||
return True, "发送了批量消息"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 错误处理和重试
|
|
||||||
|
|
||||||
```python
|
|
||||||
class ReliableMessageAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
max_retries = 3
|
|
||||||
retry_count = 0
|
|
||||||
|
|
||||||
while retry_count < max_retries:
|
|
||||||
try:
|
|
||||||
await self.send_text("重要消息")
|
|
||||||
return True, "消息发送成功"
|
|
||||||
except Exception as e:
|
|
||||||
retry_count += 1
|
|
||||||
logger.warning(f"消息发送失败 (尝试 {retry_count}/{max_retries}): {e}")
|
|
||||||
|
|
||||||
if retry_count < max_retries:
|
|
||||||
import asyncio
|
|
||||||
await asyncio.sleep(1) # 等待1秒后重试
|
|
||||||
|
|
||||||
return False, "消息发送失败,已达到最大重试次数"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 最佳实践
|
|
||||||
|
|
||||||
### 1. 消息发送最佳实践
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ✅ 好的做法
|
|
||||||
class GoodMessageAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 1. 检查配置
|
|
||||||
if not self.get_config("features.enable_messages", True):
|
|
||||||
return True, "消息功能已禁用"
|
|
||||||
|
|
||||||
# 2. 简洁的消息发送
|
|
||||||
await self.send_text("简洁明了的消息")
|
|
||||||
|
|
||||||
# 3. 适当的表情使用
|
|
||||||
if self.get_config("features.enable_emoji", True):
|
|
||||||
await self.send_emoji("😊")
|
|
||||||
|
|
||||||
return True, "消息发送完成"
|
|
||||||
|
|
||||||
# ❌ 避免的做法
|
|
||||||
class BadMessageAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 避免:过长的消息
|
|
||||||
await self.send_text("这是一条非常非常长的消息" * 50)
|
|
||||||
|
|
||||||
# 避免:过多的表情
|
|
||||||
for emoji in ["😊", "🎉", "✨", "🌟", "💫"]:
|
|
||||||
await self.send_emoji(emoji)
|
|
||||||
|
|
||||||
return True, "发送了糟糕的消息"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 错误处理
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ✅ 推荐的错误处理
|
|
||||||
class SafeMessageAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
try:
|
|
||||||
message = self.get_config("messages.default", "默认消息")
|
|
||||||
await self.send_text(message)
|
|
||||||
return True, "消息发送成功"
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"消息发送失败: {e}")
|
|
||||||
# 可选:发送备用消息
|
|
||||||
await self.send_text("消息发送遇到问题,请稍后再试")
|
|
||||||
return False, f"发送失败: {str(e)}"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 性能优化
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ✅ 性能友好的消息发送
|
|
||||||
class OptimizedMessageAction(BaseAction):
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
|
||||||
# 合并多个短消息为一条长消息
|
|
||||||
parts = [
|
|
||||||
"第一部分信息",
|
|
||||||
"第二部分信息",
|
|
||||||
"第三部分信息"
|
|
||||||
]
|
|
||||||
|
|
||||||
combined_message = "\n".join(parts)
|
|
||||||
await self.send_text(combined_message)
|
|
||||||
|
|
||||||
return True, "发送了优化的消息"
|
|
||||||
```
|
|
||||||
|
|
||||||
通过新的API格式,消息发送变得更加简洁高效!
|
|
||||||
@@ -15,7 +15,7 @@ Command是直接响应用户明确指令的组件,与Action不同,Command是
|
|||||||
## 🆚 Action vs Command 核心区别
|
## 🆚 Action vs Command 核心区别
|
||||||
|
|
||||||
| 特征 | Action | Command |
|
| 特征 | Action | Command |
|
||||||
|-----|-------|---------|
|
| ------------------ | --------------------- | ---------------- |
|
||||||
| **触发方式** | 麦麦主动决策使用 | 用户主动触发 |
|
| **触发方式** | 麦麦主动决策使用 | 用户主动触发 |
|
||||||
| **决策机制** | 两层决策(激活+使用) | 直接匹配执行 |
|
| **决策机制** | 两层决策(激活+使用) | 直接匹配执行 |
|
||||||
| **随机性** | 有随机性和智能性 | 确定性执行 |
|
| **随机性** | 有随机性和智能性 | 确定性执行 |
|
||||||
@@ -51,7 +51,7 @@ class MyCommand(BaseCommand):
|
|||||||
### 属性说明
|
### 属性说明
|
||||||
|
|
||||||
| 属性 | 类型 | 说明 |
|
| 属性 | 类型 | 说明 |
|
||||||
|-----|------|------|
|
| --------------------- | --------- | -------------------- |
|
||||||
| `command_pattern` | str | 正则表达式匹配模式 |
|
| `command_pattern` | str | 正则表达式匹配模式 |
|
||||||
| `command_help` | str | 命令帮助说明 |
|
| `command_help` | str | 命令帮助说明 |
|
||||||
| `command_examples` | List[str] | 使用示例列表 |
|
| `command_examples` | List[str] | 使用示例列表 |
|
||||||
@@ -148,7 +148,7 @@ class LogCommand(BaseCommand):
|
|||||||
### 拦截控制的用途
|
### 拦截控制的用途
|
||||||
|
|
||||||
| 场景 | intercept_message | 说明 |
|
| 场景 | intercept_message | 说明 |
|
||||||
|-----|------------------|------|
|
| -------- | ----------------- | -------------------------- |
|
||||||
| 系统命令 | True | 防止命令被当作普通消息处理 |
|
| 系统命令 | True | 防止命令被当作普通消息处理 |
|
||||||
| 查询命令 | True | 直接返回结果,无需后续处理 |
|
| 查询命令 | True | 直接返回结果,无需后续处理 |
|
||||||
| 日志命令 | False | 记录但允许消息继续流转 |
|
| 日志命令 | False | 记录但允许消息继续流转 |
|
||||||
@@ -386,55 +386,6 @@ class CustomPrefixCommand(BaseCommand):
|
|||||||
return True, f"投掷了{count}面骰子,结果{result}"
|
return True, f"投掷了{count}面骰子,结果{result}"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔧 新API格式使用指南
|
|
||||||
|
|
||||||
### 消息发送
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 新API格式 ✅
|
|
||||||
await self.send_text("消息内容")
|
|
||||||
await self.send_emoji("😊")
|
|
||||||
|
|
||||||
# 旧API格式 ❌
|
|
||||||
await self.api.send_text_to_group("消息内容", group_id, "qq")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 配置访问
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 新API格式 ✅
|
|
||||||
config_value = self.get_config("section.key", "default_value")
|
|
||||||
|
|
||||||
# 旧API格式 ❌
|
|
||||||
config_value = self.api.get_config("section.key", "default_value")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 用户信息获取
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 新API格式 ✅
|
|
||||||
user_id = self.user_id
|
|
||||||
user_nickname = self.user_nickname
|
|
||||||
is_group_chat = self.is_group
|
|
||||||
|
|
||||||
# 旧API格式 ❌
|
|
||||||
user_id = self.message.message_info.user_info.user_id
|
|
||||||
```
|
|
||||||
|
|
||||||
### 动作记录
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 新API格式 ✅ (在Action中)
|
|
||||||
await self.store_action_info(
|
|
||||||
action_build_into_prompt=True,
|
|
||||||
action_prompt_display="执行了某操作",
|
|
||||||
action_done=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# 旧API格式 ❌
|
|
||||||
await self.api.store_action_info(...)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 性能优化建议
|
## 📊 性能优化建议
|
||||||
|
|
||||||
### 1. 正则表达式优化
|
### 1. 正则表达式优化
|
||||||
@@ -479,8 +430,6 @@ async def execute(self) -> Tuple[bool, Optional[str]]:
|
|||||||
return False, f"执行失败: {e}"
|
return False, f"执行失败: {e}"
|
||||||
```
|
```
|
||||||
|
|
||||||
通过新的API格式,Command开发变得更加简洁和直观!
|
|
||||||
|
|
||||||
## 🎯 最佳实践
|
## 🎯 最佳实践
|
||||||
|
|
||||||
### 1. 命令设计原则
|
### 1. 命令设计原则
|
||||||
@@ -535,8 +484,8 @@ async def execute(self) -> Tuple[bool, Optional[str]]:
|
|||||||
```python
|
```python
|
||||||
async def execute(self) -> Tuple[bool, Optional[str]]:
|
async def execute(self) -> Tuple[bool, Optional[str]]:
|
||||||
# 从配置读取设置
|
# 从配置读取设置
|
||||||
max_items = self.api.get_config("command.max_items", 10)
|
max_items = self.get_config("command.max_items", 10)
|
||||||
timeout = self.api.get_config("command.timeout", 30)
|
timeout = self.get_config("command.timeout", 30)
|
||||||
|
|
||||||
# 使用配置进行处理
|
# 使用配置进行处理
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -8,10 +8,28 @@
|
|||||||
|
|
||||||
## 📖 目录
|
## 📖 目录
|
||||||
|
|
||||||
1. [配置定义:Schema驱动的配置系统](#配置定义schema驱动的配置系统)
|
1. [配置架构变更说明](#配置架构变更说明)
|
||||||
2. [配置访问:在Action和Command中使用配置](#配置访问在action和command中使用配置)
|
2. [配置定义:Schema驱动的配置系统](#配置定义schema驱动的配置系统)
|
||||||
3. [完整示例:从定义到使用](#完整示例从定义到使用)
|
3. [配置访问:在Action和Command中使用配置](#配置访问在action和command中使用配置)
|
||||||
4. [最佳实践与注意事项](#最佳实践与注意事项)
|
4. [完整示例:从定义到使用](#完整示例从定义到使用)
|
||||||
|
5. [最佳实践与注意事项](#最佳实践与注意事项)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 配置架构变更说明
|
||||||
|
|
||||||
|
- **`_manifest.json`** - 负责插件的**元数据信息**(静态)
|
||||||
|
- 插件名称、版本、描述
|
||||||
|
- 作者信息、许可证
|
||||||
|
- 仓库链接、关键词、分类
|
||||||
|
- 组件列表、兼容性信息
|
||||||
|
|
||||||
|
- **`config.toml`** - 负责插件的**运行时配置**(动态)
|
||||||
|
- `enabled` - 是否启用插件
|
||||||
|
- 功能参数配置
|
||||||
|
- 组件启用开关
|
||||||
|
- 用户可调整的行为参数
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -101,7 +119,7 @@ class MutePlugin(BasePlugin):
|
|||||||
|
|
||||||
# 步骤1: 定义配置节的描述
|
# 步骤1: 定义配置节的描述
|
||||||
config_section_descriptions = {
|
config_section_descriptions = {
|
||||||
"plugin": "插件基本信息配置",
|
"plugin": "插件启用配置",
|
||||||
"components": "组件启用控制",
|
"components": "组件启用控制",
|
||||||
"mute": "核心禁言功能配置",
|
"mute": "核心禁言功能配置",
|
||||||
"smart_mute": "智能禁言Action的专属配置",
|
"smart_mute": "智能禁言Action的专属配置",
|
||||||
@@ -111,10 +129,7 @@ class MutePlugin(BasePlugin):
|
|||||||
# 步骤2: 使用ConfigField定义详细的配置Schema
|
# 步骤2: 使用ConfigField定义详细的配置Schema
|
||||||
config_schema = {
|
config_schema = {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": ConfigField(type=str, default="mute_plugin", description="插件名称", required=True),
|
"enabled": ConfigField(type=bool, default=False, description="是否启用插件")
|
||||||
"version": ConfigField(type=str, default="2.0.0", description="插件版本号"),
|
|
||||||
"enabled": ConfigField(type=bool, default=False, description="是否启用插件"),
|
|
||||||
"description": ConfigField(type=str, default="群聊禁言管理插件", description="插件描述", required=True)
|
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"enable_smart_mute": ConfigField(type=bool, default=True, description="是否启用智能禁言Action"),
|
"enable_smart_mute": ConfigField(type=bool, default=True, description="是否启用智能禁言Action"),
|
||||||
@@ -170,21 +185,12 @@ class MutePlugin(BasePlugin):
|
|||||||
# mute_plugin - 自动生成的配置文件
|
# mute_plugin - 自动生成的配置文件
|
||||||
# 群聊禁言管理插件,提供智能禁言功能
|
# 群聊禁言管理插件,提供智能禁言功能
|
||||||
|
|
||||||
# 插件基本信息配置
|
# 插件启用配置
|
||||||
[plugin]
|
[plugin]
|
||||||
|
|
||||||
# 插件名称 (必需)
|
|
||||||
name = "mute_plugin"
|
|
||||||
|
|
||||||
# 插件版本号
|
|
||||||
version = "2.0.0"
|
|
||||||
|
|
||||||
# 是否启用插件
|
# 是否启用插件
|
||||||
enabled = false
|
enabled = false
|
||||||
|
|
||||||
# 插件描述 (必需)
|
|
||||||
description = "群聊禁言管理插件"
|
|
||||||
|
|
||||||
|
|
||||||
# 组件启用控制
|
# 组件启用控制
|
||||||
[components]
|
[components]
|
||||||
@@ -378,7 +384,7 @@ class GreetingPlugin(BasePlugin):
|
|||||||
|
|
||||||
# 配置节描述
|
# 配置节描述
|
||||||
config_section_descriptions = {
|
config_section_descriptions = {
|
||||||
"plugin": "插件基本信息",
|
"plugin": "插件启用配置",
|
||||||
"greeting": "问候功能配置",
|
"greeting": "问候功能配置",
|
||||||
"features": "功能开关配置",
|
"features": "功能开关配置",
|
||||||
"messages": "消息模板配置"
|
"messages": "消息模板配置"
|
||||||
@@ -387,8 +393,7 @@ class GreetingPlugin(BasePlugin):
|
|||||||
# 配置Schema定义
|
# 配置Schema定义
|
||||||
config_schema = {
|
config_schema = {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
|
"enabled": ConfigField(type=bool, default=True, description="是否启用插件")
|
||||||
"version": ConfigField(type=str, default="1.0.0", description="插件版本")
|
|
||||||
},
|
},
|
||||||
"greeting": {
|
"greeting": {
|
||||||
"template": ConfigField(
|
"template": ConfigField(
|
||||||
|
|||||||
@@ -10,31 +10,43 @@
|
|||||||
|
|
||||||
- [🧱 Action组件详解](action-components.md) - 掌握最核心的Action组件
|
- [🧱 Action组件详解](action-components.md) - 掌握最核心的Action组件
|
||||||
- [💻 Command组件详解](command-components.md) - 学习直接响应命令的组件
|
- [💻 Command组件详解](command-components.md) - 学习直接响应命令的组件
|
||||||
- [⚙️ 配置管理指南](configuration-guide.md) - 学会使用配置驱动开发
|
- [⚙️ 配置管理指南](configuration-guide.md) - 学会使用自动生成的插件配置文件
|
||||||
|
- [📄 Manifest系统指南](manifest-guide.md) - 了解插件元数据管理和配置架构
|
||||||
- [🔧 工具系统详解](tool-system.md) - 工具系统的使用和开发(非主要功能)
|
|
||||||
|
|
||||||
## API浏览
|
## API浏览
|
||||||
|
|
||||||
### 🔗 核心通信API
|
### 消息发送与处理API
|
||||||
- [📡 消息API](api/message-api.md) - 消息接收和处理接口
|
|
||||||
- [📤 发送API](api/send-api.md) - 各种类型消息发送接口
|
- [📤 发送API](api/send-api.md) - 各种类型消息发送接口
|
||||||
- [💬 聊天API](api/chat-api.md) - 聊天流管理和查询接口
|
- [消息API](api/message-api.md) - 消息获取,消息构建,消息查询接口
|
||||||
|
- [聊天流API](api/chat-api.md) - 聊天流管理和查询接口
|
||||||
|
|
||||||
### 🤖 AI与生成API
|
### AI与生成API
|
||||||
- [🧠 LLM API](api/llm-api.md) - 大语言模型交互接口
|
- [LLM API](api/llm-api.md) - 大语言模型交互接口,可以使用内置LLM生成内容
|
||||||
- [✨ 回复生成器API](api/generator-api.md) - 智能回复生成接口
|
- [✨ 回复生成器API](api/generator-api.md) - 智能回复生成接口,可以使用内置风格化生成器
|
||||||
|
|
||||||
|
### 表情包api
|
||||||
- [😊 表情包API](api/emoji-api.md) - 表情包选择和管理接口
|
- [😊 表情包API](api/emoji-api.md) - 表情包选择和管理接口
|
||||||
|
|
||||||
### 📊 数据与配置API
|
### 关系系统api
|
||||||
|
- [人物信息API](api/person-api.md) - 用户信息,处理麦麦认识的人和关系的接口
|
||||||
|
|
||||||
|
### 数据与配置API
|
||||||
- [🗄️ 数据库API](api/database-api.md) - 数据库操作接口
|
- [🗄️ 数据库API](api/database-api.md) - 数据库操作接口
|
||||||
- [⚙️ 配置API](api/config-api.md) - 配置读取和用户信息接口
|
- [⚙️ 配置API](api/config-api.md) - 配置读取和用户信息接口
|
||||||
- [👤 个人信息API](api/person-api.md) - 用户信息查询接口
|
|
||||||
|
|
||||||
### 🛠️ 工具API
|
### 工具API
|
||||||
- [🔧 工具API](api/utils-api.md) - 文件操作、时间处理等工具函数
|
- [工具API](api/utils-api.md) - 文件操作、时间处理等工具函数
|
||||||
|
|
||||||
|
|
||||||
|
## 实验性
|
||||||
|
|
||||||
|
这些功能将在未来重构或移除
|
||||||
|
- [🔧 工具系统详解](tool-system.md) - 工具系统的使用和开发
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 支持
|
||||||
|
|
||||||
> 如果你在文档中发现错误或需要补充,请:
|
> 如果你在文档中发现错误或需要补充,请:
|
||||||
|
|
||||||
1. 检查最新的文档版本
|
1. 检查最新的文档版本
|
||||||
@@ -4,6 +4,26 @@
|
|||||||
|
|
||||||
MaiBot插件系统现在强制要求每个插件都必须包含一个 `_manifest.json` 文件。这个文件描述了插件的基本信息、依赖关系、组件等重要元数据。
|
MaiBot插件系统现在强制要求每个插件都必须包含一个 `_manifest.json` 文件。这个文件描述了插件的基本信息、依赖关系、组件等重要元数据。
|
||||||
|
|
||||||
|
### 🔄 配置架构:Manifest与Config的职责分离
|
||||||
|
|
||||||
|
为了避免信息重复和提高维护性,我们采用了**双文件架构**:
|
||||||
|
|
||||||
|
- **`_manifest.json`** - 插件的**静态元数据**
|
||||||
|
- 插件身份信息(名称、版本、描述)
|
||||||
|
- 开发者信息(作者、许可证、仓库)
|
||||||
|
- 系统信息(兼容性、组件列表、分类)
|
||||||
|
|
||||||
|
- **`config.toml`** - 插件的**运行时配置**
|
||||||
|
- 启用状态 (`enabled`)
|
||||||
|
- 功能参数配置
|
||||||
|
- 用户可调整的行为设置
|
||||||
|
|
||||||
|
这种分离确保了:
|
||||||
|
- ✅ 元数据信息统一管理
|
||||||
|
- ✅ 运行时配置灵活调整
|
||||||
|
- ✅ 避免重复维护
|
||||||
|
- ✅ 更清晰的职责划分
|
||||||
|
|
||||||
## 🔧 Manifest文件结构
|
## 🔧 Manifest文件结构
|
||||||
|
|
||||||
### 必需字段
|
### 必需字段
|
||||||
|
|||||||
@@ -217,6 +217,20 @@ class ActionPlanner(BasePlanner):
|
|||||||
# 如果repair_json直接返回了字典对象,直接使用
|
# 如果repair_json直接返回了字典对象,直接使用
|
||||||
parsed_json = fixed_json_string
|
parsed_json = fixed_json_string
|
||||||
|
|
||||||
|
# 处理repair_json可能返回列表的情况
|
||||||
|
if isinstance(parsed_json, list):
|
||||||
|
if parsed_json:
|
||||||
|
# 取列表中最后一个元素(通常是最完整的)
|
||||||
|
parsed_json = parsed_json[-1]
|
||||||
|
logger.warning(f"{self.log_prefix}LLM返回了多个JSON对象,使用最后一个: {parsed_json}")
|
||||||
|
else:
|
||||||
|
parsed_json = {}
|
||||||
|
|
||||||
|
# 确保parsed_json是字典
|
||||||
|
if not isinstance(parsed_json, dict):
|
||||||
|
logger.error(f"{self.log_prefix}解析后的JSON不是字典类型: {type(parsed_json)}")
|
||||||
|
parsed_json = {}
|
||||||
|
|
||||||
# 提取决策,提供默认值
|
# 提取决策,提供默认值
|
||||||
extracted_action = parsed_json.get("action", "no_reply")
|
extracted_action = parsed_json.get("action", "no_reply")
|
||||||
extracted_reasoning = ""
|
extracted_reasoning = ""
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import os
|
|||||||
import importlib
|
import importlib
|
||||||
import importlib.util
|
import importlib.util
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import traceback
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from src.plugin_system.base.base_plugin import BasePlugin
|
from src.plugin_system.base.base_plugin import BasePlugin
|
||||||
@@ -151,6 +152,7 @@ class PluginManager:
|
|||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
# manifest文件格式错误或验证失败
|
# manifest文件格式错误或验证失败
|
||||||
|
traceback.print_exc()
|
||||||
total_failed_registration += 1
|
total_failed_registration += 1
|
||||||
error_msg = f"manifest验证失败: {str(e)}"
|
error_msg = f"manifest验证失败: {str(e)}"
|
||||||
self.failed_plugins[plugin_name] = error_msg
|
self.failed_plugins[plugin_name] = error_msg
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ class CoreActionsPlugin(BasePlugin):
|
|||||||
|
|
||||||
# 配置节描述
|
# 配置节描述
|
||||||
config_section_descriptions = {
|
config_section_descriptions = {
|
||||||
"plugin": "插件基本信息配置",
|
"plugin": "插件启用配置",
|
||||||
"components": "核心组件启用配置",
|
"components": "核心组件启用配置",
|
||||||
"no_reply": "不回复动作配置",
|
"no_reply": "不回复动作配置",
|
||||||
"emoji": "表情动作配置",
|
"emoji": "表情动作配置",
|
||||||
@@ -360,12 +360,7 @@ class CoreActionsPlugin(BasePlugin):
|
|||||||
# 配置Schema定义
|
# 配置Schema定义
|
||||||
config_schema = {
|
config_schema = {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": ConfigField(type=str, default="core_actions", description="插件名称", required=True),
|
|
||||||
"version": ConfigField(type=str, default="1.0.0", description="插件版本号"),
|
|
||||||
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
|
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
|
||||||
"description": ConfigField(
|
|
||||||
type=str, default="系统核心动作插件,提供基础聊天交互功能", description="插件描述", required=True
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"),
|
"enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[inner]
|
[inner]
|
||||||
version = "2.23.0"
|
version = "2.24.0"
|
||||||
|
|
||||||
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
||||||
#如果你想要修改配置文件,请在修改后将version的值进行变更
|
#如果你想要修改配置文件,请在修改后将version的值进行变更
|
||||||
@@ -43,7 +43,7 @@ identity_detail = [
|
|||||||
expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)"
|
expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)"
|
||||||
enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通)
|
enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通)
|
||||||
learning_interval = 600 # 学习间隔 单位秒
|
learning_interval = 600 # 学习间隔 单位秒
|
||||||
selection_mode = "llm" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择,'random' 使用传统随机选择
|
selection_mode = "random" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择,'random' 使用传统随机选择
|
||||||
|
|
||||||
[relationship]
|
[relationship]
|
||||||
enable_relationship = true # 是否启用关系系统
|
enable_relationship = true # 是否启用关系系统
|
||||||
@@ -320,12 +320,12 @@ temp = 0.2
|
|||||||
|
|
||||||
|
|
||||||
[model.lpmm_qa] # 问答模型
|
[model.lpmm_qa] # 问答模型
|
||||||
name = "Pro/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B"
|
name = "Qwen/Qwen3-30B-A3B"
|
||||||
provider = "SILICONFLOW"
|
provider = "SILICONFLOW"
|
||||||
pri_in = 4.0
|
pri_in = 0.7
|
||||||
pri_out = 16.0
|
pri_out = 2.8
|
||||||
temp = 0.7
|
temp = 0.7
|
||||||
|
enable_thinking = false # 是否启用思考
|
||||||
|
|
||||||
[maim_message]
|
[maim_message]
|
||||||
auth_token = [] # 认证令牌,用于API验证,为空则不启用验证
|
auth_token = [] # 认证令牌,用于API验证,为空则不启用验证
|
||||||
|
|||||||
Reference in New Issue
Block a user