fix: 修整所有日志与报错为中文

This commit is contained in:
DLmaster361
2025-08-30 20:30:43 +08:00
parent 389e06cf9e
commit f62740f20b
20 changed files with 363 additions and 422 deletions

View File

@@ -325,7 +325,7 @@ class MaaUserConfig(ConfigBase):
"Stage_Remain": plan.get_current_info("Stage_Remain").getValue(),
}
else:
raise ValueError("Invalid plan type")
raise ValueError("不存在的计划表配置")
class MaaConfig(ConfigBase):
@@ -438,7 +438,7 @@ class MaaPlanConfig(ConfigBase):
return self.config_item_dict["ALL"][name]
else:
raise ValueError("The mode is invalid.")
raise ValueError("非法的计划表模式")
class GeneralUserConfig(ConfigBase):
@@ -571,8 +571,8 @@ class AppConfig(GlobalConfig):
logger.info("")
logger.info("===================================")
logger.info("AUTO_MAA 后端应用程序")
logger.info(f"版本号 v{self.VERSION}")
logger.info(f"工作目录 {Path.cwd()}")
logger.info(f"版本号: v{self.VERSION}")
logger.info(f"工作目录: {Path.cwd()}")
logger.info("===================================")
self.log_path = Path.cwd() / "debug/app.log"
@@ -640,7 +640,7 @@ class AppConfig(GlobalConfig):
# v1.7-->v1.8
if version[0][0] == "v1.7" or if_streaming:
logger.info(
"数据文件版本更新v1.7-->v1.8",
"数据文件版本更新: v1.7-->v1.8",
)
if_streaming = True
@@ -675,7 +675,7 @@ class AppConfig(GlobalConfig):
# v1.8-->v1.9
if version[0][0] == "v1.8" or if_streaming:
logger.info(
"数据文件版本更新v1.8-->v1.9",
"数据文件版本更新: v1.8-->v1.9",
)
if_streaming = True
@@ -891,14 +891,14 @@ class AppConfig(GlobalConfig):
) -> tuple[uuid.UUID, ConfigBase]:
"""添加脚本配置"""
logger.info(f"添加脚本配置{script}")
logger.info(f"添加脚本配置: {script}")
return await self.ScriptConfig.add(CLASS_BOOK[script])
async def get_script(self, script_id: Optional[str]) -> tuple[list, dict]:
"""获取脚本配置"""
logger.info(f"获取脚本配置{script_id}")
logger.info(f"获取脚本配置: {script_id}")
if script_id is None:
data = await self.ScriptConfig.toDict()
@@ -914,18 +914,16 @@ class AppConfig(GlobalConfig):
) -> None:
"""更新脚本配置"""
logger.info(f"更新脚本配置{script_id}")
logger.info(f"更新脚本配置: {script_id}")
uid = uuid.UUID(script_id)
if uid in self.task_dict:
raise RuntimeError(
f"Cannot update script {script_id} while tasks are running."
)
raise RuntimeError(f"脚本 {script_id} 正在运行, 无法更新配置项")
for group, items in data.items():
for name, value in items.items():
logger.debug(f"更新脚本配置{script_id} - {group}.{name} = {value}")
logger.debug(f"更新脚本配置: {script_id} - {group}.{name} = {value}")
await self.ScriptConfig[uid].set(group, name, value)
await self.ScriptConfig.save()
@@ -933,42 +931,38 @@ class AppConfig(GlobalConfig):
async def del_script(self, script_id: str) -> None:
"""删除脚本配置"""
logger.info(f"删除脚本配置{script_id}")
logger.info(f"删除脚本配置: {script_id}")
uid = uuid.UUID(script_id)
if uid in self.task_dict:
raise RuntimeError(
f"Cannot delete script {script_id} while tasks are running."
)
raise RuntimeError(f"脚本 {script_id} 正在运行, 无法删除")
await self.ScriptConfig.remove(uid)
async def reorder_script(self, index_list: list[str]) -> None:
"""重新排序脚本"""
logger.info(f"重新排序脚本{index_list}")
logger.info(f"重新排序脚本: {index_list}")
await self.ScriptConfig.setOrder([uuid.UUID(_) for _ in index_list])
async def import_script_from_file(self, script_id: str, jsonFile: str) -> None:
"""从文件加载脚本配置"""
logger.info(f"从文件加载脚本配置{script_id} - {jsonFile}")
logger.info(f"从文件加载脚本配置: {script_id} - {jsonFile}")
uid = uuid.UUID(script_id)
file_path = Path(jsonFile)
if uid not in self.ScriptConfig:
logger.error(f"{script_id} 不存在")
raise KeyError(f"Script ID {script_id} not found in ScriptConfig.")
raise KeyError(f"脚本 {script_id} 不存在")
if not isinstance(self.ScriptConfig[uid], GeneralConfig):
logger.error(f"{script_id} 不是通用脚本配置")
raise TypeError(
f"Script ID {script_id} is not a General script configuration."
)
raise TypeError(f"脚本 {script_id} 不是通用脚本配置")
if not Path(file_path).exists():
logger.error(f"文件不存在{file_path}")
raise FileNotFoundError(f"File not found: {file_path}")
logger.error(f"文件不存在: {file_path}")
raise FileNotFoundError(f"文件不存在: {file_path}")
data = json.loads(file_path.read_text(encoding="utf-8"))
await self.ScriptConfig[uid].load(data)
@@ -979,19 +973,17 @@ class AppConfig(GlobalConfig):
async def export_script_to_file(self, script_id: str, jsonFile: str):
"""导出脚本配置到文件"""
logger.info(f"导出配置到文件{script_id} - {jsonFile}")
logger.info(f"导出配置到文件: {script_id} - {jsonFile}")
uid = uuid.UUID(script_id)
file_path = Path(jsonFile)
if uid not in self.ScriptConfig:
logger.error(f"{script_id} 不存在")
raise KeyError(f"Script ID {script_id} not found in ScriptConfig.")
raise KeyError(f"脚本 {script_id} 不存在")
if not isinstance(self.ScriptConfig[uid], GeneralConfig):
logger.error(f"{script_id} 不是通用脚本配置")
raise TypeError(
f"Script ID {script_id} is not a General script configuration."
)
raise TypeError(f"脚本 {script_id} 不是通用脚本配置")
temp = await self.ScriptConfig[uid].toDict(
ignore_multi_config=True, if_decrypt=False
@@ -1022,25 +1014,23 @@ class AppConfig(GlobalConfig):
async def import_script_from_web(self, script_id: str, url: str):
"""从「AUTO_MAA 配置分享中心」导入配置"""
logger.info(f"从网络加载脚本配置{script_id} - {url}")
logger.info(f"从网络加载脚本配置: {script_id} - {url}")
uid = uuid.UUID(script_id)
if uid not in self.ScriptConfig:
logger.error(f"{script_id} 不存在")
raise KeyError(f"Script ID {script_id} not found in ScriptConfig.")
raise KeyError(f"脚本 {script_id} 不存在")
if not isinstance(self.ScriptConfig[uid], GeneralConfig):
logger.error(f"{script_id} 不是通用脚本配置")
raise TypeError(
f"Script ID {script_id} is not a General script configuration."
)
raise TypeError(f"脚本 {script_id} 不是通用脚本配置")
response = requests.get(url, timeout=10, proxies=self.get_proxies())
if response.status_code == 200:
data = response.json()
else:
logger.warning(f"无法从 AUTO_MAA 服务器获取配置内容:{response.text}")
logger.warning(f"无法从 AUTO_MAA 服务器获取配置内容: {response.text}")
raise ConnectionError(
f"Failed to fetch configuration from AUTO_MAA server: {response.status_code}"
f"无法从 AUTO_MAA 服务器获取配置内容: {response.status_code}"
)
await self.ScriptConfig[uid].load(data)
@@ -1053,18 +1043,16 @@ class AppConfig(GlobalConfig):
):
"""上传配置到「AUTO_MAA 配置分享中心」"""
logger.info(f"上传配置到网络{script_id} - {config_name} - {author}")
logger.info(f"上传配置到网络: {script_id} - {config_name} - {author}")
uid = uuid.UUID(script_id)
if uid not in self.ScriptConfig:
logger.error(f"{script_id} 不存在")
raise KeyError(f"Script ID {script_id} not found in ScriptConfig.")
raise KeyError(f"脚本 {script_id} 不存在")
if not isinstance(self.ScriptConfig[uid], GeneralConfig):
logger.error(f"{script_id} 不是通用脚本配置")
raise TypeError(
f"Script ID {script_id} is not a General script configuration."
)
raise TypeError(f"脚本 {script_id} 不是通用脚本配置")
temp = await self.ScriptConfig[uid].toDict(
ignore_multi_config=True, if_decrypt=False
@@ -1106,7 +1094,7 @@ class AppConfig(GlobalConfig):
else:
logger.error(f"无法上传配置到 AUTO_MAA 服务器: {response.text}")
raise ConnectionError(
f"Failed to upload configuration to AUTO_MAA server: {response.status_code} - {response.text}"
f"无法上传配置到 AUTO_MAA 服务器: {response.status_code} - {response.text}"
)
async def get_user(
@@ -1114,7 +1102,7 @@ class AppConfig(GlobalConfig):
) -> tuple[list, dict]:
"""获取用户配置"""
logger.info(f"获取用户配置{script_id} - {user_id}")
logger.info(f"获取用户配置: {script_id} - {user_id}")
uid = uuid.UUID(script_id)
sc = self.ScriptConfig[uid]
@@ -1125,8 +1113,8 @@ class AppConfig(GlobalConfig):
else:
data = await sc.UserData.get(uuid.UUID(user_id))
else:
logger.error(f"Unsupported script config type: {type(sc)}")
raise TypeError(f"Unsupported script config type: {type(sc)}")
logger.error(f"不支持的脚本配置类型: {type(sc)}")
raise TypeError(f"不支持的脚本配置类型: {type(sc)}")
index = data.pop("instances", [])
@@ -1144,7 +1132,7 @@ class AppConfig(GlobalConfig):
elif isinstance(script_config, GeneralConfig):
uid, config = await script_config.UserData.add(GeneralUserConfig)
else:
raise TypeError(f"Unsupported script config type: {type(script_config)}")
raise TypeError(f"不支持的脚本配置类型: {type(script_config)}")
await self.ScriptConfig.save()
return uid, config
@@ -1154,14 +1142,14 @@ class AppConfig(GlobalConfig):
) -> None:
"""更新用户配置"""
logger.info(f"{script_id} 更新用户配置{user_id}")
logger.info(f"{script_id} 更新用户配置: {user_id}")
script_config = self.ScriptConfig[uuid.UUID(script_id)]
uid = uuid.UUID(user_id)
for group, items in data.items():
for name, value in items.items():
logger.debug(f"更新脚本配置{script_id} - {group}.{name} = {value}")
logger.debug(f"更新脚本配置: {script_id} - {group}.{name} = {value}")
if isinstance(script_config, (MaaConfig | GeneralConfig)):
await script_config.UserData[uid].set(group, name, value)
@@ -1170,7 +1158,7 @@ class AppConfig(GlobalConfig):
async def del_user(self, script_id: str, user_id: str) -> None:
"""删除用户配置"""
logger.info(f"{script_id} 删除用户配置{user_id}")
logger.info(f"{script_id} 删除用户配置: {user_id}")
script_config = self.ScriptConfig[uuid.UUID(script_id)]
uid = uuid.UUID(user_id)
@@ -1182,7 +1170,7 @@ class AppConfig(GlobalConfig):
async def reorder_user(self, script_id: str, index_list: list[str]) -> None:
"""重新排序用户"""
logger.info(f"{script_id} 重新排序用户{index_list}")
logger.info(f"{script_id} 重新排序用户: {index_list}")
script_config = self.ScriptConfig[uuid.UUID(script_id)]
@@ -1194,12 +1182,12 @@ class AppConfig(GlobalConfig):
self, script_id: str, user_id: str, jsonFile: str
) -> None:
logger.info(f"{script_id} - {user_id} 设置基建配置{jsonFile}")
logger.info(f"{script_id} - {user_id} 设置基建配置: {jsonFile}")
json_path = Path(jsonFile)
if not json_path.exists():
raise FileNotFoundError(f"File not found: {json_path}")
raise FileNotFoundError(f"文件未找到: {json_path}")
(Path.cwd() / f"data/{script_id}/{user_id}/Infrastructure").mkdir(
parents=True, exist_ok=True
@@ -1215,14 +1203,14 @@ class AppConfig(GlobalConfig):
) -> tuple[uuid.UUID, ConfigBase]:
"""添加计划表"""
logger.info(f"添加计划表{script}")
logger.info(f"添加计划表: {script}")
return await self.PlanConfig.add(CLASS_BOOK[script])
async def get_plan(self, plan_id: Optional[str]) -> tuple[list, dict]:
"""获取计划表配置"""
logger.info(f"获取计划表配置{plan_id}")
logger.info(f"获取计划表配置: {plan_id}")
if plan_id is None:
data = await self.PlanConfig.toDict()
@@ -1236,13 +1224,13 @@ class AppConfig(GlobalConfig):
async def update_plan(self, plan_id: str, data: Dict[str, Dict[str, Any]]) -> None:
"""更新计划表配置"""
logger.info(f"更新计划表配置{plan_id}")
logger.info(f"更新计划表配置: {plan_id}")
uid = uuid.UUID(plan_id)
for group, items in data.items():
for name, value in items.items():
logger.debug(f"更新计划表配置{plan_id} - {group}.{name} = {value}")
logger.debug(f"更新计划表配置: {plan_id} - {group}.{name} = {value}")
await self.PlanConfig[uid].set(group, name, value)
await self.PlanConfig.save()
@@ -1250,14 +1238,14 @@ class AppConfig(GlobalConfig):
async def del_plan(self, plan_id: str) -> None:
"""删除计划表配置"""
logger.info(f"删除计划表配置{plan_id}")
logger.info(f"删除计划表配置: {plan_id}")
await self.PlanConfig.remove(uuid.UUID(plan_id))
async def reorder_plan(self, index_list: list[str]) -> None:
"""重新排序计划表"""
logger.info(f"重新排序计划表{index_list}")
logger.info(f"重新排序计划表: {index_list}")
await self.PlanConfig.setOrder([uuid.UUID(_) for _ in index_list])
@@ -1271,7 +1259,7 @@ class AppConfig(GlobalConfig):
async def get_queue(self, queue_id: Optional[str]) -> tuple[list, dict]:
"""获取调度队列配置"""
logger.info(f"获取调度队列配置{queue_id}")
logger.info(f"获取调度队列配置: {queue_id}")
if queue_id is None:
data = await self.QueueConfig.toDict()
@@ -1287,13 +1275,13 @@ class AppConfig(GlobalConfig):
) -> None:
"""更新调度队列配置"""
logger.info(f"更新调度队列配置{queue_id}")
logger.info(f"更新调度队列配置: {queue_id}")
uid = uuid.UUID(queue_id)
for group, items in data.items():
for name, value in items.items():
logger.debug(f"更新调度队列配置{queue_id} - {group}.{name} = {value}")
logger.debug(f"更新调度队列配置: {queue_id} - {group}.{name} = {value}")
await self.QueueConfig[uid].set(group, name, value)
await self.QueueConfig.save()
@@ -1301,14 +1289,14 @@ class AppConfig(GlobalConfig):
async def del_queue(self, queue_id: str) -> None:
"""删除调度队列配置"""
logger.info(f"删除调度队列配置{queue_id}")
logger.info(f"删除调度队列配置: {queue_id}")
await self.QueueConfig.remove(uuid.UUID(queue_id))
async def reorder_queue(self, index_list: list[str]) -> None:
"""重新排序调度队列"""
logger.info(f"重新排序调度队列{index_list}")
logger.info(f"重新排序调度队列: {index_list}")
await self.QueueConfig.setOrder([uuid.UUID(_) for _ in index_list])
@@ -1328,8 +1316,8 @@ class AppConfig(GlobalConfig):
else:
data = await qc.TimeSet.get(uuid.UUID(time_set_id))
else:
logger.error(f"Unsupported queue config type: {type(qc)}")
raise TypeError(f"Unsupported queue config type: {type(qc)}")
logger.error(f"不支持的队列配置类型: {type(qc)}")
raise TypeError(f"不支持的队列配置类型: {type(qc)}")
index = data.pop("instances", [])
@@ -1345,7 +1333,7 @@ class AppConfig(GlobalConfig):
if isinstance(queue_config, QueueConfig):
uid, config = await queue_config.TimeSet.add(TimeSet)
else:
raise TypeError(f"Unsupported script config type: {type(queue_config)}")
raise TypeError(f"不支持的队列配置类型: {type(queue_config)}")
await self.QueueConfig.save()
return uid, config
@@ -1355,14 +1343,14 @@ class AppConfig(GlobalConfig):
) -> None:
"""更新时间设置配置"""
logger.info(f"{queue_id} 更新时间设置配置{time_set_id}")
logger.info(f"{queue_id} 更新时间设置配置: {time_set_id}")
queue_config = self.QueueConfig[uuid.UUID(queue_id)]
uid = uuid.UUID(time_set_id)
for group, items in data.items():
for name, value in items.items():
logger.debug(f"更新时间设置配置{queue_id} - {group}.{name} = {value}")
logger.debug(f"更新时间设置配置: {queue_id} - {group}.{name} = {value}")
if isinstance(queue_config, QueueConfig):
await queue_config.TimeSet[uid].set(group, name, value)
@@ -1371,7 +1359,7 @@ class AppConfig(GlobalConfig):
async def del_time_set(self, queue_id: str, time_set_id: str) -> None:
"""删除时间设置配置"""
logger.info(f"{queue_id} 删除时间设置配置{time_set_id}")
logger.info(f"{queue_id} 删除时间设置配置: {time_set_id}")
queue_config = self.QueueConfig[uuid.UUID(queue_id)]
uid = uuid.UUID(time_set_id)
@@ -1383,7 +1371,7 @@ class AppConfig(GlobalConfig):
async def reorder_time_set(self, queue_id: str, index_list: list[str]) -> None:
"""重新排序时间设置"""
logger.info(f"{queue_id} 重新排序时间设置{index_list}")
logger.info(f"{queue_id} 重新排序时间设置: {index_list}")
queue_config = self.QueueConfig[uuid.UUID(queue_id)]
@@ -1407,8 +1395,8 @@ class AppConfig(GlobalConfig):
else:
data = await qc.QueueItem.get(uuid.UUID(queue_item_id))
else:
logger.error(f"Unsupported queue config type: {type(qc)}")
raise TypeError(f"Unsupported queue config type: {type(qc)}")
logger.error(f"不支持的队列配置类型: {type(qc)}")
raise TypeError(f"不支持的队列配置类型: {type(qc)}")
index = data.pop("instances", [])
@@ -1424,8 +1412,8 @@ class AppConfig(GlobalConfig):
if isinstance(queue_config, QueueConfig):
uid, config = await queue_config.QueueItem.add(QueueItem)
else:
logger.warning(f"Unsupported script config type: {type(queue_config)}")
raise TypeError(f"Unsupported script config type: {type(queue_config)}")
logger.warning(f"不支持的队列配置类型: {type(queue_config)}")
raise TypeError(f"不支持的队列配置类型: {type(queue_config)}")
await self.QueueConfig.save()
return uid, config
@@ -1435,7 +1423,7 @@ class AppConfig(GlobalConfig):
) -> None:
"""更新队列项配置"""
logger.info(f"{queue_id} 更新队列项配置{queue_item_id}")
logger.info(f"{queue_id} 更新队列项配置: {queue_item_id}")
queue_config = self.QueueConfig[uuid.UUID(queue_id)]
uid = uuid.UUID(queue_item_id)
@@ -1443,9 +1431,9 @@ class AppConfig(GlobalConfig):
for group, items in data.items():
for name, value in items.items():
if uuid.UUID(value) not in self.ScriptConfig:
logger.warning(f"Script with uid {value} does not exist.")
raise ValueError(f"Script with uid {value} does not exist.")
logger.debug(f"更新队列项配置{queue_id} - {group}.{name} = {value}")
logger.warning(f"脚本 {value} 不存在")
raise ValueError(f"脚本 {value} 不存在")
logger.debug(f"更新队列项配置: {queue_id} - {group}.{name} = {value}")
if isinstance(queue_config, QueueConfig):
await queue_config.QueueItem[uid].set(group, name, value)
@@ -1454,7 +1442,7 @@ class AppConfig(GlobalConfig):
async def del_queue_item(self, queue_id: str, queue_item_id: str) -> None:
"""删除队列项配置"""
logger.info(f"{queue_id} 删除队列项配置{queue_item_id}")
logger.info(f"{queue_id} 删除队列项配置: {queue_item_id}")
queue_config = self.QueueConfig[uuid.UUID(queue_id)]
uid = uuid.UUID(queue_item_id)
@@ -1466,7 +1454,7 @@ class AppConfig(GlobalConfig):
async def reorder_queue_item(self, queue_id: str, index_list: list[str]) -> None:
"""重新排序队列项"""
logger.info(f"{queue_id} 重新排序队列项{index_list}")
logger.info(f"{queue_id} 重新排序队列项: {index_list}")
queue_config = self.QueueConfig[uuid.UUID(queue_id)]
@@ -1477,21 +1465,21 @@ class AppConfig(GlobalConfig):
async def get_setting(self) -> Dict[str, Any]:
"""获取全局设置"""
logger.info("Get global settings")
logger.info("获取全局设置")
return await self.toDict(ignore_multi_config=True)
async def update_setting(self, data: Dict[str, Dict[str, Any]]) -> None:
"""更新全局设置"""
logger.info("Update global settings...")
logger.info("更新全局设置")
for group, items in data.items():
for name, value in items.items():
logger.debug(f"Update global settings - {group}.{name} = {value}")
logger.debug(f"更新全局设置 - {group}.{name} = {value}")
await self.set(group, name, value)
logger.success("Global settings updated successfully.")
logger.success("全局设置更新成功")
def server_date(self) -> date:
"""
@@ -1545,10 +1533,8 @@ class AppConfig(GlobalConfig):
if index == "Info":
today = self.server_date().isoweekday()
logger.info(f"获取关卡信息:{index},今天是:{today}")
res_stage_info = []
for stage in RESOURCE_STAGE_INFO:
logger.info(f"available: {stage['days']},")
if (
today in stage["days"]
and stage["value"] in RESOURCE_STAGE_DROP_INFO
@@ -1602,7 +1588,7 @@ class AppConfig(GlobalConfig):
if datetime.now() - timedelta(hours=1) < datetime.strptime(
self.get("Data", "LastStageUpdated"), "%Y-%m-%d %H:%M:%S"
):
logger.info("一小时内已进行过一次检查直接使用缓存的活动关卡信息")
logger.info("一小时内已进行过一次检查, 直接使用缓存的活动关卡信息")
return json.loads(self.get("Data", "Stage"))
logger.info("开始获取活动关卡信息")
@@ -1629,7 +1615,7 @@ class AppConfig(GlobalConfig):
self.get("Data", "StageTimeStamp"), "%Y-%m-%d %H:%M:%S"
)
# 本地关卡信息无需更新直接返回本地数据
# 本地关卡信息无需更新, 直接返回本地数据
if datetime.fromtimestamp(0) < remote_time_stamp <= local_time_stamp:
logger.info("使用本地关卡信息")
@@ -1694,7 +1680,7 @@ class AppConfig(GlobalConfig):
else:
drop_name = (
"DESC:" + drop_id
) # 非纯数字直接用文本.加一个DESC前缀方便前端区分
) # 非纯数字, 直接用文本.加一个DESC前缀方便前端区分
activity_stage_drop_info.append(
{
@@ -1812,7 +1798,7 @@ class AppConfig(GlobalConfig):
if datetime.now() - timedelta(hours=1) < datetime.strptime(
self.get("Data", "LastNoticeUpdated"), "%Y-%m-%d %H:%M:%S"
):
logger.info("一小时内已进行过一次检查直接使用缓存的公告信息")
logger.info("一小时内已进行过一次检查, 直接使用缓存的公告信息")
return False, local_notice.get("notice_dict", {})
logger.info(f"开始从 AUTO_MAA 服务器获取公告信息")
@@ -1865,7 +1851,7 @@ class AppConfig(GlobalConfig):
if datetime.now() - timedelta(hours=1) < datetime.strptime(
self.get("Data", "LastWebConfigUpdated"), "%Y-%m-%d %H:%M:%S"
):
logger.info("一小时内已进行过一次检查直接使用缓存的配置分享中心信息")
logger.info("一小时内已进行过一次检查, 直接使用缓存的配置分享中心信息")
return local_web_config
logger.info(f"开始从 AUTO_MAA 服务器获取配置分享中心信息")
@@ -1927,7 +1913,7 @@ class AppConfig(GlobalConfig):
:rtype: bool
"""
logger.info(f"开始处理 MAA 日志日志长度: {len(logs)}日志标记{maa_result}")
logger.info(f"开始处理 MAA 日志, 日志长度: {len(logs)}, 日志标记: {maa_result}")
data = {
"recruit_statistics": defaultdict(int),
@@ -1960,7 +1946,7 @@ class AppConfig(GlobalConfig):
if confirmed_recruit and current_star_level:
data["recruit_statistics"][current_star_level] += 1
confirmed_recruit = False # 重置等待下一次公招
confirmed_recruit = False # 重置, 等待下一次公招
current_star_level = None # 清空已处理的星级
i += 1
@@ -1979,13 +1965,13 @@ class AppConfig(GlobalConfig):
if "完成任务: Fight" in logs[j] or "完成任务: 刷理智" in logs[j]:
end_index = j
break
# 如果遇到新的Fight任务开始则当前任务没有正常结束
# 如果遇到新的Fight任务开始, 则当前任务没有正常结束
if j < len(logs) and (
"开始任务: Fight" in logs[j] or "开始任务: 刷理智" in logs[j]
):
break
# 如果找到了结束位置记录这个任务的范围
# 如果找到了结束位置, 记录这个任务的范围
if end_index != -1:
fight_tasks.append((i, end_index))
@@ -1999,15 +1985,15 @@ class AppConfig(GlobalConfig):
current_stage = None
for line in task_logs:
# 匹配掉落统计行如"1-7 掉落统计:"
# 匹配掉落统计行, 如"1-7 掉落统计:"
drop_match = re.search(r"([A-Za-z0-9\-]+) 掉落统计:", line)
if drop_match:
# 发现新的掉落统计重置当前关卡的掉落数据
# 发现新的掉落统计, 重置当前关卡的掉落数据
current_stage = drop_match.group(1)
last_drop_stats = {}
continue
# 如果已经找到了关卡处理掉落物
# 如果已经找到了关卡, 处理掉落物
if current_stage:
item_match: List[str] = re.findall(
r"^(?!\[)(\S+?)\s*:\s*([\d,]+)(?:\s*\(\+[\d,]+\))?",
@@ -2028,7 +2014,7 @@ class AppConfig(GlobalConfig):
]:
last_drop_stats[item] = total
# 如果任务中有掉落统计更新总统计
# 如果任务中有掉落统计, 更新总统计
if current_stage and last_drop_stats:
if current_stage not in all_stage_drops:
all_stage_drops[current_stage] = {}
@@ -2048,9 +2034,7 @@ class AppConfig(GlobalConfig):
with log_path.with_suffix(".json").open("w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
logger.success(
f"MAA 日志统计完成,日志路径:{log_path}",
)
logger.success(f"MAA 日志统计完成, 日志路径: {log_path}")
return if_six_star
@@ -2066,7 +2050,7 @@ class AppConfig(GlobalConfig):
"""
logger.info(
f"开始处理通用日志日志长度: {len(logs)}日志标记{general_result}"
f"开始处理通用日志, 日志长度: {len(logs)}, 日志标记: {general_result}"
)
data: Dict[str, str] = {"general_result": general_result}
@@ -2078,7 +2062,7 @@ class AppConfig(GlobalConfig):
with log_path.with_suffix(".json").open("w", encoding="utf-8") as f:
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')}")
async def merge_statistic_info(self, statistic_path_list: List[Path]) -> dict:
"""
@@ -2088,7 +2072,7 @@ class AppConfig(GlobalConfig):
:return: 合并后的统计信息字典
"""
logger.info(f"开始合并统计信息文件共计 {len(statistic_path_list)} 个文件")
logger.info(f"开始合并统计信息文件, 共计 {len(statistic_path_list)} 个文件")
data: Dict[str, Any] = {"index": {}}
@@ -2155,9 +2139,7 @@ class AppConfig(GlobalConfig):
data["index"] = [data["index"][_] for _ in sorted(data["index"])]
logger.success(
f"统计信息合并完成,共计 {len(data['index'])} 条记录",
)
logger.success(f"统计信息合并完成, 共计 {len(data['index'])} 条记录")
return {k: v for k, v in data.items() if v}
@@ -2172,7 +2154,7 @@ class AppConfig(GlobalConfig):
"""
logger.info(
f"开始搜索历史记录合并模式{mode}日期范围{start_date}{end_date}"
f"开始搜索历史记录, 合并模式: {mode}, 日期范围: {start_date}{end_date}"
)
history_dict = {}
@@ -2215,7 +2197,7 @@ class AppConfig(GlobalConfig):
except ValueError:
logger.warning(f"非日期格式的目录: {date_folder}")
logger.success(f"历史记录搜索完成共计 {len(history_dict)} 条记录")
logger.success(f"历史记录搜索完成, 共计 {len(history_dict)} 条记录")
return {
k: v
@@ -2226,7 +2208,7 @@ class AppConfig(GlobalConfig):
"""删除超过用户设定天数的历史记录文件(基于目录日期)"""
if self.get("Function", "HistoryRetentionTime") == 0:
logger.info("历史记录永久保留跳过历史记录清理")
logger.info("历史记录永久保留, 跳过历史记录清理")
return
logger.info("开始清理超过设定天数的历史记录")

View File

@@ -64,24 +64,22 @@ class _TaskManager:
task_id = script_id
break
else:
raise ValueError(
f"The task corresponding to UID {uid} could not be found."
)
raise ValueError(f"任务 {uid} 无法找到对应脚本配置")
elif actual_id in Config.QueueConfig:
task_id = actual_id
actual_id = None
elif actual_id in Config.ScriptConfig:
task_id = uuid.uuid4()
else:
raise ValueError(f"The task corresponding to UID {uid} could not be found.")
raise ValueError(f"任务 {uid} 无法找到对应脚本配置")
if task_id in self.task_dict or (
actual_id is not None and actual_id in self.task_dict
):
raise RuntimeError(f"The task {task_id} is already running.")
raise RuntimeError(f"任务 {task_id} 已在运行")
logger.info(f"创建任务{task_id},模式:{mode}")
logger.info(f"创建任务: {task_id}, 模式: {mode}")
self.task_dict[task_id] = asyncio.create_task(
self.run_task(mode, task_id, actual_id)
)
@@ -96,7 +94,7 @@ class _TaskManager:
self, mode: str, task_id: uuid.UUID, actual_id: Optional[uuid.UUID]
):
logger.info(f"开始运行任务{task_id},模式:{mode}")
logger.info(f"开始运行任务: {task_id}, 模式: {mode}")
if mode == "设置脚本":
@@ -106,7 +104,7 @@ class _TaskManager:
task_item = GeneralManager(mode, task_id, actual_id, str(task_id))
else:
logger.error(
f"不支持的脚本类型{type(Config.ScriptConfig[task_id]).__name__}"
f"不支持的脚本类型: {type(Config.ScriptConfig[task_id]).__name__}"
)
await Config.send_json(
WebSocketMessage(
@@ -132,7 +130,7 @@ class _TaskManager:
queue = Config.QueueConfig[task_id]
if not isinstance(queue, QueueConfig):
logger.error(
f"不支持的队列类型{type(Config.QueueConfig[task_id]).__name__}"
f"不支持的队列类型: {type(Config.QueueConfig[task_id]).__name__}"
)
await Config.send_json(
WebSocketMessage(
@@ -175,7 +173,7 @@ class _TaskManager:
data={"task_list": task_list},
).model_dump()
)
logger.info(f"跳过任务{script_id}该任务已在运行列表中")
logger.info(f"跳过任务: {script_id}, 该任务已在运行列表中")
continue
# 标记为运行中
@@ -187,7 +185,7 @@ class _TaskManager:
data={"task_list": task_list},
).model_dump()
)
logger.info(f"任务开始{script_id}")
logger.info(f"任务开始: {script_id}")
if isinstance(Config.ScriptConfig[script_id], MaaConfig):
task_item = MaaManager(mode, script_id, None, str(task_id))
@@ -195,7 +193,7 @@ class _TaskManager:
task_item = GeneralManager(mode, script_id, actual_id, str(task_id))
else:
logger.error(
f"不支持的脚本类型{type(Config.ScriptConfig[script_id]).__name__}"
f"不支持的脚本类型: {type(Config.ScriptConfig[script_id]).__name__}"
)
await Config.send_json(
WebSocketMessage(
@@ -222,7 +220,7 @@ class _TaskManager:
:param task_id: 任务ID
"""
logger.info(f"中止任务{task_id}")
logger.info(f"中止任务: {task_id}")
if task_id == "ALL":
for task in self.task_dict.values():
@@ -230,7 +228,7 @@ class _TaskManager:
else:
uid = uuid.UUID(task_id)
if uid not in self.task_dict:
raise ValueError(f"The task {uid} is not running.")
raise ValueError(f"任务 {uid} 未在运行")
self.task_dict[uid].cancel()
async def remove_task(
@@ -249,7 +247,7 @@ class _TaskManager:
任务ID
"""
logger.info(f"任务结束{task_id}")
logger.info(f"任务结束: {task_id}")
# 从任务字典中移除任务
try:

View File

@@ -65,9 +65,7 @@ class _MainTimer:
if emulator_windows:
logger.info(
f"检测到模拟器窗口:{emulator_windows}", module="主业务定时器"
)
logger.info(f"检测到模拟器窗口: {emulator_windows}")
try:
keyboard.press_and_release(
"+".join(
@@ -75,12 +73,9 @@ class _MainTimer:
for _ in Config.get("Function", "BossKey").split("+")
)
)
logger.info(
f"模拟按键:{Config.get('Function', 'BossKey')}",
module="主业务定时器",
)
logger.info(f"模拟按键: {Config.get('Function', 'BossKey')}")
except Exception as e:
logger.exception(f"模拟按键时出错{e}", module="主业务定时器")
logger.exception(f"模拟按键时出错: {e}")
MainTimer = _MainTimer()

View File

@@ -70,7 +70,7 @@ class OptionsValidator(ConfigValidator):
def __init__(self, options: list):
if not options:
raise ValueError("The `options` can't be empty.")
raise ValueError("可选项不能为空")
self.options = options
@@ -110,7 +110,7 @@ class EncryptValidator(ConfigValidator):
return False
def correct(self, value: Any) -> Any:
return value if self.validate(value) else dpapi_encrypt("数据损坏请重新设置")
return value if self.validate(value) else dpapi_encrypt("数据损坏, 请重新设置")
class BoolValidator(OptionsValidator):
@@ -186,7 +186,7 @@ class ConfigItem:
配置项默认值
validator: ConfigValidator
配置项验证器默认为 None表示不进行验证
配置项验证器, 默认为 None, 表示不进行验证
"""
super().__init__()
self.group = group
@@ -199,12 +199,12 @@ class ConfigItem:
def setValue(self, value: Any):
"""
设置配置项值将自动进行验证和修正
设置配置项值, 将自动进行验证和修正
Parameters
----------
value: Any
要设置的值可以是任何合法类型
要设置的值, 可以是任何合法类型
"""
if (
@@ -215,9 +215,7 @@ class ConfigItem:
return
if self.is_locked:
raise ValueError(
f"Config item '{self.group}.{self.name}' is locked and cannot be modified."
)
raise ValueError(f"配置项 '{self.group}.{self.name}' 已锁定, 无法修改")
# deepcopy new value
try:
@@ -245,13 +243,13 @@ class ConfigItem:
def lock(self):
"""
锁定配置项锁定后无法修改配置项值
锁定配置项, 锁定后无法修改配置项值
"""
self.is_locked = True
def unlock(self):
"""
解锁配置项解锁后可以修改配置项值
解锁配置项, 解锁后可以修改配置项值
"""
self.is_locked = False
@@ -260,11 +258,11 @@ class ConfigBase:
"""
配置基类
这个类提供了基本的配置项管理功能包括连接配置文件、加载配置数据、获取和设置配置项值等。
这个类提供了基本的配置项管理功能, 包括连接配置文件、加载配置数据、获取和设置配置项值等。
此类不支持直接实例化必须通过子类来实现具体的配置项请继承此类并在子类中定义具体的配置项。
若将配置项设为类属性则所有实例都会共享同一份配置项数据。
若将配置项设为实例属性则每个实例都会有独立的配置项数据。
此类不支持直接实例化, 必须通过子类来实现具体的配置项, 请继承此类并在子类中定义具体的配置项。
若将配置项设为类属性, 则所有实例都会共享同一份配置项数据。
若将配置项设为实例属性, 则每个实例都会有独立的配置项数据。
子配置项可以是 `MultipleConfig` 的实例。
"""
@@ -281,16 +279,14 @@ class ConfigBase:
Parameters
----------
path: Path
配置文件路径必须为 JSON 文件如果不存在则会创建
配置文件路径, 必须为 JSON 文件, 如果不存在则会创建
"""
if path.suffix != ".json":
raise ValueError(
"The config file must be a JSON file with '.json' extension."
)
raise ValueError("配置文件必须是扩展名为 '.json' 的 JSON 文件")
if self.is_locked:
raise ValueError("Config is locked and cannot be modified.")
raise ValueError("配置已锁定, 无法修改")
self.file = path
@@ -310,8 +306,8 @@ class ConfigBase:
"""
从字典加载配置数据
这个方法会遍历字典中的配置项并将其设置到对应的 ConfigItem 实例中。
如果字典中包含 "SubConfigsInfo"则会加载子配置项这些子配置项应该是 MultipleConfig 的实例。
这个方法会遍历字典中的配置项, 并将其设置到对应的 ConfigItem 实例中。
如果字典中包含 "SubConfigsInfo", 则会加载子配置项, 这些子配置项应该是 MultipleConfig 的实例。
Parameters
----------
@@ -320,7 +316,7 @@ class ConfigBase:
"""
if self.is_locked:
raise ValueError("Config is locked and cannot be modified.")
raise ValueError("配置已锁定, 无法修改")
# update the value of config item
if data.get("SubConfigsInfo"):
@@ -371,15 +367,13 @@ class ConfigBase:
"""获取配置项的值"""
if not hasattr(self, f"{group}_{name}"):
raise AttributeError(f"Config item '{group}.{name}' does not exist.")
raise AttributeError(f"配置项 '{group}.{name}' 不存在")
configItem = getattr(self, f"{group}_{name}")
if isinstance(configItem, ConfigItem):
return configItem.getValue()
else:
raise TypeError(
f"Config item '{group}_{name}' is not a ConfigItem instance."
)
raise TypeError(f"配置项 '{group}.{name}' 不是 ConfigItem 实例")
async def set(self, group: str, name: str, value: Any):
"""
@@ -396,7 +390,7 @@ class ConfigBase:
"""
if not hasattr(self, f"{group}_{name}"):
raise AttributeError(f"Config item '{group}_{name}' does not exist.")
raise AttributeError(f"配置项 '{group}.{name}' 不存在")
configItem = getattr(self, f"{group}_{name}")
if isinstance(configItem, ConfigItem):
@@ -404,17 +398,13 @@ class ConfigBase:
if self.file:
await self.save()
else:
raise TypeError(
f"Config item '{group}_{name}' is not a ConfigItem instance."
)
raise TypeError(f"配置项 '{group}.{name}' 不是 ConfigItem 实例")
async def save(self):
"""保存配置"""
if not self.file:
raise ValueError(
"The `file` attribute is not set. Please set it before saving."
)
raise ValueError("文件路径未设置, 请先调用 `connect` 方法连接配置文件")
self.file.parent.mkdir(parents=True, exist_ok=True)
with self.file.open("w", encoding="utf-8") as f:
@@ -427,7 +417,7 @@ class ConfigBase:
async def lock(self):
"""
锁定配置项锁定后无法修改配置项值
锁定配置项, 锁定后无法修改配置项值
"""
self.is_locked = True
@@ -441,7 +431,7 @@ class ConfigBase:
async def unlock(self):
"""
解锁配置项解锁后可以修改配置项值
解锁配置项, 解锁后可以修改配置项值
"""
self.is_locked = False
@@ -458,24 +448,24 @@ class MultipleConfig:
"""
多配置项管理类
这个类允许管理多个配置项实例可以添加、删除、修改配置项并将其保存到 JSON 文件中。
允许通过 `config[uuid]` 访问配置项使用 `uuid in config` 检查是否存在配置项使用 `len(config)` 获取配置项数量。
这个类允许管理多个配置项实例, 可以添加、删除、修改配置项, 并将其保存到 JSON 文件中。
允许通过 `config[uuid]` 访问配置项, 使用 `uuid in config` 检查是否存在配置项, 使用 `len(config)` 获取配置项数量。
Parameters
----------
sub_config_type: List[type]
子配置项的类型列表必须是 ConfigBase 的子类
子配置项的类型列表, 必须是 ConfigBase 的子类
"""
def __init__(self, sub_config_type: List[type]):
if not sub_config_type:
raise ValueError("The `sub_config_type` can't be empty.")
raise ValueError("子配置项类型列表不能为空")
for config_type in sub_config_type:
if not issubclass(config_type, ConfigBase):
raise TypeError(
f"Config type {config_type.__name__} must be a subclass of ConfigBase."
f"配置类型 {config_type.__name__} 必须是 ConfigBase 的子类"
)
self.sub_config_type = sub_config_type
@@ -487,7 +477,7 @@ class MultipleConfig:
def __getitem__(self, key: uuid.UUID) -> ConfigBase:
"""允许通过 config[uuid] 访问配置项"""
if key not in self.data:
raise KeyError(f"Config item with uuid {key} does not exist.")
raise KeyError(f"配置项 '{key}' 不存在")
return self.data[key]
def __contains__(self, key: uuid.UUID) -> bool:
@@ -513,16 +503,14 @@ class MultipleConfig:
Parameters
----------
path: Path
配置文件路径必须为 JSON 文件如果不存在则会创建
配置文件路径, 必须为 JSON 文件, 如果不存在则会创建
"""
if path.suffix != ".json":
raise ValueError(
"The config file must be a JSON file with '.json' extension."
)
raise ValueError("配置文件必须是带有 '.json' 扩展名的 JSON 文件。")
if self.is_locked:
raise ValueError("Config is locked and cannot be modified.")
raise ValueError("配置已锁定, 无法修改")
self.file = path
@@ -542,9 +530,9 @@ class MultipleConfig:
"""
从字典加载配置数据
这个方法会遍历字典中的配置项并将其设置到对应的 ConfigBase 实例中。
如果字典中包含 "instances"则会加载子配置项这些子配置项应该是 ConfigBase 子类的实例。
如果字典中没有 "instances"则清空当前配置项。
这个方法会遍历字典中的配置项, 并将其设置到对应的 ConfigBase 实例中。
如果字典中包含 "instances", 则会加载子配置项, 这些子配置项应该是 ConfigBase 子类的实例。
如果字典中没有 "instances", 则清空当前配置项。
Parameters
----------
@@ -553,7 +541,7 @@ class MultipleConfig:
"""
if self.is_locked:
raise ValueError("Config is locked and cannot be modified.")
raise ValueError("配置已锁定, 无法修改")
if not data.get("instances"):
self.order = []
@@ -580,7 +568,7 @@ class MultipleConfig:
else:
raise ValueError(f"Unknown sub config type: {type_name}")
raise ValueError(f"未知的子配置类型: {type_name}")
if self.file:
await self.save()
@@ -589,7 +577,7 @@ class MultipleConfig:
"""
将配置项转换为字典
返回一个字典包含所有配置项的 UID 和类型以及每个配置项的具体数据。
返回一个字典, 包含所有配置项的 UID 和类型, 以及每个配置项的具体数据。
"""
data: Dict[str, Union[list, dict]] = {
@@ -616,7 +604,7 @@ class MultipleConfig:
"""
if uid not in self.data:
raise ValueError(f"Config item with uid {uid} does not exist.")
raise ValueError(f"配置项 '{uid}' 不存在。")
data: Dict[str, Union[list, dict]] = {
"instances": [
@@ -633,9 +621,7 @@ class MultipleConfig:
"""保存配置"""
if not self.file:
raise ValueError(
"The `file` attribute is not set. Please set it before saving."
)
raise ValueError("文件路径未设置, 请先调用 `connect` 方法连接配置文件")
self.file.parent.mkdir(parents=True, exist_ok=True)
with self.file.open("w", encoding="utf-8") as f:
@@ -648,7 +634,7 @@ class MultipleConfig:
Parameters
----------
config_type: type
配置项的类型必须是初始化时已声明的 ConfigBase 子类
配置项的类型, 必须是初始化时已声明的 ConfigBase 子类
Returns
-------
@@ -657,7 +643,7 @@ class MultipleConfig:
"""
if config_type not in self.sub_config_type:
raise ValueError(f"Config type {config_type.__name__} is not allowed.")
raise ValueError(f"配置类型 {config_type.__name__} 不被允许")
uid = uuid.uuid4()
self.order.append(uid)
@@ -679,15 +665,13 @@ class MultipleConfig:
"""
if self.is_locked:
raise ValueError("Config is locked and cannot be modified.")
raise ValueError("配置已锁定, 无法修改")
if uid not in self.data:
raise ValueError(f"Config item with uid {uid} does not exist.")
raise ValueError(f"配置项 '{uid}' 不存在")
if self.data[uid].is_locked:
raise ValueError(
f"Config item with uid {uid} is locked and cannot be removed."
)
raise ValueError(f"配置项 '{uid}' 已锁定, 无法移除")
self.data.pop(uid)
self.order.remove(uid)
@@ -706,7 +690,7 @@ class MultipleConfig:
"""
if set(order) != set(self.data.keys()):
raise ValueError("The order does not match the current config items.")
raise ValueError("顺序与当前配置项不匹配")
self.order = order
@@ -715,7 +699,7 @@ class MultipleConfig:
async def lock(self):
"""
锁定配置项锁定后无法修改配置项值
锁定配置项, 锁定后无法修改配置项值
"""
self.is_locked = True
@@ -725,7 +709,7 @@ class MultipleConfig:
async def unlock(self):
"""
解锁配置项解锁后可以修改配置项值
解锁配置项, 解锁后可以修改配置项值
"""
self.is_locked = False

View File

@@ -521,7 +521,7 @@ class ScriptDeleteIn(BaseModel):
class ScriptReorderIn(BaseModel):
indexList: List[str] = Field(..., description="脚本ID列表按新顺序排列")
indexList: List[str] = Field(..., description="脚本ID列表, 按新顺序排列")
class ScriptFileIn(BaseModel):
@@ -577,7 +577,7 @@ class UserDeleteIn(UserInBase):
class UserReorderIn(UserInBase):
indexList: List[str] = Field(..., description="用户ID列表按新顺序排列")
indexList: List[str] = Field(..., description="用户ID列表, 按新顺序排列")
class UserSetIn(UserInBase):
@@ -615,7 +615,7 @@ class PlanDeleteIn(BaseModel):
class PlanReorderIn(BaseModel):
indexList: List[str] = Field(..., description="计划ID列表按新顺序排列")
indexList: List[str] = Field(..., description="计划ID列表, 按新顺序排列")
class QueueCreateOut(OutBase):
@@ -681,7 +681,7 @@ class TimeSetDeleteIn(QueueSetInBase):
class TimeSetReorderIn(QueueSetInBase):
indexList: List[str] = Field(..., description="时间设置ID列表按新顺序排列")
indexList: List[str] = Field(..., description="时间设置ID列表, 按新顺序排列")
class QueueItemGetIn(QueueSetInBase):
@@ -712,13 +712,13 @@ class QueueItemDeleteIn(QueueSetInBase):
class QueueItemReorderIn(QueueSetInBase):
indexList: List[str] = Field(..., description="队列项ID列表按新顺序排列")
indexList: List[str] = Field(..., description="队列项ID列表, 按新顺序排列")
class DispatchIn(BaseModel):
taskId: str = Field(
...,
description="目标任务ID设置类任务可选对应脚本ID或用户ID代理类任务可选对应队列ID或脚本ID",
description="目标任务ID, 设置类任务可选对应脚本ID或用户ID, 代理类任务可选对应队列ID或脚本ID",
)
@@ -738,7 +738,7 @@ class WebSocketMessage(BaseModel):
...,
description="消息类型 Update: 更新数据, Message: 请求弹出对话框, Info: 需要在UI显示的消息, Signal: 程序信号",
)
data: Dict[str, Any] = Field(..., description="消息数据具体内容根据type类型而定")
data: Dict[str, Any] = Field(..., description="消息数据, 具体内容根据type类型而定")
class PowerIn(BaseModel):

View File

@@ -18,14 +18,7 @@
# Contact: DLmaster_361@163.com
"""
AUTO_MAA
AUTO_MAA服务包
v4.4
作者DLmaster_361
"""
__version__ = "4.2.0"
__version__ = "5.0.0"
__author__ = "DLmaster361 <DLmaster_361@163.com>"
__license__ = "GPL-3.0 license"

View File

@@ -54,7 +54,7 @@ class Notification:
if Config.get("Notify", "IfPushPlyer"):
logger.info(f"推送系统通知{title}")
logger.info(f"推送系统通知: {title}")
if notification.notify is not None:
notification.notify(
@@ -67,7 +67,7 @@ class Notification:
toast=True,
)
else:
logger.error("plyer.notification 未正确导入无法推送系统通知")
logger.error("plyer.notification 未正确导入, 无法推送系统通知")
return True
@@ -75,7 +75,7 @@ class Notification:
"""
推送邮件通知
:param mode: 邮件内容模式支持 "文本""网页"
:param mode: 邮件内容模式, 支持 "文本""网页"
:param title: 邮件标题
:param content: 邮件内容
:param to_address: 收件人地址
@@ -101,7 +101,7 @@ class Notification:
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址"
)
raise ValueError(
"The SMTP server address, authorization code, sender address, or recipient address is not set correctly."
"邮件通知的SMTP服务器地址、授权码、发件人地址或收件人地址未正确配置"
)
# 定义邮件正文
@@ -132,7 +132,7 @@ class Notification:
Config.get("Notify", "FromAddress"), to_address, message.as_string()
)
smtpObj.quit()
logger.success(f"邮件发送成功{title}")
logger.success(f"邮件发送成功: {title}")
def ServerChanPush(self, title, content, send_key) -> None:
"""
@@ -144,7 +144,7 @@ class Notification:
"""
if not send_key:
raise ValueError("The ServerChan SendKey can not be empty.")
raise ValueError("ServerChan SendKey 不能为空")
# 构造 URL
if send_key.startswith("sctp"):
@@ -152,7 +152,7 @@ class Notification:
if match:
url = f"https://{match.group(1)}.push.ft07.com/send/{send_key}.send"
else:
raise ValueError("SendKey format is incorrect (sctp<int>).")
raise ValueError("SendKey 格式不正确 (sctp<int>)")
else:
url = f"https://sctapi.ftqq.com/{send_key}.send"
@@ -166,9 +166,9 @@ class Notification:
result = response.json()
if result.get("code") == 0:
logger.success(f"Server酱推送通知成功{title}")
logger.success(f"Server酱推送通知成功: {title}")
else:
raise Exception(f"ServerChan failed to send notification: {response.text}")
raise Exception(f"ServerChan 推送通知失败: {response.text}")
def WebHookPush(self, title, content, webhook_url) -> None:
"""
@@ -180,7 +180,7 @@ class Notification:
"""
if not webhook_url:
raise ValueError("The webhook URL can not be empty.")
raise ValueError("WebHook 地址不能为空")
content = f"{title}\n{content}"
data = {"msgtype": "text", "text": {"content": content}}
@@ -191,9 +191,9 @@ class Notification:
info = response.json()
if info["errcode"] == 0:
logger.success(f"WebHook 推送通知成功{title}")
logger.success(f"WebHook 推送通知成功: {title}")
else:
raise Exception(f"WebHook failed to send notification: {response.text}")
raise Exception(f"WebHook 推送通知失败: {response.text}")
def CompanyWebHookBotPushImage(self, image_path: Path, webhook_url: str) -> None:
"""
@@ -204,14 +204,14 @@ class Notification:
"""
if not webhook_url:
raise ValueError("The webhook URL can not be empty.")
raise ValueError("webhook URL 不能为空")
# 压缩图片
ImageUtils.compress_image_if_needed(image_path)
# 检查图片是否存在
if not image_path.exists():
raise FileNotFoundError(f"File not found: {image_path}")
raise FileNotFoundError(f"文件未找到: {image_path}")
# 获取图片base64和md5
image_base64 = ImageUtils.get_base64_from_file(str(image_path))
@@ -228,11 +228,9 @@ class Notification:
info = response.json()
if info.get("errcode") == 0:
logger.success(f"企业微信群机器人推送图片成功{image_path.name}")
logger.success(f"企业微信群机器人推送图片成功: {image_path.name}")
else:
raise Exception(
f"Company WebHook Bot failed to send image: {response.text}"
)
raise Exception(f"企业微信群机器人推送图片失败: {response.text}")
def send_test_notification(self) -> None:
"""发送测试通知到所有已启用的通知渠道"""
@@ -242,7 +240,7 @@ class Notification:
# 发送系统通知
self.push_plyer(
"测试通知",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容, 说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
"测试通知",
3,
)
@@ -252,7 +250,7 @@ class Notification:
self.send_mail(
"文本",
"AUTO_MAA测试通知",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容, 说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
Config.get("Notify", "ToAddress"),
)
@@ -260,7 +258,7 @@ class Notification:
if Config.get("Notify", "IfServerChan"):
self.ServerChanPush(
"AUTO_MAA测试通知",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容, 说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
Config.get("Notify", "ServerChanKey"),
)
@@ -268,7 +266,7 @@ class Notification:
if Config.get("Notify", "IfCompanyWebHookBot"):
self.WebHookPush(
"AUTO_MAA测试通知",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容, 说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
Config.get("Notify", "CompanyWebHookBotUrl"),
)
Notify.CompanyWebHookBotPushImage(

View File

@@ -139,14 +139,10 @@ class _SystemHandler:
if result.returncode == 0:
logger.success(
f"程序自启动任务计划已创建: {Path.cwd() / 'AUTO_MAA.exe'}",
module="系统服务",
f"程序自启动任务计划已创建: {Path.cwd() / 'AUTO_MAA.exe'}"
)
else:
logger.error(
f"程序自启动任务计划创建失败: {result.stderr}",
module="系统服务",
)
logger.error(f"程序自启动任务计划创建失败: {result.stderr}")
finally:
# 删除临时文件
@@ -173,10 +169,7 @@ class _SystemHandler:
if result.returncode == 0:
logger.success("程序自启动任务计划已删除")
else:
logger.error(
f"程序自启动任务计划删除失败: {result.stderr}",
module="系统服务",
)
logger.error(f"程序自启动任务计划删除失败: {result.stderr}")
except Exception as e:
logger.exception(f"程序自启动任务计划删除失败: {e}")
@@ -334,7 +327,7 @@ class _SystemHandler:
if proc.info["exe"] and proc.info["exe"].lower() == str(path).lower():
pids.append(proc.info["pid"])
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
# 进程可能在此期间已结束或无法访问忽略这些异常
# 进程可能在此期间已结束或无法访问, 忽略这些异常
pass
return pids

View File

@@ -92,23 +92,23 @@ class MaaManager:
(1, 20), "%Y-%m-%d %H:%M:%S", self.check_maa_log
)
logger.success(f"{self.script_id}已锁定MAA配置提取完成")
logger.success(f"{self.script_id}已锁定, MAA配置提取完成")
def check_config(self) -> str:
"""检查配置是否可用"""
if not self.maa_exe_path.exists():
return "MAA.exe文件不存在请检查MAA路径设置"
return "MAA.exe文件不存在, 请检查MAA路径设置"
if not self.maa_set_path.exists():
return "MAA配置文件不存在请检查MAA路径设置"
return "MAA配置文件不存在, 请检查MAA路径设置"
if (self.mode != "设置脚本" or self.user_id is not None) and not (
Path.cwd() / f"data/{self.script_id}/Default/ConfigFile/gui.json"
).exists():
return "未完成 MAA 全局设置请先设置 MAA"
return "未完成 MAA 全局设置, 请先设置 MAA"
return "Success!"
async def run(self):
"""主进程运行MAA代理进程"""
"""主进程, 运行MAA代理进程"""
self.current_date = datetime.now().strftime("%m-%d")
self.curdate = Config.server_date().strftime("%Y-%m-%d")
@@ -117,7 +117,7 @@ class MaaManager:
await self.configure()
self.check_result = self.check_config()
if self.check_result != "Success!":
logger.error(f"未通过配置检查{self.check_result}")
logger.error(f"未通过配置检查: {self.check_result}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id, type="Info", data={"Error": self.check_result}
@@ -126,14 +126,14 @@ class MaaManager:
return
# 记录 MAA 配置文件
logger.info(f"记录 MAA 配置文件{self.maa_set_path}")
logger.info(f"记录 MAA 配置文件: {self.maa_set_path}")
(Path.cwd() / f"data/{self.script_id}/Temp").mkdir(parents=True, exist_ok=True)
if self.maa_set_path.exists():
shutil.copy(
self.maa_set_path, Path.cwd() / f"data/{self.script_id}/Temp/gui.json"
)
# 整理用户数据筛选需代理的用户
# 整理用户数据, 筛选需代理的用户
if self.mode != "设置脚本":
self.user_list: List[Dict[str, str]] = [
@@ -153,7 +153,7 @@ class MaaManager:
),
)
logger.info(f"用户列表创建完成已筛选用户数{len(self.user_list)}")
logger.info(f"用户列表创建完成, 已筛选用户数: {len(self.user_list)}")
# 自动代理模式
if self.mode == "自动代理":
@@ -246,7 +246,7 @@ class MaaManager:
if type != "总计" and len(user_list) > 0:
logger.info(
f"用户: {user['user_id']} - 森空岛签到{type}: {''.join(user_list)}",
f"用户: {user['user_id']} - 森空岛签到{type}: {''.join(user_list)}"
)
await Config.send_json(
WebSocketMessage(
@@ -283,14 +283,14 @@ class MaaManager:
elif self.cur_user_data.get("Info", "IfSkland"):
logger.warning(
f"用户: {user['user_id']} - 未配置森空岛签到Token跳过森空岛签到"
f"用户: {user['user_id']} - 未配置森空岛签到Token, 跳过森空岛签到"
)
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
type="Info",
data={
"Warning": f"用户 {user['name']} 未配置森空岛签到Token跳过森空岛签到"
"Warning": f"用户 {user['name']} 未配置森空岛签到Token, 跳过森空岛签到"
},
).model_dump()
)
@@ -312,7 +312,7 @@ class MaaManager:
== datetime.strptime(self.curdate, "%Y-%m-%d").isocalendar()[:2]
):
logger.info(
f"用户: {user['user_id']} - 本周剿灭模式已达上限跳过执行剿灭任务"
f"用户: {user['user_id']} - 本周剿灭模式已达上限, 跳过执行剿灭任务"
)
self.run_book[mode] = True
continue
@@ -397,7 +397,7 @@ class MaaManager:
break
logger.info(
f"用户 {user['name']} - 模式: {mode} - 尝试次数: {i + 1}/{self.script_config.get('Run','RunTimesLimit')}",
f"用户 {user['name']} - 模式: {mode} - 尝试次数: {i + 1}/{self.script_config.get('Run','RunTimesLimit')}"
)
# 配置MAA
@@ -412,7 +412,7 @@ class MaaManager:
self.emulator_arguments = set["Configurations"]["Default"][
"Start.EmulatorAddCommand"
].split()
# 如果是快捷方式进行解析
# 如果是快捷方式, 进行解析
if (
self.emulator_path.suffix == ".lnk"
and self.emulator_path.exists()
@@ -423,20 +423,20 @@ class MaaManager:
self.emulator_path = Path(shortcut.TargetPath)
self.emulator_arguments = shortcut.Arguments.split()
except Exception as e:
logger.exception(f"解析快捷方式时出现异常{e}")
logger.exception(f"解析快捷方式时出现异常: {e}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
type="Info",
data={
"Error": f"解析快捷方式时出现异常{e}",
"Error": f"解析快捷方式时出现异常: {e}",
},
).model_dump()
)
self.if_open_emulator = True
break
elif not self.emulator_path.exists():
logger.error(f"模拟器快捷方式不存在{self.emulator_path}")
logger.error(f"模拟器快捷方式不存在: {self.emulator_path}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
@@ -479,40 +479,40 @@ class MaaManager:
# 任务开始前释放ADB
try:
logger.info(f"释放ADB{self.ADB_address}")
logger.info(f"释放ADB: {self.ADB_address}")
subprocess.run(
[self.ADB_path, "disconnect", self.ADB_address],
creationflags=subprocess.CREATE_NO_WINDOW,
)
except subprocess.CalledProcessError as e:
# 忽略错误,因为可能本来就没有连接
logger.warning(f"释放ADB时出现异常{e}")
logger.warning(f"释放ADB时出现异常: {e}")
except Exception as e:
logger.exception(f"释放ADB时出现异常{e}")
logger.exception(f"释放ADB时出现异常: {e}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
type="Info",
data={"Warning": f"释放ADB时出现异常{e}"},
data={"Warning": f"释放ADB时出现异常: {e}"},
).model_dump()
)
if self.if_open_emulator_process:
try:
logger.info(
f"启动模拟器{self.emulator_path},参数:{self.emulator_arguments}"
f"启动模拟器: {self.emulator_path}, 参数: {self.emulator_arguments}"
)
await self.emulator_process_manager.open_process(
self.emulator_path, self.emulator_arguments, 0
)
except Exception as e:
logger.exception(f"启动模拟器时出现异常{e}")
logger.exception(f"启动模拟器时出现异常: {e}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
type="Info",
data={
"Error": "启动模拟器时出现异常请检查MAA中模拟器路径设置"
"Error": "启动模拟器时出现异常, 请检查MAA中模拟器路径设置"
},
).model_dump()
)
@@ -521,7 +521,7 @@ class MaaManager:
# 更新静默进程标记有效时间
logger.info(
f"更新静默进程标记{self.emulator_path}标记有效时间{datetime.now() + timedelta(seconds=self.wait_time + 10)}"
f"更新静默进程标记: {self.emulator_path}, 标记有效时间: {datetime.now() + timedelta(seconds=self.wait_time + 10)}"
)
Config.silence_dict[self.emulator_path] = (
datetime.now() + timedelta(seconds=self.wait_time + 10)
@@ -530,7 +530,7 @@ class MaaManager:
await self.search_ADB_address()
# 创建MAA任务
logger.info(f"启动MAA进程{self.maa_exe_path}")
logger.info(f"启动MAA进程: {self.maa_exe_path}")
await self.maa_process_manager.open_process(
self.maa_exe_path, [], 0
)
@@ -567,10 +567,10 @@ class MaaManager:
else:
logger.error(
f"用户: {user['user_id']} - 代理任务异常: {self.maa_result}",
f"用户: {user['user_id']} - 代理任务异常: {self.maa_result}"
)
# 打印中止信息
# 此时log变量内存储的就是出现异常的日志信息可以保存或发送用于问题排查
# 此时, log变量内存储的就是出现异常的日志信息, 可以保存或发送用于问题排查
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
@@ -581,13 +581,13 @@ class MaaManager:
).model_dump()
)
# 无命令行中止MAA与其子程序
logger.info(f"中止MAA进程{self.maa_exe_path}")
logger.info(f"中止MAA进程: {self.maa_exe_path}")
await self.maa_process_manager.kill(if_force=True)
await System.kill_process(self.maa_exe_path)
# 中止模拟器进程
logger.info(
f"中止模拟器进程{list(self.emulator_process_manager.tracked_pids)}"
f"中止模拟器进程: {list(self.emulator_process_manager.tracked_pids)}"
)
await self.emulator_process_manager.kill()
@@ -605,27 +605,27 @@ class MaaManager:
# 任务结束后释放ADB
try:
logger.info(f"释放ADB{self.ADB_address}")
logger.info(f"释放ADB: {self.ADB_address}")
subprocess.run(
[self.ADB_path, "disconnect", self.ADB_address],
creationflags=subprocess.CREATE_NO_WINDOW,
)
except subprocess.CalledProcessError as e:
# 忽略错误,因为可能本来就没有连接
logger.warning(f"释放ADB时出现异常{e}")
logger.warning(f"释放ADB时出现异常: {e}")
except Exception as e:
logger.exception(f"释放ADB时出现异常{e}")
logger.exception(f"释放ADB时出现异常: {e}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
type="Info",
data={"Error": f"释放ADB时出现异常{e}"},
data={"Error": f"释放ADB时出现异常: {e}"},
).model_dump()
)
# 任务结束后再次手动中止模拟器进程防止退出不彻底
# 任务结束后再次手动中止模拟器进程, 防止退出不彻底
if self.if_kill_emulator:
logger.info(
f"任务结束后再次中止模拟器进程{list(self.emulator_process_manager.tracked_pids)}"
f"任务结束后再次中止模拟器进程: {list(self.emulator_process_manager.tracked_pids)}"
)
await self.emulator_process_manager.kill()
self.if_open_emulator = True
@@ -677,7 +677,7 @@ class MaaManager:
if if_six_star:
await self.push_notification(
"公招六星",
f"喜报用户 {user['name']} 公招出六星啦!",
f"喜报: 用户 {user['name']} 公招出六星啦!",
{
"user_name": user["name"],
},
@@ -686,7 +686,7 @@ class MaaManager:
# 执行MAA解压更新动作
if self.maa_update_package:
logger.info(f"检测到MAA更新正在执行更新动作")
logger.info(f"检测到MAA更新, 正在执行更新动作")
await Config.send_json(
WebSocketMessage(
@@ -714,8 +714,8 @@ class MaaManager:
# 人工排查模式
elif self.mode == "人工排查":
# 人工排查时屏蔽静默操作
logger.info("人工排查任务开始屏蔽静默操作")
# 人工排查时, 屏蔽静默操作
logger.info("人工排查任务开始, 屏蔽静默操作")
Config.if_ignore_silence.append(self.script_id)
# 标记是否需要启动模拟器
@@ -751,7 +751,7 @@ class MaaManager:
# 记录当前时间
self.log_start_time = datetime.now()
# 创建MAA任务
logger.info(f"启动MAA进程{self.maa_exe_path}")
logger.info(f"启动MAA进程: {self.maa_exe_path}")
await self.maa_process_manager.open_process(
self.maa_exe_path, [], 0
)
@@ -772,9 +772,7 @@ class MaaManager:
)
if self.maa_result == "Success!":
logger.info(
f"用户: {user['user_id']} - MAA进程成功登录PRTS",
)
logger.info(f"用户: {user['user_id']} - MAA进程成功登录PRTS")
self.run_book["SignIn"] = True
await Config.send_json(
WebSocketMessage(
@@ -797,16 +795,16 @@ class MaaManager:
).model_dump()
)
# 无命令行中止MAA与其子程序
logger.info(f"中止MAA进程{self.maa_exe_path}")
logger.info(f"中止MAA进程: {self.maa_exe_path}")
await self.maa_process_manager.kill(if_force=True)
await System.kill_process(self.maa_exe_path)
self.if_open_emulator = True
await asyncio.sleep(10)
# 登录成功结束循环
# 登录成功, 结束循环
if self.run_book["SignIn"]:
break
# 登录失败询问是否结束循环
# 登录失败, 询问是否结束循环
else:
uid = str(uuid.uuid4())
@@ -818,7 +816,7 @@ class MaaManager:
"message_id": uid,
"type": "Question",
"title": "操作提示",
"message": "MAA未能正确登录到PRTS是否重试?",
"message": "MAA未能正确登录到PRTS, 是否重试?",
},
).model_dump()
)
@@ -826,7 +824,7 @@ class MaaManager:
if result.get("choice", False):
break
# 登录成功录入人工排查情况
# 登录成功, 录入人工排查情况
if self.run_book["SignIn"]:
uid = str(uuid.uuid4())
@@ -838,7 +836,7 @@ class MaaManager:
"message_id": uid,
"type": "Question",
"title": "操作提示",
"message": "请检查用户代理情况该用户是否正确完成代理任务?",
"message": "请检查用户代理情况, 该用户是否正确完成代理任务?",
},
).model_dump()
)
@@ -862,7 +860,7 @@ class MaaManager:
# 配置MAA
await self.set_maa(self.mode)
# 创建MAA任务
logger.info(f"启动MAA进程{self.maa_exe_path}")
logger.info(f"启动MAA进程: {self.maa_exe_path}")
await self.maa_process_manager.open_process(self.maa_exe_path, [], 0)
# 记录当前时间
self.log_start_time = datetime.now()
@@ -945,7 +943,7 @@ class MaaManager:
self.user_list[self.index]["status"] = "完成"
else:
logger.info(
f"用户 {self.user_list[self.index]['user_id']} 未通过人工排查",
f"用户 {self.user_list[self.index]['user_id']} 未通过人工排查"
)
await self.cur_user_data.set("Data", "IfPassCheck", False)
self.user_list[self.index]["status"] = "异常"
@@ -953,7 +951,7 @@ class MaaManager:
async def final_task(self, task: asyncio.Task):
"""结束时的收尾工作"""
logger.info("MAA 主任务已结束开始执行后续操作")
logger.info("MAA 主任务已结束, 开始执行后续操作")
await Config.ScriptConfig[self.script_id].unlock()
logger.success(f"已解锁脚本配置 {self.script_id}")
@@ -974,7 +972,7 @@ class MaaManager:
if self.mode == "人工排查":
# 解除静默操作屏蔽
logger.info("人工排查任务结束解除静默操作屏蔽")
logger.info("人工排查任务结束, 解除静默操作屏蔽")
if self.script_id in Config.if_ignore_silence:
Config.if_ignore_silence.remove(self.script_id)
@@ -998,7 +996,7 @@ class MaaManager:
if if_six_star:
await self.push_notification(
"公招六星",
f"喜报用户 {self.user_list[self.index]['name']} 公招出六星啦!",
f"喜报: 用户 {self.user_list[self.index]['name']} 公招出六星啦!",
{
"user_name": self.user_list[self.index]["name"],
},
@@ -1046,21 +1044,21 @@ class MaaManager:
# 生成结果文本
result_text = (
f"任务开始时间{result["start_time"]}结束时间{result["end_time"]}\n"
f"已完成数{result["completed_count"]}未完成数{result["uncompleted_count"]}\n\n"
f"任务开始时间: {result["start_time"]}, 结束时间: {result["end_time"]}\n"
f"已完成数: {result["completed_count"]}, 未完成数: {result["uncompleted_count"]}\n\n"
)
if len(result["failed_user"]) > 0:
result_text += (
f"{self.mode}未成功的用户\n{"\n".join(result["failed_user"])}\n"
f"{self.mode}未成功的用户: \n{"\n".join(result["failed_user"])}\n"
)
if len(result["waiting_user"]) > 0:
result_text += f"\n未开始{self.mode}的用户\n{"\n".join(result["waiting_user"])}\n"
result_text += f"\n未开始{self.mode}的用户: \n{"\n".join(result["waiting_user"])}\n"
# 推送代理结果通知
Notify.push_plyer(
title.replace("报告", "已完成!"),
f"已完成用户数{len(over_user)}未完成用户数{len(error_user) + len(wait_user)}",
f"已完成用户数{len(over_user)}未完成用户数{len(error_user) + len(wait_user)}",
f"已完成用户数: {len(over_user)}, 未完成用户数: {len(error_user) + len(wait_user)}",
f"已完成用户数: {len(over_user)}, 未完成用户数: {len(error_user) + len(wait_user)}",
10,
)
await self.push_notification("代理结果", title, result)
@@ -1081,7 +1079,7 @@ class MaaManager:
result_text = ""
# 复原 MAA 配置文件
logger.info(f"复原 MAA 配置文件{Path.cwd() / f'data/{self.script_id}/Temp'}")
logger.info(f"复原 MAA 配置文件: {Path.cwd() / f'data/{self.script_id}/Temp'}")
if (Path.cwd() / f"data/{self.script_id}/Temp/gui.json").exists():
shutil.copy(
Path.cwd() / f"data/{self.script_id}/Temp/gui.json", self.maa_set_path
@@ -1094,13 +1092,13 @@ class MaaManager:
async def get_message(self, message_id: str):
"""获取当前任务的属性值"""
logger.info(f"等待客户端回应消息{message_id}")
logger.info(f"等待客户端回应消息: {message_id}")
while True:
message = await self.message_queue.get()
if message.get("message_id") == message_id:
self.message_queue.task_done()
logger.success(f"收到客户端回应消息{message_id}")
logger.success(f"收到客户端回应消息: {message_id}")
return message
else:
self.message_queue.task_done()
@@ -1129,7 +1127,7 @@ class MaaManager:
ADB_port = int(self.ADB_address.split(":")[1])
logger.info(
f"正在搜索ADB实际地址ADB前缀{ADB_ip}初始端口{ADB_port}搜索范围{self.port_range}"
f"正在搜索ADB实际地址, ADB前缀: {ADB_ip}, 初始端口: {ADB_port}, 搜索范围: {self.port_range}"
)
for port in self.port_range:
@@ -1159,10 +1157,10 @@ class MaaManager:
)
if ADB_address in devices_result.stdout:
logger.info(f"ADB实际地址{ADB_address}")
logger.info(f"ADB实际地址: {ADB_address}")
# 断开连接
logger.info(f"断开ADB连接{ADB_address}")
logger.info(f"断开ADB连接: {ADB_address}")
subprocess.run(
[self.ADB_path, "disconnect", ADB_address],
creationflags=subprocess.CREATE_NO_WINDOW,
@@ -1171,7 +1169,7 @@ class MaaManager:
self.ADB_address = ADB_address
# 覆写当前ADB地址
logger.info(f"开始使用实际 ADB 地址覆写{self.ADB_address}")
logger.info(f"开始使用实际 ADB 地址覆写: {self.ADB_address}")
await self.maa_process_manager.kill(if_force=True)
await System.kill_process(self.maa_exe_path)
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
@@ -1186,9 +1184,9 @@ class MaaManager:
return None
else:
logger.info(f"无法连接到ADB地址{ADB_address}")
logger.info(f"无法连接到ADB地址: {ADB_address}")
else:
logger.info(f"无法连接到ADB地址{ADB_address}")
logger.info(f"无法连接到ADB地址: {ADB_address}")
async def check_maa_log(self, log_content: List[str]) -> None:
"""获取MAA日志并检查以判断MAA程序运行状态"""
@@ -1211,14 +1209,14 @@ class MaaManager:
latest_time = self.log_start_time
for _ in self.maa_logs[::-1]:
try:
if "如果长时间无进一步日志更新可能需要手动干预。" in _:
if "如果长时间无进一步日志更新, 可能需要手动干预。" in _:
continue
latest_time = datetime.strptime(_[1:20], "%Y-%m-%d %H:%M:%S")
break
except ValueError:
pass
logger.info(f"MAA最近一条日志时间{latest_time}")
logger.info(f"MAA最近一条日志时间: {latest_time}")
if self.log_check_mode == "Annihilation" and "任务出错: 刷理智" in log:
self.weekly_annihilation_limit_reached = True
@@ -1308,11 +1306,11 @@ class MaaManager:
else:
self.maa_result = "Wait"
logger.debug(f"MAA 日志分析结果{self.maa_result}")
logger.debug(f"MAA 日志分析结果: {self.maa_result}")
if self.maa_result != "Wait":
logger.info(f"MAA 任务结果{self.maa_result}日志锁已释放")
logger.info(f"MAA 任务结果: {self.maa_result}, 日志锁已释放")
self.wait_event.set()
async def set_maa(self, mode: str) -> dict:
@@ -1868,7 +1866,7 @@ class MaaManager:
async def push_notification(self, mode: str, title: str, message) -> None:
"""通过所有渠道推送通知"""
logger.info(f"开始推送通知,模式:{mode},标题:{title}")
logger.info(f"开始推送通知, 模式: {mode}, 标题: {title}")
env = Environment(loader=FileSystemLoader(str(Path.cwd() / "res/html")))
@@ -1881,14 +1879,14 @@ class MaaManager:
):
# 生成文本通知内容
message_text = (
f"任务开始时间{message['start_time']}结束时间{message['end_time']}\n"
f"已完成数{message['completed_count']}未完成数{message['uncompleted_count']}\n\n"
f"任务开始时间: {message['start_time']}, 结束时间: {message['end_time']}\n"
f"已完成数: {message['completed_count']}, 未完成数: {message['uncompleted_count']}\n\n"
)
if len(message["failed_user"]) > 0:
message_text += f"{self.mode[2:4]}未成功的用户\n{"\n".join(message["failed_user"])}\n"
message_text += f"{self.mode[2:4]}未成功的用户: \n{"\n".join(message["failed_user"])}\n"
if len(message["waiting_user"]) > 0:
message_text += f"\n未开始{self.mode[2:4]}的用户\n{"\n".join(message["waiting_user"])}\n"
message_text += f"\n未开始{self.mode[2:4]}的用户: \n{"\n".join(message["waiting_user"])}\n"
# 生成HTML通知内容
message["failed_user"] = "".join(message["failed_user"])
@@ -1990,7 +1988,7 @@ class MaaManager:
self.cur_user_data.get("Notify", "ToAddress"),
)
else:
logger.error(f"用户邮箱地址为空无法发送用户单独的邮件通知")
logger.error(f"用户邮箱地址为空, 无法发送用户单独的邮件通知")
# 发送ServerChan通知
if self.cur_user_data.get("Notify", "IfServerChan"):
@@ -2002,7 +2000,7 @@ class MaaManager:
)
else:
logger.error(
"用户ServerChan密钥为空无法发送用户单独的ServerChan通知"
"用户ServerChan密钥为空, 无法发送用户单独的ServerChan通知"
)
# 推送CompanyWebHookBot通知
@@ -2015,7 +2013,7 @@ class MaaManager:
)
else:
logger.error(
f"用户CompanyWebHookBot密钥为空无法发送用户单独的CompanyWebHookBot通知"
"用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知"
)
elif mode == "公招六星":
@@ -2066,7 +2064,7 @@ class MaaManager:
self.cur_user_data.get("Notify", "ToAddress"),
)
else:
logger.error("用户邮箱地址为空无法发送用户单独的邮件通知")
logger.error("用户邮箱地址为空, 无法发送用户单独的邮件通知")
# 发送ServerChan通知
if self.cur_user_data.get("Notify", "IfServerChan"):
@@ -2079,7 +2077,7 @@ class MaaManager:
)
else:
logger.error(
"用户ServerChan密钥为空无法发送用户单独的ServerChan通知"
"用户ServerChan密钥为空, 无法发送用户单独的ServerChan通知"
)
# 推送CompanyWebHookBot通知
@@ -2096,7 +2094,7 @@ class MaaManager:
)
else:
logger.error(
"用户CompanyWebHookBot密钥为空无法发送用户单独的CompanyWebHookBot通知"
"用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知"
)
return None

