mirror of https://github.com/Mai-with-u/MaiBot.git
commit
991306b04a
|
|
@ -39,6 +39,11 @@ class HeartFCMessageReceiver:
|
||||||
message_data: 原始消息字符串
|
message_data: 原始消息字符串
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# 通知消息不处理
|
||||||
|
if message.is_notify:
|
||||||
|
logger.debug("通知消息,跳过处理")
|
||||||
|
return
|
||||||
|
|
||||||
# 1. 消息解析与初始化
|
# 1. 消息解析与初始化
|
||||||
userinfo = message.message_info.user_info
|
userinfo = message.message_info.user_info
|
||||||
chat = message.chat_stream
|
chat = message.chat_stream
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,11 @@ class MessageStorage:
|
||||||
async def store_message(message: Union[MessageSending, MessageRecv], chat_stream: ChatStream) -> None:
|
async def store_message(message: Union[MessageSending, MessageRecv], chat_stream: ChatStream) -> None:
|
||||||
"""存储消息到数据库"""
|
"""存储消息到数据库"""
|
||||||
try:
|
try:
|
||||||
|
# 通知消息不存储
|
||||||
|
if isinstance(message, MessageRecv) and message.is_notify:
|
||||||
|
logger.debug("通知消息,跳过存储")
|
||||||
|
return
|
||||||
|
|
||||||
pattern = r"<MainRule>.*?</MainRule>|<schedule>.*?</schedule>|<UserMessage>.*?</UserMessage>"
|
pattern = r"<MainRule>.*?</MainRule>|<schedule>.*?</schedule>|<UserMessage>.*?</UserMessage>"
|
||||||
|
|
||||||
# print(message)
|
# print(message)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
"""
|
||||||
|
TOML 工具函数
|
||||||
|
|
||||||
|
提供 TOML 文件的格式化保存功能,确保数组等元素以美观的多行格式输出。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
import tomlkit
|
||||||
|
from tomlkit.items import AoT, Table, Array
|
||||||
|
|
||||||
|
|
||||||
|
def _format_toml_value(obj: Any, threshold: int, depth: int = 0) -> Any:
|
||||||
|
"""递归格式化 TOML 值,将数组转换为多行格式"""
|
||||||
|
# 处理 AoT (Array of Tables) - 保持原样,递归处理内部
|
||||||
|
if isinstance(obj, AoT):
|
||||||
|
for item in obj:
|
||||||
|
_format_toml_value(item, threshold, depth)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# 处理字典类型 (dict 或 Table)
|
||||||
|
if isinstance(obj, (dict, Table)):
|
||||||
|
for k, v in obj.items():
|
||||||
|
obj[k] = _format_toml_value(v, threshold, depth)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# 处理列表类型 (list 或 Array)
|
||||||
|
if isinstance(obj, (list, Array)):
|
||||||
|
# 如果是纯 list (非 tomlkit Array) 且包含字典/表,视为 AoT 的列表形式
|
||||||
|
# 保持结构递归处理,避免转换为 Inline Table Array (因为 Inline Table 必须单行,复杂对象不友好)
|
||||||
|
if isinstance(obj, list) and not isinstance(obj, Array) and obj and isinstance(obj[0], (dict, Table)):
|
||||||
|
for i, item in enumerate(obj):
|
||||||
|
obj[i] = _format_toml_value(item, threshold, depth)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# 决定是否多行:仅在顶层且长度超过阈值时
|
||||||
|
should_multiline = (depth == 0 and len(obj) > threshold)
|
||||||
|
|
||||||
|
# 如果已经是 tomlkit Array,原地修改以保留注释
|
||||||
|
if isinstance(obj, Array):
|
||||||
|
obj.multiline(should_multiline)
|
||||||
|
for i, item in enumerate(obj):
|
||||||
|
obj[i] = _format_toml_value(item, threshold, depth + 1)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# 普通 list:转换为 tomlkit 数组
|
||||||
|
arr = tomlkit.array()
|
||||||
|
arr.multiline(should_multiline)
|
||||||
|
|
||||||
|
for item in obj:
|
||||||
|
arr.append(_format_toml_value(item, threshold, depth + 1))
|
||||||
|
return arr
|
||||||
|
|
||||||
|
# 其他基本类型直接返回
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def save_toml_with_format(data: Any, file_path: str, multiline_threshold: int = 1) -> None:
|
||||||
|
"""格式化 TOML 数据并保存到文件"""
|
||||||
|
formatted = _format_toml_value(data, multiline_threshold) if multiline_threshold >= 0 else data
|
||||||
|
with open(file_path, "w", encoding="utf-8") as f:
|
||||||
|
tomlkit.dump(formatted, f)
|
||||||
|
|
||||||
|
|
||||||
|
def format_toml_string(data: Any, multiline_threshold: int = 1) -> str:
|
||||||
|
"""格式化 TOML 数据并返回字符串"""
|
||||||
|
formatted = _format_toml_value(data, multiline_threshold) if multiline_threshold >= 0 else data
|
||||||
|
return tomlkit.dumps(formatted)
|
||||||
|
|
@ -11,6 +11,7 @@ from rich.traceback import install
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
|
from src.common.toml_utils import format_toml_string
|
||||||
from src.config.config_base import ConfigBase
|
from src.config.config_base import ConfigBase
|
||||||
from src.config.official_configs import (
|
from src.config.official_configs import (
|
||||||
BotConfig,
|
BotConfig,
|
||||||
|
|
@ -252,7 +253,7 @@ def _update_config_generic(config_name: str, template_name: str):
|
||||||
# 如果配置有更新,立即保存到文件
|
# 如果配置有更新,立即保存到文件
|
||||||
if config_updated:
|
if config_updated:
|
||||||
with open(old_config_path, "w", encoding="utf-8") as f:
|
with open(old_config_path, "w", encoding="utf-8") as f:
|
||||||
f.write(tomlkit.dumps(old_config))
|
f.write(format_toml_string(old_config))
|
||||||
logger.info(f"已保存更新后的{config_name}配置文件")
|
logger.info(f"已保存更新后的{config_name}配置文件")
|
||||||
else:
|
else:
|
||||||
logger.info(f"未检测到{config_name}模板默认值变动")
|
logger.info(f"未检测到{config_name}模板默认值变动")
|
||||||
|
|
@ -313,9 +314,9 @@ def _update_config_generic(config_name: str, template_name: str):
|
||||||
logger.info(f"开始合并{config_name}新旧配置...")
|
logger.info(f"开始合并{config_name}新旧配置...")
|
||||||
_update_dict(new_config, old_config)
|
_update_dict(new_config, old_config)
|
||||||
|
|
||||||
# 保存更新后的配置(保留注释和格式)
|
# 保存更新后的配置(保留注释和格式,数组多行格式化)
|
||||||
with open(new_config_path, "w", encoding="utf-8") as f:
|
with open(new_config_path, "w", encoding="utf-8") as f:
|
||||||
f.write(tomlkit.dumps(new_config))
|
f.write(format_toml_string(new_config))
|
||||||
logger.info(f"{config_name}配置文件更新完成,建议检查新配置文件中的内容,以免丢失重要信息")
|
logger.info(f"{config_name}配置文件更新完成,建议检查新配置文件中的内容,以免丢失重要信息")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from fastapi import APIRouter, HTTPException, Body
|
||||||
from typing import Any, Annotated
|
from typing import Any, Annotated
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
|
from src.common.toml_utils import save_toml_with_format
|
||||||
from src.config.config import Config, APIAdapterConfig, CONFIG_DIR, PROJECT_ROOT
|
from src.config.config import Config, APIAdapterConfig, CONFIG_DIR, PROJECT_ROOT
|
||||||
from src.config.official_configs import (
|
from src.config.official_configs import (
|
||||||
BotConfig,
|
BotConfig,
|
||||||
|
|
@ -237,10 +238,9 @@ async def update_bot_config(config_data: ConfigBody):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
||||||
|
|
||||||
# 保存配置文件
|
# 保存配置文件(格式化数组为多行)
|
||||||
config_path = os.path.join(CONFIG_DIR, "bot_config.toml")
|
config_path = os.path.join(CONFIG_DIR, "bot_config.toml")
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
save_toml_with_format(config_data, config_path)
|
||||||
tomlkit.dump(config_data, f)
|
|
||||||
|
|
||||||
logger.info("麦麦主程序配置已更新")
|
logger.info("麦麦主程序配置已更新")
|
||||||
return {"success": True, "message": "配置已保存"}
|
return {"success": True, "message": "配置已保存"}
|
||||||
|
|
@ -261,10 +261,9 @@ async def update_model_config(config_data: ConfigBody):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
||||||
|
|
||||||
# 保存配置文件
|
# 保存配置文件(格式化数组为多行)
|
||||||
config_path = os.path.join(CONFIG_DIR, "model_config.toml")
|
config_path = os.path.join(CONFIG_DIR, "model_config.toml")
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
save_toml_with_format(config_data, config_path)
|
||||||
tomlkit.dump(config_data, f)
|
|
||||||
|
|
||||||
logger.info("模型配置已更新")
|
logger.info("模型配置已更新")
|
||||||
return {"success": True, "message": "配置已保存"}
|
return {"success": True, "message": "配置已保存"}
|
||||||
|
|
@ -312,9 +311,8 @@ async def update_bot_config_section(section_name: str, section_data: SectionBody
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
||||||
|
|
||||||
# 保存配置(tomlkit.dump 会保留注释)
|
# 保存配置(格式化数组为多行,保留注释)
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
save_toml_with_format(config_data, config_path)
|
||||||
tomlkit.dump(config_data, f)
|
|
||||||
|
|
||||||
logger.info(f"配置节 '{section_name}' 已更新(保留注释)")
|
logger.info(f"配置节 '{section_name}' 已更新(保留注释)")
|
||||||
return {"success": True, "message": f"配置节 '{section_name}' 已保存"}
|
return {"success": True, "message": f"配置节 '{section_name}' 已保存"}
|
||||||
|
|
@ -411,9 +409,8 @@ async def update_model_config_section(section_name: str, section_data: SectionBo
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
raise HTTPException(status_code=400, detail=f"配置数据验证失败: {str(e)}") from e
|
||||||
|
|
||||||
# 保存配置(tomlkit.dump 会保留注释)
|
# 保存配置(格式化数组为多行,保留注释)
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
save_toml_with_format(config_data, config_path)
|
||||||
tomlkit.dump(config_data, f)
|
|
||||||
|
|
||||||
logger.info(f"配置节 '{section_name}' 已更新(保留注释)")
|
logger.info(f"配置节 '{section_name}' 已更新(保留注释)")
|
||||||
return {"success": True, "message": f"配置节 '{section_name}' 已保存"}
|
return {"success": True, "message": f"配置节 '{section_name}' 已保存"}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from typing import Optional, List, Dict, Any
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import json
|
import json
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
|
from src.common.toml_utils import save_toml_with_format
|
||||||
from src.config.config import MMC_VERSION
|
from src.config.config import MMC_VERSION
|
||||||
from .git_mirror_service import get_git_mirror_service, set_update_progress_callback
|
from .git_mirror_service import get_git_mirror_service, set_update_progress_callback
|
||||||
from .token_manager import get_token_manager
|
from .token_manager import get_token_manager
|
||||||
|
|
@ -1416,8 +1417,7 @@ async def update_plugin_config(
|
||||||
# 更新值
|
# 更新值
|
||||||
for key, value in request.config.items():
|
for key, value in request.config.items():
|
||||||
existing_doc[key] = value
|
existing_doc[key] = value
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
save_toml_with_format(existing_doc, str(config_path))
|
||||||
tomlkit.dump(existing_doc, f)
|
|
||||||
|
|
||||||
logger.info(f"已更新插件配置: {plugin_id}")
|
logger.info(f"已更新插件配置: {plugin_id}")
|
||||||
|
|
||||||
|
|
@ -1544,9 +1544,8 @@ async def toggle_plugin(plugin_id: str, authorization: Optional[str] = Header(No
|
||||||
new_enabled = not current_enabled
|
new_enabled = not current_enabled
|
||||||
config["plugin"]["enabled"] = new_enabled
|
config["plugin"]["enabled"] = new_enabled
|
||||||
|
|
||||||
# 写入配置(保留注释)
|
# 写入配置(保留注释,格式化数组)
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
save_toml_with_format(config, str(config_path))
|
||||||
tomlkit.dump(config, f)
|
|
||||||
|
|
||||||
status = "启用" if new_enabled else "禁用"
|
status = "启用" if new_enabled else "禁用"
|
||||||
logger.info(f"已{status}插件: {plugin_id}")
|
logger.info(f"已{status}插件: {plugin_id}")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue