Merge branch 'dev' of https://github.com/MaiM-with-u/MaiBot into dev
This commit is contained in:
@@ -21,6 +21,8 @@
|
|||||||
- `database_api.py`中的`db_query`方法调整了参数顺序以增强参数限制的同时,保证了typing正确;`db_get`方法增加了`single_result`参数,与`db_query`保持一致。
|
- `database_api.py`中的`db_query`方法调整了参数顺序以增强参数限制的同时,保证了typing正确;`db_get`方法增加了`single_result`参数,与`db_query`保持一致。
|
||||||
5. 增加了`logging_api`,可以用`get_logger`来获取日志记录器。
|
5. 增加了`logging_api`,可以用`get_logger`来获取日志记录器。
|
||||||
6. 增加了插件和组件管理的API。
|
6. 增加了插件和组件管理的API。
|
||||||
|
7. `BaseCommand`的`execute`方法现在返回一个三元组,包含是否执行成功、可选的回复消息和是否拦截消息。
|
||||||
|
- 这意味着你终于可以动态控制是否继续后续消息的处理了。
|
||||||
|
|
||||||
# 插件系统修改
|
# 插件系统修改
|
||||||
1. 现在所有的匹配模式不再是关键字了,而是枚举类。**(可能有遗漏)**
|
1. 现在所有的匹配模式不再是关键字了,而是枚举类。**(可能有遗漏)**
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class HelloAction(BaseAction):
|
|||||||
# === 基本信息(必须填写)===
|
# === 基本信息(必须填写)===
|
||||||
action_name = "hello_greeting"
|
action_name = "hello_greeting"
|
||||||
action_description = "向用户发送问候消息"
|
action_description = "向用户发送问候消息"
|
||||||
|
activation_type = ActionActivationType.ALWAYS # 始终激活
|
||||||
|
|
||||||
# === 功能描述(必须填写)===
|
# === 功能描述(必须填写)===
|
||||||
action_parameters = {"greeting_message": "要发送的问候消息"}
|
action_parameters = {"greeting_message": "要发送的问候消息"}
|
||||||
@@ -44,8 +45,7 @@ class ByeAction(BaseAction):
|
|||||||
action_description = "向用户发送告别消息"
|
action_description = "向用户发送告别消息"
|
||||||
|
|
||||||
# 使用关键词激活
|
# 使用关键词激活
|
||||||
focus_activation_type = ActionActivationType.KEYWORD
|
activation_type = ActionActivationType.KEYWORD
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
|
|
||||||
# 关键词设置
|
# 关键词设置
|
||||||
activation_keywords = ["再见", "bye", "88", "拜拜"]
|
activation_keywords = ["再见", "bye", "88", "拜拜"]
|
||||||
@@ -75,11 +75,8 @@ class TimeCommand(BaseCommand):
|
|||||||
|
|
||||||
# === 命令设置(必须填写)===
|
# === 命令设置(必须填写)===
|
||||||
command_pattern = r"^/time$" # 精确匹配 "/time" 命令
|
command_pattern = r"^/time$" # 精确匹配 "/time" 命令
|
||||||
command_help = "查询当前时间"
|
|
||||||
command_examples = ["/time"]
|
|
||||||
intercept_message = True # 拦截消息,不让其他组件处理
|
|
||||||
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
async def execute(self) -> Tuple[bool, str, bool]:
|
||||||
"""执行时间查询"""
|
"""执行时间查询"""
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@@ -92,7 +89,7 @@ class TimeCommand(BaseCommand):
|
|||||||
message = f"⏰ 当前时间:{time_str}"
|
message = f"⏰ 当前时间:{time_str}"
|
||||||
await self.send_text(message)
|
await self.send_text(message)
|
||||||
|
|
||||||
return True, f"显示了当前时间: {time_str}"
|
return True, f"显示了当前时间: {time_str}", True
|
||||||
|
|
||||||
|
|
||||||
class PrintMessage(BaseEventHandler):
|
class PrintMessage(BaseEventHandler):
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ class ChatBot:
|
|||||||
command_result = component_registry.find_command_by_text(text)
|
command_result = component_registry.find_command_by_text(text)
|
||||||
if command_result:
|
if command_result:
|
||||||
command_class, matched_groups, command_info = command_result
|
command_class, matched_groups, command_info = command_result
|
||||||
intercept_message = command_info.intercept_message
|
|
||||||
plugin_name = command_info.plugin_name
|
plugin_name = command_info.plugin_name
|
||||||
command_name = command_info.name
|
command_name = command_info.name
|
||||||
if (
|
if (
|
||||||
@@ -115,7 +114,7 @@ class ChatBot:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 执行命令
|
# 执行命令
|
||||||
success, response = await command_instance.execute()
|
success, response, intercept_message = await command_instance.execute()
|
||||||
|
|
||||||
# 记录命令执行结果
|
# 记录命令执行结果
|
||||||
if success:
|
if success:
|
||||||
@@ -128,8 +127,6 @@ class ChatBot:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"执行命令时出错: {command_class.__name__} - {e}")
|
logger.error(f"执行命令时出错: {command_class.__name__} - {e}")
|
||||||
import traceback
|
|
||||||
|
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -138,7 +135,7 @@ class ChatBot:
|
|||||||
logger.error(f"发送错误消息失败: {send_error}")
|
logger.error(f"发送错误消息失败: {send_error}")
|
||||||
|
|
||||||
# 命令出错时,根据命令的拦截设置决定是否继续处理消息
|
# 命令出错时,根据命令的拦截设置决定是否继续处理消息
|
||||||
return True, str(e), not intercept_message
|
return True, str(e), False # 出错时继续处理消息
|
||||||
|
|
||||||
# 没有找到命令,继续处理消息
|
# 没有找到命令,继续处理消息
|
||||||
return False, None, True
|
return False, None, True
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Dict, Tuple, Optional, List
|
from typing import Dict, Tuple, Optional
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.plugin_system.base.component_types import CommandInfo, ComponentType
|
from src.plugin_system.base.component_types import CommandInfo, ComponentType
|
||||||
from src.chat.message_receive.message import MessageRecv
|
from src.chat.message_receive.message import MessageRecv
|
||||||
@@ -17,7 +17,6 @@ class BaseCommand(ABC):
|
|||||||
- command_pattern: 命令匹配的正则表达式
|
- command_pattern: 命令匹配的正则表达式
|
||||||
- command_help: 命令帮助信息
|
- command_help: 命令帮助信息
|
||||||
- command_examples: 命令使用示例列表
|
- command_examples: 命令使用示例列表
|
||||||
- intercept_message: 是否拦截消息处理(默认True拦截,False继续传递)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
command_name: str = ""
|
command_name: str = ""
|
||||||
@@ -27,11 +26,6 @@ class BaseCommand(ABC):
|
|||||||
# 默认命令设置
|
# 默认命令设置
|
||||||
command_pattern: str = r""
|
command_pattern: str = r""
|
||||||
"""命令匹配的正则表达式"""
|
"""命令匹配的正则表达式"""
|
||||||
command_help: str = ""
|
|
||||||
"""命令帮助信息"""
|
|
||||||
command_examples: List[str] = []
|
|
||||||
intercept_message: bool = True
|
|
||||||
"""是否拦截信息,默认拦截,不进行后续处理"""
|
|
||||||
|
|
||||||
def __init__(self, message: MessageRecv, plugin_config: Optional[dict] = None):
|
def __init__(self, message: MessageRecv, plugin_config: Optional[dict] = None):
|
||||||
"""初始化Command组件
|
"""初始化Command组件
|
||||||
@@ -57,11 +51,11 @@ class BaseCommand(ABC):
|
|||||||
self.matched_groups = groups
|
self.matched_groups = groups
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def execute(self) -> Tuple[bool, Optional[str]]:
|
async def execute(self) -> Tuple[bool, Optional[str], bool]:
|
||||||
"""执行Command的抽象方法,子类必须实现
|
"""执行Command的抽象方法,子类必须实现
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple[bool, Optional[str]]: (是否执行成功, 可选的回复消息)
|
Tuple[bool, Optional[str], bool]: (是否执行成功, 可选的回复消息, 是否拦截消息 不进行 后续处理)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -231,7 +225,4 @@ class BaseCommand(ABC):
|
|||||||
component_type=ComponentType.COMMAND,
|
component_type=ComponentType.COMMAND,
|
||||||
description=cls.command_description,
|
description=cls.command_description,
|
||||||
command_pattern=cls.command_pattern,
|
command_pattern=cls.command_pattern,
|
||||||
command_help=cls.command_help,
|
|
||||||
command_examples=cls.command_examples.copy() if cls.command_examples else [],
|
|
||||||
intercept_message=cls.intercept_message,
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -140,14 +140,9 @@ class CommandInfo(ComponentInfo):
|
|||||||
"""命令组件信息"""
|
"""命令组件信息"""
|
||||||
|
|
||||||
command_pattern: str = "" # 命令匹配模式(正则表达式)
|
command_pattern: str = "" # 命令匹配模式(正则表达式)
|
||||||
command_help: str = "" # 命令帮助信息
|
|
||||||
command_examples: List[str] = field(default_factory=list) # 命令使用示例
|
|
||||||
intercept_message: bool = True # 是否拦截消息处理(默认拦截)
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
if self.command_examples is None:
|
|
||||||
self.command_examples = []
|
|
||||||
self.component_type = ComponentType.COMMAND
|
self.component_type = ComponentType.COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class EventsManager:
|
|||||||
|
|
||||||
async def cancel_handler_tasks(self, handler_name: str) -> None:
|
async def cancel_handler_tasks(self, handler_name: str) -> None:
|
||||||
tasks_to_be_cancelled = self._handler_tasks.get(handler_name, [])
|
tasks_to_be_cancelled = self._handler_tasks.get(handler_name, [])
|
||||||
remaining_tasks = [task for task in tasks_to_be_cancelled if not task.done()]
|
if remaining_tasks := [task for task in tasks_to_be_cancelled if not task.done()]:
|
||||||
for task in remaining_tasks:
|
for task in remaining_tasks:
|
||||||
task.cancel()
|
task.cancel()
|
||||||
try:
|
try:
|
||||||
@@ -192,7 +192,7 @@ class EventsManager:
|
|||||||
logger.warning(f"取消事件处理器 {handler_name} 的任务超时,开始强制取消")
|
logger.warning(f"取消事件处理器 {handler_name} 的任务超时,开始强制取消")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"取消事件处理器 {handler_name} 的任务时发生异常: {e}")
|
logger.error(f"取消事件处理器 {handler_name} 的任务时发生异常: {e}")
|
||||||
finally:
|
if handler_name in self._handler_tasks:
|
||||||
del self._handler_tasks[handler_name]
|
del self._handler_tasks[handler_name]
|
||||||
|
|
||||||
async def unregister_event_subscriber(self, handler_name: str) -> bool:
|
async def unregister_event_subscriber(self, handler_name: str) -> bool:
|
||||||
|
|||||||
@@ -18,9 +18,8 @@ class ManagementCommand(BaseCommand):
|
|||||||
command_name: str = "management"
|
command_name: str = "management"
|
||||||
description: str = "管理命令"
|
description: str = "管理命令"
|
||||||
command_pattern: str = r"(?P<manage_command>^/pm(\s[a-zA-Z0-9_]+)*\s*$)"
|
command_pattern: str = r"(?P<manage_command>^/pm(\s[a-zA-Z0-9_]+)*\s*$)"
|
||||||
intercept_message: bool = True
|
|
||||||
|
|
||||||
async def execute(self) -> Tuple[bool, str]:
|
async def execute(self) -> Tuple[bool, str, bool]:
|
||||||
# sourcery skip: merge-duplicate-blocks
|
# sourcery skip: merge-duplicate-blocks
|
||||||
if (
|
if (
|
||||||
not self.message
|
not self.message
|
||||||
@@ -29,11 +28,11 @@ class ManagementCommand(BaseCommand):
|
|||||||
or str(self.message.message_info.user_info.user_id) not in self.get_config("plugin.permission", []) # type: ignore
|
or str(self.message.message_info.user_info.user_id) not in self.get_config("plugin.permission", []) # type: ignore
|
||||||
):
|
):
|
||||||
await self.send_text("你没有权限使用插件管理命令")
|
await self.send_text("你没有权限使用插件管理命令")
|
||||||
return False, "没有权限"
|
return False, "没有权限", True
|
||||||
command_list = self.matched_groups["manage_command"].strip().split(" ")
|
command_list = self.matched_groups["manage_command"].strip().split(" ")
|
||||||
if len(command_list) == 1:
|
if len(command_list) == 1:
|
||||||
await self.show_help("all")
|
await self.show_help("all")
|
||||||
return True, "帮助已发送"
|
return True, "帮助已发送", True
|
||||||
if len(command_list) == 2:
|
if len(command_list) == 2:
|
||||||
match command_list[1]:
|
match command_list[1]:
|
||||||
case "plugin":
|
case "plugin":
|
||||||
@@ -44,7 +43,7 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self.show_help("all")
|
await self.show_help("all")
|
||||||
case _:
|
case _:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if len(command_list) == 3:
|
if len(command_list) == 3:
|
||||||
if command_list[1] == "plugin":
|
if command_list[1] == "plugin":
|
||||||
match command_list[2]:
|
match command_list[2]:
|
||||||
@@ -58,7 +57,7 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self._rescan_plugin_dirs()
|
await self._rescan_plugin_dirs()
|
||||||
case _:
|
case _:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
elif command_list[1] == "component":
|
elif command_list[1] == "component":
|
||||||
if command_list[2] == "list":
|
if command_list[2] == "list":
|
||||||
await self._list_all_registered_components()
|
await self._list_all_registered_components()
|
||||||
@@ -66,10 +65,10 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self.show_help("component")
|
await self.show_help("component")
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if len(command_list) == 4:
|
if len(command_list) == 4:
|
||||||
if command_list[1] == "plugin":
|
if command_list[1] == "plugin":
|
||||||
match command_list[2]:
|
match command_list[2]:
|
||||||
@@ -83,28 +82,28 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self._add_dir(command_list[3])
|
await self._add_dir(command_list[3])
|
||||||
case _:
|
case _:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
elif command_list[1] == "component":
|
elif command_list[1] == "component":
|
||||||
if command_list[2] != "list":
|
if command_list[2] != "list":
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if command_list[3] == "enabled":
|
if command_list[3] == "enabled":
|
||||||
await self._list_enabled_components()
|
await self._list_enabled_components()
|
||||||
elif command_list[3] == "disabled":
|
elif command_list[3] == "disabled":
|
||||||
await self._list_disabled_components()
|
await self._list_disabled_components()
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if len(command_list) == 5:
|
if len(command_list) == 5:
|
||||||
if command_list[1] != "component":
|
if command_list[1] != "component":
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if command_list[2] != "list":
|
if command_list[2] != "list":
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if command_list[3] == "enabled":
|
if command_list[3] == "enabled":
|
||||||
await self._list_enabled_components(target_type=command_list[4])
|
await self._list_enabled_components(target_type=command_list[4])
|
||||||
elif command_list[3] == "disabled":
|
elif command_list[3] == "disabled":
|
||||||
@@ -113,11 +112,11 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self._list_registered_components_by_type(command_list[4])
|
await self._list_registered_components_by_type(command_list[4])
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if len(command_list) == 6:
|
if len(command_list) == 6:
|
||||||
if command_list[1] != "component":
|
if command_list[1] != "component":
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
if command_list[2] == "enable":
|
if command_list[2] == "enable":
|
||||||
if command_list[3] == "global":
|
if command_list[3] == "global":
|
||||||
await self._globally_enable_component(command_list[4], command_list[5])
|
await self._globally_enable_component(command_list[4], command_list[5])
|
||||||
@@ -125,7 +124,7 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self._locally_enable_component(command_list[4], command_list[5])
|
await self._locally_enable_component(command_list[4], command_list[5])
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
elif command_list[2] == "disable":
|
elif command_list[2] == "disable":
|
||||||
if command_list[3] == "global":
|
if command_list[3] == "global":
|
||||||
await self._globally_disable_component(command_list[4], command_list[5])
|
await self._globally_disable_component(command_list[4], command_list[5])
|
||||||
@@ -133,12 +132,12 @@ class ManagementCommand(BaseCommand):
|
|||||||
await self._locally_disable_component(command_list[4], command_list[5])
|
await self._locally_disable_component(command_list[4], command_list[5])
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
else:
|
else:
|
||||||
await self.send_text("插件管理命令不合法")
|
await self.send_text("插件管理命令不合法")
|
||||||
return False, "命令不合法"
|
return False, "命令不合法", True
|
||||||
|
|
||||||
return True, "命令执行完成"
|
return True, "命令执行完成", True
|
||||||
|
|
||||||
async def show_help(self, target: str):
|
async def show_help(self, target: str):
|
||||||
help_msg = ""
|
help_msg = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user