转换消息

pull/1195/head
UnCLAS-Prommer 2025-08-19 01:05:20 +08:00
parent 9379834171
commit 7a68ab0319
No known key found for this signature in database
3 changed files with 142 additions and 96 deletions

View File

@ -2,13 +2,14 @@ import time # 导入 time 模块以获取当前时间
import random
import re
from typing import List, Dict, Any, Tuple, Optional, Callable
from typing import List, Dict, Any, Tuple, Optional, Callable, Union
from rich.traceback import install
from src.config.config import global_config
from src.common.logger import get_logger
from src.common.message_repository import find_messages, count_messages
from src.common.data_models.database_data_model import DatabaseMessages
from src.common.data_models.message_data_model import MessageAndActionModel
from src.common.database.database_model import ActionRecords
from src.common.database.database_model import Images
from src.person_info.person_info import Person, get_person_id
@ -394,7 +395,7 @@ def num_new_messages_since_with_users(
def _build_readable_messages_internal(
messages: List[Dict[str, Any]],
messages: List[MessageAndActionModel],
replace_bot_name: bool = True,
merge_messages: bool = False,
timestamp_mode: str = "relative",
@ -402,7 +403,7 @@ def _build_readable_messages_internal(
pic_id_mapping: Optional[Dict[str, str]] = None,
pic_counter: int = 1,
show_pic: bool = True,
message_id_list: Optional[List[Dict[str, Any]]] = None,
message_id_list: Optional[List[DatabaseMessages]] = None,
) -> Tuple[str, List[Tuple[float, str, str]], Dict[str, str], int]:
"""
内部辅助函数构建可读消息字符串和原始消息详情列表
@ -433,14 +434,15 @@ def _build_readable_messages_internal(
timestamp_to_id = {}
if message_id_list:
for item in message_id_list:
message = item.get("message", {})
timestamp = message.get("time")
timestamp = item.time
if timestamp is not None:
timestamp_to_id[timestamp] = item.get("id", "")
timestamp_to_id[timestamp] = item.message_id
def process_pic_ids(content: str) -> str:
def process_pic_ids(content: Optional[str]) -> str:
"""处理内容中的图片ID将其替换为[图片x]格式"""
nonlocal current_pic_counter
if content is None:
logger.warning("Content is None when processing pic IDs.")
raise ValueError("Content is None")
# 匹配 [picid:xxxxx] 格式
pic_pattern = r"\[picid:([^\]]+)\]"
@ -460,38 +462,23 @@ def _build_readable_messages_internal(
# 1 & 2: 获取发送者信息并提取消息组件
for msg in messages:
# 检查是否是动作记录
if msg.get("is_action_record", False):
if msg.is_action_record:
is_action = True
timestamp: float = msg.get("time") # type: ignore
content = msg.get("display_message", "")
timestamp: float = msg.time
content = msg.display_message
# 对于动作记录也处理图片ID
content = process_pic_ids(content)
message_details_raw.append((timestamp, global_config.bot.nickname, content, is_action))
continue
# 检查并修复缺少的user_info字段
if "user_info" not in msg:
# 创建user_info字段
msg["user_info"] = {
"platform": msg.get("user_platform", ""),
"user_id": msg.get("user_id", ""),
"user_nickname": msg.get("user_nickname", ""),
"user_cardname": msg.get("user_cardname", ""),
}
platform = msg.user_platform
user_id = msg.user_id
user_info = msg.get("user_info", {})
platform = user_info.get("platform")
user_id = user_info.get("user_id")
user_nickname = msg.user_nickname
user_cardname = msg.user_cardname
user_nickname = user_info.get("user_nickname")
user_cardname = user_info.get("user_cardname")
timestamp: float = msg.get("time") # type: ignore
content: str
if msg.get("display_message"):
content = msg.get("display_message", "")
else:
content = msg.get("processed_plain_text", "") # 默认空字符串
timestamp = msg.time
content = msg.display_message or msg.processed_plain_text or ""
if "" in content:
content = content.replace("", "")
@ -819,7 +806,7 @@ def build_readable_messages(
truncate: bool = False,
show_actions: bool = False,
show_pic: bool = True,
message_id_list: Optional[List[Dict[str, Any]]] = None,
message_id_list: Optional[List[DatabaseMessages]] = None,
) -> str: # sourcery skip: extract-method
"""
将消息列表转换为可读的文本格式
@ -835,11 +822,24 @@ def build_readable_messages(
truncate: 是否截断长消息
show_actions: 是否显示动作记录
"""
# WIP HERE and BELOW ----------------------------------------------
# 创建messages的深拷贝避免修改原始列表
if not messages:
return ""
copy_messages = list(messages)
copy_messages: List[MessageAndActionModel] = [
MessageAndActionModel(
msg.time,
msg.user_info.user_id,
msg.user_info.platform,
msg.user_info.user_nickname,
msg.user_info.user_cardname,
msg.processed_plain_text,
msg.display_message,
msg.chat_info.platform,
)
for msg in messages
]
if show_actions and copy_messages:
# 获取所有消息的时间范围
@ -847,7 +847,7 @@ def build_readable_messages(
max_time = max(msg.time or 0 for msg in copy_messages)
# 从第一条消息中获取chat_id
chat_id = copy_messages[0].chat_id if copy_messages else None
chat_id = messages[0].chat_id if messages else None
# 获取这个时间范围内的动作记录并匹配chat_id
actions_in_range = (
@ -867,23 +867,24 @@ def build_readable_messages(
)
# 合并两部分动作记录
actions = list(actions_in_range) + list(action_after_latest)
actions: List[ActionRecords] = list(actions_in_range) + list(action_after_latest)
# 将动作记录转换为消息格式
for action in actions:
# 只有当build_into_prompt为True时才添加动作记录
if action.action_build_into_prompt:
action_msg = {
"time": action.time,
"user_id": global_config.bot.qq_account, # 使用机器人的QQ账号
"user_nickname": global_config.bot.nickname, # 使用机器人的昵称
"user_cardname": "", # 机器人没有群名片
"processed_plain_text": f"{action.action_prompt_display}",
"display_message": f"{action.action_prompt_display}",
"chat_info_platform": action.chat_info_platform,
"is_action_record": True, # 添加标识字段
"action_name": action.action_name, # 保存动作名称
}
action_msg = MessageAndActionModel(
time=float(action.time), # type: ignore
user_id=global_config.bot.qq_account, # 使用机器人的QQ账号
user_platform=global_config.bot.platform, # 使用机器人的平台
user_nickname=global_config.bot.nickname, # 使用机器人的用户名
user_cardname="", # 机器人没有群名片
processed_plain_text=f"{action.action_prompt_display}",
display_message=f"{action.action_prompt_display}",
chat_info_platform=str(action.chat_info_platform),
is_action_record=True, # 添加标识字段
action_name=str(action.action_name), # 保存动作名称
)
copy_messages.append(action_msg)
# 重新按时间排序

View File

@ -56,70 +56,99 @@ class DatabaseChatInfo(AbstractClassFlag):
@dataclass(init=False)
class DatabaseMessages(AbstractClassFlag):
message_id: str = field(default_factory=str)
time: float = field(default_factory=float)
chat_id: str = field(default_factory=str)
reply_to: Optional[str] = None
interest_value: Optional[float] = None
def __init__(
self,
message_id: str = "",
time: float = 0.0,
chat_id: str = "",
reply_to: Optional[str] = None,
interest_value: Optional[float] = None,
key_words: Optional[str] = None,
key_words_lite: Optional[str] = None,
is_mentioned: Optional[bool] = None,
processed_plain_text: Optional[str] = None,
display_message: Optional[str] = None,
priority_mode: Optional[str] = None,
priority_info: Optional[str] = None,
additional_config: Optional[str] = None,
is_emoji: bool = False,
is_picid: bool = False,
is_command: bool = False,
is_notify: bool = False,
selected_expressions: Optional[str] = None,
user_id: str = "",
user_nickname: str = "",
user_cardname: Optional[str] = None,
user_platform: str = "",
chat_info_group_id: Optional[str] = None,
chat_info_group_name: Optional[str] = None,
chat_info_group_platform: Optional[str] = None,
chat_info_user_id: str = "",
chat_info_user_nickname: str = "",
chat_info_user_cardname: Optional[str] = None,
chat_info_user_platform: str = "",
chat_info_stream_id: str = "",
chat_info_platform: str = "",
chat_info_create_time: float = 0.0,
chat_info_last_active_time: float = 0.0,
**kwargs: Any,
):
self.message_id = message_id
self.time = time
self.chat_id = chat_id
self.reply_to = reply_to
self.interest_value = interest_value
key_words: Optional[str] = None
key_words_lite: Optional[str] = None
is_mentioned: Optional[bool] = None
self.key_words = key_words
self.key_words_lite = key_words_lite
self.is_mentioned = is_mentioned
processed_plain_text: Optional[str] = None # 处理后的纯文本消息
display_message: Optional[str] = None # 显示的消息
self.processed_plain_text = processed_plain_text
self.display_message = display_message
priority_mode: Optional[str] = None
priority_info: Optional[str] = None
self.priority_mode = priority_mode
self.priority_info = priority_info
additional_config: Optional[str] = None
is_emoji: bool = False
is_picid: bool = False
is_command: bool = False
is_notify: bool = False
self.additional_config = additional_config
self.is_emoji = is_emoji
self.is_picid = is_picid
self.is_command = is_command
self.is_notify = is_notify
selected_expressions: Optional[str] = None
self.selected_expressions = selected_expressions
def __init__(self, **kwargs: Any):
defined = {f.name: f for f in fields(self.__class__)}
for name, f in defined.items():
if name in kwargs:
setattr(self, name, kwargs.pop(name))
elif f.default is not MISSING:
setattr(self, name, f.default)
else:
raise TypeError(f"缺失必需字段: {name}")
self.group_info = None
self.group_info: Optional[DatabaseGroupInfo] = None
self.user_info = DatabaseUserInfo(
user_id=kwargs.get("user_id"), # type: ignore
user_nickname=kwargs.get("user_nickname"), # type: ignore
user_cardname=kwargs.get("user_cardname"), # type: ignore
platform=kwargs.get("user_platform"), # type: ignore
user_id=user_id,
user_nickname=user_nickname,
user_cardname=user_cardname,
platform=user_platform,
)
if kwargs.get("chat_info_group_id") and kwargs.get("chat_info_group_name"):
if chat_info_group_id and chat_info_group_name:
self.group_info = DatabaseGroupInfo(
group_id=kwargs.get("chat_info_group_id"), # type: ignore
group_name=kwargs.get("chat_info_group_name"), # type: ignore
group_platform=kwargs.get("chat_info_group_platform"), # type: ignore
group_id=chat_info_group_id,
group_name=chat_info_group_name,
group_platform=chat_info_group_platform,
)
chat_user_info = DatabaseUserInfo(
user_id=kwargs.get("chat_info_user_id"), # type: ignore
user_nickname=kwargs.get("chat_info_user_nickname"), # type: ignore
user_cardname=kwargs.get("chat_info_user_cardname"), # type: ignore
platform=kwargs.get("chat_info_user_platform"), # type: ignore
)
self.chat_info = DatabaseChatInfo(
stream_id=kwargs.get("chat_info_stream_id"), # type: ignore
platform=kwargs.get("chat_info_platform"), # type: ignore
create_time=kwargs.get("chat_info_create_time"), # type: ignore
last_active_time=kwargs.get("chat_info_last_active_time"), # type: ignore
user_info=chat_user_info,
stream_id=chat_info_stream_id,
platform=chat_info_platform,
create_time=chat_info_create_time,
last_active_time=chat_info_last_active_time,
user_info=DatabaseUserInfo(
user_id=chat_info_user_id,
user_nickname=chat_info_user_nickname,
user_cardname=chat_info_user_cardname,
platform=chat_info_user_platform,
),
group_info=self.group_info,
)
if kwargs:
for key, value in kwargs.items():
setattr(self, key, value)
# def __post_init__(self):
# assert isinstance(self.message_id, str), "message_id must be a string"
# assert isinstance(self.time, float), "time must be a float"

View File

@ -0,0 +1,16 @@
from typing import Optional
from dataclasses import dataclass, field
@dataclass
class MessageAndActionModel:
time: float = field(default_factory=float)
user_id: str = field(default_factory=str)
user_platform: str = field(default_factory=str)
user_nickname: str = field(default_factory=str)
user_cardname: Optional[str] = None
processed_plain_text: Optional[str] = None
display_message: Optional[str] = None
chat_info_platform: str = field(default_factory=str)
is_action_record: bool = field(default=False)
action_name: Optional[str] = None