fix: 主要核心后端添加报错捕获机制

This commit is contained in:
DLmaster361
2025-09-28 20:38:54 +08:00
parent dfc403733f
commit 06770eb3cc
36 changed files with 357 additions and 264 deletions

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -44,9 +45,9 @@ async def get_git_version() -> VersionOut:
status="error", status="error",
message=f"{type(e).__name__}: {str(e)}", message=f"{type(e).__name__}: {str(e)}",
if_need_update=False, if_need_update=False,
current_hash="", current_hash="unknown",
current_time="", current_time="unknown",
current_version="", current_version=Config.version(),
) )
return VersionOut( return VersionOut(
if_need_update=not is_latest, if_need_update=not is_latest,

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -55,7 +56,7 @@ async def add_script(script: ScriptCreateIn = Body(...)) -> ScriptCreateOut:
@router.post( @router.post(
"/get", summary="查询脚本配置信息", response_model=ScriptGetOut, status_code=200 "/get", summary="查询脚本配置信息", response_model=ScriptGetOut, status_code=200
) )
async def get_scripts(script: ScriptGetIn = Body(...)) -> ScriptGetOut: async def get_script(script: ScriptGetIn = Body(...)) -> ScriptGetOut:
try: try:
index, data = await Config.get_script(script.scriptId) index, data = await Config.get_script(script.scriptId)

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -99,7 +100,10 @@ async def test_notify() -> OutBase:
@router.post( @router.post(
"/webhook/create", summary="创建自定义Webhook", response_model=OutBase, status_code=200 "/webhook/create",
summary="创建自定义Webhook",
response_model=OutBase,
status_code=200,
) )
async def create_webhook(webhook_data: dict = Body(...)) -> OutBase: async def create_webhook(webhook_data: dict = Body(...)) -> OutBase:
"""创建自定义Webhook""" """创建自定义Webhook"""
@@ -116,7 +120,7 @@ async def create_webhook(webhook_data: dict = Body(...)) -> OutBase:
"template": webhook_data.get("template", ""), "template": webhook_data.get("template", ""),
"enabled": webhook_data.get("enabled", True), "enabled": webhook_data.get("enabled", True),
"headers": webhook_data.get("headers", {}), "headers": webhook_data.get("headers", {}),
"method": webhook_data.get("method", "POST") "method": webhook_data.get("method", "POST"),
} }
# 获取当前配置 # 获取当前配置
@@ -127,11 +131,7 @@ async def create_webhook(webhook_data: dict = Body(...)) -> OutBase:
custom_webhooks.append(webhook_config) custom_webhooks.append(webhook_config)
# 更新配置 # 更新配置
update_data = { update_data = {"Notify": {"CustomWebhooks": custom_webhooks}}
"Notify": {
"CustomWebhooks": custom_webhooks
}
}
await Config.update_setting(update_data) await Config.update_setting(update_data)
return OutBase(message=f"Webhook '{webhook_config['name']}' 创建成功") return OutBase(message=f"Webhook '{webhook_config['name']}' 创建成功")
@@ -143,7 +143,10 @@ async def create_webhook(webhook_data: dict = Body(...)) -> OutBase:
@router.post( @router.post(
"/webhook/update", summary="更新自定义Webhook", response_model=OutBase, status_code=200 "/webhook/update",
summary="更新自定义Webhook",
response_model=OutBase,
status_code=200,
) )
async def update_webhook(webhook_data: dict = Body(...)) -> OutBase: async def update_webhook(webhook_data: dict = Body(...)) -> OutBase:
"""更新自定义Webhook""" """更新自定义Webhook"""
@@ -161,14 +164,24 @@ async def update_webhook(webhook_data: dict = Body(...)) -> OutBase:
updated = False updated = False
for i, webhook in enumerate(custom_webhooks): for i, webhook in enumerate(custom_webhooks):
if webhook.get("id") == webhook_id: if webhook.get("id") == webhook_id:
custom_webhooks[i].update({ custom_webhooks[i].update(
{
"name": webhook_data.get("name", webhook.get("name", "")), "name": webhook_data.get("name", webhook.get("name", "")),
"url": webhook_data.get("url", webhook.get("url", "")), "url": webhook_data.get("url", webhook.get("url", "")),
"template": webhook_data.get("template", webhook.get("template", "")), "template": webhook_data.get(
"enabled": webhook_data.get("enabled", webhook.get("enabled", True)), "template", webhook.get("template", "")
"headers": webhook_data.get("headers", webhook.get("headers", {})), ),
"method": webhook_data.get("method", webhook.get("method", "POST")) "enabled": webhook_data.get(
}) "enabled", webhook.get("enabled", True)
),
"headers": webhook_data.get(
"headers", webhook.get("headers", {})
),
"method": webhook_data.get(
"method", webhook.get("method", "POST")
),
}
)
updated = True updated = True
break break
@@ -176,11 +189,7 @@ async def update_webhook(webhook_data: dict = Body(...)) -> OutBase:
return OutBase(code=404, status="error", message="Webhook不存在") return OutBase(code=404, status="error", message="Webhook不存在")
# 更新配置 # 更新配置
update_data = { update_data = {"Notify": {"CustomWebhooks": custom_webhooks}}
"Notify": {
"CustomWebhooks": custom_webhooks
}
}
await Config.update_setting(update_data) await Config.update_setting(update_data)
return OutBase(message="Webhook更新成功") return OutBase(message="Webhook更新成功")
@@ -192,7 +201,10 @@ async def update_webhook(webhook_data: dict = Body(...)) -> OutBase:
@router.post( @router.post(
"/webhook/delete", summary="删除自定义Webhook", response_model=OutBase, status_code=200 "/webhook/delete",
summary="删除自定义Webhook",
response_model=OutBase,
status_code=200,
) )
async def delete_webhook(webhook_data: dict = Body(...)) -> OutBase: async def delete_webhook(webhook_data: dict = Body(...)) -> OutBase:
"""删除自定义Webhook""" """删除自定义Webhook"""
@@ -214,11 +226,7 @@ async def delete_webhook(webhook_data: dict = Body(...)) -> OutBase:
return OutBase(code=404, status="error", message="Webhook不存在") return OutBase(code=404, status="error", message="Webhook不存在")
# 更新配置 # 更新配置
update_data = { update_data = {"Notify": {"CustomWebhooks": custom_webhooks}}
"Notify": {
"CustomWebhooks": custom_webhooks
}
}
await Config.update_setting(update_data) await Config.update_setting(update_data)
return OutBase(message="Webhook删除成功") return OutBase(message="Webhook删除成功")
@@ -230,7 +238,10 @@ async def delete_webhook(webhook_data: dict = Body(...)) -> OutBase:
@router.post( @router.post(
"/webhook/test", summary="测试自定义Webhook", response_model=OutBase, status_code=200 "/webhook/test",
summary="测试自定义Webhook",
response_model=OutBase,
status_code=200,
) )
async def test_webhook(webhook_data: dict = Body(...)) -> OutBase: async def test_webhook(webhook_data: dict = Body(...)) -> OutBase:
"""测试自定义Webhook""" """测试自定义Webhook"""
@@ -242,18 +253,16 @@ async def test_webhook(webhook_data: dict = Body(...)) -> OutBase:
"template": webhook_data.get("template", ""), "template": webhook_data.get("template", ""),
"enabled": True, "enabled": True,
"headers": webhook_data.get("headers", {}), "headers": webhook_data.get("headers", {}),
"method": webhook_data.get("method", "POST") "method": webhook_data.get("method", "POST"),
} }
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
"AUTO-MAS Webhook测试", "AUTO-MAS Webhook测试",
"这是一条测试消息如果您收到此消息说明Webhook配置正确", "这是一条测试消息如果您收到此消息说明Webhook配置正确",
webhook_config webhook_config,
) )
return OutBase(message="Webhook测试成功") return OutBase(message="Webhook测试成功")
except Exception as e: except Exception as e:
return OutBase( return OutBase(code=500, status="error", message=f"Webhook测试失败: {str(e)}")
code=500, status="error", message=f"Webhook测试失败: {str(e)}"
)

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -974,7 +975,6 @@ class AppConfig(GlobalConfig):
logger.warning("Git仓库不可用返回默认版本信息") logger.warning("Git仓库不可用返回默认版本信息")
return False, "unknown", "unknown" return False, "unknown", "unknown"
try:
# 获取当前 commit # 获取当前 commit
current_commit = self.repo.head.commit current_commit = self.repo.head.commit
@@ -992,9 +992,6 @@ class AppConfig(GlobalConfig):
is_latest = bool(current_commit.hexsha == remote_commit.hexsha) is_latest = bool(current_commit.hexsha == remote_commit.hexsha)
return is_latest, commit_hash, commit_time.strftime("%Y-%m-%d %H:%M:%S") return is_latest, commit_hash, commit_time.strftime("%Y-%m-%d %H:%M:%S")
except Exception as e:
logger.warning(f"获取Git版本信息失败: {e}")
return False, "error", "error"
async def add_script( async def add_script(
self, script: Literal["MAA", "General"] self, script: Literal["MAA", "General"]
@@ -1864,7 +1861,7 @@ class AppConfig(GlobalConfig):
async def get_script_combox(self): async def get_script_combox(self):
"""获取脚本下拉框信息""" """获取脚本下拉框信息"""
logger.info("Getting script combo box information...") logger.info("开始获取脚本下拉框信息")
data = [{"label": "未选择", "value": "-"}] data = [{"label": "未选择", "value": "-"}]
for uid, script in self.ScriptConfig.items(): for uid, script in self.ScriptConfig.items():
data.append( data.append(
@@ -1873,7 +1870,7 @@ class AppConfig(GlobalConfig):
"value": str(uid), "value": str(uid),
} }
) )
logger.success("Script combo box information retrieved successfully.") logger.success("脚本下拉框信息获取成功")
return data return data
@@ -2040,7 +2037,10 @@ class AppConfig(GlobalConfig):
data["sanity"] = int(sanity_match.group(1)) data["sanity"] = int(sanity_match.group(1))
# 提取理智回满时间:理智将在 2025-09-26 18:57 回满。(17h 29m 后) # 提取理智回满时间:理智将在 2025-09-26 18:57 回满。(17h 29m 后)
sanity_full_match = re.search(r"(理智将在\s*\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s*回满。\(\d+h\s+\d+m\s+后\))", log_line) sanity_full_match = re.search(
r"(理智将在\s*\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s*回满。\(\d+h\s+\d+m\s+后\))",
log_line,
)
if sanity_full_match: if sanity_full_match:
data["sanity_full_at"] = sanity_full_match.group(1) data["sanity_full_at"] = sanity_full_match.group(1)
@@ -2150,11 +2150,11 @@ class AppConfig(GlobalConfig):
# 保存日志 # 保存日志
log_path.parent.mkdir(parents=True, exist_ok=True) log_path.parent.mkdir(parents=True, exist_ok=True)
with log_path.open("w", encoding="utf-8") as f: log_path.write_text("\n".join(logs), encoding="utf-8")
f.writelines(logs)
# 保存统计数据 # 保存统计数据
with log_path.with_suffix(".json").open("w", encoding="utf-8") as f: log_path.with_suffix(".json").write_text(
json.dump(data, f, ensure_ascii=False, indent=4) json.dumps(data, ensure_ascii=False, index=4), encoding="utf-8"
)
logger.success(f"MAA 日志统计完成, 日志路径: {log_path}") logger.success(f"MAA 日志统计完成, 日志路径: {log_path}")
@@ -2179,10 +2179,10 @@ class AppConfig(GlobalConfig):
# 保存日志 # 保存日志
log_path.parent.mkdir(parents=True, exist_ok=True) log_path.parent.mkdir(parents=True, exist_ok=True)
with log_path.with_suffix(".log").open("w", encoding="utf-8") as f: log_path.with_suffix(".log").write_text("\n".join(logs), encoding="utf-8")
f.writelines(logs) log_path.with_suffix(".json").write_text(
with log_path.with_suffix(".json").open("w", encoding="utf-8") as f: json.dumps(data, ensure_ascii=False, indent=4), encoding="utf-8"
json.dump(data, f, ensure_ascii=False, indent=4) )
logger.success(f"通用日志统计完成, 日志路径: {log_path.with_suffix('.log')}") logger.success(f"通用日志统计完成, 日志路径: {log_path.with_suffix('.log')}")
@@ -2200,8 +2200,13 @@ class AppConfig(GlobalConfig):
for json_file in statistic_path_list: for json_file in statistic_path_list:
with json_file.open("r", encoding="utf-8") as f: try:
single_data = json.load(f) single_data = json.loads(json_file.read_text(encoding="utf-8"))
except Exception as e:
logger.warning(
f"无法解析文件 {json_file}, 错误信息: {type(e).__name__}: {str(e)}"
)
continue
for key in single_data.keys(): for key in single_data.keys():

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -92,7 +93,7 @@ class _TaskManager:
return task_id return task_id
# @logger.catch @logger.catch
async def run_task( async def run_task(
self, mode: str, task_id: uuid.UUID, actual_id: Optional[uuid.UUID] self, mode: str, task_id: uuid.UUID, actual_id: Optional[uuid.UUID]
): ):
@@ -124,7 +125,17 @@ class _TaskManager:
lambda t: asyncio.create_task(task_item.final_task(t)) lambda t: asyncio.create_task(task_item.final_task(t))
) )
self.task_dict[uid].add_done_callback(partial(self.task_dict.pop, uid)) self.task_dict[uid].add_done_callback(partial(self.task_dict.pop, uid))
try:
await self.task_dict[uid] await self.task_dict[uid]
except Exception as e:
logger.error(f"任务 {task_id} 运行出错: {type(e).__name__}: {str(e)}")
await Config.send_json(
WebSocketMessage(
id=str(task_id),
type="Info",
data={"Error": f"任务运行时出错 {type(e).__name__}: {str(e)}"},
).model_dump()
)
else: else:
@@ -262,8 +273,23 @@ class _TaskManager:
self.task_dict[script_id].add_done_callback( self.task_dict[script_id].add_done_callback(
partial(self.task_dict.pop, script_id) partial(self.task_dict.pop, script_id)
) )
try:
await self.task_dict[script_id] await self.task_dict[script_id]
task["status"] = "完成" task["status"] = "完成"
except Exception as e:
logger.error(
f"任务 {script_id} 运行出错: {type(e).__name__}: {str(e)}"
)
await Config.send_json(
WebSocketMessage(
id=str(task_id),
type="Info",
data={
"Error": f"任务运行时出错 {type(e).__name__}: {str(e)}"
},
).model_dump()
)
task["status"] = "异常"
await Config.send_json( await Config.send_json(
WebSocketMessage( WebSocketMessage(
id=str(task_id), id=str(task_id),
@@ -287,7 +313,7 @@ class _TaskManager:
else: else:
uid = uuid.UUID(task_id) uid = uuid.UUID(task_id)
if uid not in self.task_dict: if uid not in self.task_dict:
raise ValueError(f"任务 {uid} 未在运行") raise ValueError("任务未在运行")
self.task_dict[uid].cancel() self.task_dict[uid].cancel()
async def remove_task( async def remove_task(

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -108,6 +109,7 @@ class _MainTimer:
).model_dump() ).model_dump()
) )
@logger.catch()
async def set_silence(self): async def set_silence(self):
"""静默模式通过模拟老板键来隐藏模拟器窗口""" """静默模式通过模拟老板键来隐藏模拟器窗口"""

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -385,9 +386,8 @@ class ConfigBase:
self.file.parent.mkdir(parents=True, exist_ok=True) self.file.parent.mkdir(parents=True, exist_ok=True)
self.file.touch() self.file.touch()
with self.file.open("r", encoding="utf-8") as f:
try: try:
data = json.load(f) data = json.loads(self.file.read_text(encoding="utf-8"))
except json.JSONDecodeError: except json.JSONDecodeError:
data = {} data = {}
@@ -499,12 +499,13 @@ class ConfigBase:
raise ValueError("文件路径未设置, 请先调用 `connect` 方法连接配置文件") raise ValueError("文件路径未设置, 请先调用 `connect` 方法连接配置文件")
self.file.parent.mkdir(parents=True, exist_ok=True) self.file.parent.mkdir(parents=True, exist_ok=True)
with self.file.open("w", encoding="utf-8") as f: self.file.write_text(
json.dump( json.dumps(
await self.toDict(not self.if_save_multi_config, if_decrypt=False), await self.toDict(not self.if_save_multi_config, if_decrypt=False),
f,
ensure_ascii=False, ensure_ascii=False,
indent=4, indent=4,
),
encoding="utf-8",
) )
async def lock(self): async def lock(self):
@@ -610,9 +611,8 @@ class MultipleConfig:
self.file.parent.mkdir(parents=True, exist_ok=True) self.file.parent.mkdir(parents=True, exist_ok=True)
self.file.touch() self.file.touch()
with self.file.open("r", encoding="utf-8") as f:
try: try:
data = json.load(f) data = json.loads(self.file.read_text(encoding="utf-8"))
except json.JSONDecodeError: except json.JSONDecodeError:
data = {} data = {}
@@ -716,8 +716,10 @@ class MultipleConfig:
raise ValueError("文件路径未设置, 请先调用 `connect` 方法连接配置文件") raise ValueError("文件路径未设置, 请先调用 `connect` 方法连接配置文件")
self.file.parent.mkdir(parents=True, exist_ok=True) self.file.parent.mkdir(parents=True, exist_ok=True)
with self.file.open("w", encoding="utf-8") as f: self.file.write_text(
json.dump(await self.toDict(), f, ensure_ascii=False, indent=4) json.dumps(await self.toDict(), ensure_ascii=False, indent=4),
encoding="utf-8",
)
async def add(self, config_type: type) -> tuple[uuid.UUID, ConfigBase]: async def add(self, config_type: type) -> tuple[uuid.UUID, ConfigBase]:
""" """

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -117,7 +118,9 @@ class CustomWebhook(BaseModel):
template: str = Field(..., description="消息模板") template: str = Field(..., description="消息模板")
enabled: bool = Field(default=True, description="是否启用") enabled: bool = Field(default=True, description="是否启用")
headers: Optional[Dict[str, str]] = Field(default=None, description="自定义请求头") headers: Optional[Dict[str, str]] = Field(default=None, description="自定义请求头")
method: Optional[Literal["POST", "GET"]] = Field(default="POST", description="请求方法") method: Optional[Literal["POST", "GET"]] = Field(
default="POST", description="请求方法"
)
class GlobalConfig_Notify(BaseModel): class GlobalConfig_Notify(BaseModel):

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -23,7 +24,6 @@ import asyncio
import aiohttp import aiohttp
import json import json
import uuid import uuid
import psutil
import platform import platform
import time import time
from typing import Dict, Any, Optional from typing import Dict, Any, Optional

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -183,11 +184,15 @@ class Notification:
raise ValueError("Webhook URL 不能为空") raise ValueError("Webhook URL 不能为空")
if not webhook_config.get("enabled", True): if not webhook_config.get("enabled", True):
logger.info(f"Webhook {webhook_config.get('name', 'Unknown')} 已禁用,跳过推送") logger.info(
f"Webhook {webhook_config.get('name', 'Unknown')} 已禁用,跳过推送"
)
return return
# 解析模板 # 解析模板
template = webhook_config.get("template", '{"title": "{title}", "content": "{content}"}') template = webhook_config.get(
"template", '{"title": "{title}", "content": "{content}"}'
)
# 替换模板变量 # 替换模板变量
try: try:
@@ -200,7 +205,7 @@ class Notification:
"content": content, "content": content,
"datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"date": datetime.now().strftime("%Y-%m-%d"), "date": datetime.now().strftime("%Y-%m-%d"),
"time": datetime.now().strftime("%H:%M:%S") "time": datetime.now().strftime("%H:%M:%S"),
} }
logger.debug(f"原始模板: {template}") logger.debug(f"原始模板: {template}")
@@ -234,8 +239,15 @@ class Notification:
formatted_template = template formatted_template = template
for key, value in template_vars.items(): for key, value in template_vars.items():
# 转义特殊字符以避免JSON解析错误 # 转义特殊字符以避免JSON解析错误
safe_value = str(value).replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') safe_value = (
formatted_template = formatted_template.replace(f"{{{key}}}", safe_value) str(value)
.replace('"', '\\"')
.replace("\n", "\\n")
.replace("\r", "\\r")
)
formatted_template = formatted_template.replace(
f"{{{key}}}", safe_value
)
# 再次尝试解析为JSON # 再次尝试解析为JSON
try: try:
@@ -266,7 +278,7 @@ class Notification:
json=data, json=data,
headers=headers, headers=headers,
timeout=10, timeout=10,
proxies=Config.get_proxies() proxies=Config.get_proxies(),
) )
else: else:
response = requests.post( response = requests.post(
@@ -274,7 +286,7 @@ class Notification:
data=data, data=data,
headers=headers, headers=headers,
timeout=10, timeout=10,
proxies=Config.get_proxies() proxies=Config.get_proxies(),
) )
else: # GET else: # GET
params = data if isinstance(data, dict) else {"message": data} params = data if isinstance(data, dict) else {"message": data}
@@ -283,17 +295,21 @@ class Notification:
params=params, params=params,
headers=headers, headers=headers,
timeout=10, timeout=10,
proxies=Config.get_proxies() proxies=Config.get_proxies(),
) )
# 检查响应 # 检查响应
if response.status_code == 200: if response.status_code == 200:
logger.success(f"自定义Webhook推送成功: {webhook_config.get('name', 'Unknown')} - {title}") logger.success(
f"自定义Webhook推送成功: {webhook_config.get('name', 'Unknown')} - {title}"
)
else: else:
raise Exception(f"HTTP {response.status_code}: {response.text}") raise Exception(f"HTTP {response.status_code}: {response.text}")
except Exception as e: except Exception as e:
raise Exception(f"自定义Webhook推送失败 ({webhook_config.get('name', 'Unknown')}): {str(e)}") raise Exception(
f"自定义Webhook推送失败 ({webhook_config.get('name', 'Unknown')}): {str(e)}"
)
async def WebHookPush(self, title, content, webhook_url) -> None: async def WebHookPush(self, title, content, webhook_url) -> None:
""" """
@@ -401,10 +417,12 @@ class Notification:
await self.CustomWebhookPush( await self.CustomWebhookPush(
"AUTO-MAS测试通知", "AUTO-MAS测试通知",
"这是 AUTO-MAS 外部通知测试信息。如果你看到了这段内容, 说明 AUTO-MAS 的通知功能已经正确配置且可以正常工作!", "这是 AUTO-MAS 外部通知测试信息。如果你看到了这段内容, 说明 AUTO-MAS 的通知功能已经正确配置且可以正常工作!",
webhook webhook,
) )
except Exception as e: except Exception as e:
logger.error(f"自定义Webhook测试失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"自定义Webhook测试失败 ({webhook.get('name', 'Unknown')}): {e}"
)
logger.success("测试通知发送完成") logger.success("测试通知发送完成")

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -1907,12 +1908,12 @@ class MaaManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, f"{message_text}\n\nAUTO-MAS 敬上", webhook
f"{message_text}\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
elif mode == "统计信息": elif mode == "统计信息":
@@ -1973,12 +1974,12 @@ class MaaManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, f"{message_text}\n\nAUTO-MAS 敬上", webhook
f"{message_text}\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
# 发送用户单独通知 # 发送用户单独通知
if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get( if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get(
@@ -2023,12 +2024,12 @@ class MaaManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, f"{message_text}\n\nAUTO-MAS 敬上", webhook
f"{message_text}\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"用户自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"用户自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
else: else:
logger.error( logger.error(
"用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知" "用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知"
@@ -2066,12 +2067,12 @@ class MaaManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, "好羡慕~\n\nAUTO-MAS 敬上", webhook
"好羡慕~\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
# 发送用户单独通知 # 发送用户单独通知
if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get( if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get(
@@ -2117,12 +2118,12 @@ class MaaManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, "好羡慕~\n\nAUTO-MAS 敬上", webhook
"好羡慕~\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"用户自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"用户自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
else: else:
logger.error( logger.error(
"用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知" "用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知"

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -992,12 +993,12 @@ class GeneralManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, f"{message_text}\n\nAUTO-MAS 敬上", webhook
f"{message_text}\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
elif mode == "统计信息": elif mode == "统计信息":
@@ -1039,12 +1040,12 @@ class GeneralManager:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, f"{message_text}\n\nAUTO-MAS 敬上", webhook
f"{message_text}\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
# 发送用户单独通知 # 发送用户单独通知
if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get( if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get(
@@ -1078,18 +1079,18 @@ class GeneralManager:
# 推送CompanyWebHookBot通知 # 推送CompanyWebHookBot通知
# 发送用户自定义Webhook通知 # 发送用户自定义Webhook通知
user_webhooks = self.cur_user_data.get("Notify", {}).get("CustomWebhooks", []) user_webhooks = self.cur_user_data.get("Notify", "CustomWebhooks")
if user_webhooks: if user_webhooks:
for webhook in user_webhooks: for webhook in user_webhooks:
if webhook.get("enabled", True): if webhook.get("enabled", True):
try: try:
await Notify.CustomWebhookPush( await Notify.CustomWebhookPush(
title, title, f"{message_text}\n\nAUTO-MAS 敬上", webhook
f"{message_text}\n\nAUTO-MAS 敬上",
webhook
) )
except Exception as e: except Exception as e:
logger.error(f"用户自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}") logger.error(
f"用户自定义Webhook推送失败 ({webhook.get('name', 'Unknown')}): {e}"
)
else: else:
logger.error( logger.error(
"用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知" "用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知"

View File

@@ -7,6 +7,7 @@
# #
# skland-checkin-ghaction Copyright © 2023 Yanstory # skland-checkin-ghaction Copyright © 2023 Yanstory
# https://github.com/Yanstory/skland-checkin-ghaction # https://github.com/Yanstory/skland-checkin-ghaction
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2025 ClozyA # Copyright © 2025 ClozyA
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 ClozyA # Copyright © 2025 ClozyA
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,5 +1,6 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.

View File

@@ -1,6 +1,7 @@
# AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software
# Copyright © 2024-2025 DLmaster361 # Copyright © 2024-2025 DLmaster361
# Copyright © 2025 MoeSnowyFox # Copyright © 2025 MoeSnowyFox
# Copyright © 2025 AUTO-MAS Team
# This file is part of AUTO-MAS. # This file is part of AUTO-MAS.
@@ -61,7 +62,7 @@ def is_admin() -> bool:
return False return False
# @logger.catch @logger.catch
def main(): def main():
if is_admin(): if is_admin():