View File

@@ -137,7 +137,7 @@ class GeneralManager:
self.check_general_log,
)
logger.success(f"{self.script_id}已锁定通用配置提取完成")
logger.success(f"{self.script_id}已锁定, 通用配置提取完成")
def check_config(self) -> str:
"""检查配置是否可用"""
@@ -150,7 +150,7 @@ class GeneralManager:
return "Success!"
async def run(self):
"""主进程运行通用脚本代理进程"""
"""主进程, 运行通用脚本代理进程"""
self.current_date = datetime.now().strftime("%m-%d")
self.curdate = Config.server_date().strftime("%Y-%m-%d")
@@ -159,7 +159,7 @@ class GeneralManager:
await self.configure()
self.check_result = self.check_config()
if self.check_result != "Success!":
logger.error(f"未通过配置检查{self.check_result}")
logger.error(f"未通过配置检查: {self.check_result}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id, type="Info", data={"Error": self.check_result}
@@ -168,7 +168,7 @@ class GeneralManager:
return
# 记录配置文件
logger.info(f"记录通用脚本配置文件{self.script_config_path}")
logger.info(f"记录通用脚本配置文件: {self.script_config_path}")
(Path.cwd() / f"data/{self.script_id}/Temp").mkdir(parents=True, exist_ok=True)
if self.script_config_path.exists():
if self.script_config.get("Script", "ConfigPathMode") == "Folder":
@@ -183,7 +183,7 @@ class GeneralManager:
Path.cwd() / f"data/{self.script_id}/Temp/config.temp",
)
# 整理用户数据筛选需代理的用户
# 整理用户数据, 筛选需代理的用户
if self.mode != "设置脚本":
self.user_list: List[Dict[str, str]] = [
@@ -197,7 +197,7 @@ class GeneralManager:
and config.get("Info", "RemainedDay") != 0
]
logger.info(f"用户列表创建完成已筛选子配置数{len(self.user_list)}")
logger.info(f"用户列表创建完成, 已筛选子配置数: {len(self.user_list)}")
# 自动代理模式
if self.mode == "自动代理":
@@ -273,7 +273,7 @@ class GeneralManager:
break
logger.info(
f"用户 {user['user_id']} - 尝试次数: {i + 1}/{self.script_config.get('Run','RunTimesLimit')}",
f"用户 {user['user_id']} - 尝试次数: {i + 1}/{self.script_config.get('Run','RunTimesLimit')}"
)
# 配置脚本
@@ -298,7 +298,7 @@ class GeneralManager:
try:
logger.info(
f"启动游戏/模拟器{self.game_path},参数:{self.script_config.get('Game','Arguments')}",
f"启动游戏/模拟器: {self.game_path}, 参数: {self.script_config.get('Game','Arguments')}"
)
await self.game_process_manager.open_process(
self.game_path,
@@ -308,12 +308,12 @@ class GeneralManager:
0,
)
except Exception as e:
logger.exception(f"启动游戏/模拟器时出现异常{e}")
logger.exception(f"启动游戏/模拟器时出现异常: {e}")
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
type="Info",
data={"Error": f"启动游戏/模拟器时出现异常{e}"},
data={"Error": f"启动游戏/模拟器时出现异常: {e}"},
).model_dump()
)
self.general_result = "游戏/模拟器启动失败"
@@ -322,7 +322,7 @@ class GeneralManager:
# 更新静默进程标记有效时间
if self.script_config.get("Game", "Type") == "Emulator":
logger.info(
f"更新静默进程标记{self.game_path}标记有效时间{datetime.now() + timedelta(seconds=self.script_config.get('Game', 'WaitTime') + 10)}"
f"更新静默进程标记: {self.game_path}, 标记有效时间: {datetime.now() + timedelta(seconds=self.script_config.get('Game', 'WaitTime') + 10)}"
)
Config.silence_dict[
self.game_path
@@ -343,7 +343,7 @@ class GeneralManager:
# 运行脚本任务
logger.info(
f"运行脚本任务{self.script_exe_path},参数:{self.script_arguments}",
f"运行脚本任务: {self.script_exe_path}, 参数: {self.script_arguments}"
)
await self.general_process_manager.open_process(
self.script_exe_path,
@@ -384,12 +384,12 @@ class GeneralManager:
)
# 中止相关程序
logger.info(f"中止相关程序{self.script_exe_path}")
logger.info(f"中止相关程序: {self.script_exe_path}")
await self.general_process_manager.kill()
await System.kill_process(self.script_exe_path)
if self.script_config.get("Game", "Enabled"):
logger.info(
f"中止游戏/模拟器进程{list(self.game_process_manager.tracked_pids)}"
f"中止游戏/模拟器进程: {list(self.game_process_manager.tracked_pids)}"
)
await self.game_process_manager.kill()
if self.script_config.get("Game", "IfForceClose"):
@@ -427,10 +427,10 @@ class GeneralManager:
else:
logger.error(
f"配置: {user['user_id']} - 代理任务异常: {self.general_result}",
f"配置: {user['user_id']} - 代理任务异常: {self.general_result}"
)
# 打印中止信息
# 此时log变量内存储的就是出现异常的日志信息可以保存或发送用于问题排查
# 此时, log变量内存储的就是出现异常的日志信息, 可以保存或发送用于问题排查
await Config.send_json(
WebSocketMessage(
id=self.ws_id,
@@ -442,12 +442,12 @@ class GeneralManager:
)
# 中止相关程序
logger.info(f"中止相关程序{self.script_exe_path}")
logger.info(f"中止相关程序: {self.script_exe_path}")
await self.general_process_manager.kill()
await System.kill_process(self.script_exe_path)
if self.script_config.get("Game", "Enabled"):
logger.info(
f"中止游戏/模拟器进程{list(self.game_process_manager.tracked_pids)}"
f"中止游戏/模拟器进程: {list(self.game_process_manager.tracked_pids)}"
)
await self.game_process_manager.kill()
if self.script_config.get("Game", "IfForceClose"):
@@ -520,7 +520,7 @@ class GeneralManager:
await self.set_general()
# 创建通用脚本任务
logger.info(
f"运行脚本任务{self.script_set_exe_path},参数:{self.script_set_arguments}"
f"运行脚本任务: {self.script_set_exe_path}, 参数: {self.script_set_arguments}"
)
await self.general_process_manager.open_process(
self.script_set_exe_path,
@@ -592,7 +592,7 @@ class GeneralManager:
async def final_task(self, task: asyncio.Task):
"""结束时的收尾工作"""
logger.info("MAA 主任务已结束开始执行后续操作")
logger.info("MAA 主任务已结束, 开始执行后续操作")
await Config.ScriptConfig[self.script_id].unlock()
logger.success(f"已解锁脚本配置 {self.script_id}")
@@ -692,21 +692,21 @@ class GeneralManager:
# 生成结果文本
result_text = (
f"任务开始时间{result['start_time']}结束时间{result['end_time']}\n"
f"已完成数{result['completed_count']}未完成数{result['uncompleted_count']}\n\n"
f"任务开始时间: {result['start_time']}, 结束时间: {result['end_time']}\n"
f"已完成数: {result['completed_count']}, 未完成数: {result['uncompleted_count']}\n\n"
)
if len(result["failed_user"]) > 0:
result_text += (
f"{self.mode}未成功的用户\n{"\n".join(result['failed_user'])}\n"
f"{self.mode}未成功的用户: \n{"\n".join(result['failed_user'])}\n"
)
if len(result["waiting_user"]) > 0:
result_text += f"\n未开始{self.mode}的用户\n{"\n".join(result['waiting_user'])}\n"
result_text += f"\n未开始{self.mode}的用户: \n{"\n".join(result['waiting_user'])}\n"
# 推送代理结果通知
Notify.push_plyer(
title.replace("报告", "已完成!"),
f"已完成配置数{len(over_user)}未完成配置数{len(error_user) + len(wait_user)}",
f"已完成配置数{len(over_user)}未完成配置数{len(error_user) + len(wait_user)}",
f"已完成配置数: {len(over_user)}, 未完成配置数: {len(error_user) + len(wait_user)}",
f"已完成配置数: {len(over_user)}, 未完成配置数: {len(error_user) + len(wait_user)}",
10,
)
await self.push_notification("代理结果", title, result)
@@ -723,7 +723,7 @@ class GeneralManager:
dirs_exist_ok=True,
)
logger.success(
f"通用脚本配置已保存到{Path.cwd() / f'data/{self.script_id}/{self.user_id}/ConfigFile'}",
f"通用脚本配置已保存到: {Path.cwd() / f'data/{self.script_id}/{self.user_id}/ConfigFile'}"
)
elif self.script_config.get("Script", "ConfigPathMode") == "File":
shutil.copy(
@@ -733,7 +733,7 @@ class GeneralManager:
/ self.script_config_path.name,
)
logger.success(
f"通用脚本配置已保存到{Path.cwd() / f'data/{self.script_id}/{self.user_id}/ConfigFile' / self.script_config_path.name}",
f"通用脚本配置已保存到: {Path.cwd() / f'data/{self.script_id}/{self.user_id}/ConfigFile' / self.script_config_path.name}"
)
result_text = ""
@@ -743,7 +743,7 @@ class GeneralManager:
and (Path.cwd() / f"data/{self.script_id}/Temp").exists()
):
logger.info(
f"复原通用脚本配置文件{Path.cwd() / f"data/{self.script_id}/Temp"}"
f"复原通用脚本配置文件: {Path.cwd() / f"data/{self.script_id}/Temp"}"
)
shutil.copytree(
Path.cwd() / f"data/{self.script_id}/Temp",
@@ -756,7 +756,7 @@ class GeneralManager:
and (Path.cwd() / f"data/{self.script_id}/Temp/config.temp").exists()
):
logger.info(
f"复原通用脚本配置文件{Path.cwd() / f"data/{self.script_id}/Temp/config.temp"}"
f"复原通用脚本配置文件: {Path.cwd() / f"data/{self.script_id}/Temp/config.temp"}"
)
shutil.copy(
Path.cwd() / f"data/{self.script_id}/Temp/config.temp",
@@ -796,7 +796,7 @@ class GeneralManager:
except ValueError:
pass
logger.info(f"通用脚本最近一条日志时间{latest_time}")
logger.info(f"通用脚本最近一条日志时间: {latest_time}")
for success_sign in self.success_log:
if success_sign in log:
@@ -811,7 +811,7 @@ class GeneralManager:
else:
for error_sign in self.error_log:
if error_sign in log:
self.general_result = f"异常日志{error_sign}"
self.general_result = f"异常日志: {error_sign}"
break
else:
if await self.general_process_manager.is_running():
@@ -827,16 +827,16 @@ class GeneralManager:
else:
self.general_result = "Success!"
logger.info(f"通用脚本日志分析结果{self.general_result}")
logger.info(f"通用脚本日志分析结果: {self.general_result}")
if self.general_result != "Wait":
logger.info(f"MAA 任务结果{self.general_result}日志锁已释放")
logger.info(f"MAA 任务结果: {self.general_result}, 日志锁已释放")
self.wait_event.set()
async def set_general(self) -> None:
"""配置通用脚本运行参数"""
logger.info(f"开始配置脚本运行参数{self.mode}")
logger.info(f"开始配置脚本运行参数: {self.mode}")
# 配置前关闭可能未正常退出的脚本进程
if self.mode == "自动代理":
@@ -887,7 +887,7 @@ class GeneralManager:
self.script_config_path,
)
logger.info(f"脚本运行参数配置完成{self.mode}")
logger.info(f"脚本运行参数配置完成: {self.mode}")
async def execute_script_task(self, script_path: Path, task_name: str) -> bool:
"""执行脚本任务并等待结束"""
@@ -901,7 +901,7 @@ class GeneralManager:
elif script_path.suffix.lower() in [".bat", ".cmd", ".exe"]:
cmd = [str(script_path)]
elif script_path.suffix.lower() == "":
logger.warning(f"{task_name}脚本没有指定后缀名无法执行")
logger.warning(f"{task_name}脚本没有指定后缀名, 无法执行")
return False
else:
# 使用系统默认程序打开
@@ -929,7 +929,7 @@ class GeneralManager:
logger.info(f"{task_name}输出: {result.stdout}")
return True
else:
logger.error(f"{task_name}执行失败返回码: {result.returncode}")
logger.error(f"{task_name}执行失败, 返回码: {result.returncode}")
if result.stderr.strip():
logger.error(f"{task_name}错误输出: {result.stderr}")
return False
@@ -944,7 +944,7 @@ class GeneralManager:
async def push_notification(self, mode: str, title: str, message) -> None:
"""通过所有渠道推送通知"""
logger.info(f"开始推送通知,模式:{mode},标题:{title}")
logger.info(f"开始推送通知, 模式: {mode}, 标题: {title}")
env = Environment(loader=FileSystemLoader(str(Path.cwd() / "res/html")))
@@ -957,14 +957,14 @@ class GeneralManager:
):
# 生成文本通知内容
message_text = (
f"任务开始时间{message['start_time']}结束时间{message['end_time']}\n"
f"已完成数{message['completed_count']}未完成数{message['uncompleted_count']}\n\n"
f"任务开始时间: {message['start_time']}, 结束时间: {message['end_time']}\n"
f"已完成数: {message['completed_count']}, 未完成数: {message['uncompleted_count']}\n\n"
)
if len(message["failed_user"]) > 0:
message_text += f"{self.mode[2:4]}未成功的配置\n{"\n".join(message['failed_user'])}\n"
message_text += f"{self.mode[2:4]}未成功的配置: \n{"\n".join(message['failed_user'])}\n"
if len(message["waiting_user"]) > 0:
message_text += f"\n未开始{self.mode[2:4]}的配置\n{"\n".join(message['waiting_user'])}\n"
message_text += f"\n未开始{self.mode[2:4]}的配置: \n{"\n".join(message['waiting_user'])}\n"
# 生成HTML通知内容
message["failed_user"] = "".join(message["failed_user"])
@@ -1049,7 +1049,7 @@ class GeneralManager:
self.cur_user_data.get("Notify", "ToAddress"),
)
else:
logger.error(f"用户邮箱地址为空无法发送用户单独的邮件通知")
logger.error(f"用户邮箱地址为空, 无法发送用户单独的邮件通知")
# 发送ServerChan通知
if self.cur_user_data.get("Notify", "IfServerChan"):
@@ -1061,7 +1061,7 @@ class GeneralManager:
)
else:
logger.error(
"用户ServerChan密钥为空无法发送用户单独的ServerChan通知"
"用户ServerChan密钥为空, 无法发送用户单独的ServerChan通知"
)
# 推送CompanyWebHookBot通知
@@ -1074,7 +1074,7 @@ class GeneralManager:
)
else:
logger.error(
"用户CompanyWebHookBot密钥为空无法发送用户单独的CompanyWebHookBot通知"
"用户CompanyWebHookBot密钥为空, 无法发送用户单独的CompanyWebHookBot通知"
)
return None

View File

@@ -74,11 +74,11 @@ async def skland_sign_in(token) -> dict:
:param token_for_sign: 用于加密的token
:param path: 请求路径(如 /api/v1/game/player/binding
:param body_or_query: GET用query字符串POST用body字符串
:param body_or_query: GET用query字符串, POST用body字符串
:return: (sign, 新的header_for_sign字典)
"""
t = str(int(time.time()) - 2) # 时间戳-2秒以防服务器时间不一致
t = str(int(time.time()) - 2) # 时间戳, -2秒以防服务器时间不一致
token_bytes = token_for_sign.encode("utf-8")
header_ca = dict(header_for_sign)
header_ca["timestamp"] = t
@@ -156,7 +156,7 @@ async def skland_sign_in(token) -> dict:
proxies=Config.get_proxies(),
).json()
if rsp["code"] != 0:
raise Exception(f'获得cred失败{rsp.get("messgae")}')
raise Exception(f"获得cred失败: {rsp.get('message')}")
sign_token = rsp["data"]["token"]
cred = rsp["data"]["cred"]
return cred, sign_token
@@ -176,7 +176,7 @@ async def skland_sign_in(token) -> dict:
).json()
if rsp["status"] != 0:
raise Exception(
f'使用token: {token[:3]}******{token[-3:]} 获得认证代码失败{rsp.get("msg")}'
f"使用token: {token[:3]}******{token[-3:]} 获得认证代码失败: {rsp.get('msg')}"
)
return rsp["data"]["code"]
@@ -197,9 +197,9 @@ async def skland_sign_in(token) -> dict:
proxies=Config.get_proxies(),
).json()
if rsp["code"] != 0:
logger.error(f"请求角色列表出现问题{rsp['message']}")
logger.error(f"请求角色列表出现问题: {rsp['message']}")
if rsp.get("message") == "用户未登录":
logger.error(f"用户登录可能失效了请重新登录!")
logger.error(f"用户登录可能失效了, 请重新登录!")
return v
# 只取明日方舟arknights的绑定账号
for i in rsp["data"]["list"]:

View File

@@ -48,7 +48,7 @@ class ImageUtils:
@staticmethod
def compress_image_if_needed(image_path: Path, max_size_mb=2) -> Path:
"""
如果图片大于max_size_mb则压缩并覆盖原文件返回原始路径Path对象
如果图片大于max_size_mb, 则压缩并覆盖原文件, 返回原始路径Path对象
"""
RESAMPLE = Image.Resampling.LANCZOS # Pillow 9.1.0及以后
@@ -82,6 +82,6 @@ class ImageUtils:
height = int(height * 0.95)
img = img.resize((width, height), RESAMPLE)
else:
raise ValueError("仅支持JPG/JPEG和PNG格式图片的压缩")
raise ValueError("仅支持JPG/JPEG和PNG格式图片的压缩")
return image_path

View File

@@ -59,7 +59,7 @@ class LogMonitor:
async def monitor_log(self):
"""监控日志文件的主循环"""
if self.log_file_path is None or not self.log_file_path.exists():
raise ValueError("Log file path is not set or does not exist.")
raise ValueError("日志文件路径未设置或文件不存在")
logger.info(f"开始监控日志文件: {self.log_file_path}")
@@ -127,7 +127,7 @@ class LogMonitor:
"""启动监控"""
if log_file_path.is_dir():
raise ValueError(f"Log file cannot be a directory: {log_file_path}")
raise ValueError(f"日志文件不能是目录: {log_file_path}")
if self.task is not None and not self.task.done():
await self.stop()

View File

@@ -27,7 +27,7 @@ from pathlib import Path
class ProcessManager:
"""进程监视器类用于跟踪主进程及其所有子进程的状态"""
"""进程监视器类, 用于跟踪主进程及其所有子进程的状态"""
def __init__(self):
super().__init__()
@@ -41,7 +41,7 @@ class ProcessManager:
self, path: Path, args: list = [], tracking_time: int = 60
) -> None:
"""
启动一个新进程并返回其pid并开始监视该进程
启动一个新进程并返回其pid, 并开始监视该进程
Parameters
----------
@@ -63,7 +63,7 @@ class ProcessManager:
async def start_monitoring(self, pid: int, tracking_time: int = 60) -> None:
"""
启动进程监视器跟踪指定的主进程及其子进程
启动进程监视器, 跟踪指定的主进程及其子进程
:param pid: 被监视进程的PID
:param tracking_time: 子进程追踪持续时间(秒)

View File

@@ -456,7 +456,7 @@ MATERIALS_MAP = {
"3261": "医疗芯片",
"3271": "辅助芯片",
"3281": "特种芯片",
"emoticon_originium_slug": "表情套组虫动",
"emoticon_originium_slug": "表情套组: 虫动",
"act29side_frag_1": "乐之节符",
"act29side_frag_2": "怒之节符",
"act29side_frag_3": "哀之节符",

View File

@@ -60,7 +60,7 @@ def get_logger(module_name: str):
"""
获取一个绑定 module 名的日志器
:param module_name: 模块名称"用户管理"
:param module_name: 模块名称, "用户管理"
:return: 绑定后的 logger
"""
return _logger.bind(module=module_name)

2
dev.md
View File

@@ -20,4 +20,4 @@ uv add <package-name>
uv remove <package-name>
```
> 💡 推荐使用uv作为默认包管理器支持现代Python项目管理特性
> 💡 推荐使用uv作为默认包管理器, 支持现代Python项目管理特性

View File

@@ -118,7 +118,7 @@ def main():
CORSMiddleware,
allow_origins=["*"], # 允许所有域名跨域访问
allow_credentials=True,
allow_methods=["*"], # 允许所有请求方法如 GET、POST、PUT、DELETE
allow_methods=["*"], # 允许所有请求方法, 如 GET、POST、PUT、DELETE
allow_headers=["*"], # 允许所有请求头
)

View File

@@ -18,7 +18,7 @@
],
"程序优化": [
"优化调度队列配置逻辑",
"优化静默进程标记逻辑避免未能及时移除导致相关功能持续开启",
"优化静默进程标记逻辑, 避免未能及时移除导致相关功能持续开启",
"MAA 代理时更新改为强制开启",
"移除 MAA 详细配置模式中的剿灭项"
]
@@ -54,7 +54,7 @@
"修复模拟器界面被异常关闭且无法重新打开的问题"
],
"程序优化": [
"重构日志记录载入更多日志记录项",
"重构日志记录, 载入更多日志记录项",
"优化日志监看启停逻辑",
"SpinBox和TimeEdit组件忽视滚轮事件"
]

View File

@@ -113,7 +113,7 @@ def search_pids(path: Path) -> list:
if proc.info["exe"] and proc.info["exe"].lower() == str(path).lower():
pids.append(proc.info["pid"])
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
# 进程可能在此期间已结束或无法访问忽略这些异常
# 进程可能在此期间已结束或无法访问, 忽略这些异常
pass
return pids
@@ -151,7 +151,7 @@ if (
config.get("Source", "GitHub") == "MirrorChyan"
and dpapi_decrypt(config.get("MirrorChyanCDK", "")) == ""
):
print("使用 MirrorChyan源但未填写 MirrorChyanCDK转用 GitHub 源")
print("使用 MirrorChyan源但未填写 MirrorChyanCDK, 转用 GitHub 源")
config["Source"] = "GitHub"
config["MirrorChyanCDK"] = ""
@@ -185,15 +185,15 @@ else:
if result["code"] != 0:
if result["code"] in MIRROR_ERROR_INFO:
print(f"获取版本信息时出错{MIRROR_ERROR_INFO[result['code']]}")
print(f"获取版本信息时出错: {MIRROR_ERROR_INFO[result['code']]}")
else:
print(
"获取版本信息时出错意料之外的错误请及时联系项目组以获取来自 Mirror 酱的技术支持"
"获取版本信息时出错: 意料之外的错误, 请及时联系项目组以获取来自 Mirror 酱的技术支持"
)
print(f" {result['msg']}")
sys.exit(1)
except Exception:
print(f"获取版本信息时出错{response.text}")
print(f"获取版本信息时出错: {response.text}")
sys.exit(1)
@@ -203,7 +203,7 @@ remote_version = version_info["data"]["version_name"]
if version.parse(remote_version) > version.parse(current_version):
# 版本更新信息
print(f"发现新版本{remote_version}当前版本{current_version}")
print(f"发现新版本: {remote_version}, 当前版本: {current_version}")
version_info_json: Dict[str, Dict[str, List[str]]] = json.loads(
re.sub(
@@ -226,7 +226,7 @@ if version.parse(remote_version) > version.parse(current_version):
update_version_info[key] += value
for key, value in update_version_info.items():
print(f"{key}")
print(f"{key}: ")
for v in value:
print(f" - {v}")
@@ -246,7 +246,7 @@ if version.parse(remote_version) > version.parse(current_version):
if response.status_code == 200:
download_url = response.url
else:
print(f"MirrorChyan 未返回下载链接使用自建下载站")
print(f"MirrorChyan 未返回下载链接, 使用自建下载站")
download_url = f"https://download.auto-mas.top/d/AUTO_MAA/AUTO_MAA_{remote_version}.zip"
elif download_source == "AutoSite":
@@ -255,10 +255,10 @@ if version.parse(remote_version) > version.parse(current_version):
)
else:
print(f"未知的下载源{download_source}请检查配置文件")
print(f"未知的下载源: {download_source}, 请检查配置文件")
sys.exit(1)
print(f"开始下载{download_url}")
print(f"开始下载: {download_url}")
# 清理可能存在的临时文件
if (Path.cwd() / "download.temp").exists():
@@ -281,13 +281,13 @@ if version.parse(remote_version) > version.parse(current_version):
check_times -= 1
print(
f"连接失败{download_url}状态码{response.status_code}剩余重试次数{check_times}",
f"连接失败: {download_url}, 状态码: {response.status_code}, 剩余重试次数: {check_times}",
)
time.sleep(1)
continue
print(f"连接成功{download_url}状态码{response.status_code}")
print(f"连接成功: {download_url}, 状态码: {response.status_code}")
file_size = int(response.headers.get("content-length", 0))
downloaded_size = 0
@@ -300,7 +300,7 @@ if version.parse(remote_version) > version.parse(current_version):
f.write(chunk)
downloaded_size += len(chunk)
# 更新指定线程的下载进度每秒更新一次
# 更新指定线程的下载进度, 每秒更新一次
if time.time() - last_time >= 1.0:
speed = (
(downloaded_size - last_download_size)
@@ -312,15 +312,15 @@ if version.parse(remote_version) > version.parse(current_version):
if speed >= 1024:
print(
f"正在下载AUTO-MAS 已下载{downloaded_size / 1048576:.2f}/{file_size / 1048576:.2f} MB {downloaded_size / file_size * 100:.2f}% 下载速度{speed / 1024:.2f} MB/s",
f"正在下载: AUTO-MAS 已下载: {downloaded_size / 1048576:.2f}/{file_size / 1048576:.2f} MB {downloaded_size / file_size * 100:.2f}% 下载速度: {speed / 1024:.2f} MB/s",
)
else:
print(
f"正在下载AUTO-MAS 已下载{downloaded_size / 1048576:.2f}/{file_size / 1048576:.2f} MB {downloaded_size / file_size * 100:.2f}% 下载速度{speed:.2f} KB/s",
f"正在下载: AUTO-MAS 已下载: {downloaded_size / 1048576:.2f}/{file_size / 1048576:.2f} MB {downloaded_size / file_size * 100:.2f}% 下载速度: {speed:.2f} KB/s",
)
print(
f"下载完成{download_url}实际下载大小{downloaded_size} 字节,耗时:{time.time() - start_time:.2f}",
f"下载完成: {download_url}, 实际下载大小: {downloaded_size} 字节, 耗时: {time.time() - start_time:.2f}",
)
break
@@ -331,7 +331,7 @@ if version.parse(remote_version) > version.parse(current_version):
check_times -= 1
print(
f"下载出错{download_url}错误信息{e}剩余重试次数{check_times}",
f"下载出错: {download_url}, 错误信息: {e}, 剩余重试次数: {check_times}",
)
time.sleep(1)
@@ -339,20 +339,20 @@ if version.parse(remote_version) > version.parse(current_version):
if (Path.cwd() / "download.temp").exists():
(Path.cwd() / "download.temp").unlink()
print(f"下载失败{download_url}")
print(f"下载失败: {download_url}")
sys.exit(1)
print(f"开始解压{Path.cwd() / 'download.temp'}{Path.cwd()}")
print(f"开始解压: {Path.cwd() / 'download.temp'}{Path.cwd()}")
while True:
try:
with zipfile.ZipFile(Path.cwd() / "download.temp", "r") as zip_ref:
zip_ref.extractall(Path.cwd())
print(f"解压完成{Path.cwd() / 'download.temp'}{Path.cwd()}")
print(f"解压完成: {Path.cwd() / 'download.temp'}{Path.cwd()}")
break
except PermissionError:
print(f"解压出错AUTO_MAA正在运行正在尝试将其关闭")
print(f"解压出错: AUTO_MAA正在运行, 正在尝试将其关闭")
kill_process(Path.cwd() / "AUTO_MAA.exe")
time.sleep(1)
@@ -375,5 +375,5 @@ if version.parse(remote_version) > version.parse(current_version):
else:
print(f"当前版本为最新版本{current_version}")
print(f"当前版本为最新版本: {current_version}")
sys.exit(0)