feat: 添加测试用例并优化代码结构
refactor(permission_manager): 调整初始化顺序和逻辑 fix(admin_manager): 修复初始化逻辑和目录创建问题 feat(ws): 优化Bot实例初始化条件 feat(message): 增强MessageSegment功能并添加测试 feat(events): 支持字符串格式的消息解析 test: 添加核心功能测试用例 refactor(plugin_manager): 改进插件路径处理 style: 清理无用导入和代码 chore: 更新依赖项
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"admins": []
|
||||
"admins": [2221577113]
|
||||
}
|
||||
@@ -6,11 +6,12 @@
|
||||
"""
|
||||
import inspect
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, TYPE_CHECKING
|
||||
|
||||
from ..bot import Bot
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
from ..config_loader import global_config
|
||||
from ..managers.permission_manager import Permission
|
||||
from ..permission import Permission
|
||||
from ..utils.executor import run_in_thread_pool
|
||||
|
||||
|
||||
@@ -22,7 +23,7 @@ class BaseHandler(ABC):
|
||||
self.handlers: List[Dict[str, Any]] = []
|
||||
|
||||
@abstractmethod
|
||||
async def handle(self, bot: Bot, event: Any):
|
||||
async def handle(self, bot: "Bot", event: Any):
|
||||
"""
|
||||
处理事件
|
||||
"""
|
||||
@@ -31,7 +32,7 @@ class BaseHandler(ABC):
|
||||
async def _run_handler(
|
||||
self,
|
||||
func: Callable,
|
||||
bot: Bot,
|
||||
bot: "Bot",
|
||||
event: Any,
|
||||
args: Optional[List[str]] = None,
|
||||
permission_granted: Optional[bool] = None
|
||||
@@ -122,7 +123,7 @@ class MessageHandler(BaseHandler):
|
||||
return func
|
||||
return decorator
|
||||
|
||||
async def handle(self, bot: Bot, event: Any):
|
||||
async def handle(self, bot: "Bot", event: Any):
|
||||
"""
|
||||
处理消息事件,分发给命令处理器或通用消息处理器
|
||||
"""
|
||||
|
||||
@@ -26,8 +26,7 @@ class AdminManager(Singleton):
|
||||
"""
|
||||
初始化 AdminManager
|
||||
"""
|
||||
super().__init__()
|
||||
if not self._initialized:
|
||||
if hasattr(self, '_initialized') and self._initialized:
|
||||
return
|
||||
|
||||
# 管理员数据文件路径
|
||||
@@ -39,7 +38,12 @@ class AdminManager(Singleton):
|
||||
)
|
||||
|
||||
self._admins: Set[int] = set()
|
||||
|
||||
# 确保数据目录存在
|
||||
os.makedirs(os.path.dirname(self.data_file), exist_ok=True)
|
||||
|
||||
logger.info("管理员管理器初始化完成")
|
||||
super().__init__()
|
||||
|
||||
async def initialize(self):
|
||||
"""
|
||||
|
||||
@@ -41,7 +41,6 @@ class PermissionManager(Singleton):
|
||||
|
||||
如果已经初始化过,则直接返回。
|
||||
"""
|
||||
super().__init__()
|
||||
if hasattr(self, '_initialized') and self._initialized:
|
||||
return
|
||||
|
||||
@@ -64,7 +63,7 @@ class PermissionManager(Singleton):
|
||||
self.load()
|
||||
|
||||
logger.info("权限管理器初始化完成")
|
||||
self._initialized = True
|
||||
super().__init__()
|
||||
|
||||
def load(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -30,12 +30,21 @@ class PluginManager:
|
||||
"""
|
||||
扫描并加载 `plugins` 目录下的所有插件。
|
||||
"""
|
||||
plugin_dir = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "..", "..", "plugins"
|
||||
)
|
||||
# 使用 pathlib 获取更可靠的路径
|
||||
# 当前文件: core/managers/plugin_manager.py
|
||||
# 目标: plugins/
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
# 回退两级到项目根目录 (core/managers -> core -> root)
|
||||
root_dir = os.path.dirname(os.path.dirname(current_dir))
|
||||
plugin_dir = os.path.join(root_dir, "plugins")
|
||||
|
||||
package_name = "plugins"
|
||||
|
||||
logger.info(f"正在从 {package_name} 加载插件...")
|
||||
if not os.path.exists(plugin_dir):
|
||||
logger.error(f"插件目录不存在: {plugin_dir}")
|
||||
return
|
||||
|
||||
logger.info(f"正在从 {package_name} 加载插件 (路径: {plugin_dir})...")
|
||||
|
||||
for _, module_name, is_pkg in pkgutil.iter_modules([plugin_dir]):
|
||||
full_module_name = f"{package_name}.{module_name}"
|
||||
|
||||
@@ -33,13 +33,10 @@ class Permission(Enum):
|
||||
return NotImplemented
|
||||
return self._level_map[self] < self._level_map[other]
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Permission):
|
||||
return NotImplemented
|
||||
return self is other
|
||||
|
||||
def __ge__(self, other):
|
||||
"""
|
||||
比较当前权限是否大于等于另一个权限。
|
||||
"""
|
||||
if not isinstance(other, Permission):
|
||||
return NotImplemented
|
||||
return self._level_map[self] >= self._level_map[other]
|
||||
|
||||
|
||||
@@ -60,7 +60,15 @@ class CodeExecutor:
|
||||
将代码执行任务添加到队列中。
|
||||
:param code: 待执行的 Python 代码字符串。
|
||||
:param callback: 执行完毕后用于回复结果的回调函数。
|
||||
:raises RuntimeError: 如果 Docker 客户端未初始化。
|
||||
"""
|
||||
if not self.docker_client:
|
||||
logger.warning("[CodeExecutor] 尝试添加任务,但 Docker 客户端未初始化。任务被拒绝。")
|
||||
# 这里可以选择抛出异常,或者直接调用回调返回错误信息
|
||||
# 为了用户体验,我们构造一个错误结果并直接调用回调(如果可能)
|
||||
# 但由于 callback 返回 Future,这里简单起见,我们记录日志并抛出异常
|
||||
raise RuntimeError("Docker环境未就绪,无法执行代码。")
|
||||
|
||||
task = {"code": code, "callback": callback}
|
||||
await self.task_queue.put(task)
|
||||
logger.info(f"[CodeExecutor] 新的代码执行任务已入队 (队列当前长度: {self.task_queue.qsize()})。")
|
||||
|
||||
@@ -128,8 +128,9 @@ class WS:
|
||||
# 使用工厂创建事件对象
|
||||
event = EventFactory.create_event(event_data)
|
||||
|
||||
# 在收到第一个 meta_event 时,初始化 Bot 实例
|
||||
if event.post_type == "meta_event" and self.bot is None:
|
||||
# 尝试初始化 Bot 实例 (如果尚未初始化且事件包含 self_id)
|
||||
# 只要事件中包含 self_id,我们就可以初始化 Bot,不必非要等待 meta_event
|
||||
if self.bot is None and hasattr(event, 'self_id'):
|
||||
self.self_id = event.self_id
|
||||
self.bot = Bot(self)
|
||||
logger.success(f"Bot 实例初始化完成: self_id={self.self_id}")
|
||||
|
||||
Reference in New Issue
Block a user