feat(core): 重构日志记录,载入更多日志记录项
This commit is contained in:
@@ -38,6 +38,7 @@ from .config import (
|
||||
GeneralSubConfig,
|
||||
Config,
|
||||
)
|
||||
from .logger import logger
|
||||
from .main_info_bar import MainInfoBar
|
||||
from .network import Network
|
||||
from .sound_player import SoundPlayer
|
||||
@@ -52,6 +53,7 @@ __all__ = [
|
||||
"MaaPlanConfig",
|
||||
"GeneralConfig",
|
||||
"GeneralSubConfig",
|
||||
"logger",
|
||||
"MainInfoBar",
|
||||
"Network",
|
||||
"SoundPlayer",
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import Signal
|
||||
import argparse
|
||||
import sqlite3
|
||||
@@ -53,6 +52,7 @@ from qfluentwidgets import (
|
||||
from urllib.parse import urlparse
|
||||
from typing import Union, Dict, List
|
||||
|
||||
from .logger import logger
|
||||
from .network import Network
|
||||
|
||||
|
||||
@@ -707,7 +707,7 @@ class GeneralSubConfig(LQConfig):
|
||||
|
||||
class AppConfig(GlobalConfig):
|
||||
|
||||
VERSION = "4.4.0.0"
|
||||
VERSION = "4.4.1.1"
|
||||
|
||||
stage_refreshed = Signal()
|
||||
PASSWORD_refreshed = Signal()
|
||||
@@ -717,8 +717,8 @@ class AppConfig(GlobalConfig):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.app_path = Path(sys.argv[0]).resolve().parent # 获取软件根目录
|
||||
self.app_path_sys = Path(sys.argv[0]).resolve() # 获取软件自身的路径
|
||||
self.app_path = Path(sys.argv[0]).resolve().parent
|
||||
self.app_path_sys = Path(sys.argv[0]).resolve()
|
||||
|
||||
self.log_path = self.app_path / "debug/AUTO_MAA.log"
|
||||
self.database_path = self.app_path / "data/data.db"
|
||||
@@ -781,7 +781,7 @@ class AppConfig(GlobalConfig):
|
||||
|
||||
self.init_logger()
|
||||
self.check_data()
|
||||
logger.info("程序初始化完成")
|
||||
logger.info("程序初始化完成", module="配置管理")
|
||||
|
||||
def init_logger(self) -> None:
|
||||
"""初始化日志记录器"""
|
||||
@@ -789,7 +789,7 @@ class AppConfig(GlobalConfig):
|
||||
logger.add(
|
||||
sink=self.log_path,
|
||||
level="DEBUG",
|
||||
format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <level>{message}</level>",
|
||||
format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{extra[module]}</cyan> | <level>{message}</level>",
|
||||
enqueue=True,
|
||||
backtrace=True,
|
||||
diagnose=True,
|
||||
@@ -797,102 +797,28 @@ class AppConfig(GlobalConfig):
|
||||
retention="1 month",
|
||||
compression="zip",
|
||||
)
|
||||
logger.info("")
|
||||
logger.info("===================================")
|
||||
logger.info("AUTO_MAA 主程序")
|
||||
logger.info(f"版本号: v{self.VERSION}")
|
||||
logger.info(f"根目录: {self.app_path}")
|
||||
logger.add(
|
||||
sink=sys.stderr,
|
||||
level="DEBUG",
|
||||
format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{extra[module]}</cyan> | <level>{message}</level>",
|
||||
enqueue=True,
|
||||
backtrace=True,
|
||||
diagnose=True,
|
||||
colorize=True,
|
||||
)
|
||||
|
||||
logger.info("", module="配置管理")
|
||||
logger.info("===================================", module="配置管理")
|
||||
logger.info("AUTO_MAA 主程序", module="配置管理")
|
||||
logger.info(f"版本号: v{self.VERSION}", module="配置管理")
|
||||
logger.info(f"根目录: {self.app_path}", module="配置管理")
|
||||
logger.info(
|
||||
f"运行模式: {'图形化界面' if self.args.mode == 'gui' else '命令行界面'}"
|
||||
f"运行模式: {'图形化界面' if self.args.mode == 'gui' else '命令行界面'}",
|
||||
module="配置管理",
|
||||
)
|
||||
logger.info("===================================")
|
||||
logger.info("===================================", module="配置管理")
|
||||
|
||||
logger.info("日志记录器初始化完成")
|
||||
|
||||
def get_stage(self) -> None:
|
||||
"""从MAA服务器获取活动关卡信息"""
|
||||
|
||||
network = Network.add_task(
|
||||
mode="get",
|
||||
url="https://api.maa.plus/MaaAssistantArknights/api/gui/StageActivity.json",
|
||||
)
|
||||
network.loop.exec()
|
||||
network_result = Network.get_result(network)
|
||||
if network_result["status_code"] == 200:
|
||||
stage_infos: List[Dict[str, Union[str, Dict[str, Union[str, int]]]]] = (
|
||||
network_result["response_json"]["Official"]["sideStoryStage"]
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"无法从MAA服务器获取活动关卡信息:{network_result['error_message']}"
|
||||
)
|
||||
stage_infos = []
|
||||
|
||||
ss_stage_dict = {"value": [], "text": []}
|
||||
|
||||
for stage_info in stage_infos:
|
||||
|
||||
if (
|
||||
datetime.strptime(
|
||||
stage_info["Activity"]["UtcStartTime"], "%Y/%m/%d %H:%M:%S"
|
||||
)
|
||||
< datetime.now()
|
||||
< datetime.strptime(
|
||||
stage_info["Activity"]["UtcExpireTime"], "%Y/%m/%d %H:%M:%S"
|
||||
)
|
||||
):
|
||||
ss_stage_dict["value"].append(stage_info["Value"])
|
||||
ss_stage_dict["text"].append(stage_info["Value"])
|
||||
|
||||
# 生成每日关卡信息
|
||||
stage_daily_info = [
|
||||
{"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"value": "1-7", "text": "1-7", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"value": "R8-11", "text": "R8-11", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{
|
||||
"value": "12-17-HARD",
|
||||
"text": "12-17-HARD",
|
||||
"days": [1, 2, 3, 4, 5, 6, 7],
|
||||
},
|
||||
{"value": "CE-6", "text": "龙门币-6/5", "days": [2, 4, 6, 7]},
|
||||
{"value": "AP-5", "text": "红票-5", "days": [1, 4, 6, 7]},
|
||||
{"value": "CA-5", "text": "技能-5", "days": [2, 3, 5, 7]},
|
||||
{"value": "LS-6", "text": "经验-6/5", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"value": "SK-5", "text": "碳-5", "days": [1, 3, 5, 6]},
|
||||
{"value": "PR-A-1", "text": "奶/盾芯片", "days": [1, 4, 5, 7]},
|
||||
{"value": "PR-A-2", "text": "奶/盾芯片组", "days": [1, 4, 5, 7]},
|
||||
{"value": "PR-B-1", "text": "术/狙芯片", "days": [1, 2, 5, 6]},
|
||||
{"value": "PR-B-2", "text": "术/狙芯片组", "days": [1, 2, 5, 6]},
|
||||
{"value": "PR-C-1", "text": "先/辅芯片", "days": [3, 4, 6, 7]},
|
||||
{"value": "PR-C-2", "text": "先/辅芯片组", "days": [3, 4, 6, 7]},
|
||||
{"value": "PR-D-1", "text": "近/特芯片", "days": [2, 3, 6, 7]},
|
||||
{"value": "PR-D-2", "text": "近/特芯片组", "days": [2, 3, 6, 7]},
|
||||
]
|
||||
|
||||
for day in range(0, 8):
|
||||
|
||||
today_stage_dict = {"value": [], "text": []}
|
||||
|
||||
for stage_info in stage_daily_info:
|
||||
|
||||
if day in stage_info["days"] or day == 0:
|
||||
today_stage_dict["value"].append(stage_info["value"])
|
||||
today_stage_dict["text"].append(stage_info["text"])
|
||||
|
||||
self.stage_dict[calendar.day_name[day - 1] if day > 0 else "ALL"] = {
|
||||
"value": today_stage_dict["value"] + ss_stage_dict["value"],
|
||||
"text": today_stage_dict["text"] + ss_stage_dict["text"],
|
||||
}
|
||||
|
||||
self.stage_refreshed.emit()
|
||||
|
||||
def server_date(self) -> date:
|
||||
"""获取当前的服务器日期"""
|
||||
|
||||
dt = datetime.now()
|
||||
if dt.time() < datetime.min.time().replace(hour=4):
|
||||
dt = dt - timedelta(days=1)
|
||||
return dt.date()
|
||||
logger.info("日志记录器初始化完成", module="配置管理")
|
||||
|
||||
def check_data(self) -> None:
|
||||
"""检查用户数据文件并处理数据文件版本更新"""
|
||||
@@ -914,11 +840,11 @@ class AppConfig(GlobalConfig):
|
||||
version = cur.fetchall()
|
||||
|
||||
if version[0][0] != "v1.7":
|
||||
logger.info("数据文件版本更新开始")
|
||||
logger.info("数据文件版本更新开始", module="配置管理")
|
||||
if_streaming = False
|
||||
# v1.4-->v1.5
|
||||
if version[0][0] == "v1.4" or if_streaming:
|
||||
logger.info("数据文件版本更新:v1.4-->v1.5")
|
||||
logger.info("数据文件版本更新:v1.4-->v1.5", module="配置管理")
|
||||
if_streaming = True
|
||||
|
||||
member_dict: Dict[str, Dict[str, Union[str, Path]]] = {}
|
||||
@@ -1046,7 +972,7 @@ class AppConfig(GlobalConfig):
|
||||
|
||||
# v1.5-->v1.6
|
||||
if version[0][0] == "v1.5" or if_streaming:
|
||||
logger.info("数据文件版本更新:v1.5-->v1.6")
|
||||
logger.info("数据文件版本更新:v1.5-->v1.6", module="配置管理")
|
||||
if_streaming = True
|
||||
cur.execute("DELETE FROM version WHERE v = ?", ("v1.5",))
|
||||
cur.execute("INSERT INTO version VALUES(?)", ("v1.6",))
|
||||
@@ -1078,7 +1004,7 @@ class AppConfig(GlobalConfig):
|
||||
pass
|
||||
# v1.6-->v1.7
|
||||
if version[0][0] == "v1.6" or if_streaming:
|
||||
logger.info("数据文件版本更新:v1.6-->v1.7")
|
||||
logger.info("数据文件版本更新:v1.6-->v1.7", module="配置管理")
|
||||
if_streaming = True
|
||||
|
||||
if (self.app_path / "config/MaaConfig").exists():
|
||||
@@ -1148,11 +1074,106 @@ class AppConfig(GlobalConfig):
|
||||
|
||||
cur.close()
|
||||
db.close()
|
||||
logger.info("数据文件版本更新完成")
|
||||
logger.success("数据文件版本更新完成", module="配置管理")
|
||||
|
||||
def get_stage(self) -> None:
|
||||
"""从MAA服务器更新活动关卡信息"""
|
||||
|
||||
logger.info("开始获取活动关卡信息", module="配置管理")
|
||||
network = Network.add_task(
|
||||
mode="get",
|
||||
url="https://api.maa.plus/MaaAssistantArknights/api/gui/StageActivity.json",
|
||||
)
|
||||
network.loop.exec()
|
||||
network_result = Network.get_result(network)
|
||||
if network_result["status_code"] == 200:
|
||||
stage_infos: List[Dict[str, Union[str, Dict[str, Union[str, int]]]]] = (
|
||||
network_result["response_json"]["Official"]["sideStoryStage"]
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"无法从MAA服务器获取活动关卡信息:{network_result['error_message']}",
|
||||
module="配置管理",
|
||||
)
|
||||
stage_infos = []
|
||||
|
||||
ss_stage_dict = {"value": [], "text": []}
|
||||
|
||||
for stage_info in stage_infos:
|
||||
|
||||
if (
|
||||
datetime.strptime(
|
||||
stage_info["Activity"]["UtcStartTime"], "%Y/%m/%d %H:%M:%S"
|
||||
)
|
||||
< datetime.now()
|
||||
< datetime.strptime(
|
||||
stage_info["Activity"]["UtcExpireTime"], "%Y/%m/%d %H:%M:%S"
|
||||
)
|
||||
):
|
||||
ss_stage_dict["value"].append(stage_info["Value"])
|
||||
ss_stage_dict["text"].append(stage_info["Value"])
|
||||
|
||||
# 生成每日关卡信息
|
||||
stage_daily_info = [
|
||||
{"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"value": "1-7", "text": "1-7", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"value": "R8-11", "text": "R8-11", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{
|
||||
"value": "12-17-HARD",
|
||||
"text": "12-17-HARD",
|
||||
"days": [1, 2, 3, 4, 5, 6, 7],
|
||||
},
|
||||
{"value": "CE-6", "text": "龙门币-6/5", "days": [2, 4, 6, 7]},
|
||||
{"value": "AP-5", "text": "红票-5", "days": [1, 4, 6, 7]},
|
||||
{"value": "CA-5", "text": "技能-5", "days": [2, 3, 5, 7]},
|
||||
{"value": "LS-6", "text": "经验-6/5", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"value": "SK-5", "text": "碳-5", "days": [1, 3, 5, 6]},
|
||||
{"value": "PR-A-1", "text": "奶/盾芯片", "days": [1, 4, 5, 7]},
|
||||
{"value": "PR-A-2", "text": "奶/盾芯片组", "days": [1, 4, 5, 7]},
|
||||
{"value": "PR-B-1", "text": "术/狙芯片", "days": [1, 2, 5, 6]},
|
||||
{"value": "PR-B-2", "text": "术/狙芯片组", "days": [1, 2, 5, 6]},
|
||||
{"value": "PR-C-1", "text": "先/辅芯片", "days": [3, 4, 6, 7]},
|
||||
{"value": "PR-C-2", "text": "先/辅芯片组", "days": [3, 4, 6, 7]},
|
||||
{"value": "PR-D-1", "text": "近/特芯片", "days": [2, 3, 6, 7]},
|
||||
{"value": "PR-D-2", "text": "近/特芯片组", "days": [2, 3, 6, 7]},
|
||||
]
|
||||
|
||||
for day in range(0, 8):
|
||||
|
||||
today_stage_dict = {"value": [], "text": []}
|
||||
|
||||
for stage_info in stage_daily_info:
|
||||
|
||||
if day in stage_info["days"] or day == 0:
|
||||
today_stage_dict["value"].append(stage_info["value"])
|
||||
today_stage_dict["text"].append(stage_info["text"])
|
||||
|
||||
self.stage_dict[calendar.day_name[day - 1] if day > 0 else "ALL"] = {
|
||||
"value": today_stage_dict["value"] + ss_stage_dict["value"],
|
||||
"text": today_stage_dict["text"] + ss_stage_dict["text"],
|
||||
}
|
||||
|
||||
self.stage_refreshed.emit()
|
||||
|
||||
logger.success("活动关卡信息更新完成", module="配置管理")
|
||||
|
||||
def server_date(self) -> date:
|
||||
"""
|
||||
获取当前的服务器日期
|
||||
|
||||
:return: 当前的服务器日期
|
||||
:rtype: date
|
||||
"""
|
||||
|
||||
dt = datetime.now()
|
||||
if dt.time() < datetime.min.time().replace(hour=4):
|
||||
dt = dt - timedelta(days=1)
|
||||
return dt.date()
|
||||
|
||||
def search_member(self) -> None:
|
||||
"""搜索所有脚本实例"""
|
||||
"""更新脚本实例配置信息"""
|
||||
|
||||
logger.info("开始搜索并读入脚本实例配置", module="配置管理")
|
||||
self.member_dict: Dict[
|
||||
str,
|
||||
Dict[
|
||||
@@ -1198,7 +1219,20 @@ class AppConfig(GlobalConfig):
|
||||
sorted(self.member_dict.items(), key=lambda x: int(x[0][3:]))
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"脚本实例配置搜索完成,共找到 {len(self.member_dict)} 个实例",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
def search_maa_user(self, name: str) -> None:
|
||||
"""
|
||||
更新指定 MAA 脚本实例的用户信息
|
||||
|
||||
:param name: 脚本实例名称
|
||||
:type name: str
|
||||
"""
|
||||
|
||||
logger.info(f"开始搜索并读入 MAA 脚本实例 {name} 的用户信息", module="配置管理")
|
||||
|
||||
user_dict: Dict[str, Dict[str, Union[Path, MaaUserConfig]]] = {}
|
||||
for user_dir in (Config.member_dict[name]["Path"] / "UserData").iterdir():
|
||||
@@ -1214,7 +1248,22 @@ class AppConfig(GlobalConfig):
|
||||
sorted(user_dict.items(), key=lambda x: int(x[0][3:]))
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"MAA 脚本实例 {name} 的用户信息搜索完成,共找到 {len(user_dict)} 个用户",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
def search_general_sub(self, name: str) -> None:
|
||||
"""
|
||||
更新指定通用脚本实例的子配置信息
|
||||
|
||||
:param name: 脚本实例名称
|
||||
:type name: str
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"开始搜索并读入通用脚本实例 {name} 的子配置信息", module="配置管理"
|
||||
)
|
||||
|
||||
user_dict: Dict[str, Dict[str, Union[Path, GeneralSubConfig]]] = {}
|
||||
for sub_dir in (Config.member_dict[name]["Path"] / "SubData").iterdir():
|
||||
@@ -1230,8 +1279,15 @@ class AppConfig(GlobalConfig):
|
||||
sorted(user_dict.items(), key=lambda x: int(x[0][3:]))
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"通用脚本实例 {name} 的子配置信息搜索完成,共找到 {len(user_dict)} 个子配置",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
def search_plan(self) -> None:
|
||||
"""搜索所有计划表"""
|
||||
"""更新计划表配置信息"""
|
||||
|
||||
logger.info("开始搜索并读入计划表配置", module="配置管理")
|
||||
|
||||
self.plan_dict: Dict[str, Dict[str, Union[str, Path, MaaPlanConfig]]] = {}
|
||||
if (self.app_path / "config/MaaPlanConfig").exists():
|
||||
@@ -1252,8 +1308,15 @@ class AppConfig(GlobalConfig):
|
||||
sorted(self.plan_dict.items(), key=lambda x: int(x[0][3:]))
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"计划表配置搜索完成,共找到 {len(self.plan_dict)} 个计划表",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
def search_queue(self):
|
||||
"""搜索所有调度队列实例"""
|
||||
"""更新调度队列实例配置信息"""
|
||||
|
||||
logger.info("开始搜索并读入调度队列配置", module="配置管理")
|
||||
|
||||
self.queue_dict: Dict[str, Dict[str, Union[Path, QueueConfig]]] = {}
|
||||
|
||||
@@ -1273,8 +1336,20 @@ class AppConfig(GlobalConfig):
|
||||
sorted(self.queue_dict.items(), key=lambda x: int(x[0][5:]))
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"调度队列配置搜索完成,共找到 {len(self.queue_dict)} 个调度队列",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
def change_queue(self, old: str, new: str) -> None:
|
||||
"""修改调度队列配置文件的队列参数"""
|
||||
"""
|
||||
修改调度队列配置文件的队列参数
|
||||
|
||||
:param old: 旧脚本名
|
||||
:param new: 新脚本名
|
||||
"""
|
||||
|
||||
logger.info(f"开始修改调度队列参数:{old} -> {new}", module="配置管理")
|
||||
|
||||
for queue in self.queue_dict.values():
|
||||
|
||||
@@ -1299,8 +1374,17 @@ class AppConfig(GlobalConfig):
|
||||
if queue["Config"].get(queue["Config"].queue_Member_10) == old:
|
||||
queue["Config"].set(queue["Config"].queue_Member_10, new)
|
||||
|
||||
logger.success(f"调度队列参数修改完成:{old} -> {new}", module="配置管理")
|
||||
|
||||
def change_plan(self, old: str, new: str) -> None:
|
||||
"""修改脚本管理所有下属用户的计划表配置参数"""
|
||||
"""
|
||||
修改脚本管理所有下属用户的计划表配置参数
|
||||
|
||||
:param old: 旧计划表名
|
||||
:param new: 新计划表名
|
||||
"""
|
||||
|
||||
logger.info(f"开始修改计划表参数:{old} -> {new}", module="配置管理")
|
||||
|
||||
for member in self.member_dict.values():
|
||||
|
||||
@@ -1309,10 +1393,21 @@ class AppConfig(GlobalConfig):
|
||||
if user["Config"].get(user["Config"].Info_StageMode) == old:
|
||||
user["Config"].set(user["Config"].Info_StageMode, new)
|
||||
|
||||
logger.success(f"计划表参数修改完成:{old} -> {new}", module="配置管理")
|
||||
|
||||
def change_maa_user_info(
|
||||
self, name: str, user_data: Dict[str, Dict[str, Union[str, Path, dict]]]
|
||||
) -> None:
|
||||
"""代理完成后保存改动的用户信息"""
|
||||
"""
|
||||
保存代理完成后发生改动的用户信息
|
||||
|
||||
:param name: 脚本实例名称
|
||||
:type name: str
|
||||
:param user_data: 用户信息字典,包含用户名称和对应的配置信息
|
||||
:type user_data: Dict[str, Dict[str, Union[str, Path, dict]]]
|
||||
"""
|
||||
|
||||
logger.info(f"开始保存 MAA 脚本实例 {name} 的用户信息变动", module="配置管理")
|
||||
|
||||
for user, info in user_data.items():
|
||||
|
||||
@@ -1345,10 +1440,21 @@ class AppConfig(GlobalConfig):
|
||||
|
||||
self.sub_info_changed.emit()
|
||||
|
||||
logger.success(f"MAA 脚本实例 {name} 的用户信息变动保存完成", module="配置管理")
|
||||
|
||||
def change_general_sub_info(
|
||||
self, name: str, sub_data: Dict[str, Dict[str, Union[str, Path, dict]]]
|
||||
) -> None:
|
||||
"""代理完成后保存改动的配置信息"""
|
||||
"""
|
||||
保存代理完成后发生改动的配置信息
|
||||
|
||||
:param name: 脚本实例名称
|
||||
:type name: str
|
||||
:param sub_data: 子配置信息字典,包含子配置名称和对应的配置信息
|
||||
:type sub_data: Dict[str, Dict[str, Union[str, Path, dict]]]
|
||||
"""
|
||||
|
||||
logger.info(f"开始保存通用脚本实例 {name} 的子配置信息变动", module="配置管理")
|
||||
|
||||
for sub, info in sub_data.items():
|
||||
|
||||
@@ -1366,27 +1472,62 @@ class AppConfig(GlobalConfig):
|
||||
|
||||
self.sub_info_changed.emit()
|
||||
|
||||
logger.success(
|
||||
f"通用脚本实例 {name} 的子配置信息变动保存完成", module="配置管理"
|
||||
)
|
||||
|
||||
def set_power_sign(self, sign: str) -> None:
|
||||
"""设置当前电源状态"""
|
||||
"""
|
||||
设置当前电源状态
|
||||
|
||||
:param sign: 电源状态标志
|
||||
"""
|
||||
|
||||
self.power_sign = sign
|
||||
self.power_sign_changed.emit()
|
||||
|
||||
logger.info(f"电源状态已更改为: {sign}", module="配置管理")
|
||||
|
||||
def save_history(self, key: str, content: dict) -> None:
|
||||
"""保存历史记录"""
|
||||
"""
|
||||
保存历史记录
|
||||
|
||||
:param key: 调度队列的键
|
||||
:type key: str
|
||||
:param content: 包含时间和历史记录内容的字典
|
||||
:type content: dict
|
||||
"""
|
||||
|
||||
if key in self.queue_dict:
|
||||
logger.info(f"保存调度队列 {key} 的历史记录", module="配置管理")
|
||||
self.queue_dict[key]["Config"].set(
|
||||
self.queue_dict[key]["Config"].Data_LastProxyTime, content["Time"]
|
||||
)
|
||||
self.queue_dict[key]["Config"].set(
|
||||
self.queue_dict[key]["Config"].Data_LastProxyHistory, content["History"]
|
||||
)
|
||||
logger.success(f"调度队列 {key} 的历史记录已保存", module="配置管理")
|
||||
else:
|
||||
logger.warning(f"保存历史记录时未找到调度队列: {key}")
|
||||
|
||||
def save_maa_log(self, log_path: Path, logs: list, maa_result: str) -> bool:
|
||||
"""保存MAA日志并生成对应统计数据"""
|
||||
"""
|
||||
保存MAA日志并生成对应统计数据
|
||||
|
||||
:param log_path: 日志文件保存路径
|
||||
:type log_path: Path
|
||||
:param logs: 日志内容列表
|
||||
:type logs: list
|
||||
:param maa_result: MAA 结果
|
||||
:type maa_result: str
|
||||
:return: 是否包含6★招募
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"开始处理 MAA 日志,日志长度: {len(logs)},日志标记:{maa_result}",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
data: Dict[str, Union[str, Dict[str, Union[int, dict]]]] = {
|
||||
"recruit_statistics": defaultdict(int),
|
||||
@@ -1431,15 +1572,17 @@ class AppConfig(GlobalConfig):
|
||||
# 查找所有Fight任务的开始和结束位置
|
||||
fight_tasks = []
|
||||
for i, line in enumerate(logs):
|
||||
if "开始任务: Fight" in line:
|
||||
if "开始任务: Fight" in line or "开始任务: 刷理智" in line:
|
||||
# 查找对应的任务结束位置
|
||||
end_index = -1
|
||||
for j in range(i + 1, len(logs)):
|
||||
if "完成任务: Fight" in logs[j]:
|
||||
if "完成任务: Fight" in logs[j] or "完成任务: 刷理智" in logs[j]:
|
||||
end_index = j
|
||||
break
|
||||
# 如果遇到新的Fight任务开始,则当前任务没有正常结束
|
||||
if j < len(logs) and "开始任务: Fight" in logs[j]:
|
||||
if j < len(logs) and (
|
||||
"开始任务: Fight" in logs[j] or "开始任务: 刷理智" in logs[j]
|
||||
):
|
||||
break
|
||||
|
||||
# 如果找到了结束位置,记录这个任务的范围
|
||||
@@ -1505,12 +1648,23 @@ 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.info(f"处理完成:{log_path}")
|
||||
logger.success(f"MAA 日志统计完成,日志路径:{log_path}", module="配置管理")
|
||||
|
||||
return if_six_star
|
||||
|
||||
def save_general_log(self, log_path: Path, logs: list, general_result: str) -> None:
|
||||
"""保存通用日志并生成对应统计数据"""
|
||||
"""
|
||||
保存通用日志并生成对应统计数据
|
||||
|
||||
:param log_path: 日志文件保存路径
|
||||
:param logs: 日志内容列表
|
||||
:param general_result: 待保存的日志结果信息
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"开始处理通用日志,日志长度: {len(logs)},日志标记:{general_result}",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
data: Dict[str, str] = {"general_result": general_result}
|
||||
|
||||
@@ -1521,10 +1675,23 @@ 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.info(f"处理完成:{log_path}")
|
||||
logger.success(
|
||||
f"通用日志统计完成,日志路径:{log_path.with_suffix('.log')}",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
def merge_statistic_info(self, statistic_path_list: List[Path]) -> dict:
|
||||
"""合并指定数据统计信息文件"""
|
||||
"""
|
||||
合并指定数据统计信息文件
|
||||
|
||||
:param statistic_path_list: 需要合并的统计信息文件路径列表
|
||||
:return: 合并后的统计信息字典
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"开始合并统计信息文件,共计 {len(statistic_path_list)} 个文件",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
data = {"index": {}}
|
||||
|
||||
@@ -1591,12 +1758,28 @@ class AppConfig(GlobalConfig):
|
||||
|
||||
data["index"] = [data["index"][_] for _ in sorted(data["index"])]
|
||||
|
||||
logger.success(
|
||||
f"统计信息合并完成,共计 {len(data['index'])} 条记录", module="配置管理"
|
||||
)
|
||||
|
||||
return {k: v for k, v in data.items() if v}
|
||||
|
||||
def search_history(
|
||||
self, mode: str, start_date: datetime, end_date: datetime
|
||||
) -> dict:
|
||||
"""搜索所有历史记录"""
|
||||
"""
|
||||
搜索指定范围内的历史记录
|
||||
|
||||
:param mode: 合并模式(按日合并、按周合并、按月合并)
|
||||
:param start_date: 开始日期
|
||||
:param end_date: 结束日期
|
||||
:return: 搜索到的历史记录字典
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"开始搜索历史记录,合并模式:{mode},日期范围:{start_date} 至 {end_date}",
|
||||
module="配置管理",
|
||||
)
|
||||
|
||||
history_dict = {}
|
||||
|
||||
@@ -1638,10 +1821,43 @@ class AppConfig(GlobalConfig):
|
||||
except ValueError:
|
||||
logger.warning(f"非日期格式的目录: {date_folder}")
|
||||
|
||||
logger.success(
|
||||
f"历史记录搜索完成,共计 {len(history_dict)} 条记录", module="配置管理"
|
||||
)
|
||||
|
||||
return {
|
||||
k: v
|
||||
for k, v in sorted(history_dict.items(), key=lambda x: x[0], reverse=True)
|
||||
}
|
||||
|
||||
def clean_old_history(self):
|
||||
"""删除超过用户设定天数的历史记录文件(基于目录日期)"""
|
||||
|
||||
if self.get(self.function_HistoryRetentionTime) == 0:
|
||||
logger.info("历史记录永久保留,跳过历史记录清理", module="配置管理")
|
||||
return
|
||||
|
||||
logger.info("开始清理超过设定天数的历史记录", module="配置管理")
|
||||
|
||||
deleted_count = 0
|
||||
|
||||
for date_folder in (self.app_path / "history").iterdir():
|
||||
if not date_folder.is_dir():
|
||||
continue # 只处理日期文件夹
|
||||
|
||||
try:
|
||||
# 只检查 `YYYY-MM-DD` 格式的文件夹
|
||||
folder_date = datetime.strptime(date_folder.name, "%Y-%m-%d")
|
||||
if datetime.now() - folder_date > timedelta(
|
||||
days=self.get(self.function_HistoryRetentionTime)
|
||||
):
|
||||
shutil.rmtree(date_folder, ignore_errors=True)
|
||||
deleted_count += 1
|
||||
logger.info(f"已删除超期日志目录: {date_folder}", module="配置管理")
|
||||
except ValueError:
|
||||
logger.warning(f"非日期格式的目录: {date_folder}", module="配置管理")
|
||||
|
||||
logger.success(f"清理完成: {deleted_count} 个日期目录", module="配置管理")
|
||||
|
||||
|
||||
Config = AppConfig()
|
||||
|
||||
34
app/core/logger.py
Normal file
34
app/core/logger.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||
# Copyright © 2024-2025 DLmaster361
|
||||
|
||||
# This file is part of AUTO_MAA.
|
||||
|
||||
# AUTO_MAA is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License,
|
||||
# or (at your option) any later version.
|
||||
|
||||
# AUTO_MAA is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
# the GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# Contact: DLmaster_361@163.com
|
||||
|
||||
"""
|
||||
AUTO_MAA
|
||||
AUTO_MAA日志组件
|
||||
v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger as _logger
|
||||
|
||||
# 设置日志 module 字段默认值
|
||||
logger = _logger.patch(
|
||||
lambda record: record["extra"].setdefault("module", "未知模块") or True
|
||||
)
|
||||
logger.remove(0)
|
||||
@@ -25,10 +25,10 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import Qt
|
||||
from qfluentwidgets import InfoBar, InfoBarPosition
|
||||
|
||||
from .logger import logger
|
||||
from .config import Config
|
||||
from .sound_player import SoundPlayer
|
||||
|
||||
@@ -46,20 +46,34 @@ class _MainInfoBar:
|
||||
|
||||
def push_info_bar(
|
||||
self, mode: str, title: str, content: str, time: int, if_force: bool = False
|
||||
):
|
||||
"""推送到信息通知栏"""
|
||||
) -> None:
|
||||
"""
|
||||
推送消息到吐司通知栏
|
||||
|
||||
:param mode: 通知栏模式,支持 "success", "warning", "error", "info"
|
||||
:param title: 通知栏标题
|
||||
:type title: str
|
||||
:param content: 通知栏内容
|
||||
:type content: str
|
||||
:param time: 显示时长,单位为毫秒
|
||||
:type time: int
|
||||
:param if_force: 是否强制推送
|
||||
:type if_force: bool
|
||||
"""
|
||||
|
||||
if Config.main_window is None:
|
||||
logger.error("信息通知栏未设置父窗口")
|
||||
logger.error("信息通知栏未设置父窗口", module="吐司通知栏")
|
||||
return None
|
||||
|
||||
# 根据 mode 获取对应的 InfoBar 方法
|
||||
info_bar_method = self.mode_mapping.get(mode)
|
||||
|
||||
if not info_bar_method:
|
||||
logger.error(f"未知的通知栏模式: {mode}")
|
||||
logger.error(f"未知的通知栏模式: {mode}", module="吐司通知栏")
|
||||
return None
|
||||
|
||||
if Config.main_window.isVisible():
|
||||
# 主窗口可见时直接推送通知
|
||||
info_bar_method(
|
||||
title=title,
|
||||
content=content,
|
||||
@@ -69,6 +83,7 @@ class _MainInfoBar:
|
||||
duration=time,
|
||||
parent=Config.main_window,
|
||||
)
|
||||
|
||||
elif if_force:
|
||||
# 如果主窗口不可见且强制推送,则录入消息队列等待窗口显示后推送
|
||||
info_bar_item = {
|
||||
@@ -80,6 +95,11 @@ class _MainInfoBar:
|
||||
if info_bar_item not in Config.info_bar_list:
|
||||
Config.info_bar_list.append(info_bar_item)
|
||||
|
||||
logger.info(
|
||||
f"主窗口不可见,已将通知栏消息录入队列: {info_bar_item}",
|
||||
module="吐司通知栏",
|
||||
)
|
||||
|
||||
if mode == "warning":
|
||||
SoundPlayer.play("发生异常")
|
||||
if mode == "error":
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QObject, QThread, QEventLoop
|
||||
import re
|
||||
import time
|
||||
@@ -33,6 +32,8 @@ import requests
|
||||
import truststore
|
||||
from pathlib import Path
|
||||
|
||||
from .logger import logger
|
||||
|
||||
|
||||
class NetworkThread(QThread):
|
||||
"""网络请求线程类"""
|
||||
@@ -48,6 +49,8 @@ class NetworkThread(QThread):
|
||||
f"NetworkThread-{mode}-{re.sub(r'(&cdk=)[^&]+(&)', r'\1******\2', url)}"
|
||||
)
|
||||
|
||||
logger.info(f"创建网络请求线程: {self.objectName()}", module="网络请求子线程")
|
||||
|
||||
self.mode = mode
|
||||
self.url = url
|
||||
self.path = path
|
||||
@@ -65,7 +68,7 @@ class NetworkThread(QThread):
|
||||
|
||||
self.loop = QEventLoop()
|
||||
|
||||
truststore.inject_into_ssl()
|
||||
truststore.inject_into_ssl() # 信任系统证书
|
||||
|
||||
@logger.catch
|
||||
def run(self) -> None:
|
||||
@@ -77,7 +80,13 @@ class NetworkThread(QThread):
|
||||
self.get_file(self.url, self.path)
|
||||
|
||||
def get_json(self, url: str) -> None:
|
||||
"""通过get方法获取json数据"""
|
||||
"""
|
||||
通过get方法获取json数据
|
||||
|
||||
:param url: 请求的URL
|
||||
"""
|
||||
|
||||
logger.info(f"子线程 {self.objectName()} 开始网络请求", module="网络请求子线程")
|
||||
|
||||
response = None
|
||||
|
||||
@@ -92,12 +101,23 @@ class NetworkThread(QThread):
|
||||
self.status_code = response.status_code if response else None
|
||||
self.response_json = None
|
||||
self.error_message = str(e)
|
||||
logger.exception(
|
||||
f"子线程 {self.objectName()} 网络请求失败:{e}",
|
||||
module="网络请求子线程",
|
||||
)
|
||||
time.sleep(self.backoff_factor)
|
||||
|
||||
self.loop.quit()
|
||||
|
||||
def get_file(self, url: str, path: Path) -> None:
|
||||
"""通过get方法下载文件"""
|
||||
"""
|
||||
通过get方法下载文件到指定路径
|
||||
|
||||
:param url: 请求的URL
|
||||
:param path: 下载文件的保存路径
|
||||
"""
|
||||
|
||||
logger.info(f"子线程 {self.objectName()} 开始下载文件", module="网络请求子线程")
|
||||
|
||||
response = None
|
||||
|
||||
@@ -114,12 +134,15 @@ class NetworkThread(QThread):
|
||||
except Exception as e:
|
||||
self.status_code = response.status_code if response else None
|
||||
self.error_message = str(e)
|
||||
logger.exception(
|
||||
f"子线程 {self.objectName()} 网络请求失败:{e}", module="网络请求子线程"
|
||||
)
|
||||
|
||||
self.loop.quit()
|
||||
|
||||
|
||||
class _Network(QObject):
|
||||
"""网络请求线程类"""
|
||||
"""网络请求线程管理类"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
@@ -127,7 +150,16 @@ class _Network(QObject):
|
||||
self.task_queue = []
|
||||
|
||||
def add_task(self, mode: str, url: str, path: Path = None) -> NetworkThread:
|
||||
"""添加网络请求任务"""
|
||||
"""
|
||||
添加网络请求任务
|
||||
|
||||
:param mode: 请求模式,支持 "get", "get_file"
|
||||
:param url: 请求的URL
|
||||
:param path: 下载文件的保存路径,仅在 mode 为 "get_file" 时有效
|
||||
:return: 返回创建的 NetworkThread 实例
|
||||
"""
|
||||
|
||||
logger.info(f"添加网络请求任务: {mode} {url} {path}", module="网络请求")
|
||||
|
||||
network_thread = NetworkThread(mode, url, path)
|
||||
|
||||
@@ -138,7 +170,12 @@ class _Network(QObject):
|
||||
return network_thread
|
||||
|
||||
def get_result(self, network_thread: NetworkThread) -> dict:
|
||||
"""获取网络请求结果"""
|
||||
"""
|
||||
获取网络请求结果
|
||||
|
||||
:param network_thread: 网络请求线程实例
|
||||
:return: 包含状态码、响应JSON和错误信息的字典
|
||||
"""
|
||||
|
||||
result = {
|
||||
"status_code": network_thread.status_code,
|
||||
@@ -155,6 +192,11 @@ class _Network(QObject):
|
||||
self.task_queue.remove(network_thread)
|
||||
network_thread.deleteLater()
|
||||
|
||||
logger.info(
|
||||
f"网络请求结果: {result['status_code']},请求子线程已结束",
|
||||
module="网络请求",
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QObject, QUrl
|
||||
from PySide6.QtMultimedia import QSoundEffect
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
from .logger import logger
|
||||
from .config import Config
|
||||
|
||||
|
||||
@@ -42,6 +42,11 @@ class _SoundPlayer(QObject):
|
||||
self.sounds_path = Config.app_path / "resources/sounds"
|
||||
|
||||
def play(self, sound_name: str):
|
||||
"""
|
||||
播放指定名称的音效
|
||||
|
||||
:param sound_name: 音效文件名(不带扩展名)
|
||||
"""
|
||||
|
||||
if not Config.get(Config.voice_Enabled):
|
||||
return
|
||||
@@ -59,6 +64,11 @@ class _SoundPlayer(QObject):
|
||||
)
|
||||
|
||||
def play_voice(self, sound_path: Path):
|
||||
"""
|
||||
播放音效文件
|
||||
|
||||
:param sound_path: 音效文件的完整路径
|
||||
"""
|
||||
|
||||
effect = QSoundEffect(self)
|
||||
effect.setVolume(1)
|
||||
|
||||
@@ -25,19 +25,18 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QThread, QObject, Signal
|
||||
from qfluentwidgets import MessageBox
|
||||
from datetime import datetime
|
||||
from packaging import version
|
||||
from typing import Dict, Union
|
||||
|
||||
from .logger import logger
|
||||
from .config import Config
|
||||
from .main_info_bar import MainInfoBar
|
||||
from .network import Network
|
||||
from .sound_player import SoundPlayer
|
||||
from app.models import MaaManager, GeneralManager
|
||||
from app.services import System
|
||||
|
||||
|
||||
class Task(QThread):
|
||||
@@ -77,7 +76,7 @@ class Task(QThread):
|
||||
|
||||
if "设置MAA" in self.mode:
|
||||
|
||||
logger.info(f"任务开始:设置{self.name}")
|
||||
logger.info(f"任务开始:设置{self.name}", module=f"业务 {self.name}")
|
||||
self.push_info_bar.emit("info", "设置MAA", self.name, 3000)
|
||||
|
||||
self.task = MaaManager(
|
||||
@@ -93,12 +92,14 @@ class Task(QThread):
|
||||
try:
|
||||
self.task.run()
|
||||
except Exception as e:
|
||||
logger.exception(f"任务异常:{self.name},错误信息:{e}")
|
||||
logger.exception(
|
||||
f"任务异常:{self.name},错误信息:{e}", module=f"业务 {self.name}"
|
||||
)
|
||||
self.push_info_bar.emit("error", "任务异常", self.name, -1)
|
||||
|
||||
elif self.mode == "设置通用脚本":
|
||||
|
||||
logger.info(f"任务开始:设置{self.name}")
|
||||
logger.info(f"任务开始:设置{self.name}", module=f"业务 {self.name}")
|
||||
self.push_info_bar.emit("info", "设置通用脚本", self.name, 3000)
|
||||
|
||||
self.task = GeneralManager(
|
||||
@@ -113,11 +114,14 @@ class Task(QThread):
|
||||
try:
|
||||
self.task.run()
|
||||
except Exception as e:
|
||||
logger.exception(f"任务异常:{self.name},错误信息:{e}")
|
||||
logger.exception(
|
||||
f"任务异常:{self.name},错误信息:{e}", module=f"业务 {self.name}"
|
||||
)
|
||||
self.push_info_bar.emit("error", "任务异常", self.name, -1)
|
||||
|
||||
else:
|
||||
|
||||
logger.info(f"任务开始:{self.name}", module=f"业务 {self.name}")
|
||||
self.task_list = [
|
||||
[
|
||||
(
|
||||
@@ -144,16 +148,21 @@ class Task(QThread):
|
||||
task[1] = "运行"
|
||||
self.update_task_list.emit(self.task_list)
|
||||
|
||||
# 检查任务是否在运行列表中
|
||||
if task[2] in Config.running_list:
|
||||
|
||||
task[1] = "跳过"
|
||||
self.update_task_list.emit(self.task_list)
|
||||
logger.info(f"跳过任务:{task[0]}")
|
||||
logger.info(
|
||||
f"跳过任务:{task[0]},该任务已在运行列表中",
|
||||
module=f"业务 {self.name}",
|
||||
)
|
||||
self.push_info_bar.emit("info", "跳过任务", task[0], 3000)
|
||||
continue
|
||||
|
||||
# 标记为运行中
|
||||
Config.running_list.append(task[2])
|
||||
logger.info(f"任务开始:{task[0]}")
|
||||
logger.info(f"任务开始:{task[0]}", module=f"业务 {self.name}")
|
||||
self.push_info_bar.emit("info", "任务开始", task[0], 3000)
|
||||
|
||||
if Config.member_dict[task[2]]["Type"] == "Maa":
|
||||
@@ -198,11 +207,11 @@ class Task(QThread):
|
||||
)
|
||||
|
||||
try:
|
||||
self.task.run()
|
||||
self.task.run() # 运行任务业务
|
||||
|
||||
task[1] = "完成"
|
||||
self.update_task_list.emit(self.task_list)
|
||||
logger.info(f"任务完成:{task[0]}")
|
||||
logger.info(f"任务完成:{task[0]}", module=f"业务 {self.name}")
|
||||
self.push_info_bar.emit("info", "任务完成", task[0], 3000)
|
||||
|
||||
except Exception as e:
|
||||
@@ -217,15 +226,29 @@ class Task(QThread):
|
||||
|
||||
task[1] = "异常"
|
||||
self.update_task_list.emit(self.task_list)
|
||||
logger.exception(f"任务异常:{task[0]},错误信息:{e}")
|
||||
logger.exception(
|
||||
f"任务异常:{task[0]},错误信息:{e}",
|
||||
module=f"业务 {self.name}",
|
||||
)
|
||||
self.push_info_bar.emit("error", "任务异常", task[0], -1)
|
||||
|
||||
# 任务结束后从运行列表中移除
|
||||
Config.running_list.remove(task[2])
|
||||
|
||||
self.accomplish.emit(self.logs)
|
||||
|
||||
def task_accomplish(self, name: str, log: dict):
|
||||
"""保存任务结果"""
|
||||
"""
|
||||
销毁任务线程并保存任务结果
|
||||
|
||||
:param name: 任务名称
|
||||
:param log: 任务日志记录
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"任务完成:{name},日志记录:{list(log.values())}",
|
||||
module=f"业务 {self.name}",
|
||||
)
|
||||
|
||||
self.logs.append([name, log])
|
||||
self.task.deleteLater()
|
||||
@@ -245,7 +268,13 @@ class _TaskManager(QObject):
|
||||
def add_task(
|
||||
self, mode: str, name: str, info: Dict[str, Dict[str, Union[str, int, bool]]]
|
||||
):
|
||||
"""添加任务"""
|
||||
"""
|
||||
添加任务
|
||||
|
||||
:param mode: 任务模式
|
||||
:param name: 任务名称
|
||||
:param info: 任务信息
|
||||
"""
|
||||
|
||||
if name in Config.running_list or name in self.task_dict:
|
||||
|
||||
@@ -253,11 +282,14 @@ class _TaskManager(QObject):
|
||||
MainInfoBar.push_info_bar("warning", "任务已存在", name, 5000)
|
||||
return None
|
||||
|
||||
logger.info(f"任务开始:{name}")
|
||||
logger.info(f"任务开始:{name},模式:{mode}", module="业务调度")
|
||||
MainInfoBar.push_info_bar("info", "任务开始", name, 3000)
|
||||
SoundPlayer.play("任务开始")
|
||||
|
||||
# 标记任务为运行中
|
||||
Config.running_list.append(name)
|
||||
|
||||
# 创建任务实例并连接信号
|
||||
self.task_dict[name] = Task(mode, name, info)
|
||||
self.task_dict[name].check_maa_version.connect(self.check_maa_version)
|
||||
self.task_dict[name].question.connect(
|
||||
@@ -273,18 +305,24 @@ class _TaskManager(QObject):
|
||||
lambda logs: self.remove_task(mode, name, logs)
|
||||
)
|
||||
|
||||
# 向UI发送信号以创建或连接GUI
|
||||
if "新调度台" in mode:
|
||||
self.create_gui.emit(self.task_dict[name])
|
||||
|
||||
elif "主调度台" in mode:
|
||||
self.connect_gui.emit(self.task_dict[name])
|
||||
|
||||
# 启动任务线程
|
||||
self.task_dict[name].start()
|
||||
|
||||
def stop_task(self, name: str):
|
||||
"""中止任务"""
|
||||
def stop_task(self, name: str) -> None:
|
||||
"""
|
||||
中止任务
|
||||
|
||||
logger.info(f"中止任务:{name}")
|
||||
:param name: 任务名称
|
||||
"""
|
||||
|
||||
logger.info(f"中止任务:{name}", module="业务调度")
|
||||
MainInfoBar.push_info_bar("info", "中止任务", name, 3000)
|
||||
|
||||
if name == "ALL":
|
||||
@@ -303,19 +341,27 @@ class _TaskManager(QObject):
|
||||
self.task_dict[name].quit()
|
||||
self.task_dict[name].wait()
|
||||
|
||||
def remove_task(self, mode: str, name: str, logs: list):
|
||||
"""任务结束后的处理"""
|
||||
def remove_task(self, mode: str, name: str, logs: list) -> None:
|
||||
"""
|
||||
处理任务结束后的收尾工作
|
||||
|
||||
logger.info(f"任务结束:{name}")
|
||||
:param mode: 任务模式
|
||||
:param name: 任务名称
|
||||
:param logs: 任务日志
|
||||
"""
|
||||
|
||||
logger.info(f"任务结束:{name}", module="业务调度")
|
||||
MainInfoBar.push_info_bar("info", "任务结束", name, 3000)
|
||||
SoundPlayer.play("任务结束")
|
||||
|
||||
# 删除任务线程,移除运行中标记
|
||||
self.task_dict[name].deleteLater()
|
||||
self.task_dict.pop(name)
|
||||
Config.running_list.remove(name)
|
||||
|
||||
if "调度队列" in name and "人工排查" not in mode:
|
||||
|
||||
# 保存调度队列历史记录
|
||||
if len(logs) > 0:
|
||||
time = logs[0][1]["Time"]
|
||||
history = ""
|
||||
@@ -331,6 +377,7 @@ class _TaskManager(QObject):
|
||||
},
|
||||
)
|
||||
|
||||
# 根据调度队列情况设置电源状态
|
||||
if (
|
||||
Config.queue_dict[name]["Config"].get(
|
||||
Config.queue_dict[name]["Config"].queueSet_AfterAccomplish
|
||||
@@ -347,9 +394,14 @@ class _TaskManager(QObject):
|
||||
if Config.args.mode == "cli" and Config.power_sign == "NoAction":
|
||||
Config.set_power_sign("KillSelf")
|
||||
|
||||
def check_maa_version(self, v: str):
|
||||
"""检查MAA版本"""
|
||||
def check_maa_version(self, v: str) -> None:
|
||||
"""
|
||||
检查MAA版本,如果版本过低则推送通知
|
||||
|
||||
:param v: 当前MAA版本
|
||||
"""
|
||||
|
||||
logger.info(f"检查MAA版本:{v}", module="业务调度")
|
||||
network = Network.add_task(
|
||||
mode="get",
|
||||
url="https://mirrorchyan.com/api/resources/MAA/latest?user_agent=AutoMaaGui&os=win&arch=x64&channel=stable",
|
||||
@@ -359,7 +411,10 @@ class _TaskManager(QObject):
|
||||
if network_result["status_code"] == 200:
|
||||
maa_info = network_result["response_json"]
|
||||
else:
|
||||
logger.warning(f"获取MAA版本信息时出错:{network_result['error_message']}")
|
||||
logger.warning(
|
||||
f"获取MAA版本信息时出错:{network_result['error_message']}",
|
||||
module="业务调度",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"获取MAA版本信息时出错",
|
||||
@@ -371,7 +426,8 @@ class _TaskManager(QObject):
|
||||
if version.parse(maa_info["data"]["version_name"]) > version.parse(v):
|
||||
|
||||
logger.info(
|
||||
f"检测到MAA版本过低:{v},最新版本:{maa_info['data']['version_name']}"
|
||||
f"检测到MAA版本过低:{v},最新版本:{maa_info['data']['version_name']}",
|
||||
module="业务调度",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"info",
|
||||
@@ -380,8 +436,19 @@ class _TaskManager(QObject):
|
||||
-1,
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"MAA版本检查完成:{v},最新版本:{maa_info['data']['version_name']}",
|
||||
module="业务调度",
|
||||
)
|
||||
|
||||
def push_dialog(self, name: str, title: str, content: str):
|
||||
"""推送对话框"""
|
||||
"""
|
||||
推送来自任务线程的对话框
|
||||
|
||||
:param name: 任务名称
|
||||
:param title: 对话框标题
|
||||
:param content: 对话框内容
|
||||
"""
|
||||
|
||||
choice = MessageBox(title, content, Config.main_window)
|
||||
choice.yesButton.setText("是")
|
||||
|
||||
@@ -25,12 +25,11 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QObject, QTimer
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import keyboard
|
||||
|
||||
from .logger import logger
|
||||
from .config import Config
|
||||
from .task_manager import TaskManager
|
||||
from app.services import System
|
||||
@@ -45,14 +44,31 @@ class _MainTimer(QObject):
|
||||
self.Timer.timeout.connect(self.timed_start)
|
||||
self.Timer.timeout.connect(self.set_silence)
|
||||
self.Timer.timeout.connect(self.check_power)
|
||||
self.Timer.start(1000)
|
||||
|
||||
self.LongTimer = QTimer()
|
||||
self.LongTimer.timeout.connect(self.long_timed_task)
|
||||
|
||||
def start(self):
|
||||
"""启动定时器"""
|
||||
|
||||
logger.info("启动主定时器", module="主业务定时器")
|
||||
self.Timer.start(1000)
|
||||
self.LongTimer.start(3600000)
|
||||
|
||||
def stop(self):
|
||||
"""停止定时器"""
|
||||
|
||||
logger.info("停止主定时器", module="主业务定时器")
|
||||
self.Timer.stop()
|
||||
self.Timer.deleteLater()
|
||||
self.LongTimer.stop()
|
||||
self.LongTimer.deleteLater()
|
||||
|
||||
def long_timed_task(self):
|
||||
"""长时间定期检定任务"""
|
||||
|
||||
logger.info("执行长时间定期检定任务", module="主业务定时器")
|
||||
|
||||
Config.get_stage()
|
||||
Config.main_window.setting.show_notice()
|
||||
if Config.get(Config.update_IfAutoUpdate):
|
||||
@@ -82,7 +98,7 @@ class _MainTimer(QObject):
|
||||
and name not in Config.running_list
|
||||
):
|
||||
|
||||
logger.info(f"定时任务:{name}")
|
||||
logger.info(f"定时唤起任务:{name}。", module="主业务定时器")
|
||||
TaskManager.add_task("自动代理_新调度台", name, data)
|
||||
|
||||
def set_silence(self):
|
||||
@@ -109,13 +125,20 @@ class _MainTimer(QObject):
|
||||
for _ in Config.get(Config.function_BossKey).split("+")
|
||||
)
|
||||
)
|
||||
logger.info(
|
||||
f"模拟按键:{Config.get(Config.function_BossKey)}",
|
||||
module="主业务定时器",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"模拟按键时出错:{e}")
|
||||
logger.exception(f"模拟按键时出错:{e}", module="主业务定时器")
|
||||
|
||||
def check_power(self):
|
||||
"""检查电源操作"""
|
||||
|
||||
if Config.power_sign != "NoAction" and not Config.running_list:
|
||||
|
||||
logger.info(f"触发电源操作:{Config.power_sign}", module="主业务定时器")
|
||||
|
||||
from app.ui import ProgressRingMessageBox
|
||||
|
||||
mode_book = {
|
||||
@@ -129,9 +152,13 @@ class _MainTimer(QObject):
|
||||
Config.main_window, f"{mode_book[Config.power_sign]}倒计时"
|
||||
)
|
||||
if choice.exec():
|
||||
logger.info(
|
||||
f"确认执行电源操作:{Config.power_sign}", module="主业务定时器"
|
||||
)
|
||||
System.set_power(Config.power_sign)
|
||||
Config.set_power_sign("NoAction")
|
||||
else:
|
||||
logger.info(f"取消电源操作:{Config.power_sign}", module="主业务定时器")
|
||||
Config.set_power_sign("NoAction")
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QObject, Signal, QEventLoop, QFileSystemWatcher, QTimer
|
||||
import json
|
||||
import subprocess
|
||||
@@ -38,7 +37,7 @@ from pathlib import Path
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from typing import Union, List, Dict
|
||||
|
||||
from app.core import Config, MaaConfig, MaaUserConfig
|
||||
from app.core import Config, MaaConfig, MaaUserConfig, logger
|
||||
from app.services import Notify, Crypto, System, skland_sign_in
|
||||
from app.utils import ProcessManager
|
||||
|
||||
@@ -77,19 +76,21 @@ class MaaManager(QObject):
|
||||
self.user_list = ""
|
||||
self.mode = mode
|
||||
self.config_path = config["Path"]
|
||||
self.name = config["Config"].get(config["Config"].MaaSet_Name)
|
||||
self.user_config_path = user_config_path
|
||||
|
||||
self.emulator_process_manager = ProcessManager()
|
||||
self.maa_process_manager = ProcessManager()
|
||||
|
||||
self.log_monitor = QFileSystemWatcher()
|
||||
self.log_monitor.fileChanged.connect(self.check_maa_log)
|
||||
self.log_monitor_timer = QTimer()
|
||||
self.log_monitor_timer.timeout.connect(self.refresh_maa_log)
|
||||
self.monitor_loop = QEventLoop()
|
||||
self.log_start_time = datetime.now()
|
||||
self.log_check_mode = None
|
||||
|
||||
self.maa_process_manager.processClosed.connect(
|
||||
lambda: self.log_monitor.fileChanged.emit("进程结束检查")
|
||||
)
|
||||
self.maa_process_manager.processClosed.connect(self.check_maa_log)
|
||||
|
||||
self.question_loop = QEventLoop()
|
||||
self.question_response.connect(self.__capture_response)
|
||||
@@ -118,10 +119,14 @@ class MaaManager(QObject):
|
||||
|
||||
self.data = dict(sorted(self.data.items(), key=lambda x: int(x[0][3:])))
|
||||
|
||||
logger.success(
|
||||
f"MAA控制器初始化完成,当前模式: {self.mode}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
def configure(self):
|
||||
"""提取配置信息"""
|
||||
|
||||
self.name = self.set["MaaSet"]["Name"]
|
||||
self.maa_root_path = Path(self.set["MaaSet"]["Path"])
|
||||
self.maa_set_path = self.maa_root_path / "config/gui.json"
|
||||
self.maa_log_path = self.maa_root_path / "debug/gui.log"
|
||||
@@ -132,6 +137,8 @@ class MaaManager(QObject):
|
||||
for i in range(0, 2 * self.set["RunSet"]["ADBSearchRange"])
|
||||
]
|
||||
|
||||
logger.success("MAA配置提取完成", module=f"MAA调度器-{self.name}")
|
||||
|
||||
def run(self):
|
||||
"""主进程,运行MAA代理进程"""
|
||||
|
||||
@@ -143,7 +150,9 @@ class MaaManager(QObject):
|
||||
# 检查MAA路径是否可用
|
||||
if not self.maa_exe_path.exists() or not self.maa_set_path.exists():
|
||||
|
||||
logger.error("未正确配置MAA路径,MAA代理进程中止")
|
||||
logger.error(
|
||||
"未正确配置MAA路径,MAA代理进程中止", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error", "启动MAA代理进程失败", "您还未正确配置MAA路径!", -1
|
||||
)
|
||||
@@ -174,6 +183,11 @@ class MaaManager(QObject):
|
||||
]
|
||||
self.create_user_list.emit(self.user_list)
|
||||
|
||||
logger.info(
|
||||
f"用户列表创建完成,已筛选用户数:{len(self.user_list)}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
# 自动代理模式
|
||||
if self.mode == "自动代理":
|
||||
|
||||
@@ -208,7 +222,7 @@ class MaaManager(QObject):
|
||||
self.update_user_list.emit(self.user_list)
|
||||
continue
|
||||
|
||||
logger.info(f"{self.name} | 开始代理用户: {user[0]}")
|
||||
logger.info(f"开始代理用户: {user[0]}", module=f"MAA调度器-{self.name}")
|
||||
|
||||
# 初始化代理情况记录和模式替换表
|
||||
run_book = {"Annihilation": False, "Routine": False}
|
||||
@@ -244,7 +258,8 @@ class MaaManager(QObject):
|
||||
if type != "总计" and len(user_list) > 0:
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 用户: {user[0]} - 森空岛签到{type}: {'、'.join(user_list)}"
|
||||
f"用户: {user[0]} - 森空岛签到{type}: {'、'.join(user_list)}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"info",
|
||||
@@ -255,10 +270,7 @@ class MaaManager(QObject):
|
||||
|
||||
if skland_result["总计"] == 0:
|
||||
self.push_info_bar.emit(
|
||||
"info",
|
||||
"森空岛签到失败",
|
||||
user[0],
|
||||
-1,
|
||||
"info", "森空岛签到失败", user[0], -1
|
||||
)
|
||||
|
||||
if (
|
||||
@@ -274,7 +286,8 @@ class MaaManager(QObject):
|
||||
|
||||
elif user_data["Info"]["IfSkland"]:
|
||||
logger.warning(
|
||||
f"{self.name} | 用户: {user[0]} - 未配置森空岛签到Token,跳过森空岛签到"
|
||||
f"用户: {user[0]} - 未配置森空岛签到Token,跳过森空岛签到",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"warning", "森空岛签到失败", "未配置鹰角网络通行证登录凭证", -1
|
||||
@@ -296,7 +309,8 @@ class MaaManager(QObject):
|
||||
== datetime.strptime(curdate, "%Y-%m-%d").isocalendar()[:2]
|
||||
):
|
||||
logger.info(
|
||||
f"{self.name} | 用户: {user_data["Info"]["Name"]} - 本周剿灭模式已达上限,跳过执行剿灭任务"
|
||||
f"用户: {user_data['Info']['Name']} - 本周剿灭模式已达上限,跳过执行剿灭任务",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
run_book[mode] = True
|
||||
continue
|
||||
@@ -313,7 +327,8 @@ class MaaManager(QObject):
|
||||
self.data[user[2]]["Path"] / f"{mode}/gui.json"
|
||||
).exists():
|
||||
logger.error(
|
||||
f"{self.name} | 用户: {user[0]} - 未找到{mode_book[mode][5:7]}配置文件"
|
||||
f"用户: {user[0]} - 未找到{mode_book[mode][5:7]}配置文件",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
@@ -399,6 +414,11 @@ class MaaManager(QObject):
|
||||
],
|
||||
}
|
||||
|
||||
logger.info(
|
||||
f"用户: {user[0]} - 模式: {mode_book[mode]} - 任务列表: {list(self.task_dict.values())}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
# 尝试次数循环
|
||||
for i in range(self.set["RunSet"]["RunTimesLimit"]):
|
||||
|
||||
@@ -409,13 +429,13 @@ class MaaManager(QObject):
|
||||
break
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 用户: {user[0]} - 模式: {mode_book[mode]} - 尝试次数: {i + 1}/{self.set["RunSet"]["RunTimesLimit"]}"
|
||||
f"用户: {user[0]} - 模式: {mode_book[mode]} - 尝试次数: {i + 1}/{self.set["RunSet"]["RunTimesLimit"]}"
|
||||
)
|
||||
|
||||
# 配置MAA
|
||||
set = self.set_maa(mode_book[mode], user[2])
|
||||
# 记录当前时间
|
||||
start_time = datetime.now()
|
||||
self.log_start_time = datetime.now()
|
||||
|
||||
# 记录模拟器与ADB路径
|
||||
self.emulator_path = Path(
|
||||
@@ -435,8 +455,9 @@ class MaaManager(QObject):
|
||||
self.emulator_path = Path(shortcut.TargetPath)
|
||||
self.emulator_arguments = shortcut.Arguments.split()
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"{self.name} | 解析快捷方式时出现异常:{e}"
|
||||
logger.exception(
|
||||
f"解析快捷方式时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
@@ -448,7 +469,8 @@ class MaaManager(QObject):
|
||||
break
|
||||
elif not self.emulator_path.exists():
|
||||
logger.error(
|
||||
f"{self.name} | 模拟器快捷方式不存在:{self.emulator_path}"
|
||||
f"模拟器快捷方式不存在:{self.emulator_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
@@ -489,16 +511,25 @@ class MaaManager(QObject):
|
||||
|
||||
# 任务开始前释放ADB
|
||||
try:
|
||||
logger.info(f"{self.name} | 释放ADB:{self.ADB_address}")
|
||||
logger.info(
|
||||
f"释放ADB:{self.ADB_address}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
subprocess.run(
|
||||
[self.ADB_path, "disconnect", self.ADB_address],
|
||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
# 忽略错误,因为可能本来就没有连接
|
||||
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||
logger.warning(
|
||||
f"释放ADB时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||
logger.exception(
|
||||
f"释放ADB时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"释放ADB时出现异常",
|
||||
@@ -509,13 +540,17 @@ class MaaManager(QObject):
|
||||
if self.if_open_emulator_process:
|
||||
try:
|
||||
logger.info(
|
||||
f"{self.name} | 启动模拟器:{self.emulator_path},参数:{self.emulator_arguments}"
|
||||
f"启动模拟器:{self.emulator_path},参数:{self.emulator_arguments}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.emulator_process_manager.open_process(
|
||||
self.emulator_path, self.emulator_arguments, 0
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"{self.name} | 启动模拟器时出现异常:{e}")
|
||||
logger.exception(
|
||||
f"启动模拟器时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"启动模拟器时出现异常",
|
||||
@@ -526,14 +561,24 @@ class MaaManager(QObject):
|
||||
break
|
||||
|
||||
# 添加静默进程标记
|
||||
logger.info(
|
||||
f"添加静默进程标记:{self.emulator_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
Config.silence_list.append(self.emulator_path)
|
||||
|
||||
self.search_ADB_address()
|
||||
|
||||
# 创建MAA任务
|
||||
self.maa_process_manager.open_process(self.maa_exe_path, [], 10)
|
||||
logger.info(
|
||||
f"启动MAA进程:{self.maa_exe_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.maa_process_manager.open_process(self.maa_exe_path, [], 0)
|
||||
|
||||
# 监测MAA运行状态
|
||||
self.start_monitor(start_time, mode_book[mode])
|
||||
self.log_check_mode = mode_book[mode]
|
||||
self.start_monitor()
|
||||
|
||||
if self.maa_result == "Success!":
|
||||
|
||||
@@ -541,11 +586,21 @@ class MaaManager(QObject):
|
||||
run_book[mode] = True
|
||||
|
||||
# 从配置文件中解析所需信息
|
||||
while not self.isInterruptionRequested:
|
||||
try:
|
||||
with self.maa_set_path.open(
|
||||
mode="r", encoding="utf-8"
|
||||
) as f:
|
||||
data = json.load(f)
|
||||
break
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
f"解析MAA配置文件时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.sleep(1)
|
||||
|
||||
if not self.isInterruptionRequested:
|
||||
# 记录自定义基建索引
|
||||
user_data["Data"]["CustomInfrastPlanIndex"] = data[
|
||||
"Configurations"
|
||||
@@ -564,7 +619,8 @@ class MaaManager(QObject):
|
||||
]
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 用户: {user[0]} - MAA进程完成代理任务"
|
||||
f"用户: {user[0]} - MAA进程完成代理任务",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.update_log_text.emit(
|
||||
"检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
||||
@@ -573,7 +629,8 @@ class MaaManager(QObject):
|
||||
self.sleep(10)
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 用户: {user[0]} - 代理任务异常: {self.maa_result}"
|
||||
f"用户: {user[0]} - 代理任务异常: {self.maa_result}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
# 打印中止信息
|
||||
# 此时,log变量内存储的就是出现异常的日志信息,可以保存或发送用于问题排查
|
||||
@@ -581,20 +638,38 @@ class MaaManager(QObject):
|
||||
f"{self.maa_result}\n正在中止相关程序\n请等待10s"
|
||||
)
|
||||
# 无命令行中止MAA与其子程序
|
||||
logger.info(
|
||||
f"中止MAA进程:{self.maa_exe_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.maa_process_manager.kill(if_force=True)
|
||||
System.kill_process(self.maa_exe_path)
|
||||
|
||||
# 中止模拟器进程
|
||||
logger.info(
|
||||
f"中止模拟器进程:{list(self.emulator_process_manager.tracked_pids)}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.emulator_process_manager.kill()
|
||||
|
||||
self.if_open_emulator = True
|
||||
|
||||
# 从配置文件中解析所需信息
|
||||
while not self.isInterruptionRequested:
|
||||
try:
|
||||
with self.maa_set_path.open(
|
||||
mode="r", encoding="utf-8"
|
||||
) as f:
|
||||
data = json.load(f)
|
||||
break
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
f"解析MAA配置文件时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.sleep(1)
|
||||
|
||||
if not self.isInterruptionRequested:
|
||||
# 记录自定义基建索引
|
||||
if self.task_dict["Base"] == "False":
|
||||
user_data["Data"]["CustomInfrastPlanIndex"] = data[
|
||||
@@ -628,16 +703,25 @@ class MaaManager(QObject):
|
||||
|
||||
# 任务结束后释放ADB
|
||||
try:
|
||||
logger.info(f"{self.name} | 释放ADB:{self.ADB_address}")
|
||||
logger.info(
|
||||
f"释放ADB:{self.ADB_address}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
subprocess.run(
|
||||
[self.ADB_path, "disconnect", self.ADB_address],
|
||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
# 忽略错误,因为可能本来就没有连接
|
||||
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||
logger.warning(
|
||||
f"释放ADB时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||
logger.exception(
|
||||
f"释放ADB时出现异常:{e}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"释放ADB时出现异常",
|
||||
@@ -646,6 +730,10 @@ class MaaManager(QObject):
|
||||
)
|
||||
# 任务结束后再次手动中止模拟器进程,防止退出不彻底
|
||||
if self.if_kill_emulator:
|
||||
logger.info(
|
||||
f"任务结束后再次中止模拟器进程:{list(self.emulator_process_manager.tracked_pids)}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.emulator_process_manager.kill()
|
||||
self.if_open_emulator = True
|
||||
|
||||
@@ -658,13 +746,13 @@ class MaaManager(QObject):
|
||||
# 保存运行日志以及统计信息
|
||||
if_six_star = Config.save_maa_log(
|
||||
Config.app_path
|
||||
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{start_time.strftime("%H-%M-%S")}.log",
|
||||
self.check_maa_log(start_time, mode_book[mode]),
|
||||
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{self.log_start_time.strftime("%H-%M-%S")}.log",
|
||||
self.check_maa_log(),
|
||||
self.maa_result,
|
||||
)
|
||||
user_logs_list.append(
|
||||
Config.app_path
|
||||
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{start_time.strftime("%H-%M-%S")}.json",
|
||||
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{self.log_start_time.strftime("%H-%M-%S")}.json",
|
||||
)
|
||||
if if_six_star:
|
||||
self.push_notification(
|
||||
@@ -681,7 +769,8 @@ class MaaManager(QObject):
|
||||
if self.maa_update_package:
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 检测到MAA更新,正在执行更新动作"
|
||||
f"检测到MAA更新,正在执行更新动作",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
self.update_log_text.emit(
|
||||
@@ -698,7 +787,9 @@ class MaaManager(QObject):
|
||||
|
||||
self.maa_update_package = ""
|
||||
|
||||
logger.info(f"{self.name} | 更新动作结束")
|
||||
logger.info(
|
||||
f"更新动作结束", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
# 发送统计信息
|
||||
statistics = Config.merge_statistic_info(user_logs_list)
|
||||
@@ -727,6 +818,10 @@ class MaaManager(QObject):
|
||||
user_data["Info"]["RemainedDay"] -= 1
|
||||
user_data["Data"]["ProxyTimes"] += 1
|
||||
user[1] = "完成"
|
||||
logger.success(
|
||||
f"用户 {user[0]} 的自动代理任务已完成",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
Notify.push_plyer(
|
||||
"成功完成一个自动代理任务!",
|
||||
f"已完成用户 {user[0].replace("_", " 今天的")}任务",
|
||||
@@ -735,6 +830,10 @@ class MaaManager(QObject):
|
||||
)
|
||||
else:
|
||||
# 录入代理失败的用户
|
||||
logger.error(
|
||||
f"用户 {user[0]} 的自动代理任务未完成",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
user[1] = "异常"
|
||||
|
||||
self.update_user_list.emit(self.user_list)
|
||||
@@ -743,6 +842,9 @@ class MaaManager(QObject):
|
||||
elif self.mode == "人工排查":
|
||||
|
||||
# 人工排查时,屏蔽静默操作
|
||||
logger.info(
|
||||
"人工排查任务开始,屏蔽静默操作", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
Config.if_ignore_silence = True
|
||||
|
||||
# 标记是否需要启动模拟器
|
||||
@@ -759,7 +861,7 @@ class MaaManager(QObject):
|
||||
if self.isInterruptionRequested:
|
||||
break
|
||||
|
||||
logger.info(f"{self.name} | 开始排查用户: {user[0]}")
|
||||
logger.info(f"开始排查用户: {user[0]}", module=f"MAA调度器-{self.name}")
|
||||
|
||||
user[1] = "运行"
|
||||
self.update_user_list.emit(self.user_list)
|
||||
@@ -776,27 +878,38 @@ class MaaManager(QObject):
|
||||
self.set_maa("人工排查", user[2])
|
||||
|
||||
# 记录当前时间
|
||||
start_time = datetime.now()
|
||||
self.log_start_time = datetime.now()
|
||||
# 创建MAA任务
|
||||
self.maa_process_manager.open_process(self.maa_exe_path, [], 10)
|
||||
logger.info(
|
||||
f"启动MAA进程:{self.maa_exe_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.maa_process_manager.open_process(self.maa_exe_path, [], 0)
|
||||
|
||||
# 监测MAA运行状态
|
||||
self.start_monitor(start_time, "人工排查")
|
||||
self.log_check_mode = "人工排查"
|
||||
self.start_monitor()
|
||||
|
||||
if self.maa_result == "Success!":
|
||||
logger.info(
|
||||
f"{self.name} | 用户: {user[0]} - MAA进程成功登录PRTS"
|
||||
f"用户: {user[0]} - MAA进程成功登录PRTS",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
run_book[0] = True
|
||||
self.update_log_text.emit("检测到MAA进程成功登录PRTS")
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 用户: {user[0]} - MAA未能正确登录到PRTS: {self.maa_result}"
|
||||
f"用户: {user[0]} - MAA未能正确登录到PRTS: {self.maa_result}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.update_log_text.emit(
|
||||
f"{self.maa_result}\n正在中止相关程序\n请等待10s"
|
||||
)
|
||||
# 无命令行中止MAA与其子程序
|
||||
logger.info(
|
||||
f"中止MAA进程:{self.maa_exe_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.maa_process_manager.kill(if_force=True)
|
||||
System.kill_process(self.maa_exe_path)
|
||||
self.if_open_emulator = True
|
||||
@@ -825,17 +938,25 @@ class MaaManager(QObject):
|
||||
|
||||
# 结果录入
|
||||
if run_book[0] and run_book[1]:
|
||||
logger.info(f"{self.name} | 用户 {user[0]} 通过人工排查")
|
||||
logger.info(
|
||||
f"用户 {user[0]} 通过人工排查", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
user_data["Data"]["IfPassCheck"] = True
|
||||
user[1] = "完成"
|
||||
else:
|
||||
logger.info(f"{self.name} | 用户 {user[0]} 未通过人工排查")
|
||||
logger.info(
|
||||
f"用户 {user[0]} 未通过人工排查",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
user_data["Data"]["IfPassCheck"] = False
|
||||
user[1] = "异常"
|
||||
|
||||
self.update_user_list.emit(self.user_list)
|
||||
|
||||
# 解除静默操作屏蔽
|
||||
logger.info(
|
||||
"人工排查任务结束,解除静默操作屏蔽", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
Config.if_ignore_silence = False
|
||||
|
||||
# 设置MAA模式
|
||||
@@ -844,20 +965,32 @@ class MaaManager(QObject):
|
||||
# 配置MAA
|
||||
self.set_maa(self.mode, "")
|
||||
# 创建MAA任务
|
||||
self.maa_process_manager.open_process(self.maa_exe_path, [], 10)
|
||||
logger.info(
|
||||
f"启动MAA进程:{self.maa_exe_path}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
self.maa_process_manager.open_process(self.maa_exe_path, [], 0)
|
||||
# 记录当前时间
|
||||
start_time = datetime.now()
|
||||
self.log_start_time = datetime.now()
|
||||
|
||||
# 监测MAA运行状态
|
||||
self.start_monitor(start_time, "设置MAA")
|
||||
self.log_check_mode = "设置MAA"
|
||||
self.start_monitor()
|
||||
|
||||
if "全局" in self.mode:
|
||||
(self.config_path / "Default").mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy(self.maa_set_path, self.config_path / "Default")
|
||||
logger.success(
|
||||
f"全局MAA配置文件已保存到 {self.config_path / 'Default/gui.json'}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
elif "用户" in self.mode:
|
||||
self.user_config_path.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy(self.maa_set_path, self.user_config_path)
|
||||
logger.success(
|
||||
f"用户MAA配置文件已保存到 {self.user_config_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
result_text = ""
|
||||
|
||||
@@ -866,10 +999,18 @@ class MaaManager(QObject):
|
||||
|
||||
# 关闭可能未正常退出的MAA进程
|
||||
if self.isInterruptionRequested:
|
||||
logger.info(
|
||||
f"关闭可能未正常退出的MAA进程:{self.maa_exe_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.maa_process_manager.kill(if_force=True)
|
||||
System.kill_process(self.maa_exe_path)
|
||||
|
||||
# 复原MAA配置文件
|
||||
logger.info(
|
||||
f"复原MAA配置文件:{self.maa_set_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
shutil.copy(self.config_path / "Default/gui.json", self.maa_set_path)
|
||||
|
||||
# 更新用户数据
|
||||
@@ -930,7 +1071,9 @@ class MaaManager(QObject):
|
||||
self.accomplish.emit({"Time": begin_time, "History": result_text})
|
||||
|
||||
def requestInterruption(self) -> None:
|
||||
logger.info(f"{self.name} | 收到任务中止申请")
|
||||
"""请求中止任务"""
|
||||
|
||||
logger.info(f"收到任务中止申请", module=f"MAA调度器-{self.name}")
|
||||
|
||||
if len(self.log_monitor.files()) != 0:
|
||||
self.interrupt.emit()
|
||||
@@ -940,17 +1083,25 @@ class MaaManager(QObject):
|
||||
self.wait_loop.quit()
|
||||
|
||||
def push_question(self, title: str, message: str) -> bool:
|
||||
"""推送询问窗口"""
|
||||
|
||||
logger.info(
|
||||
f"推送询问窗口:{title} - {message}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
self.question.emit(title, message)
|
||||
self.question_loop.exec()
|
||||
return self.response
|
||||
|
||||
def __capture_response(self, response: bool) -> None:
|
||||
"""捕获询问窗口的响应"""
|
||||
logger.info(f"捕获询问窗口响应:{response}", module=f"MAA调度器-{self.name}")
|
||||
self.response = response
|
||||
|
||||
def sleep(self, time: int) -> None:
|
||||
"""非阻塞型等待"""
|
||||
|
||||
logger.info(f"等待 {time} 秒", module=f"MAA调度器-{self.name}")
|
||||
QTimer.singleShot(time * 1000, self.wait_loop.quit)
|
||||
self.wait_loop.exec()
|
||||
|
||||
@@ -970,6 +1121,10 @@ class MaaManager(QObject):
|
||||
QTimer.singleShot(
|
||||
10000, partial(Config.silence_list.remove, self.emulator_path)
|
||||
)
|
||||
logger.info(
|
||||
f"10s后移除静默进程标记:{self.emulator_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
if "-" in self.ADB_address:
|
||||
ADB_ip = f"{self.ADB_address.split("-")[0]}-"
|
||||
@@ -980,7 +1135,8 @@ class MaaManager(QObject):
|
||||
ADB_port = int(self.ADB_address.split(":")[1])
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 正在搜索ADB实际地址,ADB前缀:{ADB_ip},初始端口:{ADB_port},搜索范围:{self.port_range}"
|
||||
f"正在搜索ADB实际地址,ADB前缀:{ADB_ip},初始端口:{ADB_port},搜索范围:{self.port_range}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
for port in self.port_range:
|
||||
@@ -1010,9 +1166,14 @@ class MaaManager(QObject):
|
||||
)
|
||||
if ADB_address in devices_result.stdout:
|
||||
|
||||
logger.info(f"{self.name} | ADB实际地址:{ADB_address}")
|
||||
logger.info(
|
||||
f"ADB实际地址:{ADB_address}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
# 断开连接
|
||||
logger.info(
|
||||
f"断开ADB连接:{ADB_address}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
subprocess.run(
|
||||
[self.ADB_path, "disconnect", ADB_address],
|
||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||
@@ -1021,6 +1182,10 @@ class MaaManager(QObject):
|
||||
self.ADB_address = ADB_address
|
||||
|
||||
# 覆写当前ADB地址
|
||||
logger.info(
|
||||
f"开始使用实际 ADB 地址覆写:{self.ADB_address}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.maa_process_manager.kill(if_force=True)
|
||||
System.kill_process(self.maa_exe_path)
|
||||
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
||||
@@ -1036,9 +1201,14 @@ class MaaManager(QObject):
|
||||
return None
|
||||
|
||||
else:
|
||||
logger.info(f"{self.name} | 无法连接到ADB地址:{ADB_address}")
|
||||
logger.info(
|
||||
f"无法连接到ADB地址:{ADB_address}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
else:
|
||||
logger.info(f"{self.name} | 无法连接到ADB地址:{ADB_address}")
|
||||
logger.info(
|
||||
f"无法连接到ADB地址:{ADB_address}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
if not self.isInterruptionRequested:
|
||||
self.play_sound.emit("ADB失败")
|
||||
@@ -1046,14 +1216,19 @@ class MaaManager(QObject):
|
||||
def refresh_maa_log(self) -> None:
|
||||
"""刷新MAA日志"""
|
||||
|
||||
logger.debug(
|
||||
f"刷新MAA日志:{self.maa_log_path}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
with self.maa_log_path.open(mode="r", encoding="utf-8") as f:
|
||||
pass
|
||||
|
||||
# 一分钟内未执行日志变化检查,强制检查一次
|
||||
if datetime.now() - self.last_check_time > timedelta(minutes=1):
|
||||
self.log_monitor.fileChanged.emit("1分钟超时检查")
|
||||
logger.info("触发 1 分钟超时检查", module=f"MAA调度器-{self.name}")
|
||||
self.check_maa_log()
|
||||
|
||||
def check_maa_log(self, start_time: datetime, mode: str) -> list:
|
||||
def check_maa_log(self) -> list:
|
||||
"""获取MAA日志并检查以判断MAA程序运行状态"""
|
||||
|
||||
self.last_check_time = datetime.now()
|
||||
@@ -1066,7 +1241,7 @@ class MaaManager(QObject):
|
||||
if not if_log_start:
|
||||
try:
|
||||
entry_time = datetime.strptime(entry[1:20], "%Y-%m-%d %H:%M:%S")
|
||||
if entry_time > start_time:
|
||||
if entry_time > self.log_start_time:
|
||||
if_log_start = True
|
||||
logs.append(entry)
|
||||
except ValueError:
|
||||
@@ -1093,11 +1268,15 @@ class MaaManager(QObject):
|
||||
if version_match:
|
||||
self.maa_version = f"v{version_match.group(1)}"
|
||||
self.check_maa_version.emit(self.maa_version)
|
||||
logger.info(
|
||||
f"检测到MAA版本:{self.maa_version}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
if "自动代理" in mode:
|
||||
if "自动代理" in self.log_check_mode:
|
||||
|
||||
# 获取最近一条日志的时间
|
||||
latest_time = start_time
|
||||
latest_time = self.log_start_time
|
||||
for _ in logs[::-1]:
|
||||
try:
|
||||
if "如果长时间无进一步日志更新,可能需要手动干预。" in _:
|
||||
@@ -1107,12 +1286,16 @@ class MaaManager(QObject):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
logger.info(
|
||||
f"MAA最近一条日志时间:{latest_time}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
time_book = {
|
||||
"自动代理_剿灭": "AnnihilationTimeLimit",
|
||||
"自动代理_日常": "RoutineTimeLimit",
|
||||
}
|
||||
|
||||
if mode == "自动代理_剿灭" and "剿灭任务失败" in log:
|
||||
if self.log_check_mode == "自动代理_剿灭" and "剿灭任务失败" in log:
|
||||
self.weekly_annihilation_limit_reached = True
|
||||
else:
|
||||
self.weekly_annihilation_limit_reached = False
|
||||
@@ -1164,7 +1347,7 @@ class MaaManager(QObject):
|
||||
self.maa_result = "MAA在完成任务前退出"
|
||||
|
||||
elif datetime.now() - latest_time > timedelta(
|
||||
minutes=self.set["RunSet"][time_book[mode]]
|
||||
minutes=self.set["RunSet"][time_book[self.log_check_mode]]
|
||||
):
|
||||
self.maa_result = "MAA进程超时"
|
||||
|
||||
@@ -1174,7 +1357,7 @@ class MaaManager(QObject):
|
||||
else:
|
||||
self.maa_result = "Wait"
|
||||
|
||||
elif mode == "人工排查":
|
||||
elif self.log_check_mode == "人工排查":
|
||||
if "完成任务: StartUp" in log or "完成任务: 开始唤醒" in log:
|
||||
self.maa_result = "Success!"
|
||||
elif "请 「检查连接设置」 → 「尝试重启模拟器与 ADB」 → 「重启电脑」" in log:
|
||||
@@ -1193,7 +1376,7 @@ class MaaManager(QObject):
|
||||
else:
|
||||
self.maa_result = "Wait"
|
||||
|
||||
elif mode == "设置MAA":
|
||||
elif self.log_check_mode == "设置MAA":
|
||||
if (
|
||||
"MaaAssistantArknights GUI exited" in log
|
||||
or not self.maa_process_manager.is_running()
|
||||
@@ -1202,20 +1385,24 @@ class MaaManager(QObject):
|
||||
else:
|
||||
self.maa_result = "Wait"
|
||||
|
||||
logger.info(
|
||||
f"MAA日志分析结果:{self.maa_result}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
if self.maa_result != "Wait":
|
||||
|
||||
self.quit_monitor()
|
||||
|
||||
return logs
|
||||
|
||||
def start_monitor(self, start_time: datetime, mode: str) -> None:
|
||||
def start_monitor(self) -> None:
|
||||
"""开始监视MAA日志"""
|
||||
|
||||
logger.info(f"{self.name} | 开始监视MAA日志")
|
||||
self.log_monitor.addPath(str(self.maa_log_path))
|
||||
self.log_monitor.fileChanged.connect(
|
||||
lambda: self.check_maa_log(start_time, mode)
|
||||
logger.info(
|
||||
f"开始监视MAA日志,路径:{self.maa_log_path},日志起始时间:{self.log_start_time},模式:{self.log_check_mode}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.log_monitor.addPath(str(self.maa_log_path))
|
||||
self.log_monitor_timer.start(1000)
|
||||
self.last_check_time = datetime.now()
|
||||
self.monitor_loop.exec()
|
||||
@@ -1225,16 +1412,29 @@ class MaaManager(QObject):
|
||||
|
||||
if len(self.log_monitor.files()) != 0:
|
||||
|
||||
logger.info(f"{self.name} | 退出MAA日志监视")
|
||||
logger.info(
|
||||
f"MAA日志监视器移除路径:{self.maa_log_path}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
self.log_monitor.removePath(str(self.maa_log_path))
|
||||
self.log_monitor.fileChanged.disconnect()
|
||||
|
||||
else:
|
||||
logger.warning(
|
||||
f"MAA日志监视器没有正在监看的路径:{self.log_monitor.files()}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
self.log_monitor_timer.stop()
|
||||
self.last_check_time = None
|
||||
self.monitor_loop.quit()
|
||||
|
||||
logger.info("MAA日志监视锁已释放", module=f"MAA调度器-{self.name}")
|
||||
|
||||
def set_maa(self, mode, index) -> dict:
|
||||
"""配置MAA运行参数"""
|
||||
logger.info(f"{self.name} | 配置MAA运行参数: {mode}/{index}")
|
||||
logger.info(
|
||||
f"开始配置MAA运行参数: {mode}/{index}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
if "设置MAA" not in self.mode and "更新MAA" not in mode:
|
||||
user_data = self.data[index]["Config"]
|
||||
@@ -1804,12 +2004,17 @@ class MaaManager(QObject):
|
||||
with self.maa_set_path.open(mode="w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
logger.success(
|
||||
f"MAA运行参数配置完成: {mode}/{index}", module=f"MAA调度器-{self.name}"
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
def agree_bilibili(self, if_agree):
|
||||
"""向MAA写入Bilibili协议相关任务"""
|
||||
logger.info(
|
||||
f"{self.name} | Bilibili协议相关任务状态: {"启用" if if_agree else "禁用"}"
|
||||
f"Bilibili协议相关任务状态: {'启用' if if_agree else '禁用'}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
with self.maa_tasks_path.open(mode="r", encoding="utf-8") as f:
|
||||
@@ -1843,6 +2048,10 @@ class MaaManager(QObject):
|
||||
user_data: Dict[str, Dict[str, Union[str, int, bool]]] = None,
|
||||
) -> None:
|
||||
"""通过所有渠道推送通知"""
|
||||
logger.info(
|
||||
f"开始推送通知,模式:{mode},标题:{title}",
|
||||
module=f"MAA调度器-{self.name}",
|
||||
)
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(str(Config.app_path / "resources/html"))
|
||||
@@ -1971,9 +2180,7 @@ class MaaManager(QObject):
|
||||
user_data["Notify"]["ToAddress"],
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 用户邮箱地址为空,无法发送用户单独的邮件通知"
|
||||
)
|
||||
logger.error(f"用户邮箱地址为空,无法发送用户单独的邮件通知")
|
||||
|
||||
# 发送ServerChan通知
|
||||
if user_data["Notify"]["IfServerChan"]:
|
||||
@@ -2051,9 +2258,7 @@ class MaaManager(QObject):
|
||||
user_data["Notify"]["ToAddress"],
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 用户邮箱地址为空,无法发送用户单独的邮件通知"
|
||||
)
|
||||
logger.error(f"用户邮箱地址为空,无法发送用户单独的邮件通知")
|
||||
|
||||
# 发送ServerChan通知
|
||||
if user_data["Notify"]["IfServerChan"]:
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QObject, Signal, QEventLoop, QFileSystemWatcher, QTimer
|
||||
import os
|
||||
import sys
|
||||
@@ -37,7 +36,7 @@ from pathlib import Path
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from typing import Union, List, Dict
|
||||
|
||||
from app.core import Config, GeneralConfig, GeneralSubConfig
|
||||
from app.core import Config, GeneralConfig, GeneralSubConfig, logger
|
||||
from app.services import Notify, System
|
||||
from app.utils import ProcessManager
|
||||
|
||||
@@ -75,19 +74,20 @@ class GeneralManager(QObject):
|
||||
self.sub_list = []
|
||||
self.mode = mode
|
||||
self.config_path = config["Path"]
|
||||
self.name = config["Config"].get(config["Config"].Script_Name)
|
||||
self.sub_config_path = sub_config_path
|
||||
|
||||
self.game_process_manager = ProcessManager()
|
||||
self.script_process_manager = ProcessManager()
|
||||
|
||||
self.log_monitor = QFileSystemWatcher()
|
||||
self.log_monitor.fileChanged.connect(self.check_script_log)
|
||||
self.log_monitor_timer = QTimer()
|
||||
self.log_monitor_timer.timeout.connect(self.refresh_log)
|
||||
self.monitor_loop = QEventLoop()
|
||||
self.loge_start_time = datetime.now()
|
||||
|
||||
self.script_process_manager.processClosed.connect(
|
||||
lambda: self.log_monitor.fileChanged.emit("进程结束检查")
|
||||
)
|
||||
self.script_process_manager.processClosed.connect(self.check_script_log)
|
||||
|
||||
self.question_loop = QEventLoop()
|
||||
self.question_response.connect(self.__capture_response)
|
||||
@@ -111,6 +111,10 @@ class GeneralManager(QObject):
|
||||
|
||||
self.data = dict(sorted(self.data.items(), key=lambda x: int(x[0][3:])))
|
||||
|
||||
logger.success(
|
||||
f"初始化通用调度器,模式:{self.mode}", module=f"通用调度器-{self.name}"
|
||||
)
|
||||
|
||||
def check_config_info(self) -> bool:
|
||||
"""检查配置完整性"""
|
||||
|
||||
@@ -124,7 +128,7 @@ class GeneralManager(QObject):
|
||||
) or (
|
||||
self.set["Game"]["Enabled"] and not Path(self.set["Game"]["Path"]).exists()
|
||||
):
|
||||
logger.error("脚本配置缺失")
|
||||
logger.error("脚本配置缺失", module=f"通用调度器-{self.name}")
|
||||
self.push_info_bar.emit("error", "脚本配置缺失", "请检查脚本配置!", -1)
|
||||
return False
|
||||
|
||||
@@ -133,7 +137,6 @@ class GeneralManager(QObject):
|
||||
def configure(self):
|
||||
"""提取配置信息"""
|
||||
|
||||
self.name = self.set["Script"]["Name"]
|
||||
self.script_root_path = Path(self.set["Script"]["RootPath"])
|
||||
self.script_exe_path = Path(self.set["Script"]["ScriptPath"])
|
||||
self.script_config_path = Path(self.set["Script"]["ConfigPath"])
|
||||
@@ -166,9 +169,23 @@ class GeneralManager(QObject):
|
||||
curdate = Config.server_date().strftime("%Y-%m-%d")
|
||||
begin_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if self.mode == "人工排查":
|
||||
|
||||
logger.error("通用脚本不支持人工排查模式", module=f"通用调度器-{self.name}")
|
||||
self.accomplish.emit(
|
||||
{
|
||||
"Time": begin_time,
|
||||
"History": "通用脚本不支持人工排查模式,通用代理进程中止",
|
||||
}
|
||||
)
|
||||
return None
|
||||
|
||||
# 检查配置完整性
|
||||
if not self.check_config_info():
|
||||
|
||||
logger.error(
|
||||
"配置不完整,无法启动通用代理进程", module=f"通用调度器-{self.name}"
|
||||
)
|
||||
self.accomplish.emit(
|
||||
{"Time": begin_time, "History": "由于配置不完整,通用代理进程中止"}
|
||||
)
|
||||
@@ -190,6 +207,11 @@ class GeneralManager(QObject):
|
||||
]
|
||||
self.create_user_list.emit(self.sub_list)
|
||||
|
||||
logger.info(
|
||||
f"配置列表创建完成,已筛选子配置数:{len(self.sub_list)}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
# 自动代理模式
|
||||
if self.mode == "自动代理":
|
||||
|
||||
@@ -222,14 +244,17 @@ class GeneralManager(QObject):
|
||||
self.update_user_list.emit(self.sub_list)
|
||||
continue
|
||||
|
||||
logger.info(f"{self.name} | 开始代理配置: {sub[0]}")
|
||||
logger.info(f"开始代理配置: {sub[0]}", module=f"通用调度器-{self.name}")
|
||||
|
||||
sub_start_time = datetime.now()
|
||||
|
||||
run_book = False
|
||||
|
||||
if not (self.data[sub[2]]["Path"] / "ConfigFiles").exists():
|
||||
logger.error(f"{self.name} | 配置: {sub[0]} - 未找到配置文件")
|
||||
logger.error(
|
||||
f"配置: {sub[0]} - 未找到配置文件",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"启动通用代理进程失败",
|
||||
@@ -246,11 +271,12 @@ class GeneralManager(QObject):
|
||||
break
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 用户: {sub[0]} - 尝试次数: {i + 1}/{self.set['Run']['RunTimesLimit']}"
|
||||
f"用户: {sub[0]} - 尝试次数: {i + 1}/{self.set['Run']['RunTimesLimit']}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
# 记录当前时间
|
||||
start_time = datetime.now()
|
||||
self.log_start_time = datetime.now()
|
||||
# 配置脚本
|
||||
self.set_sub(sub[2])
|
||||
# 执行任务前脚本
|
||||
@@ -267,7 +293,8 @@ class GeneralManager(QObject):
|
||||
|
||||
try:
|
||||
logger.info(
|
||||
f"{self.name} | 启动游戏/模拟器:{self.game_path},参数:{self.set['Game']['Arguments']}"
|
||||
f"启动游戏/模拟器:{self.game_path},参数:{self.set['Game']['Arguments']}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.game_process_manager.open_process(
|
||||
self.game_path,
|
||||
@@ -275,8 +302,9 @@ class GeneralManager(QObject):
|
||||
0,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"{self.name} | 启动游戏/模拟器时出现异常:{e}"
|
||||
logger.exception(
|
||||
f"启动游戏/模拟器时出现异常:{e}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
@@ -289,6 +317,10 @@ class GeneralManager(QObject):
|
||||
|
||||
# 添加静默进程标记
|
||||
if self.set["Game"]["Style"] == "Emulator":
|
||||
logger.info(
|
||||
f"添加静默进程标记:{self.game_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
Config.silence_list.append(self.game_path)
|
||||
|
||||
self.update_log_text.emit(
|
||||
@@ -299,6 +331,10 @@ class GeneralManager(QObject):
|
||||
|
||||
# 10s后移除静默进程标记
|
||||
if self.set["Game"]["Style"] == "Emulator":
|
||||
logger.info(
|
||||
f"10s后移除静默进程标记:{self.game_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
QTimer.singleShot(
|
||||
10000,
|
||||
partial(Config.silence_list.remove, self.game_path),
|
||||
@@ -306,7 +342,8 @@ class GeneralManager(QObject):
|
||||
|
||||
# 运行脚本任务
|
||||
logger.info(
|
||||
f"{self.name} | 运行脚本任务:{self.script_exe_path},参数:{self.set['Script']['Arguments']}"
|
||||
f"运行脚本任务:{self.script_exe_path},参数:{self.set['Script']['Arguments']}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.script_process_manager.open_process(
|
||||
self.script_exe_path,
|
||||
@@ -315,7 +352,7 @@ class GeneralManager(QObject):
|
||||
)
|
||||
|
||||
# 监测运行状态
|
||||
self.start_monitor(start_time)
|
||||
self.start_monitor()
|
||||
|
||||
if self.script_result == "Success!":
|
||||
|
||||
@@ -323,15 +360,24 @@ class GeneralManager(QObject):
|
||||
run_book = True
|
||||
|
||||
# 中止相关程序
|
||||
logger.info(
|
||||
f"中止相关程序:{self.script_exe_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.script_process_manager.kill()
|
||||
System.kill_process(self.script_exe_path)
|
||||
if self.set["Game"]["Enabled"]:
|
||||
logger.info(
|
||||
f"中止游戏/模拟器进程:{list(self.game_process_manager.tracked_pids)}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.game_process_manager.kill()
|
||||
if self.set["Game"]["IfForceClose"]:
|
||||
System.kill_process(self.game_path)
|
||||
|
||||
logger.info(
|
||||
f"{self.name} | 配置: {sub[0]} - 通用脚本进程完成代理任务"
|
||||
f"配置: {sub[0]} - 通用脚本进程完成代理任务",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.update_log_text.emit(
|
||||
"检测到通用脚本进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
||||
@@ -340,7 +386,8 @@ class GeneralManager(QObject):
|
||||
self.sleep(10)
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 配置: {sub[0]} - 代理任务异常: {self.script_result}"
|
||||
f"配置: {sub[0]} - 代理任务异常: {self.script_result}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
# 打印中止信息
|
||||
# 此时,log变量内存储的就是出现异常的日志信息,可以保存或发送用于问题排查
|
||||
@@ -349,8 +396,16 @@ class GeneralManager(QObject):
|
||||
)
|
||||
|
||||
# 中止相关程序
|
||||
logger.info(
|
||||
f"中止相关程序:{self.script_exe_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.script_process_manager.kill()
|
||||
if self.set["Game"]["Enabled"]:
|
||||
logger.info(
|
||||
f"中止游戏/模拟器进程:{list(self.game_process_manager.tracked_pids)}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.game_process_manager.kill()
|
||||
if self.set["Game"]["IfForceClose"]:
|
||||
System.kill_process(self.game_path)
|
||||
@@ -380,8 +435,8 @@ class GeneralManager(QObject):
|
||||
# 保存运行日志以及统计信息
|
||||
Config.save_general_log(
|
||||
Config.app_path
|
||||
/ f"history/{curdate}/{sub_data['Info']['Name']}/{start_time.strftime("%H-%M-%S")}.log",
|
||||
self.check_script_log(start_time),
|
||||
/ f"history/{curdate}/{sub_data['Info']['Name']}/{self.log_start_time.strftime("%H-%M-%S")}.log",
|
||||
self.check_script_log(),
|
||||
self.script_result,
|
||||
)
|
||||
|
||||
@@ -409,6 +464,10 @@ class GeneralManager(QObject):
|
||||
sub_data["Info"]["RemainedDay"] -= 1
|
||||
sub_data["Data"]["ProxyTimes"] += 1
|
||||
sub[1] = "完成"
|
||||
logger.success(
|
||||
f"配置: {sub[0]} - 代理任务完成",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
Notify.push_plyer(
|
||||
"成功完成一个自动代理任务!",
|
||||
f"已完成配置 {sub[0].replace("_", " 今天的")}任务",
|
||||
@@ -418,6 +477,10 @@ class GeneralManager(QObject):
|
||||
else:
|
||||
# 录入代理失败的用户
|
||||
sub[1] = "异常"
|
||||
logger.error(
|
||||
f"配置: {sub[0]} - 代理任务异常: {self.script_result}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
self.update_user_list.emit(self.sub_list)
|
||||
|
||||
@@ -429,17 +492,20 @@ class GeneralManager(QObject):
|
||||
|
||||
try:
|
||||
# 创建通用脚本任务
|
||||
logger.info(f"{self.name} | 无参数启动通用脚本:{self.script_exe_path}")
|
||||
logger.info(
|
||||
f"无参数启动通用脚本:{self.script_exe_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.script_process_manager.open_process(
|
||||
self.script_exe_path,
|
||||
tracking_time=60 if self.set["Script"]["IfTrackProcess"] else 0,
|
||||
)
|
||||
|
||||
# 记录当前时间
|
||||
start_time = datetime.now()
|
||||
self.log_start_time = datetime.now()
|
||||
|
||||
# 监测通用脚本运行状态
|
||||
self.start_monitor(start_time)
|
||||
self.start_monitor()
|
||||
|
||||
self.sub_config_path.mkdir(parents=True, exist_ok=True)
|
||||
if self.set["Script"]["ConfigPathMode"] == "文件夹":
|
||||
@@ -448,16 +514,23 @@ class GeneralManager(QObject):
|
||||
self.sub_config_path,
|
||||
dirs_exist_ok=True,
|
||||
)
|
||||
logger.success(
|
||||
f"通用脚本配置已保存到:{self.sub_config_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
else:
|
||||
shutil.copy(self.script_config_path, self.sub_config_path)
|
||||
logger.success(
|
||||
f"通用脚本配置已保存到:{self.sub_config_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{self.name} | 启动通用脚本时出现异常:{e}")
|
||||
logger.exception(
|
||||
f"启动通用脚本时出现异常:{e}", module=f"通用调度器-{self.name}"
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"启动通用脚本时出现异常",
|
||||
"请检查相关设置",
|
||||
-1,
|
||||
"error", "启动通用脚本时出现异常", "请检查相关设置", -1
|
||||
)
|
||||
|
||||
result_text = ""
|
||||
@@ -467,9 +540,17 @@ class GeneralManager(QObject):
|
||||
|
||||
# 关闭可能未正常退出的通用脚本进程
|
||||
if self.isInterruptionRequested:
|
||||
logger.info(
|
||||
f"关闭可能未正常退出的通用脚本进程:{self.script_exe_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.script_process_manager.kill(if_force=True)
|
||||
System.kill_process(self.script_exe_path)
|
||||
if self.set["Game"]["Enabled"]:
|
||||
logger.info(
|
||||
f"关闭可能未正常退出的游戏/模拟器进程:{list(self.game_process_manager.tracked_pids)}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.game_process_manager.kill(if_force=True)
|
||||
if self.set["Game"]["IfForceClose"]:
|
||||
System.kill_process(self.game_path)
|
||||
@@ -527,7 +608,9 @@ class GeneralManager(QObject):
|
||||
self.accomplish.emit({"Time": begin_time, "History": result_text})
|
||||
|
||||
def requestInterruption(self) -> None:
|
||||
logger.info(f"{self.name} | 收到任务中止申请")
|
||||
"""请求中止通用脚本任务"""
|
||||
|
||||
logger.info(f"收到任务中止申请", module=f"通用调度器-{self.name}")
|
||||
|
||||
if len(self.log_monitor.files()) != 0:
|
||||
self.interrupt.emit()
|
||||
@@ -537,29 +620,45 @@ class GeneralManager(QObject):
|
||||
self.wait_loop.quit()
|
||||
|
||||
def push_question(self, title: str, message: str) -> bool:
|
||||
"""推送问题询问"""
|
||||
|
||||
logger.info(
|
||||
f"推送问题询问:{title} - {message}", module=f"通用调度器-{self.name}"
|
||||
)
|
||||
|
||||
self.question.emit(title, message)
|
||||
self.question_loop.exec()
|
||||
return self.response
|
||||
|
||||
def __capture_response(self, response: bool) -> None:
|
||||
"""捕获问题询问的响应"""
|
||||
|
||||
logger.info(f"捕获问题询问的响应:{response}", module=f"通用调度器-{self.name}")
|
||||
self.response = response
|
||||
|
||||
def sleep(self, time: int) -> None:
|
||||
"""非阻塞型等待"""
|
||||
|
||||
logger.info(f"等待 {time} 秒", module=f"通用调度器-{self.name}")
|
||||
|
||||
QTimer.singleShot(time * 1000, self.wait_loop.quit)
|
||||
self.wait_loop.exec()
|
||||
|
||||
def refresh_log(self) -> None:
|
||||
"""刷新脚本日志"""
|
||||
|
||||
logger.debug(
|
||||
f"刷新通用脚本日志:{self.script_log_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
with self.script_log_path.open(mode="r", encoding="utf-8") as f:
|
||||
pass
|
||||
|
||||
# 一分钟内未执行日志变化检查,强制检查一次
|
||||
if (datetime.now() - self.last_check_time).total_seconds() > 60:
|
||||
self.log_monitor.fileChanged.emit("1分钟超时检查")
|
||||
logger.info("触发 1 分钟超时检查", module=f"通用调度器-{self.name}")
|
||||
self.check_script_log()
|
||||
|
||||
def strptime(
|
||||
self, date_string: str, format: str, default_date: datetime
|
||||
@@ -589,7 +688,7 @@ class GeneralManager(QObject):
|
||||
|
||||
return datetime(**datetime_kwargs)
|
||||
|
||||
def check_script_log(self, start_time: datetime) -> list:
|
||||
def check_script_log(self) -> list:
|
||||
"""获取脚本日志并检查以判断脚本程序运行状态"""
|
||||
|
||||
self.last_check_time = datetime.now()
|
||||
@@ -607,7 +706,7 @@ class GeneralManager(QObject):
|
||||
self.last_check_time,
|
||||
)
|
||||
|
||||
if entry_time > start_time:
|
||||
if entry_time > self.log_start_time:
|
||||
if_log_start = True
|
||||
logs.append(entry)
|
||||
except ValueError:
|
||||
@@ -625,7 +724,7 @@ class GeneralManager(QObject):
|
||||
if "自动代理" in self.mode:
|
||||
|
||||
# 获取最近一条日志的时间
|
||||
latest_time = start_time
|
||||
latest_time = self.log_start_time
|
||||
for _ in logs[::-1]:
|
||||
try:
|
||||
latest_time = self.strptime(
|
||||
@@ -637,6 +736,11 @@ class GeneralManager(QObject):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
logger.info(
|
||||
f"通用脚本最近一条日志时间:{latest_time}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
for success_sign in self.success_log:
|
||||
if success_sign in log:
|
||||
self.script_result = "Success!"
|
||||
@@ -668,18 +772,25 @@ class GeneralManager(QObject):
|
||||
else:
|
||||
self.script_result = "Success!"
|
||||
|
||||
logger.info(
|
||||
f"通用脚本日志分析结果:{self.script_result}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
if self.script_result != "Wait":
|
||||
|
||||
self.quit_monitor()
|
||||
|
||||
return logs
|
||||
|
||||
def start_monitor(self, start_time: datetime) -> None:
|
||||
def start_monitor(self) -> None:
|
||||
"""开始监视通用脚本日志"""
|
||||
|
||||
logger.info(f"{self.name} | 开始监视通用脚本日志")
|
||||
logger.info(
|
||||
f"开始监视通用脚本日志,路径:{self.script_log_path},日志起始时间:{self.log_start_time}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.log_monitor.addPath(str(self.script_log_path))
|
||||
self.log_monitor.fileChanged.connect(lambda: self.check_script_log(start_time))
|
||||
self.log_monitor_timer.start(1000)
|
||||
self.last_check_time = datetime.now()
|
||||
self.monitor_loop.exec()
|
||||
@@ -689,16 +800,27 @@ class GeneralManager(QObject):
|
||||
|
||||
if len(self.log_monitor.files()) != 0:
|
||||
|
||||
logger.info(f"{self.name} | 退出通用脚本日志监视")
|
||||
logger.info(
|
||||
f"通用脚本日志监视器移除路径:{self.script_log_path}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
self.log_monitor.removePath(str(self.script_log_path))
|
||||
self.log_monitor.fileChanged.disconnect()
|
||||
|
||||
else:
|
||||
logger.warning(
|
||||
f"通用脚本日志监视器没有正在监看的路径:{self.log_monitor.files()}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
self.log_monitor_timer.stop()
|
||||
self.last_check_time = None
|
||||
self.monitor_loop.quit()
|
||||
|
||||
logger.info("通用脚本日志监视锁已释放", module=f"通用调度器-{self.name}")
|
||||
|
||||
def set_sub(self, index: str = "") -> dict:
|
||||
"""配置通用脚本运行参数"""
|
||||
logger.info(f"{self.name} | 配置脚本运行参数: {index}")
|
||||
logger.info(f"开始配置脚本运行参数:{index}", module=f"通用调度器-{self.name}")
|
||||
|
||||
# 配置前关闭可能未正常退出的脚本进程
|
||||
System.kill_process(self.script_exe_path)
|
||||
@@ -732,11 +854,15 @@ class GeneralManager(QObject):
|
||||
self.script_config_path,
|
||||
)
|
||||
|
||||
logger.info(f"脚本运行参数配置完成:{index}", module=f"通用调度器-{self.name}")
|
||||
|
||||
def execute_script_task(self, script_path: Path, task_name: str) -> bool:
|
||||
"""执行脚本任务并等待结束"""
|
||||
|
||||
try:
|
||||
logger.info(f"{self.name} | 开始执行{task_name}: {script_path}")
|
||||
logger.info(
|
||||
f"开始执行{task_name}: {script_path}", module=f"通用调度器-{self.name}"
|
||||
)
|
||||
|
||||
# 根据文件类型选择执行方式
|
||||
if script_path.suffix.lower() == ".py":
|
||||
@@ -744,7 +870,10 @@ class GeneralManager(QObject):
|
||||
elif script_path.suffix.lower() in [".bat", ".cmd", ".exe"]:
|
||||
cmd = [str(script_path)]
|
||||
elif script_path.suffix.lower() == "":
|
||||
logger.warning(f"{self.name} | {task_name}脚本没有指定后缀名,无法执行")
|
||||
logger.warning(
|
||||
f"{task_name}脚本没有指定后缀名,无法执行",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
return False
|
||||
else:
|
||||
# 使用系统默认程序打开
|
||||
@@ -767,23 +896,32 @@ class GeneralManager(QObject):
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info(f"{self.name} | {task_name}执行成功")
|
||||
logger.info(f"{task_name}执行成功", module=f"通用调度器-{self.name}")
|
||||
if result.stdout.strip():
|
||||
logger.info(f"{self.name} | {task_name}输出: {result.stdout}")
|
||||
logger.info(
|
||||
f"{task_name}输出: {result.stdout}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
return True
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | {task_name}执行失败,返回码: {result.returncode}"
|
||||
f"{task_name}执行失败,返回码: {result.returncode}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
if result.stderr.strip():
|
||||
logger.error(f"{self.name} | {task_name}错误输出: {result.stderr}")
|
||||
logger.error(
|
||||
f"{task_name}错误输出: {result.stderr}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.error(f"{self.name} | {task_name}执行超时")
|
||||
logger.error(f"{task_name}执行超时", module=f"通用调度器-{self.name}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.exception(f"{self.name} | 执行{task_name}时出现异常: {e}")
|
||||
logger.exception(
|
||||
f"执行{task_name}时出现异常: {e}", module=f"通用调度器-{self.name}"
|
||||
)
|
||||
return False
|
||||
|
||||
def push_notification(
|
||||
@@ -795,6 +933,11 @@ class GeneralManager(QObject):
|
||||
) -> None:
|
||||
"""通过所有渠道推送通知"""
|
||||
|
||||
logger.info(
|
||||
f"开始推送通知,模式:{mode},标题:{title}",
|
||||
module=f"通用调度器-{self.name}",
|
||||
)
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(str(Config.app_path / "resources/html"))
|
||||
)
|
||||
@@ -902,9 +1045,7 @@ class GeneralManager(QObject):
|
||||
sub_data["Notify"]["ToAddress"],
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 用户邮箱地址为空,无法发送用户单独的邮件通知"
|
||||
)
|
||||
logger.error(f"用户邮箱地址为空,无法发送用户单独的邮件通知")
|
||||
|
||||
# 发送ServerChan通知
|
||||
if sub_data["Notify"]["IfServerChan"]:
|
||||
|
||||
@@ -33,13 +33,14 @@ from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.utils import formataddr
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
import requests
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
from loguru import logger
|
||||
|
||||
from plyer import notification
|
||||
|
||||
from app.core import Config
|
||||
from app.core import Config, logger
|
||||
from app.services.security import Crypto
|
||||
from app.utils.ImageUtils import ImageUtils
|
||||
|
||||
@@ -51,11 +52,21 @@ class Notification(QObject):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
def push_plyer(self, title, message, ticker, t):
|
||||
"""推送系统通知"""
|
||||
def push_plyer(self, title, message, ticker, t) -> bool:
|
||||
"""
|
||||
推送系统通知
|
||||
|
||||
:param title: 通知标题
|
||||
:param message: 通知内容
|
||||
:param ticker: 通知横幅
|
||||
:param t: 通知持续时间
|
||||
:return: bool
|
||||
"""
|
||||
|
||||
if Config.get(Config.notify_IfPushPlyer):
|
||||
|
||||
logger.info(f"推送系统通知:{title}", module="通知服务")
|
||||
|
||||
notification.notify(
|
||||
title=title,
|
||||
message=message,
|
||||
@@ -69,7 +80,15 @@ class Notification(QObject):
|
||||
return True
|
||||
|
||||
def send_mail(self, mode, title, content, to_address) -> None:
|
||||
"""推送邮件通知"""
|
||||
"""
|
||||
推送邮件通知
|
||||
|
||||
:param mode: 邮件内容模式,支持 "文本" 和 "网页"
|
||||
:param title: 邮件标题
|
||||
:param content: 邮件内容
|
||||
:param to_address: 收件人地址
|
||||
"""
|
||||
|
||||
if (
|
||||
Config.get(Config.notify_SMTPServerAddress) == ""
|
||||
or Config.get(Config.notify_AuthorizationCode) == ""
|
||||
@@ -87,7 +106,8 @@ class Notification(QObject):
|
||||
)
|
||||
):
|
||||
logger.error(
|
||||
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址"
|
||||
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址",
|
||||
module="通知服务",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
@@ -110,42 +130,43 @@ class Notification(QObject):
|
||||
)
|
||||
) # 发件人显示的名字
|
||||
message["To"] = formataddr(
|
||||
(
|
||||
Header("AUTO_MAA用户", "utf-8").encode(),
|
||||
to_address,
|
||||
)
|
||||
(Header("AUTO_MAA用户", "utf-8").encode(), to_address)
|
||||
) # 收件人显示的名字
|
||||
message["Subject"] = Header(title, "utf-8")
|
||||
|
||||
if mode == "网页":
|
||||
message.attach(MIMEText(content, "html", "utf-8"))
|
||||
|
||||
smtpObj = smtplib.SMTP_SSL(
|
||||
Config.get(Config.notify_SMTPServerAddress),
|
||||
465,
|
||||
)
|
||||
smtpObj = smtplib.SMTP_SSL(Config.get(Config.notify_SMTPServerAddress), 465)
|
||||
smtpObj.login(
|
||||
Config.get(Config.notify_FromAddress),
|
||||
Crypto.win_decryptor(Config.get(Config.notify_AuthorizationCode)),
|
||||
)
|
||||
smtpObj.sendmail(
|
||||
Config.get(Config.notify_FromAddress),
|
||||
to_address,
|
||||
message.as_string(),
|
||||
Config.get(Config.notify_FromAddress), to_address, message.as_string()
|
||||
)
|
||||
smtpObj.quit()
|
||||
logger.success("邮件发送成功")
|
||||
return None
|
||||
logger.success(f"邮件发送成功:{title}", module="通知服务")
|
||||
except Exception as e:
|
||||
logger.error(f"发送邮件时出错:\n{e}")
|
||||
logger.exception(f"发送邮件时出错:{e}", module="通知服务")
|
||||
self.push_info_bar.emit("error", "发送邮件时出错", f"{e}", -1)
|
||||
return None
|
||||
return None
|
||||
|
||||
def ServerChanPush(self, title, content, send_key, tag, channel):
|
||||
"""使用Server酱推送通知"""
|
||||
def ServerChanPush(
|
||||
self, title, content, send_key, tag, channel
|
||||
) -> Union[bool, str]:
|
||||
"""
|
||||
使用Server酱推送通知
|
||||
|
||||
:param title: 通知标题
|
||||
:param content: 通知内容
|
||||
:param send_key: Server酱的SendKey
|
||||
:param tag: 通知标签
|
||||
:param channel: 通知频道
|
||||
:return: bool or str
|
||||
"""
|
||||
|
||||
if not send_key:
|
||||
logger.error("请正确设置Server酱的SendKey")
|
||||
logger.error("请正确设置Server酱的SendKey", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error", "Server酱通知推送异常", "请正确设置Server酱的SendKey", -1
|
||||
)
|
||||
@@ -176,7 +197,7 @@ class Notification(QObject):
|
||||
if is_valid(tags):
|
||||
options["tags"] = tags
|
||||
else:
|
||||
logger.warning("Server酱 Tag 配置不正确,将被忽略")
|
||||
logger.warning("Server酱 Tag 配置不正确,将被忽略", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"warning",
|
||||
"Server酱通知推送异常",
|
||||
@@ -187,7 +208,9 @@ class Notification(QObject):
|
||||
if is_valid(channels):
|
||||
options["channel"] = channels
|
||||
else:
|
||||
logger.warning("Server酱 Channel 配置不正确,将被忽略")
|
||||
logger.warning(
|
||||
"Server酱 Channel 配置不正确,将被忽略", module="通知服务"
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"warning",
|
||||
"Server酱通知推送异常",
|
||||
@@ -212,18 +235,20 @@ class Notification(QObject):
|
||||
result = response.json()
|
||||
|
||||
if result.get("code") == 0:
|
||||
logger.info("Server酱推送通知成功")
|
||||
logger.success(f"Server酱推送通知成功:{title}", module="通知服务")
|
||||
return True
|
||||
else:
|
||||
error_code = result.get("code", "-1")
|
||||
logger.error(f"Server酱通知推送失败:响应码:{error_code}")
|
||||
logger.exception(
|
||||
f"Server酱通知推送失败:响应码:{error_code}", module="通知服务"
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error", "Server酱通知推送失败", f"响应码:{error_code}", -1
|
||||
)
|
||||
return f"Server酱通知推送失败:{error_code}"
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("Server酱通知推送异常")
|
||||
logger.exception(f"Server酱通知推送异常:{e}", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"Server酱通知推送异常",
|
||||
@@ -232,10 +257,18 @@ class Notification(QObject):
|
||||
)
|
||||
return f"Server酱通知推送异常:{str(e)}"
|
||||
|
||||
def CompanyWebHookBotPush(self, title, content, webhook_url):
|
||||
"""使用企业微信群机器人推送通知"""
|
||||
def CompanyWebHookBotPush(self, title, content, webhook_url) -> Union[bool, str]:
|
||||
"""
|
||||
使用企业微信群机器人推送通知
|
||||
|
||||
:param title: 通知标题
|
||||
:param content: 通知内容
|
||||
:param webhook_url: 企业微信群机器人的WebHook地址
|
||||
:return: bool or str
|
||||
"""
|
||||
|
||||
if webhook_url == "":
|
||||
logger.error("请正确设置企业微信群机器人的WebHook地址")
|
||||
logger.error("请正确设置企业微信群机器人的WebHook地址", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人通知推送异常",
|
||||
@@ -264,7 +297,7 @@ class Notification(QObject):
|
||||
err = e
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
logger.error(f"推送企业微信群机器人时出错:{err}")
|
||||
logger.error(f"推送企业微信群机器人时出错:{err}", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人通知推送失败",
|
||||
@@ -274,10 +307,10 @@ class Notification(QObject):
|
||||
return None
|
||||
|
||||
if info["errcode"] == 0:
|
||||
logger.info("企业微信群机器人推送通知成功")
|
||||
logger.success(f"企业微信群机器人推送通知成功:{title}", module="通知服务")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"企业微信群机器人推送通知失败:{info}")
|
||||
logger.error(f"企业微信群机器人推送通知失败:{info}", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人通知推送失败",
|
||||
@@ -287,7 +320,14 @@ class Notification(QObject):
|
||||
return f"使用企业微信群机器人推送通知时出错:{err}"
|
||||
|
||||
def CompanyWebHookBotPushImage(self, image_path: Path, webhook_url: str) -> bool:
|
||||
"""使用企业微信群机器人推送图片通知"""
|
||||
"""
|
||||
使用企业微信群机器人推送图片通知
|
||||
|
||||
:param image_path: 图片文件路径
|
||||
:param webhook_url: 企业微信群机器人的WebHook地址
|
||||
:return: bool
|
||||
"""
|
||||
|
||||
try:
|
||||
# 压缩图片
|
||||
ImageUtils.compress_image_if_needed(image_path)
|
||||
@@ -295,7 +335,8 @@ class Notification(QObject):
|
||||
# 检查图片是否存在
|
||||
if not image_path.exists():
|
||||
logger.error(
|
||||
"图片推送异常 | 图片不存在或者压缩失败,请检查图片路径是否正确"
|
||||
"图片推送异常 | 图片不存在或者压缩失败,请检查图片路径是否正确",
|
||||
module="通知服务",
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
@@ -306,7 +347,9 @@ class Notification(QObject):
|
||||
return False
|
||||
|
||||
if not webhook_url:
|
||||
logger.error("请正确设置企业微信群机器人的WebHook地址")
|
||||
logger.error(
|
||||
"请正确设置企业微信群机器人的WebHook地址", module="通知服务"
|
||||
)
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人通知推送异常",
|
||||
@@ -320,7 +363,7 @@ class Notification(QObject):
|
||||
image_base64 = ImageUtils.get_base64_from_file(str(image_path))
|
||||
image_md5 = ImageUtils.calculate_md5_from_file(str(image_path))
|
||||
except Exception as e:
|
||||
logger.exception(f"图片编码或MD5计算失败:{e}")
|
||||
logger.exception(f"图片编码或MD5计算失败:{e}", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人通知推送异常",
|
||||
@@ -349,10 +392,12 @@ class Notification(QObject):
|
||||
break
|
||||
except requests.RequestException as e:
|
||||
err = e
|
||||
logger.warning(f"推送企业微信群机器人图片第{_+1}次失败:{e}")
|
||||
logger.exception(
|
||||
f"推送企业微信群机器人图片第{_+1}次失败:{e}", module="通知服务"
|
||||
)
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
logger.error(f"推送企业微信群机器人图片时出错:{err}")
|
||||
logger.error("推送企业微信群机器人图片时出错", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人图片推送失败",
|
||||
@@ -362,10 +407,13 @@ class Notification(QObject):
|
||||
return False
|
||||
|
||||
if info.get("errcode") == 0:
|
||||
logger.info("企业微信群机器人推送图片成功")
|
||||
logger.success(
|
||||
f"企业微信群机器人推送图片成功:{image_path.name}",
|
||||
module="通知服务",
|
||||
)
|
||||
return True
|
||||
else:
|
||||
logger.error(f"企业微信群机器人推送图片失败:{info}")
|
||||
logger.error(f"企业微信群机器人推送图片失败:{info}", module="通知服务")
|
||||
self.push_info_bar.emit(
|
||||
"error",
|
||||
"企业微信群机器人图片推送失败",
|
||||
@@ -386,6 +434,9 @@ class Notification(QObject):
|
||||
|
||||
def send_test_notification(self):
|
||||
"""发送测试通知到所有已启用的通知渠道"""
|
||||
|
||||
logger.info("发送测试通知到所有已启用的通知渠道", module="通知服务")
|
||||
|
||||
# 发送系统通知
|
||||
self.push_plyer(
|
||||
"测试通知",
|
||||
@@ -425,6 +476,8 @@ class Notification(QObject):
|
||||
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||
)
|
||||
|
||||
logger.info("测试通知发送完成", module="通知服务")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -25,18 +25,15 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
import hashlib
|
||||
import random
|
||||
import secrets
|
||||
import base64
|
||||
import win32crypt
|
||||
from pathlib import Path
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_OAEP
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from typing import List, Dict, Union
|
||||
|
||||
from app.core import Config
|
||||
|
||||
@@ -44,7 +41,12 @@ from app.core import Config
|
||||
class CryptoHandler:
|
||||
|
||||
def get_PASSWORD(self, PASSWORD: str) -> None:
|
||||
"""配置管理密钥"""
|
||||
"""
|
||||
配置管理密钥
|
||||
|
||||
:param PASSWORD: 管理密钥
|
||||
:type PASSWORD: str
|
||||
"""
|
||||
|
||||
# 生成目录
|
||||
Config.key_path.mkdir(parents=True, exist_ok=True)
|
||||
@@ -85,7 +87,12 @@ class CryptoHandler:
|
||||
(Config.app_path / "data/key/private_key.bin").write_bytes(private_key_local)
|
||||
|
||||
def AUTO_encryptor(self, note: str) -> str:
|
||||
"""使用AUTO_MAA的算法加密数据"""
|
||||
"""
|
||||
使用AUTO_MAA的算法加密数据
|
||||
|
||||
:param note: 数据明文
|
||||
:type note: str
|
||||
"""
|
||||
|
||||
if note == "":
|
||||
return ""
|
||||
@@ -100,7 +107,16 @@ class CryptoHandler:
|
||||
return base64.b64encode(encrypted).decode("utf-8")
|
||||
|
||||
def AUTO_decryptor(self, note: str, PASSWORD: str) -> str:
|
||||
"""使用AUTO_MAA的算法解密数据"""
|
||||
"""
|
||||
使用AUTO_MAA的算法解密数据
|
||||
|
||||
:param note: 数据密文
|
||||
:type note: str
|
||||
:param PASSWORD: 管理密钥
|
||||
:type PASSWORD: str
|
||||
:return: 解密后的明文
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
if note == "":
|
||||
return ""
|
||||
@@ -142,7 +158,14 @@ class CryptoHandler:
|
||||
return note
|
||||
|
||||
def change_PASSWORD(self, PASSWORD_old: str, PASSWORD_new: str) -> None:
|
||||
"""修改管理密钥"""
|
||||
"""
|
||||
修改管理密钥
|
||||
|
||||
:param PASSWORD_old: 旧管理密钥
|
||||
:type PASSWORD_old: str
|
||||
:param PASSWORD_new: 新管理密钥
|
||||
:type PASSWORD_new: str
|
||||
"""
|
||||
|
||||
for member in Config.member_dict.values():
|
||||
|
||||
@@ -168,7 +191,12 @@ class CryptoHandler:
|
||||
del user["Password"]
|
||||
|
||||
def reset_PASSWORD(self, PASSWORD_new: str) -> None:
|
||||
"""重置管理密钥"""
|
||||
"""
|
||||
重置管理密钥
|
||||
|
||||
:param PASSWORD_new: 新管理密钥
|
||||
:type PASSWORD_new: str
|
||||
"""
|
||||
|
||||
self.get_PASSWORD(PASSWORD_new)
|
||||
|
||||
@@ -176,12 +204,25 @@ class CryptoHandler:
|
||||
|
||||
if member["Type"] == "Maa":
|
||||
for user in member["UserData"].values():
|
||||
user["Config"].set(user["Config"].Info_Password, "")
|
||||
user["Config"].set(
|
||||
user["Config"].Info_Password, self.AUTO_encryptor("数据已重置")
|
||||
)
|
||||
|
||||
def win_encryptor(
|
||||
self, note: str, description: str = None, entropy: bytes = None
|
||||
) -> str:
|
||||
"""使用Windows DPAPI加密数据"""
|
||||
"""
|
||||
使用Windows DPAPI加密数据
|
||||
|
||||
:param note: 数据明文
|
||||
:type note: str
|
||||
:param description: 描述信息
|
||||
:type description: str
|
||||
:param entropy: 随机熵
|
||||
:type entropy: bytes
|
||||
:return: 加密后的数据
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
if note == "":
|
||||
return ""
|
||||
@@ -192,7 +233,16 @@ class CryptoHandler:
|
||||
return base64.b64encode(encrypted).decode("utf-8")
|
||||
|
||||
def win_decryptor(self, note: str, entropy: bytes = None) -> str:
|
||||
"""使用Windows DPAPI解密数据"""
|
||||
"""
|
||||
使用Windows DPAPI解密数据
|
||||
|
||||
:param note: 数据密文
|
||||
:type note: str
|
||||
:param entropy: 随机熵
|
||||
:type entropy: bytes
|
||||
:return: 解密后的明文
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
if note == "":
|
||||
return ""
|
||||
@@ -202,21 +252,15 @@ class CryptoHandler:
|
||||
)
|
||||
return decrypted[1].decode("utf-8")
|
||||
|
||||
def search_member(self) -> List[Dict[str, Union[Path, list]]]:
|
||||
"""搜索所有脚本实例及其用户数据库路径"""
|
||||
|
||||
member_list = []
|
||||
|
||||
if (Config.app_path / "config/MaaConfig").exists():
|
||||
for subdir in (Config.app_path / "config/MaaConfig").iterdir():
|
||||
if subdir.is_dir():
|
||||
|
||||
member_list.append({"Path": subdir / "user_data.db"})
|
||||
|
||||
return member_list
|
||||
|
||||
def check_PASSWORD(self, PASSWORD: str) -> bool:
|
||||
"""验证管理密钥"""
|
||||
"""
|
||||
验证管理密钥
|
||||
|
||||
:param PASSWORD: 管理密钥
|
||||
:type PASSWORD: str
|
||||
:return: 是否验证通过
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
return bool(
|
||||
self.AUTO_decryptor(self.AUTO_encryptor("-"), PASSWORD) != "管理密钥错误"
|
||||
|
||||
@@ -32,7 +32,6 @@ v4.4
|
||||
作者:DLmaster_361、ClozyA
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
import time
|
||||
import json
|
||||
import hmac
|
||||
@@ -40,7 +39,7 @@ import hashlib
|
||||
import requests
|
||||
from urllib import parse
|
||||
|
||||
from app.core import Config
|
||||
from app.core import Config, logger
|
||||
|
||||
|
||||
def skland_sign_in(token) -> dict:
|
||||
@@ -71,15 +70,16 @@ def skland_sign_in(token) -> dict:
|
||||
"vName": "1.5.1",
|
||||
}
|
||||
|
||||
# 生成签名
|
||||
def generate_signature(token_for_sign: str, path, body_or_query):
|
||||
"""
|
||||
生成请求签名
|
||||
|
||||
:param token_for_sign: 用于加密的token
|
||||
:param path: 请求路径(如 /api/v1/game/player/binding)
|
||||
:param body_or_query: GET用query字符串,POST用body字符串
|
||||
:return: (sign, 新的header_for_sign字典)
|
||||
"""
|
||||
|
||||
t = str(int(time.time()) - 2) # 时间戳,-2秒以防服务器时间不一致
|
||||
token_bytes = token_for_sign.encode("utf-8")
|
||||
header_ca = dict(header_for_sign)
|
||||
@@ -91,10 +91,10 @@ def skland_sign_in(token) -> dict:
|
||||
md5 = hashlib.md5(hex_s.encode("utf-8")).hexdigest()
|
||||
return md5, header_ca
|
||||
|
||||
# 获取带签名的header
|
||||
def get_sign_header(url: str, method, body, old_header, sign_token):
|
||||
"""
|
||||
获取带签名的请求头
|
||||
|
||||
:param url: 请求完整url
|
||||
:param method: 请求方式 GET/POST
|
||||
:param body: POST请求体或GET时为None
|
||||
@@ -102,6 +102,7 @@ def skland_sign_in(token) -> dict:
|
||||
:param sign_token: 当前会话的签名token
|
||||
:return: 新请求头
|
||||
"""
|
||||
|
||||
h = json.loads(json.dumps(old_header))
|
||||
p = parse.urlparse(url)
|
||||
if method.lower() == "get":
|
||||
@@ -115,15 +116,21 @@ def skland_sign_in(token) -> dict:
|
||||
h[i] = header_ca[i]
|
||||
return h
|
||||
|
||||
# 复制请求头并添加cred
|
||||
def copy_header(cred):
|
||||
"""
|
||||
复制请求头并添加cred
|
||||
|
||||
:param cred: 当前会话的cred
|
||||
:return: 新的请求头
|
||||
"""
|
||||
v = json.loads(json.dumps(header))
|
||||
v["cred"] = cred
|
||||
return v
|
||||
|
||||
# 使用token一步步拿到cred和sign_token
|
||||
def login_by_token(token_code):
|
||||
"""
|
||||
使用token一步步拿到cred和sign_token
|
||||
|
||||
:param token_code: 你的skyland token
|
||||
:return: (cred, sign_token)
|
||||
"""
|
||||
@@ -136,8 +143,14 @@ def skland_sign_in(token) -> dict:
|
||||
grant_code = get_grant_code(token_code)
|
||||
return get_cred(grant_code)
|
||||
|
||||
# 通过grant code换cred和sign_token
|
||||
def get_cred(grant):
|
||||
"""
|
||||
通过grant code获取cred和sign_token
|
||||
|
||||
:param grant: grant code
|
||||
:return: (cred, sign_token)
|
||||
"""
|
||||
|
||||
rsp = requests.post(
|
||||
cred_code_url,
|
||||
json={"code": grant, "kind": 1},
|
||||
@@ -153,8 +166,13 @@ def skland_sign_in(token) -> dict:
|
||||
cred = rsp["data"]["cred"]
|
||||
return cred, sign_token
|
||||
|
||||
# 通过token换grant code
|
||||
def get_grant_code(token):
|
||||
"""
|
||||
通过token获取grant code
|
||||
|
||||
:param token: 你的skyland token
|
||||
:return: grant code
|
||||
"""
|
||||
rsp = requests.post(
|
||||
grant_code_url,
|
||||
json={"appCode": app_code, "token": token, "type": 0},
|
||||
@@ -170,10 +188,10 @@ def skland_sign_in(token) -> dict:
|
||||
)
|
||||
return rsp["data"]["code"]
|
||||
|
||||
# 获取已绑定的角色列表
|
||||
def get_binding_list(cred, sign_token):
|
||||
"""
|
||||
查询绑定的角色
|
||||
查询已绑定的角色列表
|
||||
|
||||
:param cred: 当前cred
|
||||
:param sign_token: 当前sign_token
|
||||
:return: 角色列表
|
||||
@@ -190,9 +208,15 @@ def skland_sign_in(token) -> dict:
|
||||
},
|
||||
).json()
|
||||
if rsp["code"] != 0:
|
||||
logger.error(f"森空岛服务 | 请求角色列表出现问题:{rsp['message']}")
|
||||
logger.error(
|
||||
f"森空岛服务 | 请求角色列表出现问题:{rsp['message']}",
|
||||
module="森空岛签到",
|
||||
)
|
||||
if rsp.get("message") == "用户未登录":
|
||||
logger.error(f"森空岛服务 | 用户登录可能失效了,请重新登录!")
|
||||
logger.error(
|
||||
f"森空岛服务 | 用户登录可能失效了,请重新登录!",
|
||||
module="森空岛签到",
|
||||
)
|
||||
return v
|
||||
# 只取明日方舟(arknights)的绑定账号
|
||||
for i in rsp["data"]["list"]:
|
||||
@@ -201,10 +225,10 @@ def skland_sign_in(token) -> dict:
|
||||
v.extend(i.get("bindingList"))
|
||||
return v
|
||||
|
||||
# 执行签到
|
||||
def do_sign(cred, sign_token) -> dict:
|
||||
"""
|
||||
对所有绑定的角色进行签到
|
||||
|
||||
:param cred: 当前cred
|
||||
:param sign_token: 当前sign_token
|
||||
:return: 签到结果字典
|
||||
@@ -257,5 +281,5 @@ def skland_sign_in(token) -> dict:
|
||||
# 依次签到
|
||||
return do_sign(cred, sign_token)
|
||||
except Exception as e:
|
||||
logger.error(f"森空岛服务 | 森空岛签到失败: {e}")
|
||||
logger.exception(f"森空岛服务 | 森空岛签到失败: {e}", module="森空岛签到")
|
||||
return {"成功": [], "重复": [], "失败": [], "总计": 0}
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import QApplication
|
||||
import sys
|
||||
import ctypes
|
||||
@@ -38,7 +37,7 @@ import getpass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from app.core import Config
|
||||
from app.core import Config, logger
|
||||
|
||||
|
||||
class _SystemHandler:
|
||||
@@ -147,9 +146,15 @@ class _SystemHandler:
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info(f"任务计划程序自启动已创建: {Config.app_path_sys}")
|
||||
logger.success(
|
||||
f"程序自启动任务计划已创建: {Config.app_path_sys}",
|
||||
module="系统服务",
|
||||
)
|
||||
else:
|
||||
logger.error(f"创建任务计划失败: {result.stderr}")
|
||||
logger.error(
|
||||
f"程序自启动任务计划创建失败: {result.stderr}",
|
||||
module="系统服务",
|
||||
)
|
||||
|
||||
finally:
|
||||
# 删除临时文件
|
||||
@@ -159,7 +164,7 @@ class _SystemHandler:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"设置任务计划程序自启动失败: {e}")
|
||||
logger.exception(f"程序自启动任务计划创建失败: {e}", module="系统服务")
|
||||
|
||||
elif not Config.get(Config.start_IfSelfStart) and self.is_startup():
|
||||
|
||||
@@ -174,40 +179,49 @@ class _SystemHandler:
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info("任务计划程序自启动已删除")
|
||||
logger.success("程序自启动任务计划已删除", module="系统服务")
|
||||
else:
|
||||
logger.error(f"删除任务计划失败: {result.stderr}")
|
||||
logger.error(
|
||||
f"程序自启动任务计划删除失败: {result.stderr}",
|
||||
module="系统服务",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"删除任务计划程序自启动失败: {e}")
|
||||
logger.exception(f"程序自启动任务计划删除失败: {e}", module="系统服务")
|
||||
|
||||
def set_power(self, mode) -> None:
|
||||
"""
|
||||
执行系统电源操作
|
||||
|
||||
:param mode: 电源操作模式,支持 "NoAction", "Shutdown", "Hibernate", "Sleep", "KillSelf"
|
||||
"""
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
|
||||
if mode == "NoAction":
|
||||
|
||||
logger.info("不执行系统电源操作")
|
||||
logger.info("不执行系统电源操作", module="系统服务")
|
||||
|
||||
elif mode == "Shutdown":
|
||||
|
||||
logger.info("执行关机操作")
|
||||
logger.info("执行关机操作", module="系统服务")
|
||||
subprocess.run(["shutdown", "/s", "/t", "0"])
|
||||
|
||||
elif mode == "Hibernate":
|
||||
|
||||
logger.info("执行休眠操作")
|
||||
logger.info("执行休眠操作", module="系统服务")
|
||||
subprocess.run(["shutdown", "/h"])
|
||||
|
||||
elif mode == "Sleep":
|
||||
|
||||
logger.info("执行睡眠操作")
|
||||
logger.info("执行睡眠操作", module="系统服务")
|
||||
subprocess.run(
|
||||
["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"]
|
||||
)
|
||||
|
||||
elif mode == "KillSelf":
|
||||
|
||||
logger.info("执行退出主程序操作", module="系统服务")
|
||||
Config.main_window.close()
|
||||
QApplication.quit()
|
||||
sys.exit(0)
|
||||
@@ -216,25 +230,26 @@ class _SystemHandler:
|
||||
|
||||
if mode == "NoAction":
|
||||
|
||||
logger.info("不执行系统电源操作")
|
||||
logger.info("不执行系统电源操作", module="系统服务")
|
||||
|
||||
elif mode == "Shutdown":
|
||||
|
||||
logger.info("执行关机操作")
|
||||
logger.info("执行关机操作", module="系统服务")
|
||||
subprocess.run(["shutdown", "-h", "now"])
|
||||
|
||||
elif mode == "Hibernate":
|
||||
|
||||
logger.info("执行休眠操作")
|
||||
logger.info("执行休眠操作", module="系统服务")
|
||||
subprocess.run(["systemctl", "hibernate"])
|
||||
|
||||
elif mode == "Sleep":
|
||||
|
||||
logger.info("执行睡眠操作")
|
||||
logger.info("执行睡眠操作", module="系统服务")
|
||||
subprocess.run(["systemctl", "suspend"])
|
||||
|
||||
elif mode == "KillSelf":
|
||||
|
||||
logger.info("执行退出主程序操作", module="系统服务")
|
||||
Config.main_window.close()
|
||||
QApplication.quit()
|
||||
sys.exit(0)
|
||||
@@ -252,11 +267,11 @@ class _SystemHandler:
|
||||
)
|
||||
return result.returncode == 0
|
||||
except Exception as e:
|
||||
logger.error(f"检查任务计划程序失败: {e}")
|
||||
logger.exception(f"检查任务计划程序失败: {e}", module="系统服务")
|
||||
return False
|
||||
|
||||
def get_window_info(self) -> list:
|
||||
"""获取当前窗口信息"""
|
||||
"""获取当前前台窗口信息"""
|
||||
|
||||
def callback(hwnd, window_info):
|
||||
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd):
|
||||
@@ -270,7 +285,13 @@ class _SystemHandler:
|
||||
return window_info
|
||||
|
||||
def kill_process(self, path: Path) -> None:
|
||||
"""根据路径中止进程"""
|
||||
"""
|
||||
根据路径中止进程
|
||||
|
||||
:param path: 进程路径
|
||||
"""
|
||||
|
||||
logger.info(f"开始中止进程: {path}", module="系统服务")
|
||||
|
||||
for pid in self.search_pids(path):
|
||||
killprocess = subprocess.Popen(
|
||||
@@ -280,8 +301,17 @@ class _SystemHandler:
|
||||
)
|
||||
killprocess.wait()
|
||||
|
||||
logger.success(f"进程已中止: {path}", module="系统服务")
|
||||
|
||||
def search_pids(self, path: Path) -> list:
|
||||
"""根据路径查找进程PID"""
|
||||
"""
|
||||
根据路径查找进程PID
|
||||
|
||||
:param path: 进程路径
|
||||
:return: 匹配的进程PID列表
|
||||
"""
|
||||
|
||||
logger.info(f"开始查找进程 PID: {path}", module="系统服务")
|
||||
|
||||
pids = []
|
||||
for proc in psutil.process_iter(["pid", "exe"]):
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
@@ -48,7 +47,7 @@ from PySide6.QtGui import QTextCursor
|
||||
from typing import List, Dict
|
||||
|
||||
|
||||
from app.core import Config, TaskManager, Task, MainInfoBar, SoundPlayer
|
||||
from app.core import Config, TaskManager, Task, MainInfoBar, logger
|
||||
from .Widget import StatefulItemCard, ComboBoxMessageBox, PivotArea
|
||||
|
||||
|
||||
@@ -59,10 +58,12 @@ class DispatchCenter(QWidget):
|
||||
|
||||
self.setObjectName("调度中枢")
|
||||
|
||||
# 添加任务按钮
|
||||
self.multi_button = PushButton(FluentIcon.ADD, "添加任务", self)
|
||||
self.multi_button.setToolTip("添加任务")
|
||||
self.multi_button.clicked.connect(self.start_multi_task)
|
||||
|
||||
# 电源动作设置组件
|
||||
self.power_combox = ComboBox()
|
||||
self.power_combox.addItem("无动作", userData="NoAction")
|
||||
self.power_combox.addItem("退出软件", userData="KillSelf")
|
||||
@@ -72,15 +73,18 @@ class DispatchCenter(QWidget):
|
||||
self.power_combox.setCurrentText("无动作")
|
||||
self.power_combox.currentIndexChanged.connect(self.set_power_sign)
|
||||
|
||||
# 导航栏
|
||||
self.pivotArea = PivotArea(self)
|
||||
self.pivot = self.pivotArea.pivot
|
||||
|
||||
# 导航页面组
|
||||
self.stackedWidget = QStackedWidget(self)
|
||||
self.stackedWidget.setContentsMargins(0, 0, 0, 0)
|
||||
self.stackedWidget.setStyleSheet("background: transparent; border: none;")
|
||||
|
||||
self.script_list: Dict[str, DispatchCenter.DispatchBox] = {}
|
||||
|
||||
# 添加主调度台
|
||||
dispatch_box = self.DispatchBox("主调度台", self)
|
||||
self.script_list["主调度台"] = dispatch_box
|
||||
self.stackedWidget.addWidget(self.script_list["主调度台"])
|
||||
@@ -91,6 +95,7 @@ class DispatchCenter(QWidget):
|
||||
icon=FluentIcon.CAFE,
|
||||
)
|
||||
|
||||
# 顶栏组合
|
||||
h_layout = QHBoxLayout()
|
||||
h_layout.addWidget(self.multi_button)
|
||||
h_layout.addWidget(self.pivotArea)
|
||||
@@ -108,7 +113,13 @@ class DispatchCenter(QWidget):
|
||||
)
|
||||
|
||||
def add_board(self, task: Task) -> None:
|
||||
"""添加一个调度台界面"""
|
||||
"""
|
||||
为任务添加一个调度台界面并绑定信号
|
||||
|
||||
:param task: 任务对象
|
||||
"""
|
||||
|
||||
logger.info(f"添加调度台:{task.name}", module="调度中枢")
|
||||
|
||||
dispatch_box = self.DispatchBox(task.name, self)
|
||||
|
||||
@@ -129,19 +140,36 @@ class DispatchCenter(QWidget):
|
||||
|
||||
self.pivot.addItem(routeKey=f"调度台_{task.name}", text=f"调度台 {task.name}")
|
||||
|
||||
logger.success(f"调度台 {task.name} 添加成功", module="调度中枢")
|
||||
|
||||
def del_board(self, name: str) -> None:
|
||||
"""删除指定子界面"""
|
||||
"""
|
||||
删除指定子界面
|
||||
|
||||
:param name: 子界面名称
|
||||
"""
|
||||
|
||||
logger.info(f"删除调度台:{name}", module="调度中枢")
|
||||
|
||||
self.pivot.setCurrentItem("主调度台")
|
||||
self.stackedWidget.removeWidget(self.script_list[name])
|
||||
self.script_list[name].deleteLater()
|
||||
self.script_list.pop(name)
|
||||
self.pivot.removeWidget(name)
|
||||
|
||||
logger.success(f"调度台 {name} 删除成功", module="调度中枢")
|
||||
|
||||
def connect_main_board(self, task: Task) -> None:
|
||||
"""连接主调度台"""
|
||||
"""
|
||||
将任务连接到主调度台
|
||||
|
||||
:param task: 任务对象
|
||||
"""
|
||||
|
||||
logger.info(f"主调度台载入任务:{task.name}", module="调度中枢")
|
||||
|
||||
self.script_list["主调度台"].top_bar.Lable.setText(
|
||||
f"{task.name} - {task.mode.replace("_主调度台","")}模式"
|
||||
f"{task.name} - {task.mode.replace('_主调度台','')}模式"
|
||||
)
|
||||
self.script_list["主调度台"].top_bar.Lable.show()
|
||||
self.script_list["主调度台"].top_bar.object.hide()
|
||||
@@ -170,8 +198,17 @@ class DispatchCenter(QWidget):
|
||||
lambda logs: self.disconnect_main_board(task.name, logs)
|
||||
)
|
||||
|
||||
logger.success(f"主调度台成功载入:{task.name} ", module="调度中枢")
|
||||
|
||||
def disconnect_main_board(self, name: str, logs: list) -> None:
|
||||
"""断开主调度台"""
|
||||
"""
|
||||
断开主调度台
|
||||
|
||||
:param name: 任务名称
|
||||
:param logs: 任务日志列表
|
||||
"""
|
||||
|
||||
logger.info(f"主调度台断开任务:{name}", module="调度中枢")
|
||||
|
||||
self.script_list["主调度台"].top_bar.Lable.hide()
|
||||
self.script_list["主调度台"].top_bar.object.show()
|
||||
@@ -191,6 +228,8 @@ class DispatchCenter(QWidget):
|
||||
else:
|
||||
self.script_list["主调度台"].info.log_text.text.setText("没有任务被执行")
|
||||
|
||||
logger.success(f"主调度台成功断开:{name}", module="调度中枢")
|
||||
|
||||
def update_top_bar(self):
|
||||
"""更新顶栏"""
|
||||
|
||||
@@ -253,10 +292,7 @@ class DispatchCenter(QWidget):
|
||||
self.power_combox.currentIndexChanged.connect(self.set_power_sign)
|
||||
logger.warning("没有正在运行的任务,无法设置任务完成后动作")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"没有正在运行的任务",
|
||||
"无法设置任务完成后动作",
|
||||
5000,
|
||||
"warning", "没有正在运行的任务", "无法设置任务完成后动作", 5000
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -264,7 +300,7 @@ class DispatchCenter(QWidget):
|
||||
Config.set_power_sign(self.power_combox.currentData())
|
||||
|
||||
def start_multi_task(self) -> None:
|
||||
"""开始任务"""
|
||||
"""开始多开任务"""
|
||||
|
||||
# 获取所有可用的队列和实例
|
||||
text_list = []
|
||||
@@ -300,7 +336,9 @@ class DispatchCenter(QWidget):
|
||||
if choice.exec() and choice.input[0].currentIndex() != -1:
|
||||
|
||||
if choice.input[0].currentData() in Config.running_list:
|
||||
logger.warning(f"任务已存在:{choice.input[0].currentData()}")
|
||||
logger.warning(
|
||||
f"任务已存在:{choice.input[0].currentData()}", module="调度中枢"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "任务已存在", choice.input[0].currentData(), 5000
|
||||
)
|
||||
@@ -308,7 +346,9 @@ class DispatchCenter(QWidget):
|
||||
|
||||
if "调度队列" in choice.input[0].currentData():
|
||||
|
||||
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
||||
logger.info(
|
||||
f"用户添加任务:{choice.input[0].currentData()}", module="调度中枢"
|
||||
)
|
||||
TaskManager.add_task(
|
||||
"自动代理_新调度台",
|
||||
choice.input[0].currentData(),
|
||||
@@ -317,7 +357,9 @@ class DispatchCenter(QWidget):
|
||||
|
||||
elif "脚本" in choice.input[0].currentData():
|
||||
|
||||
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
||||
logger.info(
|
||||
f"用户添加任务:{choice.input[0].currentData()}", module="调度中枢"
|
||||
)
|
||||
TaskManager.add_task(
|
||||
"自动代理_新调度台",
|
||||
f"自定义队列 - {choice.input[0].currentData()}",
|
||||
@@ -384,24 +426,26 @@ class DispatchCenter(QWidget):
|
||||
Layout.addWidget(self.main_button)
|
||||
|
||||
def start_main_task(self):
|
||||
"""开始任务"""
|
||||
"""从主调度台开始任务"""
|
||||
|
||||
if self.object.currentIndex() == -1:
|
||||
logger.warning("未选择调度对象")
|
||||
logger.warning("未选择调度对象", module="调度中枢")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择调度对象", "请选择后再开始任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.mode.currentIndex() == -1:
|
||||
logger.warning("未选择调度模式")
|
||||
logger.warning("未选择调度模式", module="调度中枢")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择调度模式", "请选择后再开始任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.object.currentData() in Config.running_list:
|
||||
logger.warning(f"任务已存在:{self.object.currentData()}")
|
||||
logger.warning(
|
||||
f"任务已存在:{self.object.currentData()}", module="调度中枢"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "任务已存在", self.object.currentData(), 5000
|
||||
)
|
||||
@@ -413,7 +457,7 @@ class DispatchCenter(QWidget):
|
||||
== "General"
|
||||
and self.mode.currentData() == "人工排查"
|
||||
):
|
||||
logger.warning("通用脚本类型不存在人工排查功能")
|
||||
logger.warning("通用脚本类型不存在人工排查功能", module="调度中枢")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "不支持的任务", "通用脚本无人工排查功能", 5000
|
||||
)
|
||||
@@ -421,7 +465,9 @@ class DispatchCenter(QWidget):
|
||||
|
||||
if "调度队列" in self.object.currentData():
|
||||
|
||||
logger.info(f"用户添加任务:{self.object.currentData()}")
|
||||
logger.info(
|
||||
f"用户添加任务:{self.object.currentData()}", module="调度中枢"
|
||||
)
|
||||
TaskManager.add_task(
|
||||
f"{self.mode.currentText()}_主调度台",
|
||||
self.object.currentData(),
|
||||
@@ -430,7 +476,9 @@ class DispatchCenter(QWidget):
|
||||
|
||||
elif "脚本" in self.object.currentData():
|
||||
|
||||
logger.info(f"用户添加任务:{self.object.currentData()}")
|
||||
logger.info(
|
||||
f"用户添加任务:{self.object.currentData()}", module="调度中枢"
|
||||
)
|
||||
TaskManager.add_task(
|
||||
f"{self.mode.currentText()}_主调度台",
|
||||
"自定义队列",
|
||||
@@ -476,7 +524,11 @@ class DispatchCenter(QWidget):
|
||||
self.task_cards: List[StatefulItemCard] = []
|
||||
|
||||
def create_task(self, task_list: list):
|
||||
"""创建任务队列"""
|
||||
"""
|
||||
创建任务队列
|
||||
|
||||
:param task_list: 包含任务信息的任务列表
|
||||
"""
|
||||
|
||||
while self.Layout.count() > 0:
|
||||
item = self.Layout.takeAt(0)
|
||||
@@ -495,7 +547,11 @@ class DispatchCenter(QWidget):
|
||||
self.Layout.addStretch(1)
|
||||
|
||||
def update_task(self, task_list: list):
|
||||
"""更新任务队列"""
|
||||
"""
|
||||
更新任务队列信息
|
||||
|
||||
:param task_list: 包含任务信息的任务列表
|
||||
"""
|
||||
|
||||
for i in range(len(task_list)):
|
||||
|
||||
@@ -514,7 +570,11 @@ class DispatchCenter(QWidget):
|
||||
self.user_cards: List[StatefulItemCard] = []
|
||||
|
||||
def create_user(self, user_list: list):
|
||||
"""创建用户队列"""
|
||||
"""
|
||||
创建用户队列
|
||||
|
||||
:param user_list: 包含用户信息的用户列表
|
||||
"""
|
||||
|
||||
while self.Layout.count() > 0:
|
||||
item = self.Layout.takeAt(0)
|
||||
@@ -533,7 +593,11 @@ class DispatchCenter(QWidget):
|
||||
self.Layout.addStretch(1)
|
||||
|
||||
def update_user(self, user_list: list):
|
||||
"""更新用户队列"""
|
||||
"""
|
||||
更新用户队列信息
|
||||
|
||||
:param user_list: 包含用户信息的用户列表
|
||||
"""
|
||||
|
||||
for i in range(len(user_list)):
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
import zipfile
|
||||
import requests
|
||||
import subprocess
|
||||
@@ -46,7 +45,7 @@ from PySide6.QtCore import QThread, Signal, QTimer, QEventLoop
|
||||
|
||||
from typing import List, Dict, Union
|
||||
|
||||
from app.core import Config
|
||||
from app.core import Config, logger
|
||||
from app.services import System
|
||||
|
||||
|
||||
@@ -83,6 +82,8 @@ class DownloadProcess(QThread):
|
||||
|
||||
self.setObjectName(f"DownloadProcess-{url}-{start_byte}-{end_byte}")
|
||||
|
||||
logger.info(f"创建下载子线程:{self.objectName()}", module="下载子线程")
|
||||
|
||||
self.url = url
|
||||
self.start_byte = start_byte
|
||||
self.end_byte = end_byte
|
||||
@@ -97,7 +98,8 @@ class DownloadProcess(QThread):
|
||||
self.download_path.unlink()
|
||||
|
||||
logger.info(
|
||||
f"开始下载:{self.url},范围:{self.start_byte}-{self.end_byte},存储地址:{self.download_path}"
|
||||
f"开始下载:{self.url},范围:{self.start_byte}-{self.end_byte},存储地址:{self.download_path}",
|
||||
module="下载子线程",
|
||||
)
|
||||
|
||||
headers = (
|
||||
@@ -129,13 +131,17 @@ class DownloadProcess(QThread):
|
||||
self.check_times -= 1
|
||||
|
||||
logger.error(
|
||||
f"连接失败:{self.url},状态码:{response.status_code},剩余重试次数:{self.check_times}"
|
||||
f"连接失败:{self.url},状态码:{response.status_code},剩余重试次数:{self.check_times}",
|
||||
module="下载子线程",
|
||||
)
|
||||
|
||||
time.sleep(1)
|
||||
continue
|
||||
|
||||
logger.info(f"连接成功:{self.url},状态码:{response.status_code}")
|
||||
logger.info(
|
||||
f"连接成功:{self.url},状态码:{response.status_code}",
|
||||
module="下载子线程",
|
||||
)
|
||||
|
||||
downloaded_size = 0
|
||||
with self.download_path.open(mode="wb") as f:
|
||||
@@ -155,13 +161,14 @@ class DownloadProcess(QThread):
|
||||
if self.download_path.exists():
|
||||
self.download_path.unlink()
|
||||
self.accomplish.emit(0)
|
||||
logger.info(f"下载中止:{self.url}")
|
||||
logger.info(f"下载中止:{self.url}", module="下载子线程")
|
||||
|
||||
else:
|
||||
|
||||
self.accomplish.emit(time.time() - start_time)
|
||||
logger.success(
|
||||
f"下载完成:{self.url},实际下载大小:{downloaded_size} 字节,耗时:{time.time() - start_time:.2f} 秒"
|
||||
f"下载完成:{self.url},实际下载大小:{downloaded_size} 字节,耗时:{time.time() - start_time:.2f} 秒",
|
||||
module="下载子线程",
|
||||
)
|
||||
|
||||
break
|
||||
@@ -172,7 +179,8 @@ class DownloadProcess(QThread):
|
||||
self.check_times -= 1
|
||||
|
||||
logger.exception(
|
||||
f"下载出错:{self.url},错误信息:{e},剩余重试次数:{self.check_times}"
|
||||
f"下载出错:{self.url},错误信息:{e},剩余重试次数:{self.check_times}",
|
||||
module="下载子线程",
|
||||
)
|
||||
time.sleep(1)
|
||||
|
||||
@@ -181,7 +189,7 @@ class DownloadProcess(QThread):
|
||||
if self.download_path.exists():
|
||||
self.download_path.unlink()
|
||||
self.accomplish.emit(0)
|
||||
logger.error(f"下载失败:{self.url}")
|
||||
logger.error(f"下载失败:{self.url}", module="下载子线程")
|
||||
|
||||
|
||||
class ZipExtractProcess(QThread):
|
||||
@@ -195,6 +203,8 @@ class ZipExtractProcess(QThread):
|
||||
|
||||
self.setObjectName(f"ZipExtractProcess-{name}")
|
||||
|
||||
logger.info(f"创建解压子线程:{self.objectName()}", module="解压子线程")
|
||||
|
||||
self.name = name
|
||||
self.app_path = app_path
|
||||
self.download_path = download_path
|
||||
@@ -204,7 +214,10 @@ class ZipExtractProcess(QThread):
|
||||
|
||||
try:
|
||||
|
||||
logger.info(f"开始解压:{self.download_path} 到 {self.app_path}")
|
||||
logger.info(
|
||||
f"开始解压:{self.download_path} 到 {self.app_path}",
|
||||
module="解压子线程",
|
||||
)
|
||||
|
||||
while True:
|
||||
|
||||
@@ -215,7 +228,10 @@ class ZipExtractProcess(QThread):
|
||||
with zipfile.ZipFile(self.download_path, "r") as zip_ref:
|
||||
zip_ref.extractall(self.app_path)
|
||||
self.accomplish.emit()
|
||||
logger.success(f"解压完成:{self.download_path} 到 {self.app_path}")
|
||||
logger.success(
|
||||
f"解压完成:{self.download_path} 到 {self.app_path}",
|
||||
module="解压子线程",
|
||||
)
|
||||
break
|
||||
except PermissionError:
|
||||
if self.name == "AUTO_MAA":
|
||||
@@ -223,7 +239,10 @@ class ZipExtractProcess(QThread):
|
||||
System.kill_process(self.app_path / "AUTO_MAA.exe")
|
||||
else:
|
||||
self.info.emit(f"解压出错:{self.name}正在运行,正在等待其关闭")
|
||||
logger.warning(f"解压出错:{self.name}正在运行,正在等待其关闭")
|
||||
logger.warning(
|
||||
f"解压出错:{self.name}正在运行,正在等待其关闭",
|
||||
module="解压子线程",
|
||||
)
|
||||
time.sleep(1)
|
||||
|
||||
except Exception as e:
|
||||
@@ -231,7 +250,7 @@ class ZipExtractProcess(QThread):
|
||||
e = str(e)
|
||||
e = "\n".join([e[_ : _ + 75] for _ in range(0, len(e), 75)])
|
||||
self.info.emit(f"解压更新时出错:\n{e}")
|
||||
logger.exception(f"解压更新时出错:{e}")
|
||||
logger.exception(f"解压更新时出错:{e}", module="解压子线程")
|
||||
return None
|
||||
|
||||
|
||||
@@ -277,17 +296,27 @@ class DownloadManager(QDialog):
|
||||
|
||||
def run(self) -> None:
|
||||
|
||||
logger.info(
|
||||
f"开始执行下载任务:{self.name},版本:{version_text(self.version)}",
|
||||
module="下载管理器",
|
||||
)
|
||||
|
||||
if self.name == "AUTO_MAA":
|
||||
if self.config["mode"] == "Proxy":
|
||||
self.test_speed_task1()
|
||||
self.speed_test_accomplish.connect(self.download_task1)
|
||||
self.start_test_speed()
|
||||
self.speed_test_accomplish.connect(self.start_download)
|
||||
elif self.config["mode"] == "MirrorChyan":
|
||||
self.download_task1()
|
||||
self.start_download()
|
||||
elif self.config["mode"] == "MirrorChyan":
|
||||
self.download_task1()
|
||||
self.start_download()
|
||||
|
||||
def get_download_url(self, mode: str) -> Union[str, Dict[str, str]]:
|
||||
"""获取下载链接"""
|
||||
"""
|
||||
生成下载链接
|
||||
|
||||
:param mode: "测速" 或 "下载"
|
||||
:return: 测速模式返回 url 字典,下载模式返回 url 字符串
|
||||
"""
|
||||
|
||||
url_dict = {}
|
||||
|
||||
@@ -362,7 +391,8 @@ class DownloadManager(QDialog):
|
||||
if response.status_code == 200:
|
||||
return response.url
|
||||
|
||||
def test_speed_task1(self) -> None:
|
||||
def start_test_speed(self) -> None:
|
||||
"""启动测速任务,下载4MB文件以测试下载速度"""
|
||||
|
||||
if self.isInterruptionRequested:
|
||||
return None
|
||||
@@ -370,7 +400,7 @@ class DownloadManager(QDialog):
|
||||
url_dict = self.get_download_url("测速")
|
||||
self.test_speed_result: Dict[str, float] = {}
|
||||
|
||||
logger.info(f"测速链接:{url_dict}")
|
||||
logger.info(f"开始测速任务,链接:{url_dict}", module="下载管理器")
|
||||
|
||||
for name, url in url_dict.items():
|
||||
|
||||
@@ -387,10 +417,11 @@ class DownloadManager(QDialog):
|
||||
)
|
||||
self.test_speed_result[name] = -1
|
||||
self.download_process_dict[name].accomplish.connect(
|
||||
partial(self.test_speed_task2, name)
|
||||
partial(self.check_test_speed, name)
|
||||
)
|
||||
|
||||
self.download_process_dict[name].start()
|
||||
|
||||
# 创建防超时定时器,30秒后强制停止测速
|
||||
timer = QTimer(self)
|
||||
timer.setSingleShot(True)
|
||||
timer.timeout.connect(partial(self.kill_speed_test, name))
|
||||
@@ -401,11 +432,22 @@ class DownloadManager(QDialog):
|
||||
self.update_progress(0, 1, 0)
|
||||
|
||||
def kill_speed_test(self, name: str) -> None:
|
||||
"""
|
||||
强制停止测速任务
|
||||
|
||||
:param name: 测速任务的名称
|
||||
"""
|
||||
|
||||
if name in self.download_process_dict:
|
||||
self.download_process_dict[name].requestInterruption()
|
||||
|
||||
def test_speed_task2(self, name: str, t: float) -> None:
|
||||
def check_test_speed(self, name: str, t: float) -> None:
|
||||
"""
|
||||
更新测速子任务wc信息,并检查测速任务是否允许结束
|
||||
|
||||
:param name: 测速任务的名称
|
||||
:param t: 测速任务的耗时
|
||||
"""
|
||||
|
||||
# 计算下载速度
|
||||
if self.isInterruptionRequested:
|
||||
@@ -453,12 +495,13 @@ class DownloadManager(QDialog):
|
||||
|
||||
# 保存测速结果
|
||||
self.config["speed_result"] = self.test_speed_result
|
||||
logger.info(f"测速结果:{self.test_speed_result}")
|
||||
logger.success(f"测速完成,结果:{self.test_speed_result}", module="下载管理器")
|
||||
|
||||
self.update_info("测速完成!")
|
||||
self.speed_test_accomplish.emit()
|
||||
|
||||
def download_task1(self) -> None:
|
||||
def start_download(self) -> None:
|
||||
"""开始下载任务"""
|
||||
|
||||
if self.isInterruptionRequested:
|
||||
return None
|
||||
@@ -466,6 +509,8 @@ class DownloadManager(QDialog):
|
||||
url = self.get_download_url("下载")
|
||||
self.downloaded_size_list: List[List[int, bool]] = []
|
||||
|
||||
logger.info(f"开始下载任务,链接:{url}", module="下载管理器")
|
||||
|
||||
response = requests.head(
|
||||
url,
|
||||
timeout=10,
|
||||
@@ -506,20 +551,27 @@ class DownloadManager(QDialog):
|
||||
)
|
||||
self.downloaded_size_list.append([0, False])
|
||||
self.download_process_dict[f"part{i}"].progress.connect(
|
||||
partial(self.download_task2, i)
|
||||
partial(self.update_download, i)
|
||||
)
|
||||
self.download_process_dict[f"part{i}"].accomplish.connect(
|
||||
partial(self.download_task3, i)
|
||||
partial(self.check_download, i)
|
||||
)
|
||||
self.download_process_dict[f"part{i}"].start()
|
||||
|
||||
def download_task2(self, index: str, current: int) -> None:
|
||||
"""更新下载进度"""
|
||||
def update_download(self, index: str, current: int) -> None:
|
||||
"""
|
||||
更新子任务下载进度,将信息更新到 UI 上
|
||||
|
||||
:param index: 下载任务的索引
|
||||
:param current: 当前下载大小
|
||||
"""
|
||||
|
||||
# 更新指定线程的下载进度
|
||||
self.downloaded_size_list[index][0] = current
|
||||
self.downloaded_size = sum([_[0] for _ in self.downloaded_size_list])
|
||||
self.update_progress(0, self.file_size, self.downloaded_size)
|
||||
|
||||
# 速度每秒更新一次
|
||||
if time.time() - self.last_time >= 1.0:
|
||||
self.speed = (
|
||||
(self.downloaded_size - self.last_download_size)
|
||||
@@ -538,7 +590,13 @@ class DownloadManager(QDialog):
|
||||
f"正在下载:{self.name} 已下载:{self.downloaded_size / 1048576:.2f}/{self.file_size / 1048576:.2f} MB ({self.downloaded_size / self.file_size * 100:.2f}%) 下载速度:{self.speed:.2f} KB/s",
|
||||
)
|
||||
|
||||
def download_task3(self, index: str, t: float) -> None:
|
||||
def check_download(self, index: str, t: float) -> None:
|
||||
"""
|
||||
更新下载子任务完成信息,检查下载任务是否完成,完成后自动执行后续处理任务
|
||||
|
||||
:param index: 下载任务的索引
|
||||
:param t: 下载任务的耗时
|
||||
"""
|
||||
|
||||
# 标记下载线程完成
|
||||
self.downloaded_size_list[index][1] = True
|
||||
@@ -560,7 +618,8 @@ class DownloadManager(QDialog):
|
||||
|
||||
# 合并下载的分段文件
|
||||
logger.info(
|
||||
f"所有分段下载完成:{self.name},开始合并分段文件到 {self.download_path}"
|
||||
f"所有分段下载完成:{self.name},开始合并分段文件到 {self.download_path}",
|
||||
module="下载管理器",
|
||||
)
|
||||
with self.download_path.open(mode="wb") as outfile:
|
||||
for i in range(self.config["thread_numb"]):
|
||||
@@ -571,7 +630,8 @@ class DownloadManager(QDialog):
|
||||
self.download_path.with_suffix(f".part{i}").unlink()
|
||||
|
||||
logger.success(
|
||||
f"合并完成:{self.name},下载文件大小:{self.download_path.stat().st_size} 字节"
|
||||
f"合并完成:{self.name},下载文件大小:{self.download_path.stat().st_size} 字节",
|
||||
module="下载管理器",
|
||||
)
|
||||
|
||||
self.update_info("正在解压更新文件")
|
||||
@@ -610,9 +670,21 @@ class DownloadManager(QDialog):
|
||||
self.download_accomplish.emit()
|
||||
|
||||
def update_info(self, text: str) -> None:
|
||||
"""
|
||||
更新信息文本
|
||||
|
||||
:param text: 要显示的信息文本
|
||||
"""
|
||||
self.info.setText(text)
|
||||
|
||||
def update_progress(self, begin: int, end: int, current: int) -> None:
|
||||
"""
|
||||
更新进度条
|
||||
|
||||
:param begin: 进度条起始值
|
||||
:param end: 进度条结束值
|
||||
:param current: 进度条当前值
|
||||
"""
|
||||
|
||||
if begin == 0 and end == 0:
|
||||
self.progress_2.setVisible(False)
|
||||
@@ -626,7 +698,7 @@ class DownloadManager(QDialog):
|
||||
def requestInterruption(self) -> None:
|
||||
"""请求中断下载任务"""
|
||||
|
||||
logger.info("收到下载任务中止请求")
|
||||
logger.info("收到下载任务中止请求", module="下载管理器")
|
||||
|
||||
self.isInterruptionRequested = True
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
@@ -51,11 +50,12 @@ from pathlib import Path
|
||||
from typing import List, Dict
|
||||
|
||||
|
||||
from app.core import Config, SoundPlayer
|
||||
from app.core import Config, SoundPlayer, logger
|
||||
from .Widget import StatefulItemCard, QuantifiedItemCard, QuickExpandGroupCard
|
||||
|
||||
|
||||
class History(QWidget):
|
||||
"""历史记录界面"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -81,10 +81,21 @@ class History(QWidget):
|
||||
self.history_card_list = []
|
||||
|
||||
def reload_history(self, mode: str, start_date: QDate, end_date: QDate) -> None:
|
||||
"""加载历史记录界面"""
|
||||
"""
|
||||
加载历史记录界面
|
||||
|
||||
:param mode: 查询模式
|
||||
:param start_date: 查询范围起始日期
|
||||
:param end_date: 查询范围结束日期
|
||||
"""
|
||||
|
||||
logger.info(
|
||||
f"查询历史记录: {mode}, {start_date.toString()}, {end_date.toString()}",
|
||||
module="历史记录",
|
||||
)
|
||||
SoundPlayer.play("历史记录查询")
|
||||
|
||||
# 清空已有的历史记录卡片
|
||||
while self.content_layout.count() > 0:
|
||||
item = self.content_layout.takeAt(0)
|
||||
if item.spacerItem():
|
||||
@@ -100,6 +111,7 @@ class History(QWidget):
|
||||
datetime(end_date.year(), end_date.month(), end_date.day()),
|
||||
)
|
||||
|
||||
# 生成历史记录卡片并添加到布局中
|
||||
for date, user_dict in history_dict.items():
|
||||
|
||||
self.history_card_list.append(self.HistoryCard(date, user_dict, self))
|
||||
@@ -154,7 +166,13 @@ class History(QWidget):
|
||||
Layout.addWidget(self.search)
|
||||
|
||||
def select_date(self, date: str) -> None:
|
||||
"""选中最近一段时间并启动查询"""
|
||||
"""
|
||||
选中最近一段时间并启动查询
|
||||
|
||||
:param date: 选择的时间段("week" 或 "month")
|
||||
"""
|
||||
|
||||
logger.info(f"选择最近{date}的记录并开始查询", module="历史记录")
|
||||
|
||||
server_date = Config.server_date()
|
||||
if date == "week":
|
||||
@@ -187,6 +205,7 @@ class History(QWidget):
|
||||
|
||||
self.user_history_card_list = []
|
||||
|
||||
# 生成用户历史记录卡片并添加到布局中
|
||||
for user, info in user_dict.items():
|
||||
self.user_history_card_list.append(
|
||||
self.UserHistoryCard(user, info, self)
|
||||
@@ -219,7 +238,12 @@ class History(QWidget):
|
||||
self.update_info("数据总览")
|
||||
|
||||
def get_statistics(self, mode: str) -> dict:
|
||||
"""生成GUI相应结构化统计数据"""
|
||||
"""
|
||||
生成GUI相应结构化统计数据
|
||||
|
||||
:param mode: 查询模式
|
||||
:return: 结构化统计数据
|
||||
"""
|
||||
|
||||
history_info = Config.merge_statistic_info(
|
||||
self.user_history if mode == "数据总览" else [Path(mode)]
|
||||
@@ -244,7 +268,11 @@ class History(QWidget):
|
||||
return statistics_info
|
||||
|
||||
def update_info(self, index: str) -> None:
|
||||
"""更新信息"""
|
||||
"""
|
||||
更新信息到UI界面
|
||||
|
||||
:param index: 选择的索引
|
||||
"""
|
||||
|
||||
# 移除已有统计信息UI组件
|
||||
while self.statistics_card.count() > 0:
|
||||
@@ -254,8 +282,10 @@ class History(QWidget):
|
||||
elif item.widget():
|
||||
item.widget().deleteLater()
|
||||
|
||||
# 统计信息上传至 UI
|
||||
if index == "数据总览":
|
||||
|
||||
# 生成数据统计信息卡片组
|
||||
for name, item_list in self.get_statistics("数据总览").items():
|
||||
|
||||
statistics_card = self.StatisticsCard(name, item_list, self)
|
||||
@@ -268,10 +298,12 @@ class History(QWidget):
|
||||
single_history = self.get_statistics(index)
|
||||
log_path = Path(index).with_suffix(".log")
|
||||
|
||||
# 生成单个历史记录的统计信息卡片组
|
||||
for name, item_list in single_history.items():
|
||||
statistics_card = self.StatisticsCard(name, item_list, self)
|
||||
self.statistics_card.addWidget(statistics_card)
|
||||
|
||||
# 显示日志信息并绑定点击事件
|
||||
with log_path.open("r", encoding="utf-8") as f:
|
||||
log = f.read()
|
||||
|
||||
@@ -291,6 +323,7 @@ class History(QWidget):
|
||||
self.setMinimumHeight(300)
|
||||
|
||||
class IndexCard(HeaderCardWidget):
|
||||
"""历史记录索引卡片组"""
|
||||
|
||||
index_changed = Signal(str)
|
||||
|
||||
@@ -304,9 +337,11 @@ class History(QWidget):
|
||||
|
||||
self.index_cards: List[StatefulItemCard] = []
|
||||
|
||||
# 生成索引卡片信息
|
||||
index_list = Config.merge_statistic_info(history_list)["index"]
|
||||
index_list.insert(0, ["数据总览", "运行", "数据总览"])
|
||||
|
||||
# 生成索引卡片组件并绑定点击事件
|
||||
for index in index_list:
|
||||
|
||||
self.index_cards.append(StatefulItemCard(index[:2]))
|
||||
@@ -318,6 +353,7 @@ class History(QWidget):
|
||||
self.Layout.addStretch(1)
|
||||
|
||||
class StatisticsCard(HeaderCardWidget):
|
||||
"""历史记录统计信息卡片组"""
|
||||
|
||||
def __init__(self, name: str, item_list: list, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -340,6 +376,7 @@ class History(QWidget):
|
||||
self.Layout.addStretch(1)
|
||||
|
||||
class LogCard(HeaderCardWidget):
|
||||
"""历史记录日志卡片"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
@@ -49,7 +48,7 @@ import json
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from app.core import Config, MainInfoBar, Network
|
||||
from app.core import Config, MainInfoBar, Network, logger
|
||||
from .Widget import Banner, IconButton
|
||||
|
||||
|
||||
@@ -160,8 +159,12 @@ class Home(QWidget):
|
||||
def get_home_image(self) -> None:
|
||||
"""获取主页图片"""
|
||||
|
||||
logger.info("获取主页图片", module="主页")
|
||||
|
||||
if Config.get(Config.function_HomeImageMode) == "默认":
|
||||
pass
|
||||
|
||||
logger.info("使用默认主页图片", module="主页")
|
||||
|
||||
elif Config.get(Config.function_HomeImageMode) == "自定义":
|
||||
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
@@ -180,7 +183,7 @@ class Home(QWidget):
|
||||
/ f"resources/images/Home/BannerCustomize{Path(file_path).suffix}",
|
||||
)
|
||||
|
||||
logger.info(f"自定义主页图片更换成功:{file_path}")
|
||||
logger.info(f"自定义主页图片更换成功:{file_path}", module="主页")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success",
|
||||
"主页图片更换成功",
|
||||
@@ -189,7 +192,7 @@ class Home(QWidget):
|
||||
)
|
||||
|
||||
else:
|
||||
logger.warning("自定义主页图片更换失败:未选择图片文件")
|
||||
logger.warning("自定义主页图片更换失败:未选择图片文件", module="主页")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"主页图片更换失败",
|
||||
@@ -198,7 +201,7 @@ class Home(QWidget):
|
||||
)
|
||||
elif Config.get(Config.function_HomeImageMode) == "主题图像":
|
||||
|
||||
# 从远程服务器获取最新主题图像
|
||||
# 从远程服务器获取最新主题图像信息
|
||||
network = Network.add_task(
|
||||
mode="get",
|
||||
url="https://gitee.com/DLmaster_361/AUTO_MAA/raw/server/theme_image.json",
|
||||
@@ -209,7 +212,8 @@ class Home(QWidget):
|
||||
theme_image = network_result["response_json"]
|
||||
else:
|
||||
logger.warning(
|
||||
f"获取最新主题图像时出错:{network_result['error_message']}"
|
||||
f"获取最新主题图像时出错:{network_result['error_message']}",
|
||||
module="主页",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
@@ -230,6 +234,7 @@ class Home(QWidget):
|
||||
else:
|
||||
time_local = datetime.strptime("2000-01-01 00:00", "%Y-%m-%d %H:%M")
|
||||
|
||||
# 检查主题图像是否需要更新
|
||||
if not (
|
||||
Config.app_path / "resources/images/Home/BannerTheme.jpg"
|
||||
).exists() or (
|
||||
@@ -253,7 +258,9 @@ class Home(QWidget):
|
||||
) as f:
|
||||
json.dump(theme_image, f, ensure_ascii=False, indent=4)
|
||||
|
||||
logger.success(f"主题图像「{theme_image["name"]}」下载成功")
|
||||
logger.success(
|
||||
f"主题图像「{theme_image["name"]}」下载成功", module="主页"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"success",
|
||||
"主题图像下载成功",
|
||||
@@ -264,7 +271,8 @@ class Home(QWidget):
|
||||
else:
|
||||
|
||||
logger.warning(
|
||||
f"下载最新主题图像时出错:{network_result['error_message']}"
|
||||
f"下载最新主题图像时出错:{network_result['error_message']}",
|
||||
module="主页",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
@@ -275,18 +283,16 @@ class Home(QWidget):
|
||||
|
||||
else:
|
||||
|
||||
logger.info("主题图像已是最新")
|
||||
logger.info("主题图像已是最新", module="主页")
|
||||
MainInfoBar.push_info_bar(
|
||||
"info",
|
||||
"主题图像已是最新",
|
||||
"主题图像已是最新!",
|
||||
3000,
|
||||
"info", "主题图像已是最新", "主题图像已是最新!", 3000
|
||||
)
|
||||
|
||||
self.set_banner()
|
||||
|
||||
def set_banner(self):
|
||||
"""设置主页图像"""
|
||||
|
||||
if Config.get(Config.function_HomeImageMode) == "默认":
|
||||
self.banner.set_banner_image(
|
||||
str(Config.app_path / "resources/images/Home/BannerDefault.png")
|
||||
@@ -366,7 +372,7 @@ class ButtonGroup(SimpleCardWidget):
|
||||
doc_button = IconButton(
|
||||
FluentIcon.CHAT.icon(color=QColor("#fff")),
|
||||
tip_title="官方社群",
|
||||
tip_content="加入官方群聊【AUTO_MAA绝赞DeBug中!】",
|
||||
tip_content="加入官方群聊「AUTO_MAA绝赞DeBug中!」",
|
||||
isTooltip=True,
|
||||
)
|
||||
doc_button.setIconSize(QSize(32, 32))
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import QApplication, QSystemTrayIcon
|
||||
from qfluentwidgets import (
|
||||
Action,
|
||||
@@ -45,7 +44,7 @@ from datetime import datetime, timedelta
|
||||
import shutil
|
||||
import darkdetect
|
||||
|
||||
from app.core import Config, TaskManager, MainTimer, MainInfoBar, SoundPlayer
|
||||
from app.core import Config, logger, TaskManager, MainTimer, MainInfoBar, SoundPlayer
|
||||
from app.services import Notify, Crypto, System
|
||||
from .home import Home
|
||||
from .member_manager import MemberManager
|
||||
@@ -57,6 +56,7 @@ from .setting import Setting
|
||||
|
||||
|
||||
class AUTO_MAA(MSFluentWindow):
|
||||
"""AUTO_MAA主界面"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -77,9 +77,11 @@ class AUTO_MAA(MSFluentWindow):
|
||||
self.splashScreen = SplashScreen(self.windowIcon(), self)
|
||||
self.show_ui("显示主窗口", if_quick=True)
|
||||
|
||||
# 设置主窗口的引用,便于各组件访问
|
||||
Config.main_window = self.window()
|
||||
|
||||
# 创建主窗口
|
||||
# 创建各子窗口
|
||||
logger.info("正在创建各子窗口", module="主窗口")
|
||||
self.home = Home(self)
|
||||
self.plan_manager = PlanManager(self)
|
||||
self.member_manager = MemberManager(self)
|
||||
@@ -138,8 +140,10 @@ class AUTO_MAA(MSFluentWindow):
|
||||
NavigationItemPosition.BOTTOM,
|
||||
)
|
||||
self.stackedWidget.currentChanged.connect(self.__currentChanged)
|
||||
logger.success("各子窗口创建完成", module="主窗口")
|
||||
|
||||
# 创建系统托盘及其菜单
|
||||
logger.info("正在创建系统托盘", module="主窗口")
|
||||
self.tray = QSystemTrayIcon(
|
||||
QIcon(str(Config.app_path / "resources/icons/AUTO_MAA.ico")), self
|
||||
)
|
||||
@@ -181,9 +185,11 @@ class AUTO_MAA(MSFluentWindow):
|
||||
# 设置托盘菜单
|
||||
self.tray.setContextMenu(self.tray_menu)
|
||||
self.tray.activated.connect(self.on_tray_activated)
|
||||
logger.success("系统托盘创建完成", module="主窗口")
|
||||
|
||||
self.set_min_method()
|
||||
|
||||
# 绑定各组件信号
|
||||
Config.sub_info_changed.connect(self.member_manager.refresh_dashboard)
|
||||
Config.power_sign_changed.connect(self.dispatch_center.update_power_sign)
|
||||
TaskManager.create_gui.connect(self.dispatch_center.add_board)
|
||||
@@ -205,6 +211,8 @@ class AUTO_MAA(MSFluentWindow):
|
||||
self.themeListener.systemThemeChanged.connect(self.switch_theme)
|
||||
self.themeListener.start()
|
||||
|
||||
logger.success("AUTO_MAA主程序初始化完成", module="主窗口")
|
||||
|
||||
def switch_theme(self) -> None:
|
||||
"""切换主题"""
|
||||
|
||||
@@ -348,8 +356,10 @@ class AUTO_MAA(MSFluentWindow):
|
||||
def start_up_task(self) -> None:
|
||||
"""启动时任务"""
|
||||
|
||||
# 清理旧日志
|
||||
self.clean_old_logs()
|
||||
logger.info("开始执行启动时任务", module="主窗口")
|
||||
|
||||
# 清理旧历史记录
|
||||
Config.clean_old_history()
|
||||
|
||||
# 清理安装包
|
||||
if (Config.app_path / "AUTO_MAA-Setup.exe").exists():
|
||||
@@ -373,6 +383,9 @@ class AUTO_MAA(MSFluentWindow):
|
||||
|
||||
self.start_main_task()
|
||||
|
||||
# 启动定时器
|
||||
MainTimer.start()
|
||||
|
||||
# 获取公告
|
||||
self.setting.show_notice(if_first=True)
|
||||
|
||||
@@ -420,41 +433,16 @@ class AUTO_MAA(MSFluentWindow):
|
||||
)
|
||||
System.set_power("KillSelf")
|
||||
|
||||
def clean_old_logs(self):
|
||||
"""
|
||||
删除超过用户设定天数的日志文件(基于目录日期)
|
||||
"""
|
||||
|
||||
if Config.get(Config.function_HistoryRetentionTime) == 0:
|
||||
logger.info("由于用户设置日志永久保留,跳过日志清理")
|
||||
return
|
||||
|
||||
deleted_count = 0
|
||||
|
||||
for date_folder in (Config.app_path / "history").iterdir():
|
||||
if not date_folder.is_dir():
|
||||
continue # 只处理日期文件夹
|
||||
|
||||
try:
|
||||
# 只检查 `YYYY-MM-DD` 格式的文件夹
|
||||
folder_date = datetime.strptime(date_folder.name, "%Y-%m-%d")
|
||||
if datetime.now() - folder_date > timedelta(
|
||||
days=Config.get(Config.function_HistoryRetentionTime)
|
||||
):
|
||||
shutil.rmtree(date_folder, ignore_errors=True)
|
||||
deleted_count += 1
|
||||
logger.info(f"已删除超期日志目录: {date_folder}")
|
||||
except ValueError:
|
||||
logger.warning(f"非日期格式的目录: {date_folder}")
|
||||
|
||||
logger.info(f"清理完成: {deleted_count} 个日期目录")
|
||||
logger.success("启动时任务执行完成", module="主窗口")
|
||||
|
||||
def start_main_task(self) -> None:
|
||||
"""启动主任务"""
|
||||
|
||||
logger.info("正在启动主任务", module="主窗口")
|
||||
|
||||
if "调度队列_1" in Config.queue_dict:
|
||||
|
||||
logger.info("自动添加任务:调度队列_1")
|
||||
logger.info("自动添加任务:调度队列_1", module="主窗口")
|
||||
TaskManager.add_task(
|
||||
"自动代理_主调度台",
|
||||
"调度队列_1",
|
||||
@@ -463,18 +451,22 @@ class AUTO_MAA(MSFluentWindow):
|
||||
|
||||
elif "脚本_1" in Config.member_dict:
|
||||
|
||||
logger.info("自动添加任务:脚本_1")
|
||||
logger.info("自动添加任务:脚本_1", module="主窗口")
|
||||
TaskManager.add_task(
|
||||
"自动代理_主调度台", "自定义队列", {"Queue": {"Member_1": "脚本_1"}}
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
logger.warning("启动主任务失败:未找到有效的主任务配置文件")
|
||||
logger.warning(
|
||||
"启动主任务失败:未找到有效的主任务配置文件", module="主窗口"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "启动主任务失败", "「调度队列_1」与「脚本_1」均不存在", -1
|
||||
)
|
||||
|
||||
logger.success("主任务启动完成", module="主窗口")
|
||||
|
||||
def __currentChanged(self, index: int) -> None:
|
||||
"""切换界面时任务"""
|
||||
|
||||
@@ -489,20 +481,18 @@ class AUTO_MAA(MSFluentWindow):
|
||||
def closeEvent(self, event: QCloseEvent):
|
||||
"""清理残余进程"""
|
||||
|
||||
logger.info("保存窗口位置与大小信息", module="主窗口")
|
||||
self.show_ui("隐藏到托盘", if_quick=True)
|
||||
|
||||
# 清理各功能线程
|
||||
MainTimer.Timer.stop()
|
||||
MainTimer.Timer.deleteLater()
|
||||
MainTimer.LongTimer.stop()
|
||||
MainTimer.LongTimer.deleteLater()
|
||||
MainTimer.stop()
|
||||
TaskManager.stop_task("ALL")
|
||||
|
||||
# 关闭主题监听
|
||||
self.themeListener.terminate()
|
||||
self.themeListener.deleteLater()
|
||||
|
||||
logger.info("AUTO_MAA主程序关闭")
|
||||
logger.info("----------------END----------------")
|
||||
logger.info("AUTO_MAA主程序关闭", module="主窗口")
|
||||
logger.info("----------------END----------------", module="主窗口")
|
||||
|
||||
event.accept()
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QFileDialog,
|
||||
@@ -61,6 +60,7 @@ import json
|
||||
|
||||
from app.core import (
|
||||
Config,
|
||||
logger,
|
||||
MainInfoBar,
|
||||
TaskManager,
|
||||
MaaConfig,
|
||||
@@ -109,31 +109,22 @@ class MemberManager(QWidget):
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
self.tools = CommandBar()
|
||||
|
||||
self.member_manager = self.MemberSettingBox(self)
|
||||
|
||||
# 逐个添加动作
|
||||
self.tools.addActions(
|
||||
[
|
||||
Action(FluentIcon.ADD_TO, "新建脚本实例", triggered=self.add_member),
|
||||
Action(
|
||||
FluentIcon.ADD_TO, "新建脚本实例", triggered=self.add_setting_box
|
||||
),
|
||||
Action(
|
||||
FluentIcon.REMOVE_FROM,
|
||||
"删除脚本实例",
|
||||
triggered=self.del_setting_box,
|
||||
FluentIcon.REMOVE_FROM, "删除脚本实例", triggered=self.del_member
|
||||
),
|
||||
]
|
||||
)
|
||||
self.tools.addSeparator()
|
||||
self.tools.addActions(
|
||||
[
|
||||
Action(
|
||||
FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_setting_box
|
||||
),
|
||||
Action(
|
||||
FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_setting_box
|
||||
),
|
||||
Action(FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_member),
|
||||
Action(FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_member),
|
||||
]
|
||||
)
|
||||
self.tools.addSeparator()
|
||||
@@ -156,7 +147,7 @@ class MemberManager(QWidget):
|
||||
layout.addWidget(self.tools)
|
||||
layout.addWidget(self.member_manager)
|
||||
|
||||
def add_setting_box(self):
|
||||
def add_member(self):
|
||||
"""添加一个脚本实例"""
|
||||
|
||||
choice = ComboBoxMessageBox(
|
||||
@@ -167,10 +158,15 @@ class MemberManager(QWidget):
|
||||
)
|
||||
if choice.exec() and choice.input[0].currentIndex() != -1:
|
||||
|
||||
logger.info(
|
||||
f"添加脚本实例: {choice.input[0].currentText()}", module="脚本管理"
|
||||
)
|
||||
|
||||
if choice.input[0].currentText() == "MAA":
|
||||
|
||||
index = len(Config.member_dict) + 1
|
||||
|
||||
# 初始化 MAA 配置
|
||||
maa_config = MaaConfig()
|
||||
maa_config.load(
|
||||
Config.app_path / f"config/MaaConfig/脚本_{index}/config.json",
|
||||
@@ -188,12 +184,13 @@ class MemberManager(QWidget):
|
||||
"UserData": {},
|
||||
}
|
||||
|
||||
# 添加 MAA 实例设置界面
|
||||
self.member_manager.add_SettingBox(
|
||||
index, self.MemberSettingBox.MaaSettingBox
|
||||
)
|
||||
self.member_manager.switch_SettingBox(index)
|
||||
|
||||
logger.success(f"MAA实例 脚本_{index} 添加成功")
|
||||
logger.success(f"MAA实例 脚本_{index} 添加成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"添加 MAA 实例 脚本_{index}", 3000
|
||||
)
|
||||
@@ -203,6 +200,7 @@ class MemberManager(QWidget):
|
||||
|
||||
index = len(Config.member_dict) + 1
|
||||
|
||||
# 初始化通用配置
|
||||
general_config = GeneralConfig()
|
||||
general_config.load(
|
||||
Config.app_path / f"config/GeneralConfig/脚本_{index}/config.json",
|
||||
@@ -220,31 +218,32 @@ class MemberManager(QWidget):
|
||||
"SubData": {},
|
||||
}
|
||||
|
||||
# 添加通用实例设置界面
|
||||
self.member_manager.add_SettingBox(
|
||||
index, self.MemberSettingBox.GeneralSettingBox
|
||||
)
|
||||
self.member_manager.switch_SettingBox(index)
|
||||
|
||||
logger.success(f"通用实例 脚本_{index} 添加成功")
|
||||
logger.success(f"通用实例 脚本_{index} 添加成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"添加通用实例 脚本_{index}", 3000
|
||||
)
|
||||
SoundPlayer.play("添加脚本实例")
|
||||
|
||||
def del_setting_box(self):
|
||||
def del_member(self):
|
||||
"""删除一个脚本实例"""
|
||||
|
||||
name = self.member_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("删除脚本实例时未选择脚本实例")
|
||||
logger.warning("删除脚本实例时未选择脚本实例", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if len(Config.running_list) > 0:
|
||||
logger.warning("删除脚本实例时调度队列未停止运行")
|
||||
logger.warning("删除脚本实例时调度队列未停止运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||
)
|
||||
@@ -253,8 +252,11 @@ class MemberManager(QWidget):
|
||||
choice = MessageBox("确认", f"确定要删除 {name} 实例吗?", self.window())
|
||||
if choice.exec():
|
||||
|
||||
logger.info(f"正在删除脚本实例: {name}", module="脚本管理")
|
||||
|
||||
self.member_manager.clear_SettingBox()
|
||||
|
||||
# 删除脚本实例的配置文件并同步修改相应配置项
|
||||
shutil.rmtree(Config.member_dict[name]["Path"])
|
||||
Config.change_queue(name, "禁用")
|
||||
for i in range(int(name[3:]) + 1, len(Config.member_dict) + 1):
|
||||
@@ -266,19 +268,19 @@ class MemberManager(QWidget):
|
||||
|
||||
self.member_manager.show_SettingBox(max(int(name[3:]) - 1, 1))
|
||||
|
||||
logger.success(f"脚本实例 {name} 删除成功")
|
||||
logger.success(f"脚本实例 {name} 删除成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"删除脚本实例 {name}", 3000
|
||||
)
|
||||
SoundPlayer.play("删除脚本实例")
|
||||
|
||||
def left_setting_box(self):
|
||||
def left_member(self):
|
||||
"""向左移动脚本实例"""
|
||||
|
||||
name = self.member_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("向左移动脚本实例时未选择脚本实例")
|
||||
logger.warning("向左移动脚本实例时未选择脚本实例", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
||||
)
|
||||
@@ -287,21 +289,24 @@ class MemberManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == 1:
|
||||
logger.warning("向左移动脚本实例时已到达最左端")
|
||||
logger.warning("向左移动脚本实例时已到达最左端", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是第一个脚本实例", "无法向左移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if len(Config.running_list) > 0:
|
||||
logger.warning("向左移动脚本实例时调度队列未停止运行")
|
||||
logger.warning("向左移动脚本实例时调度队列未停止运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在向左移动脚本实例: {name}", module="脚本管理")
|
||||
|
||||
self.member_manager.clear_SettingBox()
|
||||
|
||||
# 移动脚本实例配置文件并同步修改配置项
|
||||
Config.member_dict[name]["Path"].rename(
|
||||
Config.member_dict[name]["Path"].with_name("脚本_0")
|
||||
)
|
||||
@@ -317,16 +322,16 @@ class MemberManager(QWidget):
|
||||
|
||||
self.member_manager.show_SettingBox(index - 1)
|
||||
|
||||
logger.success(f"脚本实例 {name} 左移成功")
|
||||
logger.success(f"脚本实例 {name} 左移成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"左移脚本实例 {name}", 3000)
|
||||
|
||||
def right_setting_box(self):
|
||||
def right_member(self):
|
||||
"""向右移动脚本实例"""
|
||||
|
||||
name = self.member_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("向右移动脚本实例时未选择脚本实例")
|
||||
logger.warning("向右移动脚本实例时未选择脚本实例", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
||||
)
|
||||
@@ -335,21 +340,24 @@ class MemberManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == len(Config.member_dict):
|
||||
logger.warning("向右移动脚本实例时已到达最右端")
|
||||
logger.warning("向右移动脚本实例时已到达最右端", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是最后一个脚本实例", "无法向右移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if len(Config.running_list) > 0:
|
||||
logger.warning("向右移动脚本实例时调度队列未停止运行")
|
||||
logger.warning("向右移动脚本实例时调度队列未停止运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在向右移动脚本实例: {name}", module="脚本管理")
|
||||
|
||||
self.member_manager.clear_SettingBox()
|
||||
|
||||
# 移动脚本实例配置文件并同步修改配置项
|
||||
Config.member_dict[name]["Path"].rename(
|
||||
Config.member_dict[name]["Path"].with_name("脚本_0")
|
||||
)
|
||||
@@ -365,7 +373,7 @@ class MemberManager(QWidget):
|
||||
|
||||
self.member_manager.show_SettingBox(index + 1)
|
||||
|
||||
logger.success(f"脚本实例 {name} 右移成功")
|
||||
logger.success(f"脚本实例 {name} 右移成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"右移脚本实例 {name}", 3000)
|
||||
|
||||
def member_downloader(self):
|
||||
@@ -373,7 +381,7 @@ class MemberManager(QWidget):
|
||||
|
||||
if not Config.get(Config.update_MirrorChyanCDK):
|
||||
|
||||
logger.warning("脚本下载器未设置CDK")
|
||||
logger.warning("脚本下载器未设置CDK", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"未设置Mirror酱CDK",
|
||||
@@ -392,7 +400,10 @@ class MemberManager(QWidget):
|
||||
if network_result["status_code"] == 200:
|
||||
apps_info = network_result["response_json"]
|
||||
else:
|
||||
logger.warning(f"获取应用列表时出错:{network_result['error_message']}")
|
||||
logger.warning(
|
||||
f"获取应用列表时出错:{network_result['error_message']}",
|
||||
module="脚本管理",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"获取应用列表时出错",
|
||||
@@ -419,7 +430,9 @@ class MemberManager(QWidget):
|
||||
str(Config.app_path / f"script/{app_rid}"),
|
||||
)
|
||||
if not folder:
|
||||
logger.warning(f"选择{app_name}下载目录时未选择文件夹")
|
||||
logger.warning(
|
||||
f"选择{app_name}下载目录时未选择文件夹", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "警告", f"未选择{app_name}下载目录", 5000
|
||||
)
|
||||
@@ -442,7 +455,10 @@ class MemberManager(QWidget):
|
||||
|
||||
if app_info["code"] != 0:
|
||||
|
||||
logger.error(f"获取版本信息时出错:{app_info["msg"]}")
|
||||
logger.error(
|
||||
f"获取应用版本信息时出错:{app_info["msg"]}",
|
||||
module="脚本管理",
|
||||
)
|
||||
|
||||
error_remark_dict = {
|
||||
1001: "获取版本信息的URL参数不正确",
|
||||
@@ -475,7 +491,10 @@ class MemberManager(QWidget):
|
||||
|
||||
return None
|
||||
|
||||
logger.warning(f"获取版本信息时出错:{network_result['error_message']}")
|
||||
logger.warning(
|
||||
f"获取版本信息时出错:{network_result['error_message']}",
|
||||
module="脚本管理",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"获取版本信息时出错",
|
||||
@@ -484,6 +503,8 @@ class MemberManager(QWidget):
|
||||
)
|
||||
return None
|
||||
|
||||
# 创建下载管理器并开始下载
|
||||
logger.info(f"开始下载{app_name},下载目录:{folder}", module="脚本管理")
|
||||
self.downloader = DownloadManager(
|
||||
Path(folder),
|
||||
app_rid,
|
||||
@@ -502,6 +523,7 @@ class MemberManager(QWidget):
|
||||
self.downloader.run()
|
||||
|
||||
def show_password(self):
|
||||
"""显示或隐藏密码"""
|
||||
|
||||
if Config.PASSWORD == "":
|
||||
choice = LineEditMessageBox(
|
||||
@@ -529,6 +551,7 @@ class MemberManager(QWidget):
|
||||
def reload_plan_name(self):
|
||||
"""刷新计划表名称"""
|
||||
|
||||
# 生成计划列表信息
|
||||
plan_list = [
|
||||
["固定"] + [_ for _ in Config.plan_dict.keys()],
|
||||
["固定"]
|
||||
@@ -541,6 +564,8 @@ class MemberManager(QWidget):
|
||||
for k, v in Config.plan_dict.items()
|
||||
],
|
||||
]
|
||||
|
||||
# 刷新所有脚本实例的计划表名称
|
||||
for member in self.member_manager.script_list:
|
||||
|
||||
if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox):
|
||||
@@ -616,7 +641,12 @@ class MemberManager(QWidget):
|
||||
self.show_SettingBox(1)
|
||||
|
||||
def show_SettingBox(self, index) -> None:
|
||||
"""加载所有子界面"""
|
||||
"""
|
||||
加载所有子界面并切换到指定子界面
|
||||
|
||||
:param index: 要切换到的子界面索引
|
||||
:type index: int
|
||||
"""
|
||||
|
||||
Config.search_member()
|
||||
|
||||
@@ -629,7 +659,14 @@ class MemberManager(QWidget):
|
||||
self.switch_SettingBox(index)
|
||||
|
||||
def switch_SettingBox(self, index: int, if_chang_pivot: bool = True) -> None:
|
||||
"""切换到指定的子界面"""
|
||||
"""
|
||||
切换到指定的子界面
|
||||
|
||||
:param index: 要切换到的子界面索引
|
||||
:type index: int
|
||||
:param if_chang_pivot: 是否更改导航栏的当前项
|
||||
:type if_chang_pivot: bool
|
||||
"""
|
||||
|
||||
if len(Config.member_dict) == 0:
|
||||
return None
|
||||
@@ -666,7 +703,14 @@ class MemberManager(QWidget):
|
||||
self.pivot.clear()
|
||||
|
||||
def add_SettingBox(self, uid: int, type: Type) -> None:
|
||||
"""添加指定类型设置子界面"""
|
||||
"""
|
||||
添加指定类型设置子界面
|
||||
|
||||
:param uid: 脚本实例的唯一标识符
|
||||
:type uid: int
|
||||
:param type: 要添加的设置子界面类型
|
||||
:type type: Type
|
||||
"""
|
||||
|
||||
if type == self.MaaSettingBox:
|
||||
setting_box = self.MaaSettingBox(uid, self)
|
||||
@@ -762,6 +806,7 @@ class MemberManager(QWidget):
|
||||
self.viewLayout.addLayout(Layout)
|
||||
|
||||
def PathClicked(self):
|
||||
"""选择MAA目录并验证"""
|
||||
|
||||
folder = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
@@ -769,7 +814,9 @@ class MemberManager(QWidget):
|
||||
self.config.get(self.config.MaaSet_Path),
|
||||
)
|
||||
if not folder or self.config.get(self.config.MaaSet_Path) == folder:
|
||||
logger.warning("选择MAA目录时未选择文件夹或未更改文件夹")
|
||||
logger.warning(
|
||||
"选择MAA目录时未选择文件夹或未更改文件夹", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "警告", "未选择文件夹或未更改文件夹", 5000
|
||||
)
|
||||
@@ -778,7 +825,9 @@ class MemberManager(QWidget):
|
||||
not (Path(folder) / "config/gui.json").exists()
|
||||
or not (Path(folder) / "MAA.exe").exists()
|
||||
):
|
||||
logger.warning("选择MAA目录时未找到MAA程序或配置文件")
|
||||
logger.warning(
|
||||
"选择MAA目录时未找到MAA程序或配置文件", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "警告", "未找到MAA程序或配置文件", 5000
|
||||
)
|
||||
@@ -938,6 +987,9 @@ class MemberManager(QWidget):
|
||||
|
||||
index = len(Config.member_dict[self.name]["UserData"]) + 1
|
||||
|
||||
logger.info(f"正在添加 {self.name} 用户_{index}", module="脚本管理")
|
||||
|
||||
# 初始化用户配置信息
|
||||
user_config = MaaUserConfig()
|
||||
user_config.load(
|
||||
Config.member_dict[self.name]["Path"]
|
||||
@@ -952,10 +1004,13 @@ class MemberManager(QWidget):
|
||||
"Config": user_config,
|
||||
}
|
||||
|
||||
# 添加用户设置面板
|
||||
self.user_manager.add_userSettingBox(index)
|
||||
self.user_manager.switch_SettingBox(f"用户_{index}")
|
||||
|
||||
logger.success(f"{self.name} 用户_{index} 添加成功")
|
||||
logger.success(
|
||||
f"{self.name} 用户_{index} 添加成功", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 添加 用户_{index}", 3000
|
||||
)
|
||||
@@ -967,20 +1022,20 @@ class MemberManager(QWidget):
|
||||
name = self.user_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择用户")
|
||||
logger.warning("未选择用户", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择用户", "请先选择一个用户", 5000
|
||||
)
|
||||
return None
|
||||
if name == "用户仪表盘":
|
||||
logger.warning("试图删除用户仪表盘")
|
||||
logger.warning("试图删除用户仪表盘", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择用户", "请勿尝试删除用户仪表盘", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
@@ -991,8 +1046,11 @@ class MemberManager(QWidget):
|
||||
)
|
||||
if choice.exec():
|
||||
|
||||
logger.info(f"正在删除 {self.name} {name}", module="脚本管理")
|
||||
|
||||
self.user_manager.clear_SettingBox()
|
||||
|
||||
# 删除用户配置文件并同步修改相应配置项
|
||||
shutil.rmtree(
|
||||
Config.member_dict[self.name]["UserData"][name]["Path"]
|
||||
)
|
||||
@@ -1015,7 +1073,9 @@ class MemberManager(QWidget):
|
||||
f"用户_{max(int(name[3:]) - 1, 1)}"
|
||||
)
|
||||
|
||||
logger.success(f"{self.name} {name} 删除成功")
|
||||
logger.success(
|
||||
f"{self.name} {name} 删除成功", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 删除 {name}", 3000
|
||||
)
|
||||
@@ -1027,13 +1087,13 @@ class MemberManager(QWidget):
|
||||
name = self.user_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择用户")
|
||||
logger.warning("未选择用户", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择用户", "请先选择一个用户", 5000
|
||||
)
|
||||
return None
|
||||
if name == "用户仪表盘":
|
||||
logger.warning("试图移动用户仪表盘")
|
||||
logger.warning("试图移动用户仪表盘", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择用户", "请勿尝试移动用户仪表盘", 5000
|
||||
)
|
||||
@@ -1042,21 +1102,24 @@ class MemberManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == 1:
|
||||
logger.warning("向前移动用户时已到达最左端")
|
||||
logger.warning("向前移动用户时已到达最左端", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是第一个用户", "无法向前移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在向前移动 {self.name} {name}", module="脚本管理")
|
||||
|
||||
self.user_manager.clear_SettingBox()
|
||||
|
||||
# 移动用户配置文件并同步修改配置项
|
||||
Config.member_dict[self.name]["UserData"][name]["Path"].rename(
|
||||
Config.member_dict[self.name]["UserData"][name][
|
||||
"Path"
|
||||
@@ -1075,7 +1138,7 @@ class MemberManager(QWidget):
|
||||
|
||||
self.user_manager.show_SettingBox(f"用户_{index - 1}")
|
||||
|
||||
logger.success(f"{self.name} {name} 前移成功")
|
||||
logger.success(f"{self.name} {name} 前移成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 前移 {name}", 3000
|
||||
)
|
||||
@@ -1086,13 +1149,13 @@ class MemberManager(QWidget):
|
||||
name = self.user_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择用户")
|
||||
logger.warning("未选择用户", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择用户", "请先选择一个用户", 5000
|
||||
)
|
||||
return None
|
||||
if name == "用户仪表盘":
|
||||
logger.warning("试图删除用户仪表盘")
|
||||
logger.warning("试图删除用户仪表盘", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择用户", "请勿尝试移动用户仪表盘", 5000
|
||||
)
|
||||
@@ -1101,19 +1164,21 @@ class MemberManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == len(Config.member_dict[self.name]["UserData"]):
|
||||
logger.warning("向后移动用户时已到达最右端")
|
||||
logger.warning("向后移动用户时已到达最右端", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是最后一个用户", "无法向后移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在向后移动 {self.name} {name}", module="脚本管理")
|
||||
|
||||
self.user_manager.clear_SettingBox()
|
||||
|
||||
Config.member_dict[self.name]["UserData"][name]["Path"].rename(
|
||||
@@ -1134,7 +1199,7 @@ class MemberManager(QWidget):
|
||||
|
||||
self.user_manager.show_SettingBox(f"用户_{index + 1}")
|
||||
|
||||
logger.success(f"{self.name} {name} 后移成功")
|
||||
logger.success(f"{self.name} {name} 后移成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 后移 {name}", 3000
|
||||
)
|
||||
@@ -1180,7 +1245,12 @@ class MemberManager(QWidget):
|
||||
self.show_SettingBox("用户仪表盘")
|
||||
|
||||
def show_SettingBox(self, index: str) -> None:
|
||||
"""加载所有子界面"""
|
||||
"""
|
||||
加载所有子界面并切换到指定子界面
|
||||
|
||||
:param index: 要切换到的子界面索引或名称
|
||||
:type index: str
|
||||
"""
|
||||
|
||||
Config.search_maa_user(self.name)
|
||||
|
||||
@@ -1192,7 +1262,14 @@ class MemberManager(QWidget):
|
||||
def switch_SettingBox(
|
||||
self, index: str, if_change_pivot: bool = True
|
||||
) -> None:
|
||||
"""切换到指定的子界面"""
|
||||
"""
|
||||
切换到指定的子界面
|
||||
|
||||
:param index: 要切换到的子界面索引或名称
|
||||
:type index: str
|
||||
:param if_change_pivot: 是否更改导航栏的当前项
|
||||
:type if_change_pivot: bool
|
||||
"""
|
||||
|
||||
if len(Config.member_dict[self.name]["UserData"]) == 0:
|
||||
index = "用户仪表盘"
|
||||
@@ -1214,7 +1291,7 @@ class MemberManager(QWidget):
|
||||
)
|
||||
|
||||
def clear_SettingBox(self) -> None:
|
||||
"""清空所有子界面"""
|
||||
"""清空除用户仪表盘外所有子界面"""
|
||||
|
||||
for sub_interface in self.script_list:
|
||||
Config.stage_refreshed.disconnect(
|
||||
@@ -1232,7 +1309,12 @@ class MemberManager(QWidget):
|
||||
self.pivot.addItem(routeKey="用户仪表盘", text="用户仪表盘")
|
||||
|
||||
def add_userSettingBox(self, uid: int) -> None:
|
||||
"""添加一个用户设置界面"""
|
||||
"""
|
||||
添加一个用户设置界面
|
||||
|
||||
:param uid: 用户的唯一标识符
|
||||
:type uid: int
|
||||
"""
|
||||
|
||||
setting_box = self.UserMemberSettingBox(self.name, uid, self)
|
||||
|
||||
@@ -1292,6 +1374,12 @@ class MemberManager(QWidget):
|
||||
Config.PASSWORD_refreshed.connect(self.load_info)
|
||||
|
||||
def load_info(self):
|
||||
"""加载用户信息到仪表盘"""
|
||||
|
||||
logger.info(
|
||||
f"正在加载 {self.name} 用户信息到仪表盘",
|
||||
module="脚本管理",
|
||||
)
|
||||
|
||||
self.user_data = Config.member_dict[self.name]["UserData"]
|
||||
|
||||
@@ -1452,6 +1540,10 @@ class MemberManager(QWidget):
|
||||
int(name[3:]) - 1, 11, button
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"{self.name} 用户仪表盘成功加载信息", module="脚本管理"
|
||||
)
|
||||
|
||||
class UserMemberSettingBox(HeaderCardWidget):
|
||||
"""用户管理子页面"""
|
||||
|
||||
@@ -1915,6 +2007,7 @@ class MemberManager(QWidget):
|
||||
self.switch_infrastructure()
|
||||
|
||||
def switch_mode(self) -> None:
|
||||
"""切换用户配置模式"""
|
||||
|
||||
if self.config.get(self.config.Info_Mode) == "简洁":
|
||||
|
||||
@@ -1931,6 +2024,7 @@ class MemberManager(QWidget):
|
||||
self.card_Routine.setVisible(True)
|
||||
|
||||
def switch_stage_mode(self) -> None:
|
||||
"""切换关卡配置模式"""
|
||||
|
||||
for card, name in zip(
|
||||
[
|
||||
@@ -1967,6 +2061,7 @@ class MemberManager(QWidget):
|
||||
)
|
||||
|
||||
def switch_infrastructure(self) -> None:
|
||||
"""切换基建配置模式"""
|
||||
|
||||
if (
|
||||
self.config.get(self.config.Info_InfrastMode)
|
||||
@@ -1988,6 +2083,7 @@ class MemberManager(QWidget):
|
||||
)
|
||||
|
||||
def refresh_stage(self):
|
||||
"""刷新关卡配置"""
|
||||
|
||||
self.card_Stage.reLoadOptions(
|
||||
Config.stage_dict["ALL"]["value"],
|
||||
@@ -2011,6 +2107,7 @@ class MemberManager(QWidget):
|
||||
)
|
||||
|
||||
def refresh_password(self):
|
||||
"""刷新密码配置"""
|
||||
|
||||
self.card_Password.setValue(
|
||||
self.card_Password.qconfig.get(
|
||||
@@ -2054,7 +2151,7 @@ class MemberManager(QWidget):
|
||||
"""配置MAA子配置"""
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
@@ -2463,7 +2560,12 @@ class MemberManager(QWidget):
|
||||
self.addGroupWidget(widget)
|
||||
|
||||
def change_path(self, old_path: Path, new_path: Path) -> None:
|
||||
"""根据脚本根目录重新计算配置文件路径"""
|
||||
"""
|
||||
根据脚本根目录重新计算配置文件路径
|
||||
|
||||
:param old_path: 旧路径
|
||||
:param new_path: 新路径
|
||||
"""
|
||||
|
||||
path_list = [
|
||||
self.config.Script_ScriptPath,
|
||||
@@ -2491,7 +2593,8 @@ class MemberManager(QWidget):
|
||||
|
||||
self.config.set(configItem, str(old_path))
|
||||
logger.warning(
|
||||
f"配置路径 {new_path} 不在脚本根目录下,已重置为 {old_path}"
|
||||
f"配置路径 {new_path} 不在脚本根目录下,已重置为 {old_path}",
|
||||
module="脚本管理",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "路径异常", "所选路径不在脚本根目录下", 5000
|
||||
@@ -2738,6 +2841,11 @@ class MemberManager(QWidget):
|
||||
|
||||
index = len(Config.member_dict[self.name]["SubData"]) + 1
|
||||
|
||||
logger.info(
|
||||
f"正在添加 {self.name} 的配置_{index}", module="脚本管理"
|
||||
)
|
||||
|
||||
# 初始化通用配置
|
||||
sub_config = GeneralSubConfig()
|
||||
sub_config.load(
|
||||
Config.member_dict[self.name]["Path"]
|
||||
@@ -2752,10 +2860,13 @@ class MemberManager(QWidget):
|
||||
"Config": sub_config,
|
||||
}
|
||||
|
||||
# 添加通用配置页面
|
||||
self.sub_manager.add_SettingBox(index)
|
||||
self.sub_manager.switch_SettingBox(f"配置_{index}")
|
||||
|
||||
logger.success(f"{self.name} 配置_{index} 添加成功")
|
||||
logger.success(
|
||||
f"{self.name} 配置_{index} 添加成功", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 添加 配置_{index}", 3000
|
||||
)
|
||||
@@ -2767,20 +2878,20 @@ class MemberManager(QWidget):
|
||||
name = self.sub_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择配置")
|
||||
logger.warning("未选择配置", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择配置", "请先选择一个配置", 5000
|
||||
)
|
||||
return None
|
||||
if name == "配置仪表盘":
|
||||
logger.warning("试图删除配置仪表盘")
|
||||
logger.warning("试图删除配置仪表盘", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择配置", "请勿尝试删除配置仪表盘", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
@@ -2791,8 +2902,13 @@ class MemberManager(QWidget):
|
||||
)
|
||||
if choice.exec():
|
||||
|
||||
logger.info(
|
||||
f"正在删除 {self.name} 的配置_{name}", module="脚本管理"
|
||||
)
|
||||
|
||||
self.sub_manager.clear_SettingBox()
|
||||
|
||||
# 删除配置文件并同步到相关配置项
|
||||
shutil.rmtree(
|
||||
Config.member_dict[self.name]["SubData"][name]["Path"]
|
||||
)
|
||||
@@ -2815,7 +2931,9 @@ class MemberManager(QWidget):
|
||||
f"配置_{max(int(name[3:]) - 1, 1)}"
|
||||
)
|
||||
|
||||
logger.success(f"{self.name} {name} 删除成功")
|
||||
logger.success(
|
||||
f"{self.name} {name} 删除成功", module="脚本管理"
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 删除 {name}", 3000
|
||||
)
|
||||
@@ -2827,13 +2945,13 @@ class MemberManager(QWidget):
|
||||
name = self.sub_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择配置")
|
||||
logger.warning("未选择配置", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择配置", "请先选择一个配置", 5000
|
||||
)
|
||||
return None
|
||||
if name == "配置仪表盘":
|
||||
logger.warning("试图移动配置仪表盘")
|
||||
logger.warning("试图移动配置仪表盘", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择配置", "请勿尝试移动配置仪表盘", 5000
|
||||
)
|
||||
@@ -2842,21 +2960,26 @@ class MemberManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == 1:
|
||||
logger.warning("向前移动配置时已到达最左端")
|
||||
logger.warning("向前移动配置时已到达最左端", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是第一个配置", "无法向前移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(
|
||||
f"正在将 {self.name} 的配置_{name} 前移", module="脚本管理"
|
||||
)
|
||||
|
||||
self.sub_manager.clear_SettingBox()
|
||||
|
||||
# 移动配置文件并同步到相关配置项
|
||||
Config.member_dict[self.name]["SubData"][name]["Path"].rename(
|
||||
Config.member_dict[self.name]["SubData"][name][
|
||||
"Path"
|
||||
@@ -2875,7 +2998,7 @@ class MemberManager(QWidget):
|
||||
|
||||
self.sub_manager.show_SettingBox(f"配置_{index - 1}")
|
||||
|
||||
logger.success(f"{self.name} {name} 前移成功")
|
||||
logger.success(f"{self.name} {name} 前移成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 前移 {name}", 3000
|
||||
)
|
||||
@@ -2886,13 +3009,13 @@ class MemberManager(QWidget):
|
||||
name = self.sub_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择配置")
|
||||
logger.warning("未选择配置", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择配置", "请先选择一个配置", 5000
|
||||
)
|
||||
return None
|
||||
if name == "配置仪表盘":
|
||||
logger.warning("试图删除配置仪表盘")
|
||||
logger.warning("试图删除配置仪表盘", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择配置", "请勿尝试移动配置仪表盘", 5000
|
||||
)
|
||||
@@ -2901,21 +3024,26 @@ class MemberManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == len(Config.member_dict[self.name]["SubData"]):
|
||||
logger.warning("向后移动配置时已到达最右端")
|
||||
logger.warning("向后移动配置时已到达最右端", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是最后一个配置", "无法向后移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(
|
||||
f"正在将 {self.name} 的配置_{name} 后移", module="脚本管理"
|
||||
)
|
||||
|
||||
self.sub_manager.clear_SettingBox()
|
||||
|
||||
# 移动配置文件并同步到相关配置项
|
||||
Config.member_dict[self.name]["SubData"][name]["Path"].rename(
|
||||
Config.member_dict[self.name]["SubData"][name][
|
||||
"Path"
|
||||
@@ -2934,7 +3062,7 @@ class MemberManager(QWidget):
|
||||
|
||||
self.sub_manager.show_SettingBox(f"配置_{index + 1}")
|
||||
|
||||
logger.success(f"{self.name} {name} 后移成功")
|
||||
logger.success(f"{self.name} {name} 后移成功", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"{self.name} 后移 {name}", 3000
|
||||
)
|
||||
@@ -2980,7 +3108,11 @@ class MemberManager(QWidget):
|
||||
self.show_SettingBox("配置仪表盘")
|
||||
|
||||
def show_SettingBox(self, index: str) -> None:
|
||||
"""加载所有子界面"""
|
||||
"""
|
||||
加载所有子界面
|
||||
|
||||
:param index: 要显示的子界面索引
|
||||
"""
|
||||
|
||||
Config.search_general_sub(self.name)
|
||||
|
||||
@@ -2992,7 +3124,12 @@ class MemberManager(QWidget):
|
||||
def switch_SettingBox(
|
||||
self, index: str, if_change_pivot: bool = True
|
||||
) -> None:
|
||||
"""切换到指定的子界面"""
|
||||
"""
|
||||
切换到指定的子界面
|
||||
|
||||
:param index: 要切换到的子界面索引
|
||||
:param if_change_pivot: 是否更改 pivot 的当前项
|
||||
"""
|
||||
|
||||
if len(Config.member_dict[self.name]["SubData"]) == 0:
|
||||
index = "配置仪表盘"
|
||||
@@ -3026,7 +3163,11 @@ class MemberManager(QWidget):
|
||||
self.pivot.addItem(routeKey="配置仪表盘", text="配置仪表盘")
|
||||
|
||||
def add_SettingBox(self, uid: int) -> None:
|
||||
"""添加一个配置设置界面"""
|
||||
"""
|
||||
添加一个配置设置界面
|
||||
|
||||
:param uid: 配置的唯一标识符
|
||||
"""
|
||||
|
||||
setting_box = self.SubMemberSettingBox(self.name, uid, self)
|
||||
|
||||
@@ -3073,6 +3214,12 @@ class MemberManager(QWidget):
|
||||
Config.PASSWORD_refreshed.connect(self.load_info)
|
||||
|
||||
def load_info(self):
|
||||
"""加载配置仪表盘信息"""
|
||||
|
||||
logger.info(
|
||||
f"正在加载 {self.name} 的配置仪表盘信息",
|
||||
module="脚本管理",
|
||||
)
|
||||
|
||||
self.sub_data = Config.member_dict[self.name]["SubData"]
|
||||
|
||||
@@ -3127,6 +3274,10 @@ class MemberManager(QWidget):
|
||||
int(name[3:]) - 1, 4, button
|
||||
)
|
||||
|
||||
logger.success(
|
||||
f"{self.name} 配置仪表盘信息加载成功", module="脚本管理"
|
||||
)
|
||||
|
||||
class SubMemberSettingBox(HeaderCardWidget):
|
||||
"""配置管理子页面"""
|
||||
|
||||
@@ -3302,7 +3453,7 @@ class MemberManager(QWidget):
|
||||
"""配置子配置"""
|
||||
|
||||
if self.name in Config.running_list:
|
||||
logger.warning("所属脚本正在运行")
|
||||
logger.warning("所属脚本正在运行", module="脚本管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "所属脚本正在运行", "请先停止任务", 5000
|
||||
)
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
@@ -43,7 +42,7 @@ from qfluentwidgets import (
|
||||
from typing import List, Dict, Union
|
||||
import shutil
|
||||
|
||||
from app.core import Config, MainInfoBar, MaaPlanConfig, SoundPlayer
|
||||
from app.core import Config, MainInfoBar, MaaPlanConfig, SoundPlayer, logger
|
||||
from .Widget import (
|
||||
ComboBoxMessageBox,
|
||||
LineEditSettingCard,
|
||||
@@ -66,27 +65,20 @@ class PlanManager(QWidget):
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
self.tools = CommandBar()
|
||||
|
||||
self.plan_manager = self.PlanSettingBox(self)
|
||||
|
||||
# 逐个添加动作
|
||||
self.tools.addActions(
|
||||
[
|
||||
Action(FluentIcon.ADD_TO, "新建计划表", triggered=self.add_setting_box),
|
||||
Action(
|
||||
FluentIcon.REMOVE_FROM, "删除计划表", triggered=self.del_setting_box
|
||||
),
|
||||
Action(FluentIcon.ADD_TO, "新建计划表", triggered=self.add_plan),
|
||||
Action(FluentIcon.REMOVE_FROM, "删除计划表", triggered=self.del_plan),
|
||||
]
|
||||
)
|
||||
self.tools.addSeparator()
|
||||
self.tools.addActions(
|
||||
[
|
||||
Action(
|
||||
FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_setting_box
|
||||
),
|
||||
Action(
|
||||
FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_setting_box
|
||||
),
|
||||
Action(FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_plan),
|
||||
Action(FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_plan),
|
||||
]
|
||||
)
|
||||
self.tools.addSeparator()
|
||||
@@ -94,7 +86,7 @@ class PlanManager(QWidget):
|
||||
layout.addWidget(self.tools)
|
||||
layout.addWidget(self.plan_manager)
|
||||
|
||||
def add_setting_box(self):
|
||||
def add_plan(self):
|
||||
"""添加一个计划表"""
|
||||
|
||||
choice = ComboBoxMessageBox(
|
||||
@@ -109,6 +101,7 @@ class PlanManager(QWidget):
|
||||
|
||||
index = len(Config.plan_dict) + 1
|
||||
|
||||
# 初始化 MaaPlanConfig
|
||||
maa_plan_config = MaaPlanConfig()
|
||||
maa_plan_config.load(
|
||||
Config.app_path / f"config/MaaPlanConfig/计划_{index}/config.json",
|
||||
@@ -122,29 +115,30 @@ class PlanManager(QWidget):
|
||||
"Config": maa_plan_config,
|
||||
}
|
||||
|
||||
# 添加计划表到界面
|
||||
self.plan_manager.add_MaaPlanSettingBox(index)
|
||||
self.plan_manager.switch_SettingBox(index)
|
||||
|
||||
logger.success(f"计划管理 计划_{index} 添加成功")
|
||||
logger.success(f"计划管理 计划_{index} 添加成功", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", f"添加计划表 计划_{index}", 3000
|
||||
)
|
||||
SoundPlayer.play("添加计划表")
|
||||
|
||||
def del_setting_box(self):
|
||||
def del_plan(self):
|
||||
"""删除一个计划表"""
|
||||
|
||||
name = self.plan_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("删除计划表时未选择计划表")
|
||||
logger.warning("删除计划表时未选择计划表", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择计划表", "请选择一个计划表", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if len(Config.running_list) > 0:
|
||||
logger.warning("删除计划表时调度队列未停止运行")
|
||||
logger.warning("删除计划表时调度队列未停止运行", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||
)
|
||||
@@ -153,8 +147,11 @@ class PlanManager(QWidget):
|
||||
choice = MessageBox("确认", f"确定要删除 {name} 吗?", self.window())
|
||||
if choice.exec():
|
||||
|
||||
logger.info(f"正在删除计划表 {name}", module="计划管理")
|
||||
|
||||
self.plan_manager.clear_SettingBox()
|
||||
|
||||
# 删除计划表配置文件并同步到相关配置项
|
||||
shutil.rmtree(Config.plan_dict[name]["Path"])
|
||||
Config.change_plan(name, "固定")
|
||||
for i in range(int(name[3:]) + 1, len(Config.plan_dict) + 1):
|
||||
@@ -166,17 +163,17 @@ class PlanManager(QWidget):
|
||||
|
||||
self.plan_manager.show_SettingBox(max(int(name[3:]) - 1, 1))
|
||||
|
||||
logger.success(f"计划表 {name} 删除成功")
|
||||
logger.success(f"计划表 {name} 删除成功", module="计划管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"删除计划表 {name}", 3000)
|
||||
SoundPlayer.play("删除计划表")
|
||||
|
||||
def left_setting_box(self):
|
||||
def left_plan(self):
|
||||
"""向左移动计划表"""
|
||||
|
||||
name = self.plan_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("向左移动计划表时未选择计划表")
|
||||
logger.warning("向左移动计划表时未选择计划表", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择计划表", "请选择一个计划表", 5000
|
||||
)
|
||||
@@ -185,21 +182,24 @@ class PlanManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == 1:
|
||||
logger.warning("向左移动计划表时已到达最左端")
|
||||
logger.warning("向左移动计划表时已到达最左端", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是第一个计划表", "无法向左移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if len(Config.running_list) > 0:
|
||||
logger.warning("向左移动计划表时调度队列未停止运行")
|
||||
logger.warning("向左移动计划表时调度队列未停止运行", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在左移计划表 {name}", module="计划管理")
|
||||
|
||||
self.plan_manager.clear_SettingBox()
|
||||
|
||||
# 移动配置文件并同步到相关配置项
|
||||
Config.plan_dict[name]["Path"].rename(
|
||||
Config.plan_dict[name]["Path"].with_name("计划_0")
|
||||
)
|
||||
@@ -215,16 +215,16 @@ class PlanManager(QWidget):
|
||||
|
||||
self.plan_manager.show_SettingBox(index - 1)
|
||||
|
||||
logger.success(f"计划表 {name} 左移成功")
|
||||
logger.success(f"计划表 {name} 左移成功", module="计划管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"左移计划表 {name}", 3000)
|
||||
|
||||
def right_setting_box(self):
|
||||
def right_plan(self):
|
||||
"""向右移动计划表"""
|
||||
|
||||
name = self.plan_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("向右移动计划表时未选择计划表")
|
||||
logger.warning("向右移动计划表时未选择计划表", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择计划表", "请选择一个计划表", 5000
|
||||
)
|
||||
@@ -233,21 +233,24 @@ class PlanManager(QWidget):
|
||||
index = int(name[3:])
|
||||
|
||||
if index == len(Config.plan_dict):
|
||||
logger.warning("向右移动计划表时已到达最右端")
|
||||
logger.warning("向右移动计划表时已到达最右端", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是最后一个计划表", "无法向右移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if len(Config.running_list) > 0:
|
||||
logger.warning("向右移动计划表时调度队列未停止运行")
|
||||
logger.warning("向右移动计划表时调度队列未停止运行", module="计划管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在右移计划表 {name}", module="计划管理")
|
||||
|
||||
self.plan_manager.clear_SettingBox()
|
||||
|
||||
# 移动配置文件并同步到相关配置项
|
||||
Config.plan_dict[name]["Path"].rename(
|
||||
Config.plan_dict[name]["Path"].with_name("计划_0")
|
||||
)
|
||||
@@ -263,7 +266,7 @@ class PlanManager(QWidget):
|
||||
|
||||
self.plan_manager.show_SettingBox(index + 1)
|
||||
|
||||
logger.success(f"计划表 {name} 右移成功")
|
||||
logger.success(f"计划表 {name} 右移成功", module="计划管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"右移计划表 {name}", 3000)
|
||||
|
||||
class PlanSettingBox(QWidget):
|
||||
@@ -297,7 +300,11 @@ class PlanManager(QWidget):
|
||||
self.show_SettingBox(1)
|
||||
|
||||
def show_SettingBox(self, index) -> None:
|
||||
"""加载所有子界面"""
|
||||
"""
|
||||
加载所有子界面并切换到指定的子界面
|
||||
|
||||
:param index: 要显示的子界面索引
|
||||
"""
|
||||
|
||||
Config.search_plan()
|
||||
|
||||
@@ -308,7 +315,12 @@ class PlanManager(QWidget):
|
||||
self.switch_SettingBox(index)
|
||||
|
||||
def switch_SettingBox(self, index: int, if_chang_pivot: bool = True) -> None:
|
||||
"""切换到指定的子界面"""
|
||||
"""
|
||||
切换到指定的子界面
|
||||
|
||||
:param index: 要切换到的子界面索引
|
||||
:param if_chang_pivot: 是否更改 pivot 的当前项
|
||||
"""
|
||||
|
||||
if len(Config.plan_dict) == 0:
|
||||
return None
|
||||
@@ -331,7 +343,11 @@ class PlanManager(QWidget):
|
||||
self.pivot.clear()
|
||||
|
||||
def add_MaaPlanSettingBox(self, uid: int) -> None:
|
||||
"""添加一个MAA设置界面"""
|
||||
"""
|
||||
添加一个MAA设置界面
|
||||
|
||||
:param uid: MAA计划表的唯一标识符
|
||||
"""
|
||||
|
||||
maa_plan_setting_box = self.MaaPlanSettingBox(uid, self)
|
||||
|
||||
@@ -475,6 +491,7 @@ class PlanManager(QWidget):
|
||||
)
|
||||
|
||||
def refresh_stage(self):
|
||||
"""刷新关卡列表"""
|
||||
|
||||
for group, name_dict in self.item_dict.items():
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
@@ -42,7 +41,7 @@ from qfluentwidgets import (
|
||||
)
|
||||
from typing import List
|
||||
|
||||
from app.core import QueueConfig, Config, MainInfoBar, SoundPlayer
|
||||
from app.core import QueueConfig, Config, MainInfoBar, SoundPlayer, logger
|
||||
from .Widget import (
|
||||
SwitchSettingCard,
|
||||
ComboBoxSettingCard,
|
||||
@@ -70,36 +69,31 @@ class QueueManager(QWidget):
|
||||
# 逐个添加动作
|
||||
self.tools.addActions(
|
||||
[
|
||||
Action(FluentIcon.ADD_TO, "新建调度队列", triggered=self.add_queue),
|
||||
Action(
|
||||
FluentIcon.ADD_TO, "新建调度队列", triggered=self.add_setting_box
|
||||
),
|
||||
Action(
|
||||
FluentIcon.REMOVE_FROM,
|
||||
"删除调度队列",
|
||||
triggered=self.del_setting_box,
|
||||
FluentIcon.REMOVE_FROM, "删除调度队列", triggered=self.del_queue
|
||||
),
|
||||
]
|
||||
)
|
||||
self.tools.addSeparator()
|
||||
self.tools.addActions(
|
||||
[
|
||||
Action(
|
||||
FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_setting_box
|
||||
),
|
||||
Action(
|
||||
FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_setting_box
|
||||
),
|
||||
Action(FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_queue),
|
||||
Action(FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_queue),
|
||||
]
|
||||
)
|
||||
|
||||
layout.addWidget(self.tools)
|
||||
layout.addWidget(self.queue_manager)
|
||||
|
||||
def add_setting_box(self):
|
||||
def add_queue(self):
|
||||
"""添加一个调度队列"""
|
||||
|
||||
index = len(Config.queue_dict) + 1
|
||||
|
||||
logger.info(f"正在添加调度队列_{index}", module="队列管理")
|
||||
|
||||
# 初始化队列配置
|
||||
queue_config = QueueConfig()
|
||||
queue_config.load(
|
||||
Config.app_path / f"config/QueueConfig/调度队列_{index}.json", queue_config
|
||||
@@ -111,27 +105,28 @@ class QueueManager(QWidget):
|
||||
"Config": queue_config,
|
||||
}
|
||||
|
||||
# 添加到配置界面
|
||||
self.queue_manager.add_SettingBox(index)
|
||||
self.queue_manager.switch_SettingBox(index)
|
||||
|
||||
logger.success(f"调度队列_{index} 添加成功")
|
||||
logger.success(f"调度队列_{index} 添加成功", module="队列管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"添加 调度队列_{index}", 3000)
|
||||
SoundPlayer.play("添加调度队列")
|
||||
|
||||
def del_setting_box(self):
|
||||
def del_queue(self):
|
||||
"""删除一个调度队列实例"""
|
||||
|
||||
name = self.queue_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择调度队列")
|
||||
logger.warning("未选择调度队列", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if name in Config.running_list:
|
||||
logger.warning("调度队列正在运行")
|
||||
logger.warning("调度队列正在运行", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "调度队列正在运行", "请先停止调度队列", 5000
|
||||
)
|
||||
@@ -140,8 +135,11 @@ class QueueManager(QWidget):
|
||||
choice = MessageBox("确认", f"确定要删除 {name} 吗?", self.window())
|
||||
if choice.exec():
|
||||
|
||||
logger.info(f"正在删除调度队列 {name}", module="队列管理")
|
||||
|
||||
self.queue_manager.clear_SettingBox()
|
||||
|
||||
# 删除队列配置文件并同步到相关配置项
|
||||
Config.queue_dict[name]["Path"].unlink()
|
||||
for i in range(int(name[5:]) + 1, len(Config.queue_dict) + 1):
|
||||
if Config.queue_dict[f"调度队列_{i}"]["Path"].exists():
|
||||
@@ -153,17 +151,17 @@ class QueueManager(QWidget):
|
||||
|
||||
self.queue_manager.show_SettingBox(max(int(name[5:]) - 1, 1))
|
||||
|
||||
logger.success(f"{name} 删除成功")
|
||||
logger.success(f"{name} 删除成功", module="队列管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"删除 {name}", 3000)
|
||||
SoundPlayer.play("删除调度队列")
|
||||
|
||||
def left_setting_box(self):
|
||||
def left_queue(self):
|
||||
"""向左移动调度队列实例"""
|
||||
|
||||
name = self.queue_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择调度队列")
|
||||
logger.warning("未选择调度队列", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
||||
)
|
||||
@@ -172,21 +170,24 @@ class QueueManager(QWidget):
|
||||
index = int(name[5:])
|
||||
|
||||
if index == 1:
|
||||
logger.warning("向左移动调度队列时已到达最左端")
|
||||
logger.warning("向左移动调度队列时已到达最左端", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是第一个调度队列", "无法向左移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if name in Config.running_list or f"调度队列_{index-1}" in Config.running_list:
|
||||
logger.warning("相关调度队列正在运行")
|
||||
logger.warning("相关调度队列正在运行", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "相关调度队列正在运行", "请先停止调度队列", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在左移调度队列 {name}", module="队列管理")
|
||||
|
||||
self.queue_manager.clear_SettingBox()
|
||||
|
||||
# 移动配置文件并同步到相关配置项
|
||||
Config.queue_dict[name]["Path"].rename(
|
||||
Config.queue_dict[name]["Path"].with_name("调度队列_0.json")
|
||||
)
|
||||
@@ -199,16 +200,16 @@ class QueueManager(QWidget):
|
||||
|
||||
self.queue_manager.show_SettingBox(index - 1)
|
||||
|
||||
logger.success(f"{name} 左移成功")
|
||||
logger.success(f"{name} 左移成功", module="队列管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"左移 {name}", 3000)
|
||||
|
||||
def right_setting_box(self):
|
||||
def right_queue(self):
|
||||
"""向右移动调度队列实例"""
|
||||
|
||||
name = self.queue_manager.pivot.currentRouteKey()
|
||||
|
||||
if name is None:
|
||||
logger.warning("未选择调度队列")
|
||||
logger.warning("未选择调度队列", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
||||
)
|
||||
@@ -217,21 +218,24 @@ class QueueManager(QWidget):
|
||||
index = int(name[5:])
|
||||
|
||||
if index == len(Config.queue_dict):
|
||||
logger.warning("向右移动调度队列时已到达最右端")
|
||||
logger.warning("向右移动调度队列时已到达最右端", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "已经是最后一个调度队列", "无法向右移动", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
if name in Config.running_list or f"调度队列_{index+1}" in Config.running_list:
|
||||
logger.warning("相关调度队列正在运行")
|
||||
logger.warning("相关调度队列正在运行", module="队列管理")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning", "相关调度队列正在运行", "请先停止调度队列", 5000
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(f"正在右移调度队列 {name}", module="队列管理")
|
||||
|
||||
self.queue_manager.clear_SettingBox()
|
||||
|
||||
# 移动配置文件并同步到相关配置项
|
||||
Config.queue_dict[name]["Path"].rename(
|
||||
Config.queue_dict[name]["Path"].with_name("调度队列_0.json")
|
||||
)
|
||||
@@ -244,12 +248,13 @@ class QueueManager(QWidget):
|
||||
|
||||
self.queue_manager.show_SettingBox(index + 1)
|
||||
|
||||
logger.success(f"{name} 右移成功")
|
||||
logger.success(f"{name} 右移成功", module="队列管理")
|
||||
MainInfoBar.push_info_bar("success", "操作成功", f"右移 {name}", 3000)
|
||||
|
||||
def reload_member_name(self):
|
||||
"""刷新调度队列成员"""
|
||||
|
||||
# 获取成员列表
|
||||
member_list = [
|
||||
["禁用"] + [_ for _ in Config.member_dict.keys()],
|
||||
["未启用"]
|
||||
@@ -337,7 +342,12 @@ class QueueManager(QWidget):
|
||||
self.switch_SettingBox(index)
|
||||
|
||||
def switch_SettingBox(self, index: int, if_change_pivot: bool = True) -> None:
|
||||
"""切换到指定的子界面"""
|
||||
"""
|
||||
切换到指定的子界面并切换到指定的子页面
|
||||
|
||||
:param index: 要切换到的子界面索引
|
||||
:param if_change_pivot: 是否更改导航栏当前项
|
||||
"""
|
||||
|
||||
if len(Config.queue_dict) == 0:
|
||||
return None
|
||||
|
||||
@@ -25,7 +25,6 @@ v4.4
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtCore import Qt
|
||||
@@ -49,7 +48,7 @@ from packaging import version
|
||||
from pathlib import Path
|
||||
from typing import Dict, Union
|
||||
|
||||
from app.core import Config, MainInfoBar, Network, SoundPlayer
|
||||
from app.core import Config, MainInfoBar, Network, SoundPlayer, logger
|
||||
from app.services import Crypto, System, Notify
|
||||
from .downloader import DownloadManager
|
||||
from .Widget import (
|
||||
@@ -124,7 +123,7 @@ class Setting(QWidget):
|
||||
self.window(),
|
||||
)
|
||||
if choice.exec():
|
||||
logger.success("确认授权bilibili游戏隐私政策")
|
||||
logger.success("确认授权bilibili游戏隐私政策", module="设置界面")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", "已确认授权bilibili游戏隐私政策", 3000
|
||||
)
|
||||
@@ -132,7 +131,7 @@ class Setting(QWidget):
|
||||
Config.set(Config.function_IfAgreeBilibili, False)
|
||||
else:
|
||||
|
||||
logger.info("取消授权bilibili游戏隐私政策")
|
||||
logger.info("取消授权bilibili游戏隐私政策", module="设置界面")
|
||||
MainInfoBar.push_info_bar(
|
||||
"info", "操作成功", "已取消授权bilibili游戏隐私政策", 3000
|
||||
)
|
||||
@@ -158,7 +157,7 @@ class Setting(QWidget):
|
||||
|
||||
MuMu_splash_ads_path.touch()
|
||||
|
||||
logger.success("开启跳过MuMu启动广告功能")
|
||||
logger.success("开启跳过MuMu启动广告功能", module="设置界面")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", "已开启跳过MuMu启动广告功能", 3000
|
||||
)
|
||||
@@ -170,7 +169,7 @@ class Setting(QWidget):
|
||||
if MuMu_splash_ads_path.exists() and MuMu_splash_ads_path.is_file():
|
||||
MuMu_splash_ads_path.unlink()
|
||||
|
||||
logger.info("关闭跳过MuMu启动广告功能")
|
||||
logger.info("关闭跳过MuMu启动广告功能", module="设置界面")
|
||||
MainInfoBar.push_info_bar(
|
||||
"info", "操作成功", "已关闭跳过MuMu启动广告功能", 3000
|
||||
)
|
||||
@@ -181,6 +180,8 @@ class Setting(QWidget):
|
||||
if Config.key_path.exists():
|
||||
return None
|
||||
|
||||
logger.info("未设置管理密钥,开始要求用户进行设置", module="设置界面")
|
||||
|
||||
while True:
|
||||
|
||||
choice = LineEditMessageBox(
|
||||
@@ -188,6 +189,7 @@ class Setting(QWidget):
|
||||
)
|
||||
if choice.exec() and choice.input.text() != "":
|
||||
Crypto.get_PASSWORD(choice.input.text())
|
||||
logger.success("成功设置管理密钥", module="设置界面")
|
||||
break
|
||||
else:
|
||||
choice = MessageBox(
|
||||
@@ -207,10 +209,7 @@ class Setting(QWidget):
|
||||
while if_change:
|
||||
|
||||
choice = LineEditMessageBox(
|
||||
self.window(),
|
||||
"请输入旧的管理密钥",
|
||||
"旧管理密钥",
|
||||
"密码",
|
||||
self.window(), "请输入旧的管理密钥", "旧管理密钥", "密码"
|
||||
)
|
||||
if choice.exec() and choice.input.text() != "":
|
||||
|
||||
@@ -231,6 +230,7 @@ class Setting(QWidget):
|
||||
|
||||
# 修改管理密钥
|
||||
Crypto.change_PASSWORD(PASSWORD_old, choice.input.text())
|
||||
logger.success("成功修改管理密钥", module="设置界面")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", "管理密钥修改成功", 3000
|
||||
)
|
||||
@@ -291,6 +291,7 @@ class Setting(QWidget):
|
||||
|
||||
# 重置管理密钥
|
||||
Crypto.reset_PASSWORD(choice.input.text())
|
||||
logger.success("成功重置管理密钥", module="设置界面")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", "管理密钥重置成功", 3000
|
||||
)
|
||||
@@ -316,7 +317,12 @@ class Setting(QWidget):
|
||||
)
|
||||
|
||||
def check_update(self, if_show: bool = False, if_first: bool = False) -> None:
|
||||
"""检查版本更新,调起文件下载进程"""
|
||||
"""
|
||||
检查版本更新,调起更新线程
|
||||
|
||||
:param if_show: 是否显示更新信息
|
||||
:param if_first: 是否为启动时检查更新
|
||||
"""
|
||||
|
||||
current_version = list(map(int, Config.VERSION.split(".")))
|
||||
|
||||
@@ -339,7 +345,9 @@ class Setting(QWidget):
|
||||
|
||||
if version_info["code"] != 0:
|
||||
|
||||
logger.error(f"获取版本信息时出错:{version_info['msg']}")
|
||||
logger.error(
|
||||
f"获取版本信息时出错:{version_info['msg']}", module="设置界面"
|
||||
)
|
||||
|
||||
error_remark_dict = {
|
||||
1001: "获取版本信息的URL参数不正确",
|
||||
@@ -372,7 +380,10 @@ class Setting(QWidget):
|
||||
|
||||
return None
|
||||
|
||||
logger.warning(f"获取版本信息时出错:{network_result['error_message']}")
|
||||
logger.warning(
|
||||
f"获取版本信息时出错:{network_result['error_message']}",
|
||||
module="设置界面",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"获取版本信息时出错",
|
||||
@@ -470,11 +481,12 @@ class Setting(QWidget):
|
||||
download_info = network_result["response_json"]
|
||||
else:
|
||||
logger.warning(
|
||||
f"获取应用列表时出错:{network_result['error_message']}"
|
||||
f"获取下载信息时出错:{network_result['error_message']}",
|
||||
module="设置界面",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"获取应用列表时出错",
|
||||
"获取下载信息时出错",
|
||||
f"网络错误:{network_result['status_code']}",
|
||||
5000,
|
||||
)
|
||||
@@ -492,6 +504,8 @@ class Setting(QWidget):
|
||||
"download_dict": download_info["download_dict"],
|
||||
}
|
||||
|
||||
logger.info("开始执行更新任务", module="设置界面")
|
||||
|
||||
self.downloader = DownloadManager(
|
||||
Config.app_path, "AUTO_MAA", remote_version, download_config
|
||||
)
|
||||
@@ -526,6 +540,9 @@ class Setting(QWidget):
|
||||
SoundPlayer.play("无新版本")
|
||||
|
||||
def start_setup(self) -> None:
|
||||
"""启动安装程序"""
|
||||
|
||||
logger.info("启动安装程序", module="设置界面")
|
||||
subprocess.Popen(
|
||||
[
|
||||
Config.app_path / "AUTO_MAA-Setup.exe",
|
||||
@@ -555,7 +572,10 @@ class Setting(QWidget):
|
||||
if network_result["status_code"] == 200:
|
||||
notice = network_result["response_json"]
|
||||
else:
|
||||
logger.warning(f"获取最新公告时出错:{network_result['error_message']}")
|
||||
logger.warning(
|
||||
f"获取最新公告时出错:{network_result['error_message']}",
|
||||
module="设置界面",
|
||||
)
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"获取最新公告时出错",
|
||||
|
||||
@@ -48,12 +48,7 @@ class ProcessManager(QObject):
|
||||
self.check_timer = QTimer()
|
||||
self.check_timer.timeout.connect(self.check_processes)
|
||||
|
||||
def open_process(
|
||||
self,
|
||||
path: Path,
|
||||
args: list = [],
|
||||
tracking_time: int = 60,
|
||||
) -> int:
|
||||
def open_process(self, path: Path, args: list = [], tracking_time: int = 60) -> int:
|
||||
"""
|
||||
启动一个新进程并返回其pid,并开始监视该进程
|
||||
|
||||
@@ -89,7 +84,7 @@ class ProcessManager(QObject):
|
||||
|
||||
# 扫描并记录所有相关进程
|
||||
try:
|
||||
# 获取主进程及其子进程
|
||||
# 获取主进程
|
||||
main_proc = psutil.Process(self.main_pid)
|
||||
self.tracked_pids.add(self.main_pid)
|
||||
|
||||
|
||||
192
main.py
192
main.py
@@ -44,10 +44,10 @@ def no_print(*args, **kwargs):
|
||||
builtins.print = no_print
|
||||
|
||||
|
||||
from loguru import logger
|
||||
import os
|
||||
import sys
|
||||
import ctypes
|
||||
import traceback
|
||||
from PySide6.QtWidgets import QApplication
|
||||
from qfluentwidgets import FluentTranslator
|
||||
|
||||
@@ -60,24 +60,200 @@ def is_admin() -> bool:
|
||||
return False
|
||||
|
||||
|
||||
@logger.catch
|
||||
def main():
|
||||
def show_system_error(title: str, message: str, detailed_error: str = None):
|
||||
"""使用系统级消息框显示错误"""
|
||||
try:
|
||||
# Windows系统消息框
|
||||
if sys.platform == "win32":
|
||||
# 组合完整的错误信息
|
||||
full_message = message
|
||||
if detailed_error:
|
||||
# 限制详细错误信息长度,避免消息框过大
|
||||
if len(detailed_error) > 2000:
|
||||
detailed_error = (
|
||||
detailed_error[:2000] + "\n\n... (错误信息过长已截断)"
|
||||
)
|
||||
full_message += f"\n\n详细错误信息:\n{detailed_error}"
|
||||
|
||||
# 使用ctypes调用Windows API
|
||||
ctypes.windll.user32.MessageBoxW(
|
||||
0, # 父窗口句柄
|
||||
full_message, # 消息内容
|
||||
title, # 标题
|
||||
0x10 | 0x0, # MB_ICONERROR | MB_OK
|
||||
)
|
||||
|
||||
# Linux系统 - 尝试使用zenity或kdialog
|
||||
elif sys.platform.startswith("linux"):
|
||||
full_message = message
|
||||
if detailed_error:
|
||||
full_message += f"\n\n详细错误:\n{detailed_error[:1000]}"
|
||||
|
||||
try:
|
||||
# 尝试zenity (GNOME)
|
||||
os.system(
|
||||
f'zenity --error --title="{title}" --text="{full_message}" 2>/dev/null'
|
||||
)
|
||||
except:
|
||||
try:
|
||||
# 尝试kdialog (KDE)
|
||||
os.system(
|
||||
f'kdialog --error "{full_message}" --title "{title}" 2>/dev/null'
|
||||
)
|
||||
except:
|
||||
# 降级到控制台输出
|
||||
print(f"错误: {title}")
|
||||
print(f"消息: {message}")
|
||||
if detailed_error:
|
||||
print(f"详细信息:\n{detailed_error}")
|
||||
|
||||
# macOS系统
|
||||
elif sys.platform == "darwin":
|
||||
full_message = message
|
||||
if detailed_error:
|
||||
full_message += f"\n\n详细错误:\n{detailed_error[:1000]}"
|
||||
|
||||
try:
|
||||
os.system(
|
||||
f'osascript -e \'display alert "{title}" message "{full_message}" as critical\''
|
||||
)
|
||||
except:
|
||||
print(f"错误: {title}")
|
||||
print(f"消息: {message}")
|
||||
if detailed_error:
|
||||
print(f"详细信息:\n{detailed_error}")
|
||||
|
||||
else:
|
||||
# 其他系统降级到控制台输出
|
||||
print(f"错误: {title}")
|
||||
print(f"消息: {message}")
|
||||
if detailed_error:
|
||||
print(f"详细信息:\n{detailed_error}")
|
||||
|
||||
except Exception as e:
|
||||
# 如果连系统消息框都失败了,输出到控制台
|
||||
print(f"无法显示错误对话框: {e}")
|
||||
print(f"原始错误: {title} - {message}")
|
||||
if detailed_error:
|
||||
print(f"详细错误信息:\n{detailed_error}")
|
||||
|
||||
|
||||
def save_error_log(error_info: str):
|
||||
"""保存错误日志到文件"""
|
||||
try:
|
||||
import datetime
|
||||
|
||||
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
log_dir = os.path.join(os.path.dirname(__file__), "debug")
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
|
||||
log_file = os.path.join(log_dir, f"crash_{timestamp}.log")
|
||||
with open(log_file, "w", encoding="utf-8") as f:
|
||||
f.write(f"AUTO_MAA 崩溃日志\n")
|
||||
f.write(f"时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
f.write(f"Python版本: {sys.version}\n")
|
||||
f.write(f"平台: {sys.platform}\n")
|
||||
f.write(f"工作目录: {os.getcwd()}\n")
|
||||
f.write("=" * 50 + "\n")
|
||||
f.write(error_info)
|
||||
|
||||
return log_file
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
"""主程序入口"""
|
||||
application = None
|
||||
|
||||
try:
|
||||
# 创建QApplication
|
||||
application = QApplication(sys.argv)
|
||||
|
||||
# 安装翻译器
|
||||
translator = FluentTranslator()
|
||||
application.installTranslator(translator)
|
||||
|
||||
try:
|
||||
# 导入主窗口模块
|
||||
from app.ui.main_window import AUTO_MAA
|
||||
|
||||
# 创建主窗口
|
||||
window = AUTO_MAA()
|
||||
window.show_ui("显示主窗口", if_start=True)
|
||||
window.start_up_task()
|
||||
|
||||
except ImportError as e:
|
||||
error_msg = f"模块导入失败: {str(e)}"
|
||||
detailed_error = traceback.format_exc()
|
||||
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
|
||||
|
||||
if log_file:
|
||||
error_msg += f"\n\n错误日志已保存到: {log_file}"
|
||||
|
||||
show_system_error("模块导入错误", error_msg, detailed_error)
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"主窗口创建失败: {str(e)}"
|
||||
detailed_error = traceback.format_exc()
|
||||
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
|
||||
|
||||
if log_file:
|
||||
error_msg += f"\n\n错误日志已保存到: {log_file}"
|
||||
|
||||
show_system_error("窗口创建错误", error_msg, detailed_error)
|
||||
return
|
||||
|
||||
# 启动事件循环
|
||||
sys.exit(application.exec())
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"应用程序启动失败: {str(e)}"
|
||||
detailed_error = traceback.format_exc()
|
||||
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
|
||||
|
||||
if log_file:
|
||||
error_msg += f"\n\n错误日志已保存到: {log_file}"
|
||||
|
||||
# 尝试显示错误对话框
|
||||
show_system_error("应用程序启动错误", error_msg, detailed_error)
|
||||
|
||||
# 如果有应用程序实例,确保正确退出
|
||||
if application:
|
||||
try:
|
||||
application.quit()
|
||||
except:
|
||||
pass
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def handle_exception(exc_type, exc_value, exc_traceback):
|
||||
"""全局异常处理器"""
|
||||
if issubclass(exc_type, KeyboardInterrupt):
|
||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||
return
|
||||
|
||||
error_msg = f"未处理的异常: {exc_type.__name__}: {str(exc_value)}"
|
||||
detailed_error = "".join(
|
||||
traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
)
|
||||
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
|
||||
|
||||
if log_file:
|
||||
error_msg += f"\n\n错误日志已保存到: {log_file}"
|
||||
|
||||
show_system_error("程序异常", error_msg, detailed_error)
|
||||
|
||||
|
||||
# 设置全局异常处理器
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
try:
|
||||
if is_admin():
|
||||
main()
|
||||
else:
|
||||
@@ -85,3 +261,13 @@ if __name__ == "__main__":
|
||||
None, "runas", sys.executable, os.path.realpath(sys.argv[0]), None, 1
|
||||
)
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
error_msg = f"程序启动失败: {str(e)}"
|
||||
detailed_error = traceback.format_exc()
|
||||
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
|
||||
|
||||
if log_file:
|
||||
error_msg += f"\n\n错误日志已保存到: {log_file}"
|
||||
|
||||
show_system_error("启动错误", error_msg, detailed_error)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,60 +1,14 @@
|
||||
{
|
||||
"main_version": "4.4.0.0",
|
||||
"main_version": "4.4.1.1",
|
||||
"version_info": {
|
||||
"4.4.0.0": {
|
||||
"新增功能": [
|
||||
"通用配置模式接入日志系统"
|
||||
],
|
||||
"4.4.1.1": {
|
||||
"修复BUG": [
|
||||
"信任系统证书,并添加网络代理地址配置项 #50",
|
||||
"适配 MAA 任务及基建设施日志翻译"
|
||||
"修复MAA掉落物统计功能",
|
||||
"修复模拟器界面被异常关闭且无法重新打开的问题"
|
||||
],
|
||||
"程序优化": [
|
||||
"重构历史记录保存与载入逻辑"
|
||||
]
|
||||
},
|
||||
"4.4.0.5": {
|
||||
"新增功能": [
|
||||
"添加导入导出通用配置功能"
|
||||
],
|
||||
"修复BUG": [
|
||||
"修复开机自启相关功能"
|
||||
]
|
||||
},
|
||||
"4.4.0.4": {
|
||||
"新增功能": [
|
||||
"添加重置管理密钥功能"
|
||||
],
|
||||
"修复BUG": [
|
||||
"修复无计划表时数据系统无法正常升级到v1.7的问题"
|
||||
]
|
||||
},
|
||||
"4.4.0.3": {
|
||||
"修复BUG": [
|
||||
"适配 MAA 备选关卡字段修改",
|
||||
"修复无成功日志时的脚本判定逻辑"
|
||||
],
|
||||
"程序优化": [
|
||||
"`GameId`字段改为 `Stage`,与 MAA 保持一致"
|
||||
]
|
||||
},
|
||||
"4.4.0.2": {
|
||||
"新增功能": [
|
||||
"进一步适配三月七相关配置项"
|
||||
],
|
||||
"修复BUG": [
|
||||
"适配 Mirror 酱 平台下载策略调整"
|
||||
]
|
||||
},
|
||||
"4.4.0.1": {
|
||||
"新增功能": [
|
||||
"初步完成通用调度模块"
|
||||
],
|
||||
"修复BUG": [
|
||||
"修复了程序BUG较少的BUG"
|
||||
],
|
||||
"程序优化": [
|
||||
"子线程卡死不再阻塞调度任务"
|
||||
"重构日志记录,载入更多日志记录项",
|
||||
"优化日志监看启停逻辑"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user