diff --git a/main.py b/main.py
index 50c363f..33af0c5 100644
--- a/main.py
+++ b/main.py
@@ -14,7 +14,7 @@ async def message_recv(server_connection: Server.ServerConnection):
recv_handler.server_connection = server_connection
send_handler.server_connection = server_connection
async for raw_message in server_connection:
- logger.debug(f"{raw_message[:80]}..." if len(raw_message) > 80 else raw_message)
+ logger.debug(f"{raw_message[:100]}..." if len(raw_message) > 100 else raw_message)
decoded_raw_message: dict = json.loads(raw_message)
post_type = decoded_raw_message.get("post_type")
if post_type in ["meta_event", "message", "notice"]:
diff --git a/src/config.py b/src/config.py
index b3b96f9..ee13c98 100644
--- a/src/config.py
+++ b/src/config.py
@@ -42,6 +42,7 @@ class Config:
for key in include_configs:
if key not in raw_config:
logger.error(f"配置文件中缺少必需的字段: '{key}'")
+ logger.error("你的配置文件可能过时,请尝试手动更新配置文件。")
sys.exit(1)
self.server_host = raw_config["Napcat_Server"].get("host", "localhost")
@@ -71,6 +72,21 @@ class Config:
self.use_tts = raw_config["Voice"].get("use_tts", False)
self.debug_level = raw_config["Debug"].get("level", "INFO")
+ if self.debug_level == "DEBUG":
+ logger.debug("原始配置文件内容:")
+ logger.debug(raw_config)
+ logger.debug("读取到的配置内容:")
+ logger.debug(f"平台: {self.platform}")
+ logger.debug(f"MaiBot服务器地址: {self.mai_host}:{self.mai_port}")
+ logger.debug(f"Napcat服务器地址: {self.server_host}:{self.server_port}")
+ logger.debug(f"心跳间隔: {self.napcat_heartbeat_interval}秒")
+ logger.debug(f"群聊列表类型: {self.group_list_type}")
+ logger.debug(f"群聊列表: {self.group_list}")
+ logger.debug(f"私聊列表类型: {self.private_list_type}")
+ logger.debug(f"私聊列表: {self.private_list}")
+ logger.debug(f"禁用用户ID列表: {self.ban_user_id}")
+ logger.debug(f"是否启用TTS: {self.use_tts}")
+ logger.debug(f"调试级别: {self.debug_level}")
global_config = Config()
diff --git a/src/logger.py b/src/logger.py
index c097f14..3acba4f 100644
--- a/src/logger.py
+++ b/src/logger.py
@@ -1,7 +1,6 @@
from loguru import logger
from .config import global_config
import sys
-# import builtins
logger.remove()
logger.add(
@@ -9,17 +8,3 @@ logger.add(
level=global_config.debug_level,
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
)
-
-
-# def handle_output(message: str):
-# if "连接失败" in message:
-# logger.error(message)
-# elif "收到无效的" in message:
-# logger.warning(message)
-# elif "检测到平台" in message:
-# logger.warning(message)
-# else:
-# logger.info(message)
-
-
-# builtins.print = handle_output
diff --git a/src/message_queue.py b/src/message_queue.py
index 95d646c..3720590 100644
--- a/src/message_queue.py
+++ b/src/message_queue.py
@@ -19,6 +19,7 @@ async def get_response(request_id: str) -> dict:
await asyncio.sleep(0.2)
response = response_dict.pop(request_id)
_ = response_time_dict.pop(request_id)
+ logger.trace(f"响应信息id: {request_id} 已从响应字典中取出")
return response
@@ -27,6 +28,7 @@ async def put_response(response: dict):
now_time = time.time()
response_dict[echo_id] = response
response_time_dict[echo_id] = now_time
+ logger.trace(f"响应信息id: {echo_id} 已存入响应字典")
async def check_timeout_response() -> None:
diff --git a/src/recv_handler.py b/src/recv_handler.py
index 0465e38..09e1229 100644
--- a/src/recv_handler.py
+++ b/src/recv_handler.py
@@ -5,7 +5,7 @@ import time
import asyncio
import json
import websockets as Server
-from typing import List, Tuple, Optional
+from typing import List, Tuple, Optional, Dict, Any
import uuid
from . import MetaEventType, RealMessageType, MessageType, NoticeType
@@ -75,6 +75,7 @@ class RecvHandler:
Returns:
bool: 是否允许聊天
"""
+ logger.debug(f"群聊id: {group_id}, 用户id: {user_id}")
if group_id:
if global_config.group_list_type == "whitelist" and group_id not in global_config.group_list:
logger.warning("群聊不在聊天白名单中,消息被丢弃")
@@ -84,10 +85,10 @@ class RecvHandler:
return False
else:
if global_config.private_list_type == "whitelist" and user_id not in global_config.private_list:
- logger.warning("用户不在聊天白名单中,消息被丢弃")
+ logger.warning("私聊不在聊天白名单中,消息被丢弃")
return False
elif global_config.private_list_type == "blacklist" and user_id in global_config.private_list:
- logger.warning("用户在聊天黑名单中,消息被丢弃")
+ logger.warning("私聊在聊天黑名单中,消息被丢弃")
return False
if user_id in global_config.ban_user_id:
logger.warning("用户在全局黑名单中,消息被丢弃")
@@ -110,7 +111,7 @@ class RecvHandler:
template_info: TemplateInfo = None # 模板信息,暂时为空,等待启用
format_info: FormatInfo = FormatInfo(
content_format=["text", "image", "emoji"],
- accept_format=["text", "image", "emoji", "reply"],
+ accept_format=["text", "image", "emoji", "reply", "voice"],
) # 格式化信息
if message_type == MessageType.private:
sub_type = raw_message.get("sub_type")
@@ -169,7 +170,7 @@ class RecvHandler:
)
else:
- logger.warning("私聊消息类型不支持")
+ logger.warning(f"私聊消息类型 {sub_type} 不支持")
return None
elif message_type == MessageType.group:
sub_type = raw_message.get("sub_type")
@@ -200,7 +201,7 @@ class RecvHandler:
)
else:
- logger.warning("群聊消息类型不支持")
+ logger.warning(f"群聊消息类型 {sub_type} 不支持")
return None
additional_config: dict = {}
@@ -221,13 +222,13 @@ class RecvHandler:
# 处理实际信息
if not raw_message.get("message"):
- logger.warning("消息内容为空")
+ logger.warning("原始消息内容为空")
return None
# 获取Seg列表
seg_message: List[Seg] = await self.handle_real_message(raw_message)
if not seg_message:
- logger.warning("消息内容为空")
+ logger.warning("处理后消息内容为空")
return None
submit_seg: Seg = Seg(
type="seglist",
@@ -309,38 +310,7 @@ class RecvHandler:
case RealMessageType.share:
logger.warning("暂时不支持链接解析")
case RealMessageType.forward:
- forward_message_data = sub_message.get("data")
- if not forward_message_data:
- logger.warning("转发消息内容为空")
- return None
- forward_message_id = forward_message_data.get("id")
- request_uuid = str(uuid.uuid4())
- payload = json.dumps(
- {
- "action": "get_forward_msg",
- "params": {"message_id": forward_message_id},
- "echo": request_uuid,
- }
- )
- try:
- await self.server_connection.send(payload)
- response: dict = await get_response(request_uuid)
- except TimeoutError:
- logger.error("获取转发消息超时")
- return None
- except Exception as e:
- logger.error(f"获取转发消息失败: {str(e)}")
- return None
- logger.debug(
- f"转发消息原始格式:{json.dumps(response)[:80]}..."
- if len(json.dumps(response)) > 80
- else json.dumps(response)
- )
- response_data: dict = response.get("data")
- if not response_data:
- logger.warning("转发消息内容为空或获取失败")
- return None
- messages = response_data.get("messages")
+ messages = await self.get_forward_message(sub_message)
if not messages:
logger.warning("转发消息内容为空或获取失败")
return None
@@ -352,7 +322,7 @@ class RecvHandler:
case RealMessageType.node:
logger.warning("不支持转发消息节点解析")
case _:
- logger.warning(f"未知消息类型:{sub_message_type}")
+ logger.warning(f"未知消息类型: {sub_message_type}")
return seg_message
async def handle_text_message(self, raw_message: dict) -> Seg:
@@ -406,7 +376,7 @@ class RecvHandler:
"""这部分认为是表情包"""
return Seg(type="emoji", data=image_base64)
else:
- logger.warning(f"不支持的图片类型:{image_sub_type}")
+ logger.warning(f"不支持的图片子类型:{image_sub_type}")
return None
async def handle_at_message(self, raw_message: dict, self_id: int, group_id: int) -> Seg | None:
@@ -424,22 +394,53 @@ class RecvHandler:
if message_data:
qq_id = message_data.get("qq")
if str(self_id) == str(qq_id):
+ logger.debug("机器人被at")
self_info: dict = await get_self_info(self.server_connection)
if self_info:
- return Seg(
- type=RealMessageType.text, data=f"@<{self_info.get('nickname')}:{self_info.get('user_id')}>"
- )
+ return Seg(type="text", data=f"@<{self_info.get('nickname')}:{self_info.get('user_id')}>")
else:
return None
else:
member_info: dict = await get_member_info(self.server_connection, group_id=group_id, user_id=qq_id)
if member_info:
- return Seg(
- type=RealMessageType.text, data=f"@<{member_info.get('nickname')}:{member_info.get('user_id')}>"
- )
+ return Seg(type="text", data=f"@<{member_info.get('nickname')}:{member_info.get('user_id')}>")
else:
return None
+ async def get_forward_message(self, raw_message: dict) -> Dict[str, Any] | None:
+ forward_message_data: Dict = raw_message.get("data")
+ if not forward_message_data:
+ logger.warning("转发消息内容为空")
+ return None
+ forward_message_id = forward_message_data.get("id")
+ request_uuid = str(uuid.uuid4())
+ payload = json.dumps(
+ {
+ "action": "get_forward_msg",
+ "params": {"message_id": forward_message_id},
+ "echo": request_uuid,
+ }
+ )
+ try:
+ await self.server_connection.send(payload)
+ response: dict = await get_response(request_uuid)
+ except TimeoutError:
+ logger.error("获取转发消息超时")
+ return None
+ except Exception as e:
+ logger.error(f"获取转发消息失败: {str(e)}")
+ return None
+ logger.debug(
+ f"转发消息原始格式:{json.dumps(response)[:80]}..."
+ if len(json.dumps(response)) > 80
+ else json.dumps(response)
+ )
+ response_data: Dict = response.get("data")
+ if not response_data:
+ logger.warning("转发消息内容为空或获取失败")
+ return None
+ return response_data.get("messages")
+
async def handle_reply_message(self, raw_message: dict) -> Seg | None:
# sourcery skip: move-assign-in-block, use-named-expression
"""
@@ -497,11 +498,11 @@ class RecvHandler:
if global_config.enable_poke:
handled_message: Seg = await self.handle_poke_notify(raw_message)
else:
- logger.warning("戳一戳消息被禁用")
+ logger.warning("戳一戳消息被禁用,取消戳一戳处理")
case _:
- logger.warning("不支持的notify类型")
+ logger.warning(f"不支持的notify类型: {notice_type}.{sub_type}")
case _:
- logger.warning("不支持的notice类型")
+ logger.warning(f"不支持的notice类型: {notice_type}")
return None
if not handled_message:
logger.warning("notice处理失败或不支持")
@@ -538,6 +539,8 @@ class RecvHandler:
group_name: str = None
if fetched_group_info:
group_name = fetched_group_info.get("group_name")
+ else:
+ logger.warning("无法获取戳一戳消息所在群的名称")
group_info = GroupInfo(
platform=global_config.platform,
group_id=group_id,
@@ -581,7 +584,7 @@ class RecvHandler:
first_txt = raw_info[2].get("txt", "戳了戳")
second_txt = raw_info[4].get("txt", "")
except Exception as e:
- logger.warning(f"解析戳一戳消息失败,使用默认文本:{str(e)}")
+ logger.warning(f"解析戳一戳消息失败: {str(e)},将使用默认文本")
first_txt = "戳了戳"
second_txt = ""
"""
@@ -614,12 +617,15 @@ class RecvHandler:
return None
if image_count < 5 and image_count > 0:
# 处理图片数量小于5的情况,此时解析图片为base64
+ logger.trace("图片数量小于5,开始解析图片为base64")
return await self._recursive_parse_image_seg(handled_message, True)
elif image_count > 0:
+ logger.trace("图片数量大于等于5,开始解析图片为占位符")
# 处理图片数量大于等于5的情况,此时解析图片为占位符
return await self._recursive_parse_image_seg(handled_message, False)
else:
# 处理没有图片的情况,此时直接返回
+ logger.trace("没有图片,直接返回")
return handled_message
async def _recursive_parse_image_seg(self, seg_data: Seg, to_image: bool) -> Seg:
@@ -648,6 +654,7 @@ class RecvHandler:
return Seg(type="text", data="[表情包]")
return Seg(type="emoji", data=encoded_image)
else:
+ logger.trace(f"不处理类型: {seg_data.type}")
return seg_data
else:
if seg_data.type == "seglist":
@@ -657,12 +664,11 @@ class RecvHandler:
new_seg_list.append(parsed_seg)
return Seg(type="seglist", data=new_seg_list)
elif seg_data.type == "image":
- image_url = seg_data.data
return Seg(type="text", data="[图片]")
elif seg_data.type == "emoji":
- image_url = seg_data.data
return Seg(type="text", data="[动画表情]")
else:
+ logger.trace(f"不处理类型: {seg_data.type}")
return seg_data
async def _handle_forward_message(self, message_list: list, layer: int) -> Tuple[Seg, int] | Tuple[None, int]:
@@ -676,7 +682,7 @@ class RecvHandler:
seg_data: Seg: 处理后的消息段
image_count: int: 图片数量
"""
- seg_list = []
+ seg_list: List[Seg] = []
image_count = 0
if message_list is None:
return None, 0
@@ -693,12 +699,9 @@ class RecvHandler:
message_of_sub_message = message_of_sub_message_list[0]
if message_of_sub_message.get("type") == RealMessageType.forward:
if layer >= 3:
- full_seg_data = (
- Seg(
- type="text",
- data=("--" * layer) + f"【{user_nickname}】:【转发消息】\n",
- ),
- 0,
+ full_seg_data = Seg(
+ type="text",
+ data=("--" * layer) + f"【{user_nickname}】:【转发消息】\n",
)
else:
sub_message_data = message_of_sub_message.get("data")
@@ -719,55 +722,43 @@ class RecvHandler:
continue
text_message = sub_message_data.get("text")
seg_data = Seg(type="text", data=text_message)
+ data_list: List[Any] = []
if layer > 0:
- seg_list.append(
- Seg(
- type="seglist",
- data=[
- Seg(type="text", data=("--" * layer) + user_nickname_str),
- seg_data,
- break_seg,
- ],
- )
- )
+ data_list = [
+ Seg(type="text", data=("--" * layer) + user_nickname_str),
+ seg_data,
+ break_seg,
+ ]
else:
- seg_list.append(
- Seg(
- type="seglist",
- data=[
- Seg(type="text", data=user_nickname_str),
- seg_data,
- break_seg,
- ],
- )
- )
+ data_list = [
+ Seg(type="text", data=user_nickname_str),
+ seg_data,
+ break_seg,
+ ]
+ seg_list.append(Seg(type="seglist", data=data_list))
elif message_of_sub_message.get("type") == RealMessageType.image:
image_count += 1
image_data = message_of_sub_message.get("data")
sub_type = image_data.get("sub_type")
image_url = image_data.get("url")
+ data_list: List[Any] = []
if sub_type == 0:
seg_data = Seg(type="image", data=image_url)
else:
seg_data = Seg(type="emoji", data=image_url)
if layer > 0:
- full_seg_data = Seg(
- type="seglist",
- data=[
- Seg(type="text", data=("--" * layer) + user_nickname_str),
- seg_data,
- break_seg,
- ],
- )
+ data_list = [
+ Seg(type="text", data=("--" * layer) + user_nickname_str),
+ seg_data,
+ break_seg,
+ ]
else:
- full_seg_data = Seg(
- type="seglist",
- data=[
- Seg(type="text", data=user_nickname_str),
- seg_data,
- break_seg,
- ],
- )
+ data_list = [
+ Seg(type="text", data=user_nickname_str),
+ seg_data,
+ break_seg,
+ ]
+ full_seg_data = Seg(type="seglist", data=data_list)
seg_list.append(full_seg_data)
return Seg(type="seglist", data=seg_list), image_count
diff --git a/src/send_handler.py b/src/send_handler.py
index 6bff59b..65251f9 100644
--- a/src/send_handler.py
+++ b/src/send_handler.py
@@ -42,10 +42,12 @@ class SendHandler:
if processed_message:
if group_info and user_info:
+ logger.debug("发送群聊消息")
target_id = group_info.group_id
action = "send_group_msg"
id_name = "group_id"
elif user_info:
+ logger.debug("发送私聊消息")
target_id = user_info.user_id
action = "send_private_msg"
id_name = "user_id"
@@ -81,7 +83,7 @@ class SendHandler:
if not seg_data.data:
return []
for seg in seg_data.data:
- payload = self.process_message_by_type(seg, payload)
+ payload.extend(self.process_message_by_type(seg, payload))
else:
payload = self.process_message_by_type(seg_data, payload)
return payload
@@ -119,6 +121,9 @@ class SendHandler:
temp_list = []
temp_list.append(addon)
for i in payload:
+ if i.get("type") == "reply":
+ logger.debug("检测到多个回复,使用最新的回复")
+ continue
temp_list.append(i)
return temp_list
else:
diff --git a/src/utils.py b/src/utils.py
index a266e45..f85ad9a 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -27,6 +27,7 @@ async def get_group_info(websocket: Server.ServerConnection, group_id: int) -> d
返回值需要处理可能为空的情况
"""
+ logger.debug("获取群聊信息中")
request_uuid = str(uuid.uuid4())
payload = json.dumps({"action": "get_group_info", "params": {"group_id": group_id}, "echo": request_uuid})
try:
@@ -48,6 +49,7 @@ async def get_member_info(websocket: Server.ServerConnection, group_id: int, use
返回值需要处理可能为空的情况
"""
+ logger.debug("获取群成员信息中")
request_uuid = str(uuid.uuid4())
payload = json.dumps(
{
@@ -72,6 +74,7 @@ async def get_member_info(websocket: Server.ServerConnection, group_id: int, use
async def get_image_base64(url: str) -> str:
# sourcery skip: raise-specific-error
"""获取图片/表情包的Base64"""
+ logger.debug(f"下载图片: {url}")
http = SSLAdapter()
try:
response = http.request("GET", url, timeout=10)
@@ -85,6 +88,14 @@ async def get_image_base64(url: str) -> str:
def convert_image_to_gif(image_base64: str) -> str:
+ """
+ 将Base64编码的图片转换为GIF格式
+ Parameters:
+ image_base64: str: Base64编码的图片数据
+ Returns:
+ str: Base64编码的GIF图片数据
+ """
+ logger.debug("转换图片为GIF格式")
try:
image_bytes = base64.b64decode(image_base64)
image = Image.open(io.BytesIO(image_bytes))
@@ -105,6 +116,7 @@ async def get_self_info(websocket: Server.ServerConnection) -> dict:
Returns:
data: dict: 返回的自身信息
"""
+ logger.debug("获取自身信息中")
request_uuid = str(uuid.uuid4())
payload = json.dumps({"action": "get_login_info", "params": {}, "echo": request_uuid})
try:
@@ -141,6 +153,7 @@ async def get_stranger_info(websocket: Server.ServerConnection, user_id: int) ->
Returns:
dict: 返回的陌生人信息
"""
+ logger.debug("获取陌生人信息中")
request_uuid = str(uuid.uuid4())
payload = json.dumps({"action": "get_stranger_info", "params": {"user_id": user_id}, "echo": request_uuid})
try:
@@ -165,6 +178,7 @@ async def get_message_detail(websocket: Server.ServerConnection, message_id: str
Returns:
dict: 返回的消息详情
"""
+ logger.debug("获取消息详情中")
request_uuid = str(uuid.uuid4())
payload = json.dumps({"action": "get_msg", "params": {"message_id": message_id}, "echo": request_uuid})
try: