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:
2026-01-09 00:20:30 +08:00
parent 5d07a84283
commit 77348113e3
18 changed files with 754 additions and 73 deletions

View File

@@ -0,0 +1,23 @@
"""
Models 包
导出常用的模型类,方便插件导入。
"""
from .events.base import OneBotEvent
from .events.message import MessageEvent, GroupMessageEvent, PrivateMessageEvent
from .events.notice import NoticeEvent
from .events.request import RequestEvent
from .message import MessageSegment
from .sender import Sender
__all__ = [
"OneBotEvent",
"MessageEvent",
"GroupMessageEvent",
"PrivateMessageEvent",
"NoticeEvent",
"RequestEvent",
"MessageSegment",
"Sender",
]

View File

@@ -70,7 +70,11 @@ class EventFactory:
# 解析消息段
message_list = []
raw_message_list = data.get("message", [])
if isinstance(raw_message_list, list):
if isinstance(raw_message_list, str):
# 如果消息是字符串,将其视为纯文本消息段
message_list.append(MessageSegment.text(raw_message_list))
elif isinstance(raw_message_list, list):
for item in raw_message_list:
if isinstance(item, dict):
message_list.append(MessageSegment(type=item.get("type", ""), data=item.get("data", {})))

View File

@@ -6,7 +6,7 @@
"""
from dataclasses import dataclass
from typing import Any, Dict, Optional
from typing import Any, Dict, Optional, List
@dataclass(slots=True)
@@ -23,7 +23,7 @@ class MessageSegment:
data: Dict[str, Any]
@property
def text(self) -> str:
def plain_text(self) -> str:
"""
当消息段类型为 'text' 时,快速获取其文本内容。
@@ -32,6 +32,19 @@ class MessageSegment:
"""
return self.data.get("text", "") if self.type == "text" else ""
@staticmethod
def text(text: str) -> "MessageSegment":
"""
创建一个文本消息段。
Args:
text (str): 文本内容。
Returns:
MessageSegment: 一个类型为 'text' 的消息段对象。
"""
return MessageSegment(type="text", data={"text": text})
@property
def image_url(self) -> str:
"""
@@ -93,12 +106,48 @@ class MessageSegment:
return True
return str(self.data.get("qq")) == str(user_id)
def __str__(self):
"""
返回消息段的 CQ 码字符串表示。
"""
if self.type == "text":
return self.data.get("text", "")
params = ",".join([f"{k}={v}" for k, v in self.data.items()])
if params:
return f"[CQ:{self.type},{params}]"
return f"[CQ:{self.type}]"
def __repr__(self):
"""
返回消息段对象的字符串表示形式,便于调试。
"""
return f"[MS:{self.type}:{self.data}]"
def __add__(self, other: Any) -> "List[MessageSegment]":
"""
支持消息段相加,返回消息段列表。
"""
if isinstance(other, MessageSegment):
return [self, other]
elif isinstance(other, str):
return [self, MessageSegment.text(other)]
elif isinstance(other, list):
return [self] + other
return NotImplemented
def __radd__(self, other: Any) -> "List[MessageSegment]":
"""
支持反向相加。
"""
if isinstance(other, MessageSegment):
return [other, self]
elif isinstance(other, str):
return [MessageSegment.text(other), self]
elif isinstance(other, list):
return other + [self]
return NotImplemented
# --- 快捷构造方法 ---
@staticmethod
@@ -297,17 +346,17 @@ class MessageSegment:
return MessageSegment(type="file", data={"file": file})
@staticmethod
def reply(message_id: str) -> "MessageSegment":
def reply(message_id: str | int) -> "MessageSegment":
"""
创建一个回复消息段。
Args:
message_id (str): 被回复的消息 ID。
message_id (str | int): 被回复的消息 ID。
Returns:
MessageSegment: 一个类型为 'reply' 的消息段对象。
"""
return MessageSegment(type="reply", data={"id": message_id})
return MessageSegment(type="reply", data={"id": str(message_id)})
@staticmethod
def rps() -> "MessageSegment":