diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 9ae66d2..0b27c92 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -135,18 +135,3 @@ jobs: - name: Upload Release to Server run: | scp -r artifacts/* ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:/home/user/files/AUTO_MAA/ - - name: Install obsutil - run: | - wget https://obs-community.obs.cn-north-1.myhuaweicloud.com/obsutil/current/obsutil_linux_amd64.tar.gz - tar -xzvf obsutil_linux_amd64.tar.gz --strip-components=1 - chmod 755 obsutil - ./obsutil version - - name: Upload Release to Huawei OBS - env: - OBS_AK: ${{ secrets.OBS_AK }} - OBS_SK: ${{ secrets.OBS_SK }} - OBS_ENDPOINT: ${{ secrets.OBS_ENDPOINT }} - OBS_BUCKET: ${{ secrets.OBS_BUCKET }} - run: | - ./obsutil config -i $OBS_AK -k $OBS_SK -e $OBS_ENDPOINT - ./obsutil cp artifacts/ obs://$OBS_BUCKET/releases/ -r -f diff --git a/README.md b/README.md index 3d5d9ca..4a1a8ea 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,20 @@ -# AUTO_MAA - -MAA多账号管理与自动化软件 - -!["软件图标"](https://github.com/DLmaster361/AUTO_MAA/blob/main/resources/images/AUTO_MAA.png "软件图标") +

AUTO_MAA

+

+ MAA多账号管理与自动化软件

+ 软件图标 +

--- - - -[![GitHub Stars](https://img.shields.io/github/stars/DLmaster361/AUTO_MAA?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/stargazers) -[![GitHub Forks](https://img.shields.io/github/forks/DLmaster361/AUTO_MAA?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/network) -[![GitHub Downloads](https://img.shields.io/github/downloads/DLmaster361/AUTO_MAA/total?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/releases/latest) -[![GitHub Issues](https://img.shields.io/github/issues/DLmaster361/AUTO_MAA?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/issues) -[![GitHub Contributors](https://img.shields.io/github/contributors/DLmaster361/AUTO_MAA?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/graphs/contributors) -[![GitHub License](https://img.shields.io/github/license/DLmaster361/AUTO_MAA?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/blob/main/LICENSE) -[![mirrorc](https://img.shields.io/badge/Mirror%E9%85%B1-%239af3f6?logo=countingworkspro&logoColor=4f46e5)](https://mirrorchyan.com/zh/projects?rid=AUTO_MAA) - +

+ GitHub Stars + GitHub Forks + GitHub Downloads + GitHub Issues + GitHub Contributors + GitHub License + mirrorc +

## 软件介绍 diff --git a/app/core/config.py b/app/core/config.py index 231ab69..0729d4e 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -103,6 +103,9 @@ class GlobalConfig(QConfig): "Function", "IfSilence", False, BoolValidator() ) self.function_BossKey = ConfigItem("Function", "BossKey", "") + self.function_UnattendedMode = ConfigItem( + "Function", "UnattendedMode", False, BoolValidator() + ) self.function_IfAgreeBilibili = ConfigItem( "Function", "IfAgreeBilibili", False, BoolValidator() ) @@ -614,7 +617,7 @@ class MaaUserConfig(QConfig): class AppConfig(GlobalConfig): - VERSION = "4.3.5.0" + VERSION = "4.3.6.2" gameid_refreshed = Signal() PASSWORD_refreshed = Signal() @@ -633,6 +636,7 @@ class AppConfig(GlobalConfig): self.gameid_path = self.app_path / "data/gameid.txt" self.version_path = self.app_path / "resources/version.json" + self.main_window = None self.PASSWORD = "" self.running_list = [] self.silence_list = [] diff --git a/app/core/main_info_bar.py b/app/core/main_info_bar.py index 729bb11..791f8c4 100644 --- a/app/core/main_info_bar.py +++ b/app/core/main_info_bar.py @@ -29,17 +29,15 @@ from loguru import logger from PySide6.QtCore import Qt from qfluentwidgets import InfoBar, InfoBarPosition +from .config import Config + class _MainInfoBar: """信息通知栏""" - def __init__(self, main_window=None): - - self.main_window = main_window - def push_info_bar(self, mode: str, title: str, content: str, time: int): """推送到信息通知栏""" - if self.main_window is None: + if Config.main_window is None: logger.error("信息通知栏未设置父窗口") return None @@ -61,7 +59,7 @@ class _MainInfoBar: isClosable=True, position=InfoBarPosition.TOP_RIGHT, duration=time, - parent=self.main_window, + parent=Config.main_window, ) else: logger.error(f"未知的通知栏模式: {mode}") diff --git a/app/core/task_manager.py b/app/core/task_manager.py index 51ad27f..868f611 100644 --- a/app/core/task_manager.py +++ b/app/core/task_manager.py @@ -173,10 +173,9 @@ class _TaskManager(QObject): create_gui = Signal(Task) connect_gui = Signal(Task) - def __init__(self, main_window=None): + def __init__(self): super(_TaskManager, self).__init__() - self.main_window = main_window self.task_dict: Dict[str, Task] = {} def add_task( @@ -279,7 +278,7 @@ class _TaskManager(QObject): } choice = ProgressRingMessageBox( - self.main_window, + Config.main_window, f"{mode_book[Config.queue_dict[name]["Config"].get(Config.queue_dict[name]["Config"].queueSet_AfterAccomplish)]}倒计时", ) if choice.exec(): @@ -325,7 +324,7 @@ class _TaskManager(QObject): def push_dialog(self, name: str, title: str, content: str): """推送对话框""" - choice = MessageBox(title, content, self.main_window) + choice = MessageBox(title, content, Config.main_window) choice.yesButton.setText("是") choice.cancelButton.setText("否") diff --git a/app/core/timer.py b/app/core/timer.py index 3679fd9..f019076 100644 --- a/app/core/timer.py +++ b/app/core/timer.py @@ -55,6 +55,9 @@ class _MainTimer(QWidget): """长时间定期检定任务""" Config.get_gameid() + Config.main_window.setting.show_notice() + if Config.get(Config.update_IfAutoUpdate): + Config.main_window.setting.check_update() def timed_start(self): """定时启动代理任务""" diff --git a/app/models/MAA.py b/app/models/MAA.py index e036f08..73cb04c 100644 --- a/app/models/MAA.py +++ b/app/models/MAA.py @@ -92,6 +92,7 @@ class MaaManager(QObject): self.maa_version = None self.maa_update_package = "" + self.task_dict = {} self.set = config["Config"].toDict() self.data = {} @@ -264,6 +265,67 @@ class MaaManager(QObject): ] ) + # 解析任务构成 + if user_data["Info"]["Mode"] == "简洁": + + if mode == "Annihilation": + self.task_dict = { + "WakeUp": "True", + "Recruiting": "False", + "Base": "False", + "Combat": "True", + "Mission": "False", + "Mall": "False", + "AutoRoguelike": "False", + "Reclamation": "False", + } + + elif mode == "Routine": + self.task_dict = { + "WakeUp": "True", + "Recruiting": "True", + "Base": "True", + "Combat": "True", + "Mission": "True", + "Mall": "True", + "AutoRoguelike": "False", + "Reclamation": "False", + } + + elif user_data["Info"]["Mode"] == "详细": + + with (self.data[user[2]]["Path"] / f"{mode}/gui.json").open( + mode="r", encoding="utf-8" + ) as f: + data = json.load(f) + + self.task_dict = { + "WakeUp": data["Configurations"]["Default"][ + "TaskQueue.WakeUp.IsChecked" + ], + "Recruiting": data["Configurations"]["Default"][ + "TaskQueue.Recruiting.IsChecked" + ], + "Base": data["Configurations"]["Default"][ + "TaskQueue.Base.IsChecked" + ], + "Combat": data["Configurations"]["Default"][ + "TaskQueue.Combat.IsChecked" + ], + "Mission": data["Configurations"]["Default"][ + "TaskQueue.Mission.IsChecked" + ], + "Mall": data["Configurations"]["Default"][ + "TaskQueue.Mall.IsChecked" + ], + "AutoRoguelike": data["Configurations"]["Default"][ + "TaskQueue.AutoRoguelike.IsChecked" + ], + "Reclamation": data["Configurations"]["Default"][ + "TaskQueue.Reclamation.IsChecked" + ], + } + # 尝试次数循环 for i in range(self.set["RunSet"]["RunTimesLimit"]): @@ -402,10 +464,13 @@ class MaaManager(QObject): mode="r", encoding="utf-8" ) as f: data = json.load(f) + + # 记录自定义基建索引 user_data["Data"]["CustomInfrastPlanIndex"] = data[ "Configurations" ]["Default"]["Infrast.CustomInfrastPlanIndex"] + # 记录更新包路径 if ( data["Global"]["VersionUpdate.package"] and ( @@ -451,6 +516,8 @@ class MaaManager(QObject): mode="r", encoding="utf-8" ) as f: data = json.load(f) + + # 记录更新包路径 if ( data["Global"]["VersionUpdate.package"] and ( @@ -871,26 +938,53 @@ class MaaManager(QObject): else: self.weekly_annihilation_limit_reached = False - if mode == "自动代理_日常" and "任务出错: Fight" in log: - self.maa_result = "MAA未能实际执行任务" - elif "任务出错: StartUp" in log: + if "任务出错: StartUp" in log: self.maa_result = "MAA未能正确登录PRTS" + elif "任务已全部完成!" in log: - self.maa_result = "Success!" + + if "完成任务: StartUp" in log: + self.task_dict["WakeUp"] = "False" + if "完成任务: Recruit" in log: + self.task_dict["Recruiting"] = "False" + if "完成任务: Infrast" in log: + self.task_dict["Base"] = "False" + if "完成任务: Fight" in log or "剿灭任务失败" in log: + self.task_dict["Combat"] = "False" + if "完成任务: Mall" in log: + self.task_dict["Mall"] = "False" + if "完成任务: Award" in log: + self.task_dict["Mission"] = "False" + if "完成任务: Roguelike" in log: + self.task_dict["AutoRoguelike"] = "False" + if "完成任务: Reclamation" in log: + self.task_dict["Reclamation"] = "False" + + if all(v == "False" for v in self.task_dict.values()): + self.maa_result = "Success!" + else: + self.maa_result = "MAA部分任务执行失败" + elif "请「检查连接设置」或「尝试重启模拟器与 ADB」或「重启电脑」" in log: self.maa_result = "MAA的ADB连接异常" + elif "未检测到任何模拟器" in log: self.maa_result = "MAA未检测到任何模拟器" + elif "已停止" in log: self.maa_result = "MAA在完成任务前中止" + elif "MaaAssistantArknights GUI exited" in log: self.maa_result = "MAA在完成任务前退出" + elif datetime.now() - latest_time > timedelta( minutes=self.set["RunSet"][time_book[mode]] ): self.maa_result = "MAA进程超时" + elif self.isInterruptionRequested: self.maa_result = "任务被手动中止" + else: self.maa_result = "Wait" @@ -1071,8 +1165,35 @@ class MaaManager(QObject): "Info" ]["Id"] + # 按预设设定任务 + data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = ( + self.task_dict["Recruiting"] + ) # 自动公招 + data["Configurations"]["Default"]["TaskQueue.Base.IsChecked"] = ( + self.task_dict["Base"] + ) # 基建换班 + data["Configurations"]["Default"]["TaskQueue.Combat.IsChecked"] = ( + self.task_dict["Combat"] + ) # 刷理智 + data["Configurations"]["Default"]["TaskQueue.Mission.IsChecked"] = ( + self.task_dict["Mission"] + ) # 领取奖励 + data["Configurations"]["Default"]["TaskQueue.Mall.IsChecked"] = ( + self.task_dict["Mall"] + ) # 获取信用及购物 + data["Configurations"]["Default"]["TaskQueue.AutoRoguelike.IsChecked"] = ( + self.task_dict["AutoRoguelike"] + ) # 自动肉鸽 + data["Configurations"]["Default"]["TaskQueue.Reclamation.IsChecked"] = ( + self.task_dict["Reclamation"] + ) # 生息演算 + if user_data["Info"]["Mode"] == "简洁": + data["Configurations"]["Default"][ + "TaskQueue.WakeUp.IsChecked" + ] = "True" # 开始唤醒 + data["Configurations"]["Default"]["Start.ClientType"] = user_data[ "Info" ][ @@ -1091,30 +1212,6 @@ class MaaManager(QObject): if "剿灭" in mode: - data["Configurations"]["Default"][ - "TaskQueue.WakeUp.IsChecked" - ] = "True" # 开始唤醒 - data["Configurations"]["Default"][ - "TaskQueue.Recruiting.IsChecked" - ] = "False" # 自动公招 - data["Configurations"]["Default"][ - "TaskQueue.Base.IsChecked" - ] = "False" # 基建换班 - data["Configurations"]["Default"][ - "TaskQueue.Combat.IsChecked" - ] = "True" # 刷理智 - data["Configurations"]["Default"][ - "TaskQueue.Mission.IsChecked" - ] = "False" # 领取奖励 - data["Configurations"]["Default"][ - "TaskQueue.Mall.IsChecked" - ] = "False" # 获取信用及购物 - data["Configurations"]["Default"][ - "TaskQueue.AutoRoguelike.IsChecked" - ] = "False" # 自动肉鸽 - data["Configurations"]["Default"][ - "TaskQueue.Reclamation.IsChecked" - ] = "False" # 生息演算 data["Configurations"]["Default"][ "MainFunction.Stage1" ] = "Annihilation" # 主关卡 @@ -1151,31 +1248,6 @@ class MaaManager(QObject): elif "日常" in mode: - data["Configurations"]["Default"][ - "TaskQueue.WakeUp.IsChecked" - ] = "True" # 开始唤醒 - data["Configurations"]["Default"][ - "TaskQueue.Recruiting.IsChecked" - ] = "True" # 自动公招 - data["Configurations"]["Default"][ - "TaskQueue.Base.IsChecked" - ] = "True" # 基建换班 - data["Configurations"]["Default"][ - "TaskQueue.Combat.IsChecked" - ] = "True" # 刷理智 - data["Configurations"]["Default"][ - "TaskQueue.Mission.IsChecked" - ] = "True" # 领取奖励 - data["Configurations"]["Default"][ - "TaskQueue.Mall.IsChecked" - ] = "True" # 获取信用及购物 - data["Configurations"]["Default"][ - "TaskQueue.AutoRoguelike.IsChecked" - ] = "False" # 自动肉鸽 - data["Configurations"]["Default"][ - "TaskQueue.Reclamation.IsChecked" - ] = "False" # 生息演算 - data["Configurations"]["Default"]["MainFunction.UseMedicine"] = ( "False" if user_data["Info"]["MedicineNumb"] == 0 else "True" ) # 吃理智药 diff --git a/app/services/notification.py b/app/services/notification.py index 5449edf..0f63acf 100644 --- a/app/services/notification.py +++ b/app/services/notification.py @@ -37,9 +37,6 @@ from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header from email.utils import formataddr - -from serverchan_sdk import sc_send - from app.core import Config from app.services.security import Crypto @@ -143,76 +140,91 @@ class Notification(QWidget): self.push_info_bar.emit("error", "发送邮件时出错", f"{e}", -1) def ServerChanPush(self, title, content): - """使用Server酱推送通知""" - + """使用Server酱推送通知(支持 tag 和 channel,避免使用SDK)""" if Config.get(Config.notify_IfServerChan): + send_key = Config.get(Config.notify_ServerChanKey) - if Config.get(Config.notify_ServerChanKey) == "": + if not send_key: logger.error("请正确设置Server酱的SendKey") self.push_info_bar.emit( - "error", - "Server酱通知推送异常", - "请正确设置Server酱的SendKey", - -1, + "error", "Server酱通知推送异常", "请正确设置Server酱的SendKey", -1 ) return None - else: - send_key = Config.get(Config.notify_ServerChanKey) - option = {} - is_valid = lambda s: s == "" or ( - s == "|".join(s.split("|")) and (s.count("|") == 0 or all(s.split("|"))) - ) - """ - is_valid => True, 如果启用的话需要正确设置Tag和Channel。 - 允许空的Tag和Channel即不启用,但不允许例如a||b,|a|b,a|b|,|||| - """ - send_tag = "|".join( - _.strip() for _ in Config.get(Config.notify_ServerChanTag).split("|") - ) - send_channel = "|".join( - _.strip() - for _ in Config.get(Config.notify_ServerChanChannel).split("|") - ) + try: + # 构造 URL + if send_key.startswith("sctp"): + match = re.match(r"^sctp(\d+)t", send_key) + if match: + url = f"https://{match.group(1)}.push.ft07.com/send/{send_key}.send" + else: + raise ValueError("SendKey 格式错误(sctp)") + else: + url = f"https://sctapi.ftqq.com/{send_key}.send" - if is_valid(send_tag): - option["tags"] = send_tag - else: - option["tags"] = "" - logger.warning("请正确设置Auto_MAA中ServerChan的Tag。") - self.push_info_bar.emit( - "warning", - "Server酱通知推送异常", - "请正确设置Auto_MAA中ServerChan的Tag。", - -1, + # 构建 tags 和 channel + def is_valid(s): + return s == "" or ( + s == "|".join(s.split("|")) + and (s.count("|") == 0 or all(s.split("|"))) + ) + + tags = "|".join( + _.strip() + for _ in Config.get(Config.notify_ServerChanTag).split("|") + ) + channels = "|".join( + _.strip() + for _ in Config.get(Config.notify_ServerChanChannel).split("|") ) - if is_valid(send_channel): - option["channel"] = send_channel - else: - option["channel"] = "" - logger.warning("请正确设置Auto_MAA中ServerChan的Channel。") - self.push_info_bar.emit( - "warning", - "Server酱通知推送异常", - "请正确设置Auto_MAA中ServerChan的Channel。", - -1, - ) + options = {} + if is_valid(tags): + options["tags"] = tags + else: + logger.warning("Server酱 Tag 配置不正确,将被忽略") + self.push_info_bar.emit( + "warning", + "Server酱通知推送异常", + "请正确设置 ServerChan 的 Tag", + -1, + ) - response = sc_send(send_key, title, content, option) - if response["code"] == 0: - logger.info("Server酱推送通知成功") - return True - else: - logger.info("Server酱推送通知失败") - logger.error(response) + if is_valid(channels): + options["channel"] = channels + else: + logger.warning("Server酱 Channel 配置不正确,将被忽略") + self.push_info_bar.emit( + "warning", + "Server酱通知推送异常", + "请正确设置 ServerChan 的 Channel", + -1, + ) + + # 请求发送 + params = {"title": title, "desp": content, **options} + headers = {"Content-Type": "application/json;charset=utf-8"} + + response = requests.post(url, json=params, headers=headers, timeout=10) + result = response.json() + + if result.get("code") == 0: + logger.info("Server酱推送通知成功") + return True + else: + error_code = result.get("code", "-1") + logger.error(f"Server酱通知推送失败:响应码:{error_code}") + self.push_info_bar.emit( + "error", "Server酱通知推送失败", f"响应码:{error_code}", -1 + ) + return f"Server酱通知推送失败:{error_code}" + + except Exception as e: + logger.exception("Server酱通知推送异常") self.push_info_bar.emit( - "error", - "Server酱通知推送失败", - f'使用Server酱推送通知时出错:\n{response["data"]['error']}', - -1, + "error", "Server酱通知推送异常", f"请检查相关设置,如还有问题可联系开发者", -1 ) - return f'使用Server酱推送通知时出错:\n{response["data"]['error']}' + return f"Server酱通知推送异常:{str(e)}" def CompanyWebHookBotPush(self, title, content): """使用企业微信群机器人推送通知""" diff --git a/app/services/system.py b/app/services/system.py index f329487..32f4491 100644 --- a/app/services/system.py +++ b/app/services/system.py @@ -44,9 +44,7 @@ class _SystemHandler: ES_CONTINUOUS = 0x80000000 ES_SYSTEM_REQUIRED = 0x00000001 - def __init__(self, main_window: QWidget = None): - - self.main_window = main_window + def __init__(self): self.set_Sleep() self.set_SelfStart() @@ -112,7 +110,7 @@ class _SystemHandler: elif mode == "KillSelf": - self.main_window.close() + Config.main_window.close() QApplication.quit() elif sys.platform.startswith("linux"): @@ -138,7 +136,7 @@ class _SystemHandler: elif mode == "KillSelf": - self.main_window.close() + Config.main_window.close() QApplication.quit() def is_startup(self) -> bool: diff --git a/app/ui/main_window.py b/app/ui/main_window.py index e5dbc24..e3acc55 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -26,7 +26,7 @@ v4.3 """ from loguru import logger -from PySide6.QtWidgets import QSystemTrayIcon +from PySide6.QtWidgets import QApplication, QSystemTrayIcon from qfluentwidgets import ( qconfig, Action, @@ -62,16 +62,22 @@ class AUTO_MAA(MSFluentWindow): super().__init__() self.setWindowIcon(QIcon(str(Config.app_path / "resources/icons/AUTO_MAA.ico"))) - self.setWindowTitle("AUTO_MAA") + + version_numb = list(map(int, Config.VERSION.split("."))) + version_text = ( + f"v{'.'.join(str(_) for _ in version_numb[0:3])}" + if version_numb[3] == 0 + else f"v{'.'.join(str(_) for _ in version_numb[0:3])}-beta.{version_numb[3]}" + ) + + self.setWindowTitle(f"AUTO_MAA - {version_text}") self.switch_theme() self.splashScreen = SplashScreen(self.windowIcon(), self) self.show_ui("显示主窗口", if_quick=True) - TaskManager.main_window = self.window() - MainInfoBar.main_window = self.window() - System.main_window = self.window() + Config.main_window = self.window() # 创建主窗口 self.home = Home(self) @@ -173,13 +179,19 @@ class AUTO_MAA(MSFluentWindow): # 退出主程序菜单项 self.tray_menu.addAction( - Action(FluentIcon.POWER_BUTTON, "退出主程序", triggered=self.window().close) + Action( + FluentIcon.POWER_BUTTON, + "退出主程序", + triggered=lambda: (self.window().close(), QApplication.quit()), + ) ) # 设置托盘菜单 self.tray.setContextMenu(self.tray_menu) self.tray.activated.connect(self.on_tray_activated) + self.set_min_method() + Config.user_info_changed.connect(self.member_manager.refresh_dashboard) TaskManager.create_gui.connect(self.dispatch_center.add_board) TaskManager.connect_gui.connect(self.dispatch_center.connect_main_board) @@ -255,11 +267,11 @@ class AUTO_MAA(MSFluentWindow): self.start_main_task() # 获取公告 - self.setting.show_notice(if_show=False) + self.setting.show_notice(if_first=True) # 检查更新 if Config.get(Config.update_IfAutoUpdate): - self.setting.check_update() + self.setting.check_update(if_first=True) # 直接最小化 if Config.get(Config.start_IfMinimizeDirectly): @@ -347,27 +359,37 @@ class AUTO_MAA(MSFluentWindow): if mode == "显示主窗口": # 配置主窗口 - size = list( - map( - int, - Config.get(Config.ui_size).split("x"), + if not self.window().isVisible(): + size = list( + map( + int, + Config.get(Config.ui_size).split("x"), + ) ) - ) - location = list( - map( - int, - Config.get(Config.ui_location).split("x"), + location = list( + map( + int, + Config.get(Config.ui_location).split("x"), + ) ) - ) - self.window().setGeometry(location[0], location[1], size[0], size[1]) - self.window().show() + if self.window().isMaximized(): + self.window().showNormal() + self.window().setGeometry(location[0], location[1], size[0], size[1]) + self.window().show() + if not if_quick: + if Config.get(Config.ui_maximized): + self.titleBar.maxBtn.click() + self.show_ui("配置托盘") + + if not any( + self.window().geometry().intersects(screen.availableGeometry()) + for screen in QApplication.screens() + ): + self.window().showNormal() + self.window().setGeometry(100, 100, 1200, 700) + self.window().raise_() self.window().activateWindow() - if not if_quick: - if Config.get(Config.ui_maximized): - self.window().showMaximized() - self.set_min_method() - self.show_ui("配置托盘") elif mode == "配置托盘": @@ -389,6 +411,7 @@ class AUTO_MAA(MSFluentWindow): Config.ui_location, f"{self.geometry().x()}x{self.geometry().y()}", ) + Config.set(Config.ui_maximized, self.window().isMaximized()) Config.save() diff --git a/app/ui/member_manager.py b/app/ui/member_manager.py index 2fef2e9..467345d 100644 --- a/app/ui/member_manager.py +++ b/app/ui/member_manager.py @@ -1207,14 +1207,24 @@ class MemberManager(QWidget): int(name[3:]) - 1, 9, QTableWidgetItem( - Config.gameid_dict["ALL"]["text"][ - Config.gameid_dict["ALL"]["value"].index( - config.get(config.Info_GameId_Remain) + "不使用" + if config.get(config.Info_GameId_Remain) == "-" + else ( + ( + Config.gameid_dict["ALL"]["text"][ + Config.gameid_dict["ALL"][ + "value" + ].index( + config.get( + config.Info_GameId_Remain + ) + ) + ] ) - ] - if config.get(config.Info_GameId_Remain) - in Config.gameid_dict["ALL"]["value"] - else config.get(config.Info_GameId_Remain) + if config.get(config.Info_GameId_Remain) + in Config.gameid_dict["ALL"]["value"] + else config.get(config.Info_GameId_Remain) + ) ), ) self.dashboard.setCellWidget( @@ -1403,7 +1413,10 @@ class MemberManager(QWidget): title="剩余理智关卡", content="按下回车以添加自定义关卡号", value=Config.gameid_dict["ALL"]["value"], - texts=Config.gameid_dict["ALL"]["text"], + texts=[ + "不使用" if _ == "当前/上次" else _ + for _ in Config.gameid_dict["ALL"]["text"] + ], qconfig=self.config, configItem=self.config.Info_GameId_Remain, parent=self, @@ -1513,7 +1526,10 @@ class MemberManager(QWidget): ) self.card_GameId_Remain.reLoadOptions( Config.gameid_dict["ALL"]["value"], - Config.gameid_dict["ALL"]["text"], + [ + "不使用" if _ == "当前/上次" else _ + for _ in Config.gameid_dict["ALL"]["text"] + ], ) def refresh_password(self): diff --git a/app/ui/setting.py b/app/ui/setting.py index a6780df..fe94877 100644 --- a/app/ui/setting.py +++ b/app/ui/setting.py @@ -87,9 +87,9 @@ class Setting(QWidget): self.start.card_IfSelfStart.checkedChanged.connect(System.set_SelfStart) self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD) self.updater.card_CheckUpdate.clicked.connect( - lambda: self.check_update(if_click=True) + lambda: self.check_update(if_show=True) ) - self.other.card_Notice.clicked.connect(self.show_notice) + self.other.card_Notice.clicked.connect(lambda: self.show_notice(if_show=True)) content_layout.addWidget(self.function) content_layout.addWidget(self.start) @@ -177,10 +177,7 @@ class Setting(QWidget): while True: choice = LineEditMessageBox( - self.window(), - "未检测到管理密钥,请设置您的管理密钥", - "管理密钥", - "密码", + self.window(), "请设置您的管理密钥", "管理密钥", "密码" ) if choice.exec() and choice.input.text() != "": Crypto.get_PASSWORD(choice.input.text()) @@ -258,12 +255,12 @@ class Setting(QWidget): if choice.exec(): break - def check_update(self, if_click: bool = False) -> None: + def check_update(self, if_show: bool = False, if_first: bool = False) -> None: """检查版本更新,调起文件下载进程""" current_version = list(map(int, Config.VERSION.split("."))) - if Network.if_running and if_click: + if Network.if_running and if_show: MainInfoBar.push_info_bar( "warning", "请求速度过快", "上个网络请求还未结束,请稍等片刻", 5000 ) @@ -333,8 +330,14 @@ class Setting(QWidget): ) ) - # 有版本更新 - if version.parse(version_text(remote_version)) > version.parse( + if ( + if_show + or ( + not if_show + and if_first + and not Config.get(Config.function_UnattendedMode) + ) + ) and version.parse(version_text(remote_version)) > version.parse( version_text(current_version) ): @@ -410,11 +413,26 @@ class Setting(QWidget): self.window().close() QApplication.quit() - # 无版本更新 - else: - MainInfoBar.push_info_bar("success", "更新检查", "已是最新版本~", 3000) + elif ( + if_show + or if_first + or version.parse(version_text(remote_version)) + > version.parse(version_text(current_version)) + ): - def show_notice(self, if_show: bool = True) -> None: + if version.parse(version_text(remote_version)) > version.parse( + version_text(current_version) + ): + MainInfoBar.push_info_bar( + "info", + "发现新版本", + f"{version_text(current_version)} --> {version_text(remote_version)}", + 3600000, + ) + else: + MainInfoBar.push_info_bar("success", "更新检查", "已是最新版本~", 3000) + + def show_notice(self, if_show: bool = False, if_first: bool = False) -> None: """显示公告""" # 从远程服务器获取最新公告 @@ -453,9 +471,11 @@ class Setting(QWidget): } if if_show or ( - datetime.now() + if_first + and datetime.now() > datetime.strptime(notice["time"], "%Y-%m-%d %H:%M") > time_local + and not Config.get(Config.function_UnattendedMode) ): choice = NoticeMessageBox(self.window(), "公告", notice["notice_dict"]) @@ -467,6 +487,17 @@ class Setting(QWidget): ) as f: json.dump(notice, f, ensure_ascii=False, indent=4) + elif ( + datetime.now() + > datetime.strptime(notice["time"], "%Y-%m-%d %H:%M") + > time_local + ): + + MainInfoBar.push_info_bar( + "info", "有新公告", "请前往设置界面查看公告", 3600000 + ) + return None + class FunctionSettingCard(HeaderCardWidget): @@ -501,6 +532,14 @@ class FunctionSettingCard(HeaderCardWidget): parent=self, ) self.card_IfSilence = self.SilenceSettingCard(self) + self.card_UnattendedMode = SwitchSettingCard( + icon=FluentIcon.PAGE_RIGHT, + title="无人值守模式", + content="开启后AUTO_MAA不再主动弹出对话框,以免影响代理任务运行", + qconfig=Config, + configItem=Config.function_UnattendedMode, + parent=self, + ) self.card_IfAgreeBilibili = SwitchSettingCard( icon=FluentIcon.PAGE_RIGHT, title="托管bilibili游戏隐私政策", @@ -523,6 +562,7 @@ class FunctionSettingCard(HeaderCardWidget): Layout.addWidget(self.card_HistoryRetentionTime) Layout.addWidget(self.card_IfAllowSleep) Layout.addWidget(self.card_IfSilence) + Layout.addWidget(self.card_UnattendedMode) Layout.addWidget(self.card_IfAgreeBilibili) Layout.addWidget(self.card_IfSkipMumuSplashAds) self.viewLayout.addLayout(Layout) @@ -998,9 +1038,9 @@ class OtherSettingCard(HeaderCardWidget): ) self.card_UserDocs = HyperlinkCard( url="https://clozya.github.io/AUTOMAA_docs", - text="访问", + text="查看指南", icon=FluentIcon.PAGE_RIGHT, - title="AUTO_MAA官方文档站", + title="用户指南", content="访问AUTO_MAA的官方文档站,获取使用指南和项目相关信息", parent=self, ) diff --git a/app/utils/downloader.py b/app/utils/downloader.py index c61ea84..769eb5e 100644 --- a/app/utils/downloader.py +++ b/app/utils/downloader.py @@ -613,11 +613,7 @@ class DownloadManager(QDialog): class AUTO_MAA_Downloader(QApplication): def __init__( - self, - app_path: Path, - name: str, - main_version: list, - config: dict, + self, app_path: Path, name: str, main_version: list, config: dict ) -> None: super().__init__() diff --git a/resources/docs/MAA_config_info.txt b/resources/docs/MAA_config_info.txt index 484cf60..ddab858 100644 --- a/resources/docs/MAA_config_info.txt +++ b/resources/docs/MAA_config_info.txt @@ -6,8 +6,8 @@ "TaskQueue.Recruiting.IsChecked": "True" #自动公招 "TaskQueue.Base.IsChecked": "True" #基建换班 "TaskQueue.Combat.IsChecked": "True" #刷理智 -"TaskQueue.Mission.IsChecked": "True" #领取奖励 "TaskQueue.Mall.IsChecked": "True" #获取信用及购物 +"TaskQueue.Mission.IsChecked": "True" #领取奖励 "TaskQueue.AutoRoguelike.IsChecked": "False" #自动肉鸽 "TaskQueue.Reclamation.IsChecked": "False" #生息演算 "TaskQueue.Order.WakeUp": "0" diff --git a/resources/version.json b/resources/version.json index a487841..4a5bab0 100644 --- a/resources/version.json +++ b/resources/version.json @@ -1,8 +1,28 @@ { - "main_version": "4.3.5.0", + "main_version": "4.3.6.2", "updater_version": "1.0.0.0", "announcement": "\n## 新增功能\n- 屏蔽MuMu模拟器开屏广告功能上线\n- 更新器支持多线程下载\n- 添加强制关闭ADB与模拟器等增强任务项\n## 修复BUG\n- 修复统计信息HTML模板公招匹配错误\n- 修复密码显示按钮动画异常\n- 修复`检测到MAA未能实际执行任务`报错被异常屏蔽\n- 修复MAA超时判定异常失效\n## 程序优化\n- 关机等电源操作添加100s倒计时\n- 人工排查弹窗方法优化\n- 人工排查时自动屏蔽静默操作\n- 公告样式优化", "version_info": { + "4.3.6.2": { + "新增功能": [ + "新增`无人值守模式`" + ], + "修复BUG": [ + "修复软件窗口最大化异常问题", + "修复异常操作导致窗口离开屏幕后难以复原的问题", + "修正剩余理智关卡文案", + "修复隐藏到托盘时,托盘无法退出主程序的问题", + "修复Server酱网络异常导致的卡死问题" + ], + "程序优化": [ + "主窗口显示版本号" + ] + }, + "4.3.6.1": { + "新增功能": [ + "单次自动代理任务中,已完成的子任务在重复执行时不再启用" + ] + }, "4.3.5.0": { "新增功能": [ "用户设置中新增连战次数与剩余理智关卡两项配置项", @@ -36,7 +56,6 @@ "https://ghfast.top/" ], "download_dict": { - "官方下载站-jp": "https://jp-download.fearr.xyz/AUTO_MAA/", - "官方下载站-hw": "http://hwobs.fearr.xyz/releases/artifacts/" + "官方下载站-jp": "https://jp-download.fearr.xyz/AUTO_MAA/" } } \ No newline at end of file