Compare commits
44 Commits
v4.3.4-bet
...
v4.3.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7b6743e10 | ||
|
|
ff4283e917 | ||
|
|
890886d62d | ||
|
|
fd75dda2b1 | ||
|
|
f22c1aeae3 | ||
|
|
d68d49a469 | ||
|
|
1900d4eaf5 | ||
|
|
02833209d5 | ||
| 2058c0218c | |||
|
|
8896e723eb | ||
|
|
edcc614833 | ||
|
|
23fe1ff0be | ||
|
|
19d1dc9f28 | ||
|
|
24b93cfcad | ||
|
|
d3298fac8a | ||
|
|
fba5395bf0 | ||
|
|
2c4508ee16 | ||
| d239443555 | |||
| e45ad08fab | |||
| ddf5d26c4b | |||
|
|
ce74dcf912 | ||
|
|
41412e1ef4 | ||
|
|
1395d48cd0 | ||
|
|
418c3d4742 | ||
|
|
17ec962a22 | ||
|
|
989ee73549 | ||
|
|
7e452e1253 | ||
|
|
5bdb5c8025 | ||
|
|
924a5fea0b | ||
|
|
b51a57a6ee | ||
|
|
4079188881 | ||
|
|
174163e305 | ||
|
|
0886439685 | ||
|
|
34bf5a4fe8 | ||
|
|
e6a97f2b17 | ||
|
|
fecff625a3 | ||
|
|
6f540036a0 | ||
|
|
86d72aec39 | ||
|
|
39876832f3 | ||
|
|
f3af6ddbbc | ||
|
|
ba7299e20c | ||
|
|
5db9d934b2 | ||
|
|
5c8eebf12c | ||
|
|
e725f6d2b2 |
44
.github/workflows/build-app.yml
vendored
44
.github/workflows/build-app.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
name: Build AUTO_MAA
|
name: Build AUTO_MAA
|
||||||
|
|
||||||
@@ -77,13 +77,23 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: AUTO_MAA_${{ env.AUTO_MAA_version }}
|
name: AUTO_MAA_${{ env.AUTO_MAA_version }}
|
||||||
path: |
|
path: AUTO_MAA_${{ env.AUTO_MAA_version }}.zip
|
||||||
AUTO_MAA_${{ env.AUTO_MAA_version }}.zip
|
|
||||||
- name: Upload Version_Info Artifact
|
- name: Upload Version_Info Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: version_info
|
name: version_info
|
||||||
path: version_info.txt
|
path: version_info.txt
|
||||||
|
- name: Compile Inno Setup Script
|
||||||
|
run: |
|
||||||
|
choco install innosetup
|
||||||
|
echo "C:\Program Files (x86)\Inno Setup 6" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
Expand-Archive -Path AUTO_MAA_${{ env.AUTO_MAA_version }}.zip -DestinationPath AUTO_MAA -Force
|
||||||
|
ISCC.exe "AUTO_MAA.iss"
|
||||||
|
- name: Upload Setup Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: AUTO_MAA_Setup
|
||||||
|
path: AUTO_MAA-Setup.exe
|
||||||
publish_release:
|
publish_release:
|
||||||
name: Publish release
|
name: Publish release
|
||||||
needs: build_AUTO_MAA
|
needs: build_AUTO_MAA
|
||||||
@@ -126,27 +136,3 @@ jobs:
|
|||||||
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan_release_note
|
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan_release_note
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Setup SSH Key
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
|
||||||
chmod 600 ~/.ssh/id_rsa
|
|
||||||
ssh-keyscan -H ${{ secrets.SERVER_IP }} >> ~/.ssh/known_hosts
|
|
||||||
- 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
|
|
||||||
|
|||||||
27
README.md
27
README.md
@@ -1,19 +1,20 @@
|
|||||||
# AUTO_MAA
|
<h1 align="center">AUTO_MAA</h1>
|
||||||
|
<p align="center">
|
||||||
MAA多账号管理与自动化软件
|
MAA多账号管理与自动化软件<br><br>
|
||||||
|
<img alt="软件图标" src="https://github.com/DLmaster361/AUTO_MAA/blob/main/resources/images/AUTO_MAA.png">
|
||||||

|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
</h1>
|
<p align="center">
|
||||||
|
<a href="https://github.com/DLmaster361/AUTO_MAA/stargazers"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/DLmaster361/AUTO_MAA?style=flat-square"></a>
|
||||||
[](https://github.com/DLmaster361/AUTO_MAA/stargazers)
|
<a href="https://github.com/DLmaster361/AUTO_MAA/network"><img alt="GitHub Forks" src="https://img.shields.io/github/forks/DLmaster361/AUTO_MAA?style=flat-square"></a>
|
||||||
[](https://github.com/DLmaster361/AUTO_MAA/network)
|
<a href="https://github.com/DLmaster361/AUTO_MAA/releases/latest"><img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/DLmaster361/AUTO_MAA/total?style=flat-square"></a>
|
||||||
[](https://github.com/DLmaster361/AUTO_MAA/issues)
|
<a href="https://github.com/DLmaster361/AUTO_MAA/issues"><img alt="GitHub Issues" src="https://img.shields.io/github/issues/DLmaster361/AUTO_MAA?style=flat-square"></a>
|
||||||
[](https://github.com/DLmaster361/AUTO_MAA/graphs/contributors)
|
<a href="https://github.com/DLmaster361/AUTO_MAA/graphs/contributors"><img alt="GitHub Contributors" src="https://img.shields.io/github/contributors/DLmaster361/AUTO_MAA?style=flat-square"></a>
|
||||||
[](https://github.com/DLmaster361/AUTO_MAA/blob/main/LICENSE)
|
<a href="https://github.com/DLmaster361/AUTO_MAA/blob/main/LICENSE"><img alt="GitHub License" src="https://img.shields.io/github/license/DLmaster361/AUTO_MAA?style=flat-square"></a>
|
||||||
</div>
|
<a href="https://mirrorchyan.com/zh/projects?rid=AUTO_MAA"><img alt="mirrorc" src="https://img.shields.io/badge/Mirror%E9%85%B1-%239af3f6?logo=countingworkspro&logoColor=4f46e5"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
## 软件介绍
|
## 软件介绍
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -33,7 +33,7 @@ import sys
|
|||||||
import shutil
|
import shutil
|
||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, date
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
@@ -91,7 +91,10 @@ class GlobalConfig(QConfig):
|
|||||||
OptionsValidator(["默认", "自定义", "主题图像"]),
|
OptionsValidator(["默认", "自定义", "主题图像"]),
|
||||||
)
|
)
|
||||||
self.function_HistoryRetentionTime = OptionsConfigItem(
|
self.function_HistoryRetentionTime = OptionsConfigItem(
|
||||||
"Function", "HistoryRetentionTime", 0, OptionsValidator([7, 15, 30, 60, 0])
|
"Function",
|
||||||
|
"HistoryRetentionTime",
|
||||||
|
0,
|
||||||
|
OptionsValidator([7, 15, 30, 60, 90, 180, 365, 0]),
|
||||||
)
|
)
|
||||||
self.function_IfAllowSleep = ConfigItem(
|
self.function_IfAllowSleep = ConfigItem(
|
||||||
"Function", "IfAllowSleep", False, BoolValidator()
|
"Function", "IfAllowSleep", False, BoolValidator()
|
||||||
@@ -100,6 +103,9 @@ class GlobalConfig(QConfig):
|
|||||||
"Function", "IfSilence", False, BoolValidator()
|
"Function", "IfSilence", False, BoolValidator()
|
||||||
)
|
)
|
||||||
self.function_BossKey = ConfigItem("Function", "BossKey", "")
|
self.function_BossKey = ConfigItem("Function", "BossKey", "")
|
||||||
|
self.function_UnattendedMode = ConfigItem(
|
||||||
|
"Function", "UnattendedMode", False, BoolValidator()
|
||||||
|
)
|
||||||
self.function_IfAgreeBilibili = ConfigItem(
|
self.function_IfAgreeBilibili = ConfigItem(
|
||||||
"Function", "IfAgreeBilibili", False, BoolValidator()
|
"Function", "IfAgreeBilibili", False, BoolValidator()
|
||||||
)
|
)
|
||||||
@@ -406,27 +412,24 @@ class MaaConfig(QConfig):
|
|||||||
"ExitEmulator",
|
"ExitEmulator",
|
||||||
OptionsValidator(["NoAction", "ExitGame", "ExitEmulator"]),
|
OptionsValidator(["NoAction", "ExitGame", "ExitEmulator"]),
|
||||||
)
|
)
|
||||||
self.RunSet_EnhanceTask = OptionsConfigItem(
|
|
||||||
"RunSet",
|
|
||||||
"EnhanceTask",
|
|
||||||
"None",
|
|
||||||
OptionsValidator(["None", "KillADB", "KillEmulator", "KillADB&Emulator"]),
|
|
||||||
)
|
|
||||||
self.RunSet_ProxyTimesLimit = RangeConfigItem(
|
self.RunSet_ProxyTimesLimit = RangeConfigItem(
|
||||||
"RunSet", "ProxyTimesLimit", 0, RangeValidator(0, 1024)
|
"RunSet", "ProxyTimesLimit", 0, RangeValidator(0, 1024)
|
||||||
)
|
)
|
||||||
|
self.RunSet_RunTimesLimit = RangeConfigItem(
|
||||||
|
"RunSet", "RunTimesLimit", 3, RangeValidator(1, 1024)
|
||||||
|
)
|
||||||
self.RunSet_AnnihilationTimeLimit = RangeConfigItem(
|
self.RunSet_AnnihilationTimeLimit = RangeConfigItem(
|
||||||
"RunSet", "AnnihilationTimeLimit", 40, RangeValidator(1, 1024)
|
"RunSet", "AnnihilationTimeLimit", 40, RangeValidator(1, 1024)
|
||||||
)
|
)
|
||||||
self.RunSet_RoutineTimeLimit = RangeConfigItem(
|
self.RunSet_RoutineTimeLimit = RangeConfigItem(
|
||||||
"RunSet", "RoutineTimeLimit", 10, RangeValidator(1, 1024)
|
"RunSet", "RoutineTimeLimit", 10, RangeValidator(1, 1024)
|
||||||
)
|
)
|
||||||
self.RunSet_RunTimesLimit = RangeConfigItem(
|
|
||||||
"RunSet", "RunTimesLimit", 3, RangeValidator(1, 1024)
|
|
||||||
)
|
|
||||||
self.RunSet_AnnihilationWeeklyLimit = ConfigItem(
|
self.RunSet_AnnihilationWeeklyLimit = ConfigItem(
|
||||||
"RunSet", "AnnihilationWeeklyLimit", False, BoolValidator()
|
"RunSet", "AnnihilationWeeklyLimit", False, BoolValidator()
|
||||||
)
|
)
|
||||||
|
self.RunSet_AutoUpdateMaa = ConfigItem(
|
||||||
|
"RunSet", "AutoUpdateMaa", False, BoolValidator()
|
||||||
|
)
|
||||||
|
|
||||||
def toDict(self, serialize=True):
|
def toDict(self, serialize=True):
|
||||||
"""convert config items to `dict`"""
|
"""convert config items to `dict`"""
|
||||||
@@ -518,17 +521,27 @@ class MaaUserConfig(QConfig):
|
|||||||
"Info", "Annihilation", False, BoolValidator()
|
"Info", "Annihilation", False, BoolValidator()
|
||||||
)
|
)
|
||||||
self.Info_Routine = ConfigItem("Info", "Routine", False, BoolValidator())
|
self.Info_Routine = ConfigItem("Info", "Routine", False, BoolValidator())
|
||||||
self.Info_Infrastructure = ConfigItem(
|
self.Info_InfrastMode = OptionsConfigItem(
|
||||||
"Info", "Infrastructure", False, BoolValidator()
|
"Info",
|
||||||
|
"InfrastMode",
|
||||||
|
"Normal",
|
||||||
|
OptionsValidator(["Normal", "Rotation", "Custom"]),
|
||||||
)
|
)
|
||||||
self.Info_Password = ConfigItem("Info", "Password", "")
|
self.Info_Password = ConfigItem("Info", "Password", "")
|
||||||
self.Info_Notes = ConfigItem("Info", "Notes", "无")
|
self.Info_Notes = ConfigItem("Info", "Notes", "无")
|
||||||
self.Info_MedicineNumb = ConfigItem(
|
self.Info_MedicineNumb = ConfigItem(
|
||||||
"Info", "MedicineNumb", 0, RangeValidator(0, 1024)
|
"Info", "MedicineNumb", 0, RangeValidator(0, 1024)
|
||||||
)
|
)
|
||||||
|
self.Info_SeriesNumb = OptionsConfigItem(
|
||||||
|
"Info",
|
||||||
|
"SeriesNumb",
|
||||||
|
"1",
|
||||||
|
OptionsValidator(["1000", "6", "5", "4", "3", "2", "1", "-1"]),
|
||||||
|
)
|
||||||
self.Info_GameId = ConfigItem("Info", "GameId", "-")
|
self.Info_GameId = ConfigItem("Info", "GameId", "-")
|
||||||
self.Info_GameId_1 = ConfigItem("Info", "GameId_1", "-")
|
self.Info_GameId_1 = ConfigItem("Info", "GameId_1", "-")
|
||||||
self.Info_GameId_2 = ConfigItem("Info", "GameId_2", "-")
|
self.Info_GameId_2 = ConfigItem("Info", "GameId_2", "-")
|
||||||
|
self.Info_GameId_Remain = ConfigItem("Info", "GameId_Remain", "-")
|
||||||
|
|
||||||
self.Data_LastProxyDate = ConfigItem("Data", "LastProxyDate", "2000-01-01")
|
self.Data_LastProxyDate = ConfigItem("Data", "LastProxyDate", "2000-01-01")
|
||||||
self.Data_LastAnnihilationDate = ConfigItem(
|
self.Data_LastAnnihilationDate = ConfigItem(
|
||||||
@@ -538,6 +551,9 @@ class MaaUserConfig(QConfig):
|
|||||||
"Data", "ProxyTimes", 0, RangeValidator(0, 1024)
|
"Data", "ProxyTimes", 0, RangeValidator(0, 1024)
|
||||||
)
|
)
|
||||||
self.Data_IfPassCheck = ConfigItem("Data", "IfPassCheck", True, BoolValidator())
|
self.Data_IfPassCheck = ConfigItem("Data", "IfPassCheck", True, BoolValidator())
|
||||||
|
self.Data_CustomInfrastPlanIndex = ConfigItem(
|
||||||
|
"Data", "CustomInfrastPlanIndex", "0"
|
||||||
|
)
|
||||||
|
|
||||||
def toDict(self, serialize=True):
|
def toDict(self, serialize=True):
|
||||||
"""convert config items to `dict`"""
|
"""convert config items to `dict`"""
|
||||||
@@ -606,7 +622,7 @@ class MaaUserConfig(QConfig):
|
|||||||
|
|
||||||
class AppConfig(GlobalConfig):
|
class AppConfig(GlobalConfig):
|
||||||
|
|
||||||
VERSION = "4.3.4.2"
|
VERSION = "4.3.6.0"
|
||||||
|
|
||||||
gameid_refreshed = Signal()
|
gameid_refreshed = Signal()
|
||||||
PASSWORD_refreshed = Signal()
|
PASSWORD_refreshed = Signal()
|
||||||
@@ -625,6 +641,7 @@ class AppConfig(GlobalConfig):
|
|||||||
self.gameid_path = self.app_path / "data/gameid.txt"
|
self.gameid_path = self.app_path / "data/gameid.txt"
|
||||||
self.version_path = self.app_path / "resources/version.json"
|
self.version_path = self.app_path / "resources/version.json"
|
||||||
|
|
||||||
|
self.main_window = None
|
||||||
self.PASSWORD = ""
|
self.PASSWORD = ""
|
||||||
self.running_list = []
|
self.running_list = []
|
||||||
self.silence_list = []
|
self.silence_list = []
|
||||||
@@ -752,7 +769,7 @@ class AppConfig(GlobalConfig):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# 生成本日关卡信息
|
# 生成本日关卡信息
|
||||||
days = datetime.strptime(self.server_date(), "%Y-%m-%d").isoweekday()
|
days = self.server_date().isoweekday()
|
||||||
|
|
||||||
gameid_list = [
|
gameid_list = [
|
||||||
{"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]},
|
{"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||||
@@ -787,13 +804,13 @@ class AppConfig(GlobalConfig):
|
|||||||
|
|
||||||
self.gameid_refreshed.emit()
|
self.gameid_refreshed.emit()
|
||||||
|
|
||||||
def server_date(self) -> str:
|
def server_date(self) -> date:
|
||||||
"""获取当前的服务器日期"""
|
"""获取当前的服务器日期"""
|
||||||
|
|
||||||
dt = datetime.now()
|
dt = datetime.now()
|
||||||
if dt.time() < datetime.min.time().replace(hour=4):
|
if dt.time() < datetime.min.time().replace(hour=4):
|
||||||
dt = dt - timedelta(days=1)
|
dt = dt - timedelta(days=1)
|
||||||
return dt.strftime("%Y-%m-%d")
|
return dt.date()
|
||||||
|
|
||||||
def check_data(self) -> None:
|
def check_data(self) -> None:
|
||||||
"""检查用户数据文件并处理数据文件版本更新"""
|
"""检查用户数据文件并处理数据文件版本更新"""
|
||||||
@@ -1286,11 +1303,28 @@ class AppConfig(GlobalConfig):
|
|||||||
user_config.set(
|
user_config.set(
|
||||||
user_config.Data_IfPassCheck, info["Config"]["Data"]["IfPassCheck"]
|
user_config.Data_IfPassCheck, info["Config"]["Data"]["IfPassCheck"]
|
||||||
)
|
)
|
||||||
|
user_config.set(
|
||||||
|
user_config.Data_CustomInfrastPlanIndex,
|
||||||
|
info["Config"]["Data"]["CustomInfrastPlanIndex"],
|
||||||
|
)
|
||||||
|
|
||||||
self.user_info_changed.emit()
|
self.user_info_changed.emit()
|
||||||
|
|
||||||
|
def save_history(self, key: str, content: dict) -> None:
|
||||||
|
"""保存历史记录"""
|
||||||
|
|
||||||
|
if key in self.queue_dict:
|
||||||
|
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"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.warning(f"保存历史记录时未找到调度队列: {key}")
|
||||||
|
|
||||||
def save_maa_log(self, log_path: Path, logs: list, maa_result: str) -> bool:
|
def save_maa_log(self, log_path: Path, logs: list, maa_result: str) -> bool:
|
||||||
"""保存MAA日志"""
|
"""保存MAA日志并生成初步统计数据"""
|
||||||
|
|
||||||
data: Dict[str, Union[str, Dict[str, Union[int, dict]]]] = {
|
data: Dict[str, Union[str, Dict[str, Union[int, dict]]]] = {
|
||||||
"recruit_statistics": defaultdict(int),
|
"recruit_statistics": defaultdict(int),
|
||||||
@@ -1453,9 +1487,9 @@ class AppConfig(GlobalConfig):
|
|||||||
data["drop_statistics"][stage][item] = count
|
data["drop_statistics"][stage][item] = count
|
||||||
|
|
||||||
# 合并MAA结果
|
# 合并MAA结果
|
||||||
data["maa_result"][
|
data["maa_result"][json_file.stem.replace("-", ":")] = single_data[
|
||||||
json_file.name.replace(".json", "").replace("-", ":")
|
"maa_result"
|
||||||
] = single_data["maa_result"]
|
]
|
||||||
|
|
||||||
# 生成汇总 JSON 文件
|
# 生成汇总 JSON 文件
|
||||||
if mode == "所有项":
|
if mode == "所有项":
|
||||||
@@ -1478,9 +1512,21 @@ class AppConfig(GlobalConfig):
|
|||||||
info: Dict[str, Dict[str, Union[int, dict]]] = json.load(f)
|
info: Dict[str, Dict[str, Union[int, dict]]] = json.load(f)
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
|
# 4点前的记录放在当日最后
|
||||||
|
sorted_maa_result = sorted(
|
||||||
|
info["maa_result"].items(),
|
||||||
|
key=lambda x: (
|
||||||
|
(
|
||||||
|
1
|
||||||
|
if datetime.strptime(x[0], "%H:%M:%S").time()
|
||||||
|
< datetime.min.time().replace(hour=4)
|
||||||
|
else 0
|
||||||
|
),
|
||||||
|
datetime.strptime(x[0], "%H:%M:%S"),
|
||||||
|
),
|
||||||
|
)
|
||||||
data["条目索引"] = [
|
data["条目索引"] = [
|
||||||
[k, "完成" if v == "Success!" else "异常"]
|
[k, "完成" if v == "Success!" else "异常"] for k, v in sorted_maa_result
|
||||||
for k, v in info["maa_result"].items()
|
|
||||||
]
|
]
|
||||||
data["条目索引"].insert(0, ["数据总览", "运行"])
|
data["条目索引"].insert(0, ["数据总览", "运行"])
|
||||||
data["统计数据"] = {"公招统计": list(info["recruit_statistics"].items())}
|
data["统计数据"] = {"公招统计": list(info["recruit_statistics"].items())}
|
||||||
@@ -1511,7 +1557,9 @@ class AppConfig(GlobalConfig):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def search_history(self) -> dict:
|
def search_history(
|
||||||
|
self, mode: str, start_date: datetime, end_date: datetime
|
||||||
|
) -> dict:
|
||||||
"""搜索所有历史记录"""
|
"""搜索所有历史记录"""
|
||||||
|
|
||||||
history_dict = {}
|
history_dict = {}
|
||||||
@@ -1524,34 +1572,55 @@ class AppConfig(GlobalConfig):
|
|||||||
|
|
||||||
date = datetime.strptime(date_folder.name, "%Y-%m-%d")
|
date = datetime.strptime(date_folder.name, "%Y-%m-%d")
|
||||||
|
|
||||||
history_dict[date.strftime("%Y年 %m月 %d日")] = list(
|
if not (start_date <= date <= end_date):
|
||||||
date_folder.glob("*.json")
|
continue # 只统计在范围内的日期
|
||||||
)
|
|
||||||
|
if mode == "按日合并":
|
||||||
|
|
||||||
|
history_dict[date.strftime("%Y年 %m月 %d日")] = list(
|
||||||
|
date_folder.glob("*.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
elif mode == "按周合并":
|
||||||
|
|
||||||
|
year, week, _ = date.isocalendar()
|
||||||
|
if f"{year}年 第{week}周" not in history_dict:
|
||||||
|
history_dict[f"{year}年 第{week}周"] = {}
|
||||||
|
|
||||||
|
for user in date_folder.glob("*.json"):
|
||||||
|
|
||||||
|
if user.stem not in history_dict[f"{year}年 第{week}周"]:
|
||||||
|
history_dict[f"{year}年 第{week}周"][user.stem] = list(
|
||||||
|
user.with_suffix("").glob("*.json")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
history_dict[f"{year}年 第{week}周"][user.stem] += list(
|
||||||
|
user.with_suffix("").glob("*.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
elif mode == "按月合并":
|
||||||
|
|
||||||
|
if date.strftime("%Y年 %m月") not in history_dict:
|
||||||
|
history_dict[date.strftime("%Y年 %m月")] = {}
|
||||||
|
|
||||||
|
for user in date_folder.glob("*.json"):
|
||||||
|
|
||||||
|
if user.stem not in history_dict[date.strftime("%Y年 %m月")]:
|
||||||
|
history_dict[date.strftime("%Y年 %m月")][user.stem] = list(
|
||||||
|
user.with_suffix("").glob("*.json")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
history_dict[date.strftime("%Y年 %m月")][user.stem] += list(
|
||||||
|
user.with_suffix("").glob("*.json")
|
||||||
|
)
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.warning(f"非日期格式的目录: {date_folder}")
|
logger.warning(f"非日期格式的目录: {date_folder}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
k: v
|
k: v
|
||||||
for k, v in sorted(
|
for k, v in sorted(history_dict.items(), key=lambda x: x[0], reverse=True)
|
||||||
history_dict.items(),
|
|
||||||
key=lambda x: datetime.strptime(x[0], "%Y年 %m月 %d日"),
|
|
||||||
reverse=True,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def save_history(self, key: str, content: dict) -> None:
|
|
||||||
"""保存历史记录"""
|
|
||||||
|
|
||||||
if key in self.queue_dict:
|
|
||||||
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"]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
logger.warning(f"保存历史记录时未找到调度队列: {key}")
|
|
||||||
|
|
||||||
|
|
||||||
Config = AppConfig()
|
Config = AppConfig()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -29,17 +29,15 @@ from loguru import logger
|
|||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
from qfluentwidgets import InfoBar, InfoBarPosition
|
from qfluentwidgets import InfoBar, InfoBarPosition
|
||||||
|
|
||||||
|
from .config import Config
|
||||||
|
|
||||||
|
|
||||||
class _MainInfoBar:
|
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):
|
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("信息通知栏未设置父窗口")
|
logger.error("信息通知栏未设置父窗口")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -61,7 +59,7 @@ class _MainInfoBar:
|
|||||||
isClosable=True,
|
isClosable=True,
|
||||||
position=InfoBarPosition.TOP_RIGHT,
|
position=InfoBarPosition.TOP_RIGHT,
|
||||||
duration=time,
|
duration=time,
|
||||||
parent=self.main_window,
|
parent=Config.main_window,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.error(f"未知的通知栏模式: {mode}")
|
logger.error(f"未知的通知栏模式: {mode}")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -53,8 +53,6 @@ class _Network(QThread):
|
|||||||
|
|
||||||
self.if_running = True
|
self.if_running = True
|
||||||
|
|
||||||
print(self.url)
|
|
||||||
|
|
||||||
if self.mode == "get":
|
if self.mode == "get":
|
||||||
self.get_json(self.url)
|
self.get_json(self.url)
|
||||||
elif self.mode == "get_file":
|
elif self.mode == "get_file":
|
||||||
@@ -80,6 +78,8 @@ class _Network(QThread):
|
|||||||
def get_json(self, url: str) -> None:
|
def get_json(self, url: str) -> None:
|
||||||
"""通过get方法获取json数据"""
|
"""通过get方法获取json数据"""
|
||||||
|
|
||||||
|
response = None
|
||||||
|
|
||||||
for _ in range(self.max_retries):
|
for _ in range(self.max_retries):
|
||||||
try:
|
try:
|
||||||
response = requests.get(url, timeout=self.timeout)
|
response = requests.get(url, timeout=self.timeout)
|
||||||
@@ -94,10 +94,11 @@ class _Network(QThread):
|
|||||||
time.sleep(self.backoff_factor)
|
time.sleep(self.backoff_factor)
|
||||||
|
|
||||||
self.loop.quit()
|
self.loop.quit()
|
||||||
print("quited")
|
|
||||||
|
|
||||||
def get_file(self, url: str, path: Path) -> None:
|
def get_file(self, url: str, path: Path) -> None:
|
||||||
"""通过get方法获取json数据"""
|
"""通过get方法下载文件"""
|
||||||
|
|
||||||
|
response = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get(url, timeout=10)
|
response = requests.get(url, timeout=10)
|
||||||
@@ -114,7 +115,6 @@ class _Network(QThread):
|
|||||||
self.error_message = str(e)
|
self.error_message = str(e)
|
||||||
|
|
||||||
self.loop.quit()
|
self.loop.quit()
|
||||||
print("quited-----")
|
|
||||||
|
|
||||||
|
|
||||||
Network = _Network()
|
Network = _Network()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -29,10 +29,12 @@ from loguru import logger
|
|||||||
from PySide6.QtCore import QThread, QObject, Signal
|
from PySide6.QtCore import QThread, QObject, Signal
|
||||||
from qfluentwidgets import MessageBox
|
from qfluentwidgets import MessageBox
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from packaging import version
|
||||||
from typing import Dict, Union
|
from typing import Dict, Union
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .main_info_bar import MainInfoBar
|
from .main_info_bar import MainInfoBar
|
||||||
|
from .network import Network
|
||||||
from app.models import MaaManager
|
from app.models import MaaManager
|
||||||
from app.services import System
|
from app.services import System
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@ from app.services import System
|
|||||||
class Task(QThread):
|
class Task(QThread):
|
||||||
"""业务线程"""
|
"""业务线程"""
|
||||||
|
|
||||||
|
check_maa_version = Signal(str)
|
||||||
push_info_bar = Signal(str, str, str, int)
|
push_info_bar = Signal(str, str, str, int)
|
||||||
question = Signal(str, str)
|
question = Signal(str, str)
|
||||||
question_response = Signal(bool)
|
question_response = Signal(bool)
|
||||||
@@ -77,6 +80,7 @@ class Task(QThread):
|
|||||||
Config.member_dict[self.name],
|
Config.member_dict[self.name],
|
||||||
(None if "全局" in self.mode else self.info["SetMaaInfo"]["Path"]),
|
(None if "全局" in self.mode else self.info["SetMaaInfo"]["Path"]),
|
||||||
)
|
)
|
||||||
|
self.task.check_maa_version.connect(self.check_maa_version.emit)
|
||||||
self.task.push_info_bar.connect(self.push_info_bar.emit)
|
self.task.push_info_bar.connect(self.push_info_bar.emit)
|
||||||
self.task.accomplish.connect(lambda: self.accomplish.emit([]))
|
self.task.accomplish.connect(lambda: self.accomplish.emit([]))
|
||||||
|
|
||||||
@@ -132,6 +136,7 @@ class Task(QThread):
|
|||||||
Config.member_dict[task[2]],
|
Config.member_dict[task[2]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.task.check_maa_version.connect(self.check_maa_version.emit)
|
||||||
self.task.question.connect(self.question.emit)
|
self.task.question.connect(self.question.emit)
|
||||||
self.question_response.disconnect()
|
self.question_response.disconnect()
|
||||||
self.question_response.connect(self.task.question_response.emit)
|
self.question_response.connect(self.task.question_response.emit)
|
||||||
@@ -149,6 +154,7 @@ class Task(QThread):
|
|||||||
Config.running_list.remove(task[2])
|
Config.running_list.remove(task[2])
|
||||||
|
|
||||||
task[1] = "完成"
|
task[1] = "完成"
|
||||||
|
self.update_task_list.emit(self.task_list)
|
||||||
logger.info(f"任务完成:{task[0]}")
|
logger.info(f"任务完成:{task[0]}")
|
||||||
self.push_info_bar.emit("info", "任务完成", task[0], 3000)
|
self.push_info_bar.emit("info", "任务完成", task[0], 3000)
|
||||||
|
|
||||||
@@ -166,12 +172,10 @@ class _TaskManager(QObject):
|
|||||||
|
|
||||||
create_gui = Signal(Task)
|
create_gui = Signal(Task)
|
||||||
connect_gui = Signal(Task)
|
connect_gui = Signal(Task)
|
||||||
push_info_bar = Signal(str, str, str, int)
|
|
||||||
|
|
||||||
def __init__(self, main_window=None):
|
def __init__(self):
|
||||||
super(_TaskManager, self).__init__()
|
super(_TaskManager, self).__init__()
|
||||||
|
|
||||||
self.main_window = main_window
|
|
||||||
self.task_dict: Dict[str, Task] = {}
|
self.task_dict: Dict[str, Task] = {}
|
||||||
|
|
||||||
def add_task(
|
def add_task(
|
||||||
@@ -190,6 +194,7 @@ class _TaskManager(QObject):
|
|||||||
|
|
||||||
Config.running_list.append(name)
|
Config.running_list.append(name)
|
||||||
self.task_dict[name] = Task(mode, name, info)
|
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(
|
self.task_dict[name].question.connect(
|
||||||
lambda title, content: self.push_dialog(name, title, content)
|
lambda title, content: self.push_dialog(name, title, content)
|
||||||
)
|
)
|
||||||
@@ -273,7 +278,7 @@ class _TaskManager(QObject):
|
|||||||
}
|
}
|
||||||
|
|
||||||
choice = ProgressRingMessageBox(
|
choice = ProgressRingMessageBox(
|
||||||
self.main_window,
|
Config.main_window,
|
||||||
f"{mode_book[Config.queue_dict[name]["Config"].get(Config.queue_dict[name]["Config"].queueSet_AfterAccomplish)]}倒计时",
|
f"{mode_book[Config.queue_dict[name]["Config"].get(Config.queue_dict[name]["Config"].queueSet_AfterAccomplish)]}倒计时",
|
||||||
)
|
)
|
||||||
if choice.exec():
|
if choice.exec():
|
||||||
@@ -283,10 +288,43 @@ class _TaskManager(QObject):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def check_maa_version(self, v: str):
|
||||||
|
"""检查MAA版本"""
|
||||||
|
|
||||||
|
Network.set_info(
|
||||||
|
mode="get",
|
||||||
|
url="https://mirrorchyan.com/api/resources/MAA/latest?user_agent=AutoMaaGui&os=win&arch=x64&channel=stable",
|
||||||
|
)
|
||||||
|
Network.start()
|
||||||
|
Network.loop.exec()
|
||||||
|
if Network.stutus_code == 200:
|
||||||
|
maa_info = Network.response_json
|
||||||
|
else:
|
||||||
|
logger.warning(f"获取MAA版本信息时出错:{Network.error_message}")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning",
|
||||||
|
"获取MAA版本信息时出错",
|
||||||
|
f"网络错误:{Network.stutus_code}",
|
||||||
|
5000,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if version.parse(maa_info["data"]["version_name"]) > version.parse(v):
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"检测到MAA版本过低:{v},最新版本:{maa_info['data']['version_name']}"
|
||||||
|
)
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"info",
|
||||||
|
"MAA版本过低",
|
||||||
|
f"当前版本:{v},最新稳定版:{maa_info['data']['version_name']}",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
|
||||||
def push_dialog(self, name: str, title: str, content: str):
|
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.yesButton.setText("是")
|
||||||
choice.cancelButton.setText("否")
|
choice.cancelButton.setText("否")
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -55,6 +55,9 @@ class _MainTimer(QWidget):
|
|||||||
"""长时间定期检定任务"""
|
"""长时间定期检定任务"""
|
||||||
|
|
||||||
Config.get_gameid()
|
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):
|
def timed_start(self):
|
||||||
"""定时启动代理任务"""
|
"""定时启动代理任务"""
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -28,10 +28,12 @@ v4.3
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
from PySide6.QtCore import QObject, Signal, QEventLoop, QFileSystemWatcher, QTimer
|
from PySide6.QtCore import QObject, Signal, QEventLoop, QFileSystemWatcher, QTimer
|
||||||
import json
|
import json
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
|
import win32com.client
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
from typing import Union, List, Dict
|
from typing import Union, List, Dict
|
||||||
@@ -43,6 +45,7 @@ from app.services import Notify, System
|
|||||||
class MaaManager(QObject):
|
class MaaManager(QObject):
|
||||||
"""MAA控制器"""
|
"""MAA控制器"""
|
||||||
|
|
||||||
|
check_maa_version = Signal(str)
|
||||||
question = Signal(str, str)
|
question = Signal(str, str)
|
||||||
question_response = Signal(bool)
|
question_response = Signal(bool)
|
||||||
update_user_info = Signal(str, dict)
|
update_user_info = Signal(str, dict)
|
||||||
@@ -87,6 +90,9 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
self.interrupt.connect(self.quit_monitor)
|
self.interrupt.connect(self.quit_monitor)
|
||||||
|
|
||||||
|
self.maa_version = None
|
||||||
|
self.maa_update_package = ""
|
||||||
|
self.task_dict = {}
|
||||||
self.set = config["Config"].toDict()
|
self.set = config["Config"].toDict()
|
||||||
|
|
||||||
self.data = {}
|
self.data = {}
|
||||||
@@ -107,12 +113,12 @@ class MaaManager(QObject):
|
|||||||
self.maa_set_path = self.maa_root_path / "config/gui.json"
|
self.maa_set_path = self.maa_root_path / "config/gui.json"
|
||||||
self.maa_log_path = self.maa_root_path / "debug/gui.log"
|
self.maa_log_path = self.maa_root_path / "debug/gui.log"
|
||||||
self.maa_exe_path = self.maa_root_path / "MAA.exe"
|
self.maa_exe_path = self.maa_root_path / "MAA.exe"
|
||||||
self.maa_tasks_path = self.maa_root_path / "resource/tasks.json"
|
self.maa_tasks_path = self.maa_root_path / "resource/tasks/tasks.json"
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""主进程,运行MAA代理进程"""
|
"""主进程,运行MAA代理进程"""
|
||||||
|
|
||||||
curdate = Config.server_date()
|
curdate = Config.server_date().strftime("%Y-%m-%d")
|
||||||
begin_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
begin_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
self.configure()
|
self.configure()
|
||||||
@@ -259,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"]):
|
for i in range(self.set["RunSet"]["RunTimesLimit"]):
|
||||||
|
|
||||||
@@ -284,9 +351,49 @@ class MaaManager(QObject):
|
|||||||
self.emulator_arguments = set["Configurations"]["Default"][
|
self.emulator_arguments = set["Configurations"]["Default"][
|
||||||
"Start.EmulatorAddCommand"
|
"Start.EmulatorAddCommand"
|
||||||
].split()
|
].split()
|
||||||
|
# 如果是快捷方式,进行解析
|
||||||
|
if (
|
||||||
|
self.emulator_path.suffix == ".lnk"
|
||||||
|
and self.emulator_path.exists()
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
shell = win32com.client.Dispatch("WScript.Shell")
|
||||||
|
shortcut = shell.CreateShortcut(str(self.emulator_path))
|
||||||
|
self.emulator_path = Path(shortcut.TargetPath)
|
||||||
|
self.emulator_arguments = shortcut.Arguments.split()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} | 解析快捷方式时出现异常:{e}"
|
||||||
|
)
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"解析快捷方式时出现异常",
|
||||||
|
"请检查快捷方式",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
self.if_open_emulator = True
|
||||||
|
break
|
||||||
|
elif not self.emulator_path.exists():
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} | 模拟器快捷方式不存在:{self.emulator_path}"
|
||||||
|
)
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"启动模拟器时出现异常",
|
||||||
|
"模拟器快捷方式不存在",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
self.if_open_emulator = True
|
||||||
|
break
|
||||||
|
|
||||||
self.ADB_path = Path(
|
self.ADB_path = Path(
|
||||||
set["Configurations"]["Default"]["Connect.AdbPath"]
|
set["Configurations"]["Default"]["Connect.AdbPath"]
|
||||||
)
|
)
|
||||||
|
self.ADB_path = (
|
||||||
|
self.ADB_path
|
||||||
|
if self.ADB_path.is_absolute()
|
||||||
|
else self.maa_root_path / self.ADB_path
|
||||||
|
)
|
||||||
self.ADB_address = set["Configurations"]["Default"][
|
self.ADB_address = set["Configurations"]["Default"][
|
||||||
"Connect.Address"
|
"Connect.Address"
|
||||||
]
|
]
|
||||||
@@ -300,27 +407,44 @@ class MaaManager(QObject):
|
|||||||
]
|
]
|
||||||
== "True"
|
== "True"
|
||||||
)
|
)
|
||||||
# 添加静默进程标记
|
|
||||||
Config.silence_list.append(self.emulator_path)
|
|
||||||
|
|
||||||
# 增强任务:任务开始前强杀ADB
|
# 任务开始前释放ADB
|
||||||
if "ADB" in self.set["RunSet"]["EnhanceTask"]:
|
try:
|
||||||
System.kill_process(self.ADB_path)
|
subprocess.run(
|
||||||
else:
|
[self.ADB_path, "disconnect", self.ADB_address],
|
||||||
try:
|
|
||||||
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}")
|
|
||||||
|
|
||||||
if self.if_open_emulator_process:
|
|
||||||
self.emulator_process = subprocess.Popen(
|
|
||||||
[self.emulator_path, *self.emulator_arguments],
|
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
# 忽略错误,因为可能本来就没有连接
|
||||||
|
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"释放ADB时出现异常",
|
||||||
|
"请检查MAA中ADB路径设置",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.if_open_emulator_process:
|
||||||
|
try:
|
||||||
|
self.emulator_process = subprocess.Popen(
|
||||||
|
[self.emulator_path, *self.emulator_arguments],
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.name} | 启动模拟器时出现异常:{e}")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"启动模拟器时出现异常",
|
||||||
|
"请检查MAA中模拟器路径设置",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
self.if_open_emulator = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# 添加静默进程标记
|
||||||
|
Config.silence_list.append(self.emulator_path)
|
||||||
|
|
||||||
# 创建MAA任务
|
# 创建MAA任务
|
||||||
maa = subprocess.Popen(
|
maa = subprocess.Popen(
|
||||||
@@ -331,13 +455,40 @@ class MaaManager(QObject):
|
|||||||
self.start_monitor(start_time, mode_book[mode])
|
self.start_monitor(start_time, mode_book[mode])
|
||||||
|
|
||||||
if self.maa_result == "Success!":
|
if self.maa_result == "Success!":
|
||||||
|
|
||||||
|
# 标记任务完成
|
||||||
|
run_book[mode] = True
|
||||||
|
|
||||||
|
# 从配置文件中解析所需信息
|
||||||
|
with self.maa_set_path.open(
|
||||||
|
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 (
|
||||||
|
self.maa_root_path
|
||||||
|
/ data["Global"]["VersionUpdate.package"]
|
||||||
|
).exists()
|
||||||
|
):
|
||||||
|
self.maa_update_package = data["Global"][
|
||||||
|
"VersionUpdate.package"
|
||||||
|
]
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{self.name} | 用户: {user[0]} - MAA进程完成代理任务"
|
f"{self.name} | 用户: {user[0]} - MAA进程完成代理任务"
|
||||||
)
|
)
|
||||||
run_book[mode] = True
|
|
||||||
self.update_log_text.emit(
|
self.update_log_text.emit(
|
||||||
"检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
"检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
||||||
)
|
)
|
||||||
|
|
||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
if self.isInterruptionRequested:
|
if self.isInterruptionRequested:
|
||||||
break
|
break
|
||||||
@@ -354,13 +505,30 @@ class MaaManager(QObject):
|
|||||||
# 无命令行中止MAA与其子程序
|
# 无命令行中止MAA与其子程序
|
||||||
System.kill_process(self.maa_exe_path)
|
System.kill_process(self.maa_exe_path)
|
||||||
|
|
||||||
if "Emulator" in self.set["RunSet"]["EnhanceTask"]:
|
# 中止模拟器进程
|
||||||
System.kill_process(self.emulator_path)
|
self.emulator_process.terminate()
|
||||||
else:
|
self.emulator_process.wait()
|
||||||
self.emulator_process.terminate()
|
|
||||||
self.emulator_process.wait()
|
|
||||||
|
|
||||||
self.if_open_emulator = True
|
self.if_open_emulator = True
|
||||||
|
|
||||||
|
# 从配置文件中解析所需信息
|
||||||
|
with self.maa_set_path.open(
|
||||||
|
mode="r", encoding="utf-8"
|
||||||
|
) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
# 记录更新包路径
|
||||||
|
if (
|
||||||
|
data["Global"]["VersionUpdate.package"]
|
||||||
|
and (
|
||||||
|
self.maa_root_path
|
||||||
|
/ data["Global"]["VersionUpdate.package"]
|
||||||
|
).exists()
|
||||||
|
):
|
||||||
|
self.maa_update_package = data["Global"][
|
||||||
|
"VersionUpdate.package"
|
||||||
|
]
|
||||||
|
|
||||||
# 推送异常通知
|
# 推送异常通知
|
||||||
Notify.push_plyer(
|
Notify.push_plyer(
|
||||||
"用户自动代理出现异常!",
|
"用户自动代理出现异常!",
|
||||||
@@ -376,26 +544,52 @@ class MaaManager(QObject):
|
|||||||
# 移除静默进程标记
|
# 移除静默进程标记
|
||||||
Config.silence_list.remove(self.emulator_path)
|
Config.silence_list.remove(self.emulator_path)
|
||||||
|
|
||||||
# 增强任务:任务结束后强杀ADB和模拟器或释放进程
|
# 任务结束后释放ADB
|
||||||
if "ADB" in self.set["RunSet"]["EnhanceTask"]:
|
try:
|
||||||
System.kill_process(self.ADB_path)
|
subprocess.run(
|
||||||
else:
|
[self.ADB_path, "disconnect", self.ADB_address],
|
||||||
try:
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
subprocess.run(
|
)
|
||||||
[self.ADB_path, "disconnect", self.ADB_address],
|
except subprocess.CalledProcessError as e:
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
# 忽略错误,因为可能本来就没有连接
|
||||||
)
|
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||||
except subprocess.CalledProcessError as e:
|
except Exception as e:
|
||||||
# 忽略错误,因为可能本来就没有连接
|
logger.error(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||||
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"释放ADB时出现异常",
|
||||||
|
"请检查MAA中ADB路径设置",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
# 任务结束后再次手动中止模拟器进程,防止退出不彻底
|
||||||
if self.if_kill_emulator:
|
if self.if_kill_emulator:
|
||||||
if "Emulator" in self.set["RunSet"]["EnhanceTask"]:
|
self.emulator_process.terminate()
|
||||||
System.kill_process(self.emulator_path)
|
self.emulator_process.wait()
|
||||||
else:
|
|
||||||
self.emulator_process.terminate()
|
|
||||||
self.emulator_process.wait()
|
|
||||||
self.if_open_emulator = True
|
self.if_open_emulator = True
|
||||||
|
|
||||||
|
# 执行MAA解压更新动作
|
||||||
|
if self.maa_update_package:
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"{self.name} | 检测到MAA更新,正在执行更新动作"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.update_log_text.emit(
|
||||||
|
f"检测到MAA存在更新\nMAA正在执行更新动作\n请等待10s"
|
||||||
|
)
|
||||||
|
self.set_maa("更新MAA", None)
|
||||||
|
subprocess.Popen(
|
||||||
|
[self.maa_exe_path],
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
)
|
||||||
|
for _ in range(10):
|
||||||
|
if self.isInterruptionRequested:
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
System.kill_process(self.maa_exe_path)
|
||||||
|
|
||||||
|
logger.info(f"{self.name} | 更新动作结束")
|
||||||
|
|
||||||
# 记录剿灭情况
|
# 记录剿灭情况
|
||||||
if (
|
if (
|
||||||
mode == "Annihilation"
|
mode == "Annihilation"
|
||||||
@@ -710,6 +904,19 @@ class MaaManager(QObject):
|
|||||||
else:
|
else:
|
||||||
self.update_log_text.emit("".join(logs))
|
self.update_log_text.emit("".join(logs))
|
||||||
|
|
||||||
|
# 获取MAA版本号
|
||||||
|
if not self.set["RunSet"]["AutoUpdateMaa"] and not self.maa_version:
|
||||||
|
|
||||||
|
section_match = re.search(r"={35}(.*?)={35}", log, re.DOTALL)
|
||||||
|
if section_match:
|
||||||
|
|
||||||
|
version_match = re.search(
|
||||||
|
r"Version\s+v(\d+\.\d+\.\d+(?:-\w+\.\d+)?)", section_match.group(1)
|
||||||
|
)
|
||||||
|
if version_match:
|
||||||
|
self.maa_version = f"v{version_match.group(1)}"
|
||||||
|
self.check_maa_version.emit(self.maa_version)
|
||||||
|
|
||||||
if "自动代理" in mode:
|
if "自动代理" in mode:
|
||||||
|
|
||||||
# 获取最近一条日志的时间
|
# 获取最近一条日志的时间
|
||||||
@@ -731,38 +938,67 @@ class MaaManager(QObject):
|
|||||||
else:
|
else:
|
||||||
self.weekly_annihilation_limit_reached = False
|
self.weekly_annihilation_limit_reached = False
|
||||||
|
|
||||||
if mode == "自动代理_日常" and "任务出错: Fight" in log:
|
if "任务出错: StartUp" in log:
|
||||||
self.maa_result = "检测到MAA未能实际执行任务"
|
self.maa_result = "MAA未能正确登录PRTS"
|
||||||
elif "任务出错: StartUp" in log:
|
|
||||||
self.maa_result = "检测到MAA未能正确登录PRTS"
|
|
||||||
elif "任务已全部完成!" in log:
|
elif "任务已全部完成!" in log:
|
||||||
self.maa_result = "Success!"
|
|
||||||
elif (
|
if "完成任务: StartUp" in log:
|
||||||
("请「检查连接设置」或「尝试重启模拟器与 ADB」或「重启电脑」" in log)
|
self.task_dict["WakeUp"] = "False"
|
||||||
or ("未检测到任何模拟器" in log)
|
if "完成任务: Recruit" in log:
|
||||||
or ("已停止" in log)
|
self.task_dict["Recruiting"] = "False"
|
||||||
or ("MaaAssistantArknights GUI exited" in log)
|
if "完成任务: Infrast" in log:
|
||||||
):
|
self.task_dict["Base"] = "False"
|
||||||
self.maa_result = "检测到MAA进程异常"
|
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(
|
elif datetime.now() - latest_time > timedelta(
|
||||||
minutes=self.set["RunSet"][time_book[mode]]
|
minutes=self.set["RunSet"][time_book[mode]]
|
||||||
):
|
):
|
||||||
self.maa_result = "检测到MAA进程超时"
|
self.maa_result = "MAA进程超时"
|
||||||
|
|
||||||
elif self.isInterruptionRequested:
|
elif self.isInterruptionRequested:
|
||||||
self.maa_result = "任务被手动中止"
|
self.maa_result = "任务被手动中止"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.maa_result = "Wait"
|
self.maa_result = "Wait"
|
||||||
|
|
||||||
elif mode == "人工排查":
|
elif mode == "人工排查":
|
||||||
if "完成任务: StartUp" in log:
|
if "完成任务: StartUp" in log:
|
||||||
self.maa_result = "Success!"
|
self.maa_result = "Success!"
|
||||||
elif (
|
elif "请「检查连接设置」或「尝试重启模拟器与 ADB」或「重启电脑」" in log:
|
||||||
("请「检查连接设置」或「尝试重启模拟器与 ADB」或「重启电脑」" in log)
|
self.maa_result = "MAA的ADB连接异常"
|
||||||
or ("未检测到任何模拟器" in log)
|
elif "未检测到任何模拟器" in log:
|
||||||
or ("已停止" in log)
|
self.maa_result = "MAA未检测到任何模拟器"
|
||||||
or ("MaaAssistantArknights GUI exited" in log)
|
elif "已停止" in log:
|
||||||
):
|
self.maa_result = "MAA在完成任务前中止"
|
||||||
self.maa_result = "检测到MAA进程异常"
|
elif "MaaAssistantArknights GUI exited" in log:
|
||||||
|
self.maa_result = "MAA在完成任务前退出"
|
||||||
elif self.isInterruptionRequested:
|
elif self.isInterruptionRequested:
|
||||||
self.maa_result = "任务被手动中止"
|
self.maa_result = "任务被手动中止"
|
||||||
else:
|
else:
|
||||||
@@ -808,7 +1044,7 @@ class MaaManager(QObject):
|
|||||||
"""配置MAA运行参数"""
|
"""配置MAA运行参数"""
|
||||||
logger.info(f"{self.name} | 配置MAA运行参数: {mode}/{index}")
|
logger.info(f"{self.name} | 配置MAA运行参数: {mode}/{index}")
|
||||||
|
|
||||||
if "设置MAA" not in self.mode:
|
if "设置MAA" not in self.mode and "更新MAA" not in mode:
|
||||||
user_data = self.data[index]["Config"]
|
user_data = self.data[index]["Config"]
|
||||||
|
|
||||||
# 配置MAA前关闭可能未正常退出的MAA进程
|
# 配置MAA前关闭可能未正常退出的MAA进程
|
||||||
@@ -823,7 +1059,7 @@ class MaaManager(QObject):
|
|||||||
self.config_path / "Default/gui.json",
|
self.config_path / "Default/gui.json",
|
||||||
self.maa_set_path,
|
self.maa_set_path,
|
||||||
)
|
)
|
||||||
elif (mode == "设置MAA_全局") or (
|
elif (mode in ["设置MAA_全局", "更新MAA"]) or (
|
||||||
("自动代理" in mode or "人工排查" in mode)
|
("自动代理" in mode or "人工排查" in mode)
|
||||||
and user_data["Info"]["Mode"] == "简洁"
|
and user_data["Info"]["Mode"] == "简洁"
|
||||||
):
|
):
|
||||||
@@ -850,7 +1086,7 @@ class MaaManager(QObject):
|
|||||||
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
|
|
||||||
if "设置MAA" not in mode and (
|
if ("设置MAA" not in self.mode and "更新MAA" not in mode) and (
|
||||||
(
|
(
|
||||||
user_data["Info"]["Mode"] == "简洁"
|
user_data["Info"]["Mode"] == "简洁"
|
||||||
and user_data["Info"]["Server"] == "Bilibili"
|
and user_data["Info"]["Server"] == "Bilibili"
|
||||||
@@ -898,10 +1134,20 @@ class MaaManager(QObject):
|
|||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Start.RunDirectly"
|
"Start.RunDirectly"
|
||||||
] = "True" # 启动MAA后直接运行
|
] = "True" # 启动MAA后直接运行
|
||||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = (
|
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = str(
|
||||||
"True" if self.if_open_emulator else "False"
|
self.if_open_emulator
|
||||||
) # 启动MAA后自动开启模拟器
|
) # 启动MAA后自动开启模拟器
|
||||||
|
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.ScheduledUpdateCheck"
|
||||||
|
] = "False" # 定时检查更新
|
||||||
|
data["Global"]["VersionUpdate.AutoDownloadUpdatePackage"] = str(
|
||||||
|
self.set["RunSet"]["AutoUpdateMaa"]
|
||||||
|
) # 自动下载更新包
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoInstallUpdatePackage"
|
||||||
|
] = "False" # 自动安装更新包
|
||||||
|
|
||||||
if Config.get(Config.function_IfSilence):
|
if Config.get(Config.function_IfSilence):
|
||||||
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
||||||
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
||||||
@@ -919,49 +1165,53 @@ class MaaManager(QObject):
|
|||||||
"Info"
|
"Info"
|
||||||
]["Id"]
|
]["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"] == "简洁":
|
if user_data["Info"]["Mode"] == "简洁":
|
||||||
|
|
||||||
data["Global"][
|
data["Configurations"]["Default"][
|
||||||
"VersionUpdate.ScheduledUpdateCheck"
|
"TaskQueue.WakeUp.IsChecked"
|
||||||
] = "False" # 定时检查更新
|
] = "True" # 开始唤醒
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
|
||||||
] = "False" # 自动下载更新包
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.AutoInstallUpdatePackage"
|
|
||||||
] = "False" # 自动安装更新包
|
|
||||||
data["Configurations"]["Default"]["Start.ClientType"] = user_data[
|
data["Configurations"]["Default"]["Start.ClientType"] = user_data[
|
||||||
"Info"
|
"Info"
|
||||||
][
|
][
|
||||||
"Server"
|
"Server"
|
||||||
] # 客户端类型
|
] # 客户端类型
|
||||||
|
|
||||||
|
# 整理任务顺序
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.WakeUp"] = "0"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.Recruiting"] = "1"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.Base"] = "2"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.Combat"] = "3"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.Mall"] = "4"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.Mission"] = "5"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.AutoRoguelike"] = "6"
|
||||||
|
data["Configurations"]["Default"]["TaskQueue.Order.Reclamation"] = "7"
|
||||||
|
|
||||||
if "剿灭" in mode:
|
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"][
|
data["Configurations"]["Default"][
|
||||||
"MainFunction.Stage1"
|
"MainFunction.Stage1"
|
||||||
] = "Annihilation" # 主关卡
|
] = "Annihilation" # 主关卡
|
||||||
@@ -998,31 +1248,6 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
elif "日常" in mode:
|
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"] = (
|
data["Configurations"]["Default"]["MainFunction.UseMedicine"] = (
|
||||||
"False" if user_data["Info"]["MedicineNumb"] == 0 else "True"
|
"False" if user_data["Info"]["MedicineNumb"] == 0 else "True"
|
||||||
) # 吃理智药
|
) # 吃理智药
|
||||||
@@ -1046,55 +1271,47 @@ class MaaManager(QObject):
|
|||||||
if user_data["Info"]["GameId_2"] != "-"
|
if user_data["Info"]["GameId_2"] != "-"
|
||||||
else ""
|
else ""
|
||||||
) # 备选关卡2
|
) # 备选关卡2
|
||||||
|
data["Configurations"]["Default"]["Fight.RemainingSanityStage"] = (
|
||||||
|
user_data["Info"]["GameId_Remain"]
|
||||||
|
if user_data["Info"]["GameId_Remain"] != "-"
|
||||||
|
else ""
|
||||||
|
) # 剩余理智关卡
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Fight.RemainingSanityStage"
|
"MainFunction.Series.Quantity"
|
||||||
] = "" # 剩余理智关卡
|
] = user_data["Info"][
|
||||||
# 连战次数
|
"SeriesNumb"
|
||||||
if user_data["Info"]["GameId"] == "1-7":
|
] # 连战次数
|
||||||
data["Configurations"]["Default"][
|
|
||||||
"MainFunction.Series.Quantity"
|
|
||||||
] = "6"
|
|
||||||
else:
|
|
||||||
data["Configurations"]["Default"][
|
|
||||||
"MainFunction.Series.Quantity"
|
|
||||||
] = "1"
|
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Penguin.IsDrGrandet"
|
"Penguin.IsDrGrandet"
|
||||||
] = "False" # 博朗台模式
|
] = "False" # 博朗台模式
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"GUI.CustomStageCode"
|
"GUI.CustomStageCode"
|
||||||
] = "True" # 手动输入关卡名
|
] = "True" # 手动输入关卡名
|
||||||
# 备选关卡
|
data["Configurations"]["Default"][
|
||||||
if (
|
"GUI.UseAlternateStage"
|
||||||
user_data["Info"]["GameId_1"] == "-"
|
] = "True" # 备选关卡
|
||||||
and user_data["Info"]["GameId_2"] == "-"
|
|
||||||
):
|
|
||||||
data["Configurations"]["Default"][
|
|
||||||
"GUI.UseAlternateStage"
|
|
||||||
] = "False"
|
|
||||||
else:
|
|
||||||
data["Configurations"]["Default"][
|
|
||||||
"GUI.UseAlternateStage"
|
|
||||||
] = "True"
|
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Fight.UseRemainingSanityStage"
|
"Fight.UseRemainingSanityStage"
|
||||||
] = "False" # 使用剩余理智
|
] = "True" # 使用剩余理智
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Fight.UseExpiringMedicine"
|
"Fight.UseExpiringMedicine"
|
||||||
] = "True" # 无限吃48小时内过期的理智药
|
] = "True" # 无限吃48小时内过期的理智药
|
||||||
# 自定义基建配置
|
# 自定义基建配置
|
||||||
if user_data["Info"]["Infrastructure"]:
|
if user_data["Info"]["InfrastMode"] == "Custom":
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.data[index]["Path"]
|
self.data[index]["Path"]
|
||||||
/ "Infrastructure/infrastructure.json"
|
/ "Infrastructure/infrastructure.json"
|
||||||
).exists():
|
).exists():
|
||||||
|
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Infrast.CustomInfrastEnabled"
|
"Infrast.InfrastMode"
|
||||||
] = "True" # 启用自定义基建配置
|
] = "Custom" # 基建模式
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Infrast.CustomInfrastPlanIndex"
|
"Infrast.CustomInfrastPlanIndex"
|
||||||
] = "1" # 自定义基建配置索引
|
] = user_data["Data"][
|
||||||
|
"CustomInfrastPlanIndex"
|
||||||
|
] # 自定义基建配置索引
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Infrast.DefaultInfrast"
|
"Infrast.DefaultInfrast"
|
||||||
] = "user_defined" # 内置配置
|
] = "user_defined" # 内置配置
|
||||||
@@ -1119,11 +1336,13 @@ class MaaManager(QObject):
|
|||||||
)
|
)
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Infrast.CustomInfrastEnabled"
|
"Infrast.CustomInfrastEnabled"
|
||||||
] = "False" # 禁用自定义基建配置
|
] = "Normal" # 基建模式
|
||||||
else:
|
else:
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Infrast.CustomInfrastEnabled"
|
"Infrast.InfrastMode"
|
||||||
] = "False" # 禁用自定义基建配置
|
] = user_data["Info"][
|
||||||
|
"InfrastMode"
|
||||||
|
] # 基建模式
|
||||||
|
|
||||||
elif user_data["Info"]["Mode"] == "详细":
|
elif user_data["Info"]["Mode"] == "详细":
|
||||||
|
|
||||||
@@ -1156,19 +1375,33 @@ class MaaManager(QObject):
|
|||||||
if user_data["Info"]["GameId_2"] != "-"
|
if user_data["Info"]["GameId_2"] != "-"
|
||||||
else ""
|
else ""
|
||||||
) # 备选关卡2
|
) # 备选关卡2
|
||||||
|
data["Configurations"]["Default"]["Fight.RemainingSanityStage"] = (
|
||||||
|
user_data["Info"]["GameId_Remain"]
|
||||||
|
if user_data["Info"]["GameId_Remain"] != "-"
|
||||||
|
else ""
|
||||||
|
) # 剩余理智关卡
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"MainFunction.Series.Quantity"
|
||||||
|
] = user_data["Info"][
|
||||||
|
"SeriesNumb"
|
||||||
|
] # 连战次数
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"GUI.UseAlternateStage"
|
||||||
|
] = "True" # 备选关卡
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"Fight.UseRemainingSanityStage"
|
||||||
|
] = "True" # 使用剩余理智
|
||||||
|
|
||||||
# 备选关卡
|
# 基建模式
|
||||||
if (
|
if (
|
||||||
user_data["Info"]["GameId_1"] == "-"
|
data["Configurations"]["Default"]["Infrast.InfrastMode"]
|
||||||
and user_data["Info"]["GameId_2"] == "-"
|
== "Custom"
|
||||||
):
|
):
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"GUI.UseAlternateStage"
|
"Infrast.CustomInfrastPlanIndex"
|
||||||
] = "False"
|
] = user_data["Data"][
|
||||||
else:
|
"CustomInfrastPlanIndex"
|
||||||
data["Configurations"]["Default"][
|
] # 自定义基建配置索引
|
||||||
"GUI.UseAlternateStage"
|
|
||||||
] = "True"
|
|
||||||
|
|
||||||
# 人工排查配置
|
# 人工排查配置
|
||||||
elif "人工排查" in mode:
|
elif "人工排查" in mode:
|
||||||
@@ -1186,8 +1419,8 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
||||||
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
||||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = (
|
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = str(
|
||||||
"True" if self.if_open_emulator else "False"
|
self.if_open_emulator
|
||||||
) # 启动MAA后自动开启模拟器
|
) # 启动MAA后自动开启模拟器
|
||||||
|
|
||||||
# 账号切换
|
# 账号切换
|
||||||
@@ -1301,8 +1534,63 @@ class MaaManager(QObject):
|
|||||||
"TaskQueue.Reclamation.IsChecked"
|
"TaskQueue.Reclamation.IsChecked"
|
||||||
] = "False" # 生息演算
|
] = "False" # 生息演算
|
||||||
|
|
||||||
|
elif mode == "更新MAA":
|
||||||
|
|
||||||
|
data["Current"] = "Default" # 切换配置
|
||||||
|
for i in range(1, 9):
|
||||||
|
data["Global"][f"Timer.Timer{i}"] = "False" # 时间设置
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"MainFunction.PostActions"
|
||||||
|
] = "0" # 完成后无动作
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"Start.RunDirectly"
|
||||||
|
] = "False" # 启动MAA后直接运行
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"Start.OpenEmulatorAfterLaunch"
|
||||||
|
] = "False" # 启动MAA后自动开启模拟器
|
||||||
|
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
||||||
|
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
||||||
|
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.package"
|
||||||
|
] = self.maa_update_package # 更新包路径
|
||||||
|
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.ScheduledUpdateCheck"
|
||||||
|
] = "False" # 定时检查更新
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||||
|
] = "False" # 自动下载更新包
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoInstallUpdatePackage"
|
||||||
|
] = "True" # 自动安装更新包
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.WakeUp.IsChecked"
|
||||||
|
] = "False" # 开始唤醒
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Recruiting.IsChecked"
|
||||||
|
] = "False" # 自动公招
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Base.IsChecked"
|
||||||
|
] = "False" # 基建换班
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Combat.IsChecked"
|
||||||
|
] = "False" # 刷理智
|
||||||
|
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" # 生息演算
|
||||||
|
|
||||||
# 启动模拟器仅生效一次
|
# 启动模拟器仅生效一次
|
||||||
if "设置MAA" not in mode and self.if_open_emulator:
|
if "设置MAA" not in mode and "更新MAA" not in mode and self.if_open_emulator:
|
||||||
self.if_open_emulator = False
|
self.if_open_emulator = False
|
||||||
|
|
||||||
# 覆写配置文件
|
# 覆写配置文件
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -37,9 +37,6 @@ from email.mime.text import MIMEText
|
|||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
from email.utils import formataddr
|
from email.utils import formataddr
|
||||||
|
|
||||||
from serverchan_sdk import sc_send
|
|
||||||
|
|
||||||
from app.core import Config
|
from app.core import Config
|
||||||
from app.services.security import Crypto
|
from app.services.security import Crypto
|
||||||
|
|
||||||
@@ -143,76 +140,91 @@ class Notification(QWidget):
|
|||||||
self.push_info_bar.emit("error", "发送邮件时出错", f"{e}", -1)
|
self.push_info_bar.emit("error", "发送邮件时出错", f"{e}", -1)
|
||||||
|
|
||||||
def ServerChanPush(self, title, content):
|
def ServerChanPush(self, title, content):
|
||||||
"""使用Server酱推送通知"""
|
"""使用Server酱推送通知(支持 tag 和 channel,避免使用SDK)"""
|
||||||
|
|
||||||
if Config.get(Config.notify_IfServerChan):
|
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")
|
logger.error("请正确设置Server酱的SendKey")
|
||||||
self.push_info_bar.emit(
|
self.push_info_bar.emit(
|
||||||
"error",
|
"error", "Server酱通知推送异常", "请正确设置Server酱的SendKey", -1
|
||||||
"Server酱通知推送异常",
|
|
||||||
"请正确设置Server酱的SendKey",
|
|
||||||
-1,
|
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
else:
|
|
||||||
send_key = Config.get(Config.notify_ServerChanKey)
|
|
||||||
|
|
||||||
option = {}
|
try:
|
||||||
is_valid = lambda s: s == "" or (
|
# 构造 URL
|
||||||
s == "|".join(s.split("|")) and (s.count("|") == 0 or all(s.split("|")))
|
if send_key.startswith("sctp"):
|
||||||
)
|
match = re.match(r"^sctp(\d+)t", send_key)
|
||||||
"""
|
if match:
|
||||||
is_valid => True, 如果启用的话需要正确设置Tag和Channel。
|
url = f"https://{match.group(1)}.push.ft07.com/send/{send_key}.send"
|
||||||
允许空的Tag和Channel即不启用,但不允许例如a||b,|a|b,a|b|,||||
|
else:
|
||||||
"""
|
raise ValueError("SendKey 格式错误(sctp)")
|
||||||
send_tag = "|".join(
|
else:
|
||||||
_.strip() for _ in Config.get(Config.notify_ServerChanTag).split("|")
|
url = f"https://sctapi.ftqq.com/{send_key}.send"
|
||||||
)
|
|
||||||
send_channel = "|".join(
|
|
||||||
_.strip()
|
|
||||||
for _ in Config.get(Config.notify_ServerChanChannel).split("|")
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_valid(send_tag):
|
# 构建 tags 和 channel
|
||||||
option["tags"] = send_tag
|
def is_valid(s):
|
||||||
else:
|
return s == "" or (
|
||||||
option["tags"] = ""
|
s == "|".join(s.split("|"))
|
||||||
logger.warning("请正确设置Auto_MAA中ServerChan的Tag。")
|
and (s.count("|") == 0 or all(s.split("|")))
|
||||||
self.push_info_bar.emit(
|
)
|
||||||
"warning",
|
|
||||||
"Server酱通知推送异常",
|
tags = "|".join(
|
||||||
"请正确设置Auto_MAA中ServerChan的Tag。",
|
_.strip()
|
||||||
-1,
|
for _ in Config.get(Config.notify_ServerChanTag).split("|")
|
||||||
|
)
|
||||||
|
channels = "|".join(
|
||||||
|
_.strip()
|
||||||
|
for _ in Config.get(Config.notify_ServerChanChannel).split("|")
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_valid(send_channel):
|
options = {}
|
||||||
option["channel"] = send_channel
|
if is_valid(tags):
|
||||||
else:
|
options["tags"] = tags
|
||||||
option["channel"] = ""
|
else:
|
||||||
logger.warning("请正确设置Auto_MAA中ServerChan的Channel。")
|
logger.warning("Server酱 Tag 配置不正确,将被忽略")
|
||||||
self.push_info_bar.emit(
|
self.push_info_bar.emit(
|
||||||
"warning",
|
"warning",
|
||||||
"Server酱通知推送异常",
|
"Server酱通知推送异常",
|
||||||
"请正确设置Auto_MAA中ServerChan的Channel。",
|
"请正确设置 ServerChan 的 Tag",
|
||||||
-1,
|
-1,
|
||||||
)
|
)
|
||||||
|
|
||||||
response = sc_send(send_key, title, content, option)
|
if is_valid(channels):
|
||||||
if response["code"] == 0:
|
options["channel"] = channels
|
||||||
logger.info("Server酱推送通知成功")
|
else:
|
||||||
return True
|
logger.warning("Server酱 Channel 配置不正确,将被忽略")
|
||||||
else:
|
self.push_info_bar.emit(
|
||||||
logger.info("Server酱推送通知失败")
|
"warning",
|
||||||
logger.error(response)
|
"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(
|
self.push_info_bar.emit(
|
||||||
"error",
|
"error", "Server酱通知推送异常", f"请检查相关设置,如还有问题可联系开发者", -1
|
||||||
"Server酱通知推送失败",
|
|
||||||
f'使用Server酱推送通知时出错:\n{response["data"]['error']}',
|
|
||||||
-1,
|
|
||||||
)
|
)
|
||||||
return f'使用Server酱推送通知时出错:\n{response["data"]['error']}'
|
return f"Server酱通知推送异常:{str(e)}"
|
||||||
|
|
||||||
def CompanyWebHookBotPush(self, title, content):
|
def CompanyWebHookBotPush(self, title, content):
|
||||||
"""使用企业微信群机器人推送通知"""
|
"""使用企业微信群机器人推送通知"""
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -26,7 +26,7 @@ v4.3
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from PySide6.QtWidgets import QWidget
|
from PySide6.QtWidgets import QApplication, QWidget
|
||||||
import sys
|
import sys
|
||||||
import ctypes
|
import ctypes
|
||||||
import win32gui
|
import win32gui
|
||||||
@@ -44,9 +44,7 @@ class _SystemHandler:
|
|||||||
ES_CONTINUOUS = 0x80000000
|
ES_CONTINUOUS = 0x80000000
|
||||||
ES_SYSTEM_REQUIRED = 0x00000001
|
ES_SYSTEM_REQUIRED = 0x00000001
|
||||||
|
|
||||||
def __init__(self, main_window: QWidget = None):
|
def __init__(self):
|
||||||
|
|
||||||
self.main_window = main_window
|
|
||||||
|
|
||||||
self.set_Sleep()
|
self.set_Sleep()
|
||||||
self.set_SelfStart()
|
self.set_SelfStart()
|
||||||
@@ -112,7 +110,8 @@ class _SystemHandler:
|
|||||||
|
|
||||||
elif mode == "KillSelf":
|
elif mode == "KillSelf":
|
||||||
|
|
||||||
self.main_window.close()
|
Config.main_window.close()
|
||||||
|
QApplication.quit()
|
||||||
|
|
||||||
elif sys.platform.startswith("linux"):
|
elif sys.platform.startswith("linux"):
|
||||||
|
|
||||||
@@ -137,7 +136,8 @@ class _SystemHandler:
|
|||||||
|
|
||||||
elif mode == "KillSelf":
|
elif mode == "KillSelf":
|
||||||
|
|
||||||
self.main_window.close()
|
Config.main_window.close()
|
||||||
|
QApplication.quit()
|
||||||
|
|
||||||
def is_startup(self) -> bool:
|
def is_startup(self) -> bool:
|
||||||
"""判断程序是否已经开机自启"""
|
"""判断程序是否已经开机自启"""
|
||||||
|
|||||||
109
app/ui/Widget.py
109
app/ui/Widget.py
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -26,6 +26,7 @@ v4.3
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
|
QApplication,
|
||||||
QWidget,
|
QWidget,
|
||||||
QWidget,
|
QWidget,
|
||||||
QLabel,
|
QLabel,
|
||||||
@@ -60,6 +61,7 @@ from qfluentwidgets import (
|
|||||||
TransparentToolButton,
|
TransparentToolButton,
|
||||||
TeachingTipTailPosition,
|
TeachingTipTailPosition,
|
||||||
ExpandSettingCard,
|
ExpandSettingCard,
|
||||||
|
ExpandGroupSettingCard,
|
||||||
ToolButton,
|
ToolButton,
|
||||||
PushButton,
|
PushButton,
|
||||||
PrimaryPushButton,
|
PrimaryPushButton,
|
||||||
@@ -107,7 +109,14 @@ class LineEditMessageBox(MessageBoxBase):
|
|||||||
class ComboBoxMessageBox(MessageBoxBase):
|
class ComboBoxMessageBox(MessageBoxBase):
|
||||||
"""选择对话框"""
|
"""选择对话框"""
|
||||||
|
|
||||||
def __init__(self, parent, title: str, content: List[str], list: List[List[str]]):
|
def __init__(
|
||||||
|
self,
|
||||||
|
parent,
|
||||||
|
title: str,
|
||||||
|
content: List[str],
|
||||||
|
text_list: List[List[str]],
|
||||||
|
data_list: List[List[str]] = None,
|
||||||
|
):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.title = SubtitleLabel(title)
|
self.title = SubtitleLabel(title)
|
||||||
|
|
||||||
@@ -119,7 +128,11 @@ class ComboBoxMessageBox(MessageBoxBase):
|
|||||||
for i in range(len(content)):
|
for i in range(len(content)):
|
||||||
|
|
||||||
self.input.append(ComboBox())
|
self.input.append(ComboBox())
|
||||||
self.input[i].addItems(list[i])
|
if data_list:
|
||||||
|
for j in range(len(text_list[i])):
|
||||||
|
self.input[i].addItem(text_list[i][j], userData=data_list[i][j])
|
||||||
|
else:
|
||||||
|
self.input[i].addItems(text_list[i])
|
||||||
self.input[i].setCurrentIndex(-1)
|
self.input[i].setCurrentIndex(-1)
|
||||||
self.input[i].setPlaceholderText(content[i])
|
self.input[i].setPlaceholderText(content[i])
|
||||||
Layout.addWidget(self.input[i])
|
Layout.addWidget(self.input[i])
|
||||||
@@ -543,7 +556,7 @@ class UserLableSettingCard(SettingCard):
|
|||||||
text_list.append("未通过人工排查")
|
text_list.append("未通过人工排查")
|
||||||
text_list.append(
|
text_list.append(
|
||||||
f"今日已代理{self.qconfig.get(self.configItems["ProxyTimes"])}次"
|
f"今日已代理{self.qconfig.get(self.configItems["ProxyTimes"])}次"
|
||||||
if Config.server_date()
|
if Config.server_date().strftime("%Y-%m-%d")
|
||||||
== self.qconfig.get(self.configItems["LastProxyDate"])
|
== self.qconfig.get(self.configItems["LastProxyDate"])
|
||||||
else "今日未进行代理"
|
else "今日未进行代理"
|
||||||
)
|
)
|
||||||
@@ -553,7 +566,7 @@ class UserLableSettingCard(SettingCard):
|
|||||||
self.qconfig.get(self.configItems["LastAnnihilationDate"]),
|
self.qconfig.get(self.configItems["LastAnnihilationDate"]),
|
||||||
"%Y-%m-%d",
|
"%Y-%m-%d",
|
||||||
).isocalendar()[:2]
|
).isocalendar()[:2]
|
||||||
== datetime.strptime(Config.server_date(), "%Y-%m-%d").isocalendar()[:2]
|
== Config.server_date().isocalendar()[:2]
|
||||||
else "本周剿灭未完成"
|
else "本周剿灭未完成"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -608,6 +621,53 @@ class PushAndSwitchButtonSettingCard(SettingCard):
|
|||||||
self.switchButton.setText("开" if isChecked else "关")
|
self.switchButton.setText("开" if isChecked else "关")
|
||||||
|
|
||||||
|
|
||||||
|
class PushAndComboBoxSettingCard(SettingCard):
|
||||||
|
"""Setting card with push & combo box"""
|
||||||
|
|
||||||
|
clicked = Signal()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
text: str,
|
||||||
|
texts: List[str],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: OptionsConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(icon, title, content, parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItem = configItem
|
||||||
|
self.comboBox = ComboBox(self)
|
||||||
|
self.button = PushButton(text, self)
|
||||||
|
self.hBoxLayout.addWidget(self.button, 0, Qt.AlignRight)
|
||||||
|
self.hBoxLayout.addWidget(self.comboBox, 0, Qt.AlignRight)
|
||||||
|
self.hBoxLayout.addSpacing(16)
|
||||||
|
self.button.clicked.connect(self.clicked)
|
||||||
|
|
||||||
|
self.optionToText = {o: t for o, t in zip(configItem.options, texts)}
|
||||||
|
for text, option in zip(texts, configItem.options):
|
||||||
|
self.comboBox.addItem(text, userData=option)
|
||||||
|
|
||||||
|
self.comboBox.setCurrentText(self.optionToText[self.qconfig.get(configItem)])
|
||||||
|
self.comboBox.currentIndexChanged.connect(self._onCurrentIndexChanged)
|
||||||
|
configItem.valueChanged.connect(self.setValue)
|
||||||
|
|
||||||
|
def _onCurrentIndexChanged(self, index: int):
|
||||||
|
|
||||||
|
self.qconfig.set(self.configItem, self.comboBox.itemData(index))
|
||||||
|
|
||||||
|
def setValue(self, value):
|
||||||
|
if value not in self.optionToText:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.comboBox.setCurrentText(self.optionToText[value])
|
||||||
|
self.qconfig.set(self.configItem, value)
|
||||||
|
|
||||||
|
|
||||||
class SpinBoxSettingCard(SettingCard):
|
class SpinBoxSettingCard(SettingCard):
|
||||||
"""Setting card with SpinBox"""
|
"""Setting card with SpinBox"""
|
||||||
|
|
||||||
@@ -1068,6 +1128,41 @@ class QuantifiedItemCard(CardWidget):
|
|||||||
self.Layout.addWidget(self.Numb)
|
self.Layout.addWidget(self.Numb)
|
||||||
|
|
||||||
|
|
||||||
|
class QuickExpandGroupCard(ExpandGroupSettingCard):
|
||||||
|
"""全局配置"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIcon],
|
||||||
|
title: str,
|
||||||
|
content: str = None,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
super().__init__(icon, title, content, parent)
|
||||||
|
|
||||||
|
def setExpand(self, isExpand: bool):
|
||||||
|
"""set the expand status of card"""
|
||||||
|
if self.isExpand == isExpand:
|
||||||
|
return
|
||||||
|
|
||||||
|
# update style sheet
|
||||||
|
self.isExpand = isExpand
|
||||||
|
self.setProperty("isExpand", isExpand)
|
||||||
|
self.setStyle(QApplication.style())
|
||||||
|
|
||||||
|
# start expand animation
|
||||||
|
if isExpand:
|
||||||
|
h = self.viewLayout.sizeHint().height()
|
||||||
|
self.verticalScrollBar().setValue(h)
|
||||||
|
self.expandAni.setStartValue(h)
|
||||||
|
self.expandAni.setEndValue(0)
|
||||||
|
self.expandAni.start()
|
||||||
|
else:
|
||||||
|
self.setFixedHeight(self.viewportMargins().top())
|
||||||
|
|
||||||
|
self.card.expandButton.setExpand(isExpand)
|
||||||
|
|
||||||
|
|
||||||
class IconButton(TransparentToolButton):
|
class IconButton(TransparentToolButton):
|
||||||
"""包含下拉框的自定义设置卡片类。"""
|
"""包含下拉框的自定义设置卡片类。"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -50,7 +50,7 @@ from typing import List, Dict
|
|||||||
|
|
||||||
|
|
||||||
from app.core import Config, TaskManager, Task, MainInfoBar
|
from app.core import Config, TaskManager, Task, MainInfoBar
|
||||||
from .Widget import StatefulItemCard
|
from .Widget import StatefulItemCard, ComboBoxMessageBox
|
||||||
|
|
||||||
|
|
||||||
class DispatchCenter(QWidget):
|
class DispatchCenter(QWidget):
|
||||||
@@ -89,7 +89,7 @@ class DispatchCenter(QWidget):
|
|||||||
|
|
||||||
dispatch_box = DispatchBox(task.name, self)
|
dispatch_box = DispatchBox(task.name, self)
|
||||||
|
|
||||||
dispatch_box.top_bar.button.clicked.connect(
|
dispatch_box.top_bar.main_button.clicked.connect(
|
||||||
lambda: TaskManager.stop_task(task.name)
|
lambda: TaskManager.stop_task(task.name)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -123,9 +123,10 @@ class DispatchCenter(QWidget):
|
|||||||
self.script_list["主调度台"].top_bar.Lable.show()
|
self.script_list["主调度台"].top_bar.Lable.show()
|
||||||
self.script_list["主调度台"].top_bar.object.hide()
|
self.script_list["主调度台"].top_bar.object.hide()
|
||||||
self.script_list["主调度台"].top_bar.mode.hide()
|
self.script_list["主调度台"].top_bar.mode.hide()
|
||||||
self.script_list["主调度台"].top_bar.button.clicked.disconnect()
|
self.script_list["主调度台"].top_bar.multi_button.show()
|
||||||
self.script_list["主调度台"].top_bar.button.setText("中止任务")
|
self.script_list["主调度台"].top_bar.main_button.clicked.disconnect()
|
||||||
self.script_list["主调度台"].top_bar.button.clicked.connect(
|
self.script_list["主调度台"].top_bar.main_button.setText("中止任务")
|
||||||
|
self.script_list["主调度台"].top_bar.main_button.clicked.connect(
|
||||||
lambda: TaskManager.stop_task(task.name)
|
lambda: TaskManager.stop_task(task.name)
|
||||||
)
|
)
|
||||||
task.create_task_list.connect(
|
task.create_task_list.connect(
|
||||||
@@ -153,10 +154,11 @@ class DispatchCenter(QWidget):
|
|||||||
self.script_list["主调度台"].top_bar.Lable.hide()
|
self.script_list["主调度台"].top_bar.Lable.hide()
|
||||||
self.script_list["主调度台"].top_bar.object.show()
|
self.script_list["主调度台"].top_bar.object.show()
|
||||||
self.script_list["主调度台"].top_bar.mode.show()
|
self.script_list["主调度台"].top_bar.mode.show()
|
||||||
self.script_list["主调度台"].top_bar.button.clicked.disconnect()
|
self.script_list["主调度台"].top_bar.multi_button.hide()
|
||||||
self.script_list["主调度台"].top_bar.button.setText("开始任务")
|
self.script_list["主调度台"].top_bar.main_button.clicked.disconnect()
|
||||||
self.script_list["主调度台"].top_bar.button.clicked.connect(
|
self.script_list["主调度台"].top_bar.main_button.setText("开始任务")
|
||||||
self.script_list["主调度台"].top_bar.start_task
|
self.script_list["主调度台"].top_bar.main_button.clicked.connect(
|
||||||
|
self.script_list["主调度台"].top_bar.start_main_task
|
||||||
)
|
)
|
||||||
if len(logs) > 0:
|
if len(logs) > 0:
|
||||||
history = ""
|
history = ""
|
||||||
@@ -250,25 +252,29 @@ class DispatchBox(QWidget):
|
|||||||
self.mode = ComboBox()
|
self.mode = ComboBox()
|
||||||
self.mode.setPlaceholderText("请选择调度模式")
|
self.mode.setPlaceholderText("请选择调度模式")
|
||||||
|
|
||||||
self.button = PushButton("开始任务")
|
self.multi_button = PushButton("添加任务")
|
||||||
self.button.clicked.connect(self.start_task)
|
self.multi_button.clicked.connect(self.start_multi_task)
|
||||||
|
self.main_button = PushButton("开始任务")
|
||||||
|
self.main_button.clicked.connect(self.start_main_task)
|
||||||
|
self.multi_button.hide()
|
||||||
|
|
||||||
Layout.addWidget(self.Lable)
|
Layout.addWidget(self.Lable)
|
||||||
Layout.addWidget(self.object)
|
Layout.addWidget(self.object)
|
||||||
Layout.addWidget(self.mode)
|
Layout.addWidget(self.mode)
|
||||||
Layout.addStretch(1)
|
Layout.addStretch(1)
|
||||||
Layout.addWidget(self.button)
|
Layout.addWidget(self.multi_button)
|
||||||
|
Layout.addWidget(self.main_button)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
self.Lable = SubtitleLabel(name, self)
|
self.Lable = SubtitleLabel(name, self)
|
||||||
self.button = PushButton("中止任务")
|
self.main_button = PushButton("中止任务")
|
||||||
|
|
||||||
Layout.addWidget(self.Lable)
|
Layout.addWidget(self.Lable)
|
||||||
Layout.addStretch(1)
|
Layout.addStretch(1)
|
||||||
Layout.addWidget(self.button)
|
Layout.addWidget(self.main_button)
|
||||||
|
|
||||||
def start_task(self):
|
def start_main_task(self):
|
||||||
"""开始任务"""
|
"""开始任务"""
|
||||||
|
|
||||||
if self.object.currentIndex() == -1:
|
if self.object.currentIndex() == -1:
|
||||||
@@ -312,6 +318,74 @@ class DispatchBox(QWidget):
|
|||||||
{"Queue": {"Member_1": self.object.currentData()}},
|
{"Queue": {"Member_1": self.object.currentData()}},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def start_multi_task(self):
|
||||||
|
"""开始任务"""
|
||||||
|
|
||||||
|
# 获取所有可用的队列和实例
|
||||||
|
text_list = []
|
||||||
|
data_list = []
|
||||||
|
for name, info in Config.queue_dict.items():
|
||||||
|
if name in Config.running_list:
|
||||||
|
continue
|
||||||
|
text_list.append(
|
||||||
|
"队列"
|
||||||
|
if info["Config"].get(info["Config"].queueSet_Name) == ""
|
||||||
|
else f"队列 - {info["Config"].get(info["Config"].queueSet_Name)}"
|
||||||
|
)
|
||||||
|
data_list.append(name)
|
||||||
|
|
||||||
|
for name, info in Config.member_dict.items():
|
||||||
|
if name in Config.running_list:
|
||||||
|
continue
|
||||||
|
text_list.append(
|
||||||
|
f"实例 - {info['Type']}"
|
||||||
|
if info["Config"].get(info["Config"].MaaSet_Name) == ""
|
||||||
|
else f"实例 - {info['Type']} - {info["Config"].get(info["Config"].MaaSet_Name)}"
|
||||||
|
)
|
||||||
|
data_list.append(name)
|
||||||
|
|
||||||
|
choice = ComboBoxMessageBox(
|
||||||
|
self.window(),
|
||||||
|
"选择一个对象以添加相应多开任务",
|
||||||
|
["选择调度对象"],
|
||||||
|
[text_list],
|
||||||
|
[data_list],
|
||||||
|
)
|
||||||
|
|
||||||
|
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()}")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "任务已存在", choice.input[0].currentData(), 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if "调度队列" in choice.input[0].currentData():
|
||||||
|
|
||||||
|
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
||||||
|
TaskManager.add_task(
|
||||||
|
"自动代理_新调度台",
|
||||||
|
choice.input[0].currentData(),
|
||||||
|
Config.queue_dict[choice.input[0].currentData()][
|
||||||
|
"Config"
|
||||||
|
].toDict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
elif "脚本" in choice.input[0].currentData():
|
||||||
|
|
||||||
|
if (
|
||||||
|
Config.member_dict[choice.input[0].currentData()]["Type"]
|
||||||
|
== "Maa"
|
||||||
|
):
|
||||||
|
|
||||||
|
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
||||||
|
TaskManager.add_task(
|
||||||
|
"自动代理_新调度台",
|
||||||
|
f"自定义队列 - {choice.input[0].currentData()}",
|
||||||
|
{"Queue": {"Member_1": choice.input[0].currentData()}},
|
||||||
|
)
|
||||||
|
|
||||||
class DispatchInfoCard(HeaderCardWidget):
|
class DispatchInfoCard(HeaderCardWidget):
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -36,18 +36,23 @@ from qfluentwidgets import (
|
|||||||
FluentIcon,
|
FluentIcon,
|
||||||
HeaderCardWidget,
|
HeaderCardWidget,
|
||||||
PushButton,
|
PushButton,
|
||||||
ExpandGroupSettingCard,
|
|
||||||
TextBrowser,
|
TextBrowser,
|
||||||
|
CardWidget,
|
||||||
|
ComboBox,
|
||||||
|
ZhDatePicker,
|
||||||
|
SubtitleLabel,
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Signal
|
from PySide6.QtCore import Signal, QDate
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import Union, List, Dict
|
||||||
|
|
||||||
|
|
||||||
from app.core import Config
|
from app.core import Config
|
||||||
from .Widget import StatefulItemCard, QuantifiedItemCard
|
from .Widget import StatefulItemCard, QuantifiedItemCard, QuickExpandGroupCard
|
||||||
|
|
||||||
|
|
||||||
class History(QWidget):
|
class History(QWidget):
|
||||||
@@ -58,20 +63,22 @@ class History(QWidget):
|
|||||||
|
|
||||||
content_widget = QWidget()
|
content_widget = QWidget()
|
||||||
self.content_layout = QVBoxLayout(content_widget)
|
self.content_layout = QVBoxLayout(content_widget)
|
||||||
|
self.history_top_bar = self.HistoryTopBar(self)
|
||||||
|
|
||||||
|
self.history_top_bar.search_history.connect(self.reload_history)
|
||||||
|
|
||||||
scrollArea = ScrollArea()
|
scrollArea = ScrollArea()
|
||||||
scrollArea.setWidgetResizable(True)
|
scrollArea.setWidgetResizable(True)
|
||||||
scrollArea.setWidget(content_widget)
|
scrollArea.setWidget(content_widget)
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
layout.addWidget(self.history_top_bar)
|
||||||
layout.addWidget(scrollArea)
|
layout.addWidget(scrollArea)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
self.history_card_list = []
|
self.history_card_list = []
|
||||||
|
|
||||||
self.refresh()
|
def reload_history(self, mode: str, start_date: QDate, end_date: QDate) -> None:
|
||||||
|
"""加载历史记录界面"""
|
||||||
def refresh(self):
|
|
||||||
"""刷新脚本实例界面"""
|
|
||||||
|
|
||||||
while self.content_layout.count() > 0:
|
while self.content_layout.count() > 0:
|
||||||
item = self.content_layout.takeAt(0)
|
item = self.content_layout.takeAt(0)
|
||||||
@@ -82,177 +89,300 @@ class History(QWidget):
|
|||||||
|
|
||||||
self.history_card_list = []
|
self.history_card_list = []
|
||||||
|
|
||||||
history_dict = Config.search_history()
|
history_dict = Config.search_history(
|
||||||
|
mode,
|
||||||
|
datetime(start_date.year(), start_date.month(), start_date.day()),
|
||||||
|
datetime(end_date.year(), end_date.month(), end_date.day()),
|
||||||
|
)
|
||||||
|
|
||||||
for date, user_list in history_dict.items():
|
for date, user in history_dict.items():
|
||||||
|
|
||||||
self.history_card_list.append(HistoryCard(date, user_list, self))
|
self.history_card_list.append(self.HistoryCard(mode, date, user, self))
|
||||||
self.content_layout.addWidget(self.history_card_list[-1])
|
self.content_layout.addWidget(self.history_card_list[-1])
|
||||||
|
|
||||||
self.content_layout.addStretch(1)
|
self.content_layout.addStretch(1)
|
||||||
|
|
||||||
|
class HistoryTopBar(CardWidget):
|
||||||
|
"""历史记录顶部工具栏"""
|
||||||
|
|
||||||
class HistoryCard(ExpandGroupSettingCard):
|
search_history = Signal(str, QDate, QDate)
|
||||||
|
|
||||||
def __init__(self, date: str, user_list: List[Path], parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(
|
super().__init__(parent)
|
||||||
FluentIcon.HISTORY, date, f"{date}的历史运行记录与统计信息", parent
|
|
||||||
)
|
|
||||||
|
|
||||||
widget = QWidget()
|
Layout = QHBoxLayout(self)
|
||||||
Layout = QVBoxLayout(widget)
|
|
||||||
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
|
||||||
self.viewLayout.setSpacing(0)
|
|
||||||
self.addGroupWidget(widget)
|
|
||||||
|
|
||||||
self.user_history_card_list = []
|
self.lable_1 = SubtitleLabel("查询范围:")
|
||||||
|
self.start_date = ZhDatePicker()
|
||||||
|
self.start_date.setDate(QDate(2019, 5, 1))
|
||||||
|
self.lable_2 = SubtitleLabel("→")
|
||||||
|
self.end_date = ZhDatePicker()
|
||||||
|
server_date = Config.server_date()
|
||||||
|
self.end_date.setDate(
|
||||||
|
QDate(server_date.year, server_date.month, server_date.day)
|
||||||
|
)
|
||||||
|
self.mode = ComboBox()
|
||||||
|
self.mode.setPlaceholderText("请选择查询模式")
|
||||||
|
self.mode.addItems(["按日合并", "按周合并", "按月合并"])
|
||||||
|
|
||||||
for user_path in user_list:
|
self.select_month = PushButton(FluentIcon.TAG, "最近一月")
|
||||||
|
self.select_week = PushButton(FluentIcon.TAG, "最近一周")
|
||||||
|
self.search = PushButton(FluentIcon.SEARCH, "查询")
|
||||||
|
self.select_month.clicked.connect(lambda: self.select_date("month"))
|
||||||
|
self.select_week.clicked.connect(lambda: self.select_date("week"))
|
||||||
|
self.search.clicked.connect(
|
||||||
|
lambda: self.search_history.emit(
|
||||||
|
self.mode.currentText(),
|
||||||
|
self.start_date.getDate(),
|
||||||
|
self.end_date.getDate(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.user_history_card_list.append(self.UserHistoryCard(user_path, self))
|
Layout.addWidget(self.lable_1)
|
||||||
Layout.addWidget(self.user_history_card_list[-1])
|
Layout.addWidget(self.start_date)
|
||||||
|
Layout.addWidget(self.lable_2)
|
||||||
|
Layout.addWidget(self.end_date)
|
||||||
|
Layout.addWidget(self.mode)
|
||||||
|
Layout.addStretch(1)
|
||||||
|
Layout.addWidget(self.select_month)
|
||||||
|
Layout.addWidget(self.select_week)
|
||||||
|
Layout.addWidget(self.search)
|
||||||
|
|
||||||
class UserHistoryCard(HeaderCardWidget):
|
def select_date(self, date: str) -> None:
|
||||||
|
"""选中最近一段时间并启动查询"""
|
||||||
|
|
||||||
|
server_date = Config.server_date()
|
||||||
|
if date == "week":
|
||||||
|
begin_date = server_date - timedelta(weeks=1)
|
||||||
|
elif date == "month":
|
||||||
|
begin_date = server_date - timedelta(days=30)
|
||||||
|
|
||||||
|
self.start_date.setDate(
|
||||||
|
QDate(begin_date.year, begin_date.month, begin_date.day)
|
||||||
|
)
|
||||||
|
self.end_date.setDate(
|
||||||
|
QDate(server_date.year, server_date.month, server_date.day)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.search.clicked.emit()
|
||||||
|
|
||||||
|
class HistoryCard(QuickExpandGroupCard):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
user_history_path: Path,
|
mode: str,
|
||||||
|
date: str,
|
||||||
|
user: Union[List[Path], Dict[str, List[Path]]],
|
||||||
parent=None,
|
parent=None,
|
||||||
):
|
):
|
||||||
super().__init__(parent)
|
super().__init__(
|
||||||
|
FluentIcon.HISTORY, date, f"{date}的历史运行记录与统计信息", parent
|
||||||
|
)
|
||||||
|
|
||||||
self.setTitle(user_history_path.name.replace(".json", ""))
|
widget = QWidget()
|
||||||
|
Layout = QVBoxLayout(widget)
|
||||||
self.user_history_path = user_history_path
|
|
||||||
self.main_history = Config.load_maa_logs("总览", user_history_path)
|
|
||||||
|
|
||||||
self.index_card = self.IndexCard(self.main_history["条目索引"], self)
|
|
||||||
self.statistics_card = QHBoxLayout()
|
|
||||||
self.log_card = self.LogCard(self)
|
|
||||||
|
|
||||||
self.index_card.index_changed.connect(self.update_info)
|
|
||||||
|
|
||||||
self.viewLayout.addWidget(self.index_card)
|
|
||||||
self.viewLayout.addLayout(self.statistics_card)
|
|
||||||
self.viewLayout.addWidget(self.log_card)
|
|
||||||
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.viewLayout.setSpacing(0)
|
self.viewLayout.setSpacing(0)
|
||||||
self.viewLayout.setStretch(0, 1)
|
self.addGroupWidget(widget)
|
||||||
self.viewLayout.setStretch(2, 4)
|
|
||||||
|
|
||||||
self.update_info("数据总览")
|
self.user_history_card_list = []
|
||||||
|
|
||||||
def update_info(self, index: str) -> None:
|
if mode == "按日合并":
|
||||||
"""更新信息"""
|
|
||||||
|
|
||||||
if index == "数据总览":
|
for user_path in user:
|
||||||
|
self.user_history_card_list.append(
|
||||||
while self.statistics_card.count() > 0:
|
self.UserHistoryCard(mode, user_path.stem, user_path, self)
|
||||||
item = self.statistics_card.takeAt(0)
|
|
||||||
if item.spacerItem():
|
|
||||||
self.statistics_card.removeItem(item.spacerItem())
|
|
||||||
elif item.widget():
|
|
||||||
item.widget().deleteLater()
|
|
||||||
|
|
||||||
for name, item_list in self.main_history["统计数据"].items():
|
|
||||||
|
|
||||||
statistics_card = self.StatisticsCard(name, item_list, self)
|
|
||||||
self.statistics_card.addWidget(statistics_card)
|
|
||||||
|
|
||||||
self.log_card.hide()
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
single_history = Config.load_maa_logs(
|
|
||||||
"单项",
|
|
||||||
self.user_history_path.with_suffix("")
|
|
||||||
/ f"{index.replace(":","-")}.json",
|
|
||||||
)
|
|
||||||
|
|
||||||
while self.statistics_card.count() > 0:
|
|
||||||
item = self.statistics_card.takeAt(0)
|
|
||||||
if item.spacerItem():
|
|
||||||
self.statistics_card.removeItem(item.spacerItem())
|
|
||||||
elif item.widget():
|
|
||||||
item.widget().deleteLater()
|
|
||||||
|
|
||||||
for name, item_list in single_history["统计数据"].items():
|
|
||||||
|
|
||||||
statistics_card = self.StatisticsCard(name, item_list, self)
|
|
||||||
self.statistics_card.addWidget(statistics_card)
|
|
||||||
|
|
||||||
self.log_card.text.setText(single_history["日志信息"])
|
|
||||||
self.log_card.button.clicked.disconnect()
|
|
||||||
self.log_card.button.clicked.connect(
|
|
||||||
lambda: os.startfile(
|
|
||||||
self.user_history_path.with_suffix("")
|
|
||||||
/ f"{index.replace(":","-")}.log"
|
|
||||||
)
|
)
|
||||||
)
|
Layout.addWidget(self.user_history_card_list[-1])
|
||||||
self.log_card.show()
|
|
||||||
|
|
||||||
self.viewLayout.setStretch(1, self.statistics_card.count())
|
elif mode in ["按周合并", "按月合并"]:
|
||||||
|
|
||||||
self.setMinimumHeight(300)
|
for user, info in user.items():
|
||||||
|
self.user_history_card_list.append(
|
||||||
class IndexCard(HeaderCardWidget):
|
self.UserHistoryCard(mode, user, info, self)
|
||||||
|
|
||||||
index_changed = Signal(str)
|
|
||||||
|
|
||||||
def __init__(self, index_list: list, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setTitle("记录条目")
|
|
||||||
|
|
||||||
self.Layout = QVBoxLayout()
|
|
||||||
self.viewLayout.addLayout(self.Layout)
|
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
|
||||||
|
|
||||||
self.index_cards: List[StatefulItemCard] = []
|
|
||||||
|
|
||||||
for index in index_list:
|
|
||||||
|
|
||||||
self.index_cards.append(StatefulItemCard(index))
|
|
||||||
self.index_cards[-1].clicked.connect(
|
|
||||||
partial(self.index_changed.emit, index[0])
|
|
||||||
)
|
)
|
||||||
self.Layout.addWidget(self.index_cards[-1])
|
Layout.addWidget(self.user_history_card_list[-1])
|
||||||
|
|
||||||
self.Layout.addStretch(1)
|
class UserHistoryCard(HeaderCardWidget):
|
||||||
|
"""用户历史记录卡片"""
|
||||||
|
|
||||||
class StatisticsCard(HeaderCardWidget):
|
def __init__(
|
||||||
|
self,
|
||||||
def __init__(self, name: str, item_list: list, parent=None):
|
mode: str,
|
||||||
|
name: str,
|
||||||
|
user_history: Union[Path, List[Path]],
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.setTitle(name)
|
self.setTitle(name)
|
||||||
|
|
||||||
self.Layout = QVBoxLayout()
|
if mode == "按日合并":
|
||||||
self.viewLayout.addLayout(self.Layout)
|
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
|
||||||
|
|
||||||
self.item_cards: List[QuantifiedItemCard] = []
|
self.user_history_path = user_history
|
||||||
|
self.main_history = Config.load_maa_logs("总览", user_history)
|
||||||
|
|
||||||
for item in item_list:
|
self.index_card = self.IndexCard(
|
||||||
|
self.main_history["条目索引"], self
|
||||||
|
)
|
||||||
|
self.index_card.index_changed.connect(self.update_info)
|
||||||
|
self.viewLayout.addWidget(self.index_card)
|
||||||
|
|
||||||
self.item_cards.append(QuantifiedItemCard(item))
|
elif mode in ["按周合并", "按月合并"]:
|
||||||
self.Layout.addWidget(self.item_cards[-1])
|
|
||||||
|
|
||||||
if len(item_list) == 0:
|
history = Config.merge_maa_logs("指定项", user_history)
|
||||||
self.Layout.addWidget(QuantifiedItemCard(["暂无记录", ""]))
|
|
||||||
|
|
||||||
self.Layout.addStretch(1)
|
self.main_history = {}
|
||||||
|
self.main_history["统计数据"] = {
|
||||||
|
"公招统计": list(history["recruit_statistics"].items())
|
||||||
|
}
|
||||||
|
|
||||||
class LogCard(HeaderCardWidget):
|
for game_id, drops in history["drop_statistics"].items():
|
||||||
|
self.main_history["统计数据"][f"掉落统计:{game_id}"] = list(
|
||||||
|
drops.items()
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
self.statistics_card = QHBoxLayout()
|
||||||
super().__init__(parent)
|
self.log_card = self.LogCard(self)
|
||||||
self.setTitle("日志")
|
|
||||||
|
|
||||||
self.text = TextBrowser(self)
|
self.viewLayout.addLayout(self.statistics_card)
|
||||||
self.button = PushButton("打开日志文件", self)
|
self.viewLayout.addWidget(self.log_card)
|
||||||
self.button.clicked.connect(lambda: print("打开日志文件"))
|
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.viewLayout.setSpacing(0)
|
||||||
|
self.viewLayout.setStretch(0, 1)
|
||||||
|
self.viewLayout.setStretch(2, 4)
|
||||||
|
|
||||||
Layout = QVBoxLayout()
|
self.update_info("数据总览")
|
||||||
Layout.addWidget(self.text)
|
|
||||||
Layout.addWidget(self.button)
|
def update_info(self, index: str) -> None:
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
"""更新信息"""
|
||||||
self.viewLayout.addLayout(Layout)
|
|
||||||
|
if index == "数据总览":
|
||||||
|
|
||||||
|
while self.statistics_card.count() > 0:
|
||||||
|
item = self.statistics_card.takeAt(0)
|
||||||
|
if item.spacerItem():
|
||||||
|
self.statistics_card.removeItem(item.spacerItem())
|
||||||
|
elif item.widget():
|
||||||
|
item.widget().deleteLater()
|
||||||
|
|
||||||
|
for name, item_list in self.main_history["统计数据"].items():
|
||||||
|
|
||||||
|
statistics_card = self.StatisticsCard(name, item_list, self)
|
||||||
|
self.statistics_card.addWidget(statistics_card)
|
||||||
|
|
||||||
|
self.log_card.hide()
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
single_history = Config.load_maa_logs(
|
||||||
|
"单项",
|
||||||
|
self.user_history_path.with_suffix("")
|
||||||
|
/ f"{index.replace(":","-")}.json",
|
||||||
|
)
|
||||||
|
|
||||||
|
while self.statistics_card.count() > 0:
|
||||||
|
item = self.statistics_card.takeAt(0)
|
||||||
|
if item.spacerItem():
|
||||||
|
self.statistics_card.removeItem(item.spacerItem())
|
||||||
|
elif item.widget():
|
||||||
|
item.widget().deleteLater()
|
||||||
|
|
||||||
|
for name, item_list in single_history["统计数据"].items():
|
||||||
|
|
||||||
|
statistics_card = self.StatisticsCard(name, item_list, self)
|
||||||
|
self.statistics_card.addWidget(statistics_card)
|
||||||
|
|
||||||
|
self.log_card.text.setText(single_history["日志信息"])
|
||||||
|
self.log_card.open_file.clicked.disconnect()
|
||||||
|
self.log_card.open_file.clicked.connect(
|
||||||
|
lambda: os.startfile(
|
||||||
|
self.user_history_path.with_suffix("")
|
||||||
|
/ f"{index.replace(":","-")}.log"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.log_card.open_dir.clicked.disconnect()
|
||||||
|
self.log_card.open_dir.clicked.connect(
|
||||||
|
lambda: subprocess.Popen(
|
||||||
|
[
|
||||||
|
"explorer",
|
||||||
|
"/select,",
|
||||||
|
str(
|
||||||
|
self.user_history_path.with_suffix("")
|
||||||
|
/ f"{index.replace(":","-")}.log"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.log_card.show()
|
||||||
|
|
||||||
|
self.viewLayout.setStretch(1, self.statistics_card.count())
|
||||||
|
|
||||||
|
self.setMinimumHeight(300)
|
||||||
|
|
||||||
|
class IndexCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
index_changed = Signal(str)
|
||||||
|
|
||||||
|
def __init__(self, index_list: list, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("记录条目")
|
||||||
|
|
||||||
|
self.Layout = QVBoxLayout()
|
||||||
|
self.viewLayout.addLayout(self.Layout)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
|
self.index_cards: List[StatefulItemCard] = []
|
||||||
|
|
||||||
|
for index in index_list:
|
||||||
|
|
||||||
|
self.index_cards.append(StatefulItemCard(index))
|
||||||
|
self.index_cards[-1].clicked.connect(
|
||||||
|
partial(self.index_changed.emit, index[0])
|
||||||
|
)
|
||||||
|
self.Layout.addWidget(self.index_cards[-1])
|
||||||
|
|
||||||
|
self.Layout.addStretch(1)
|
||||||
|
|
||||||
|
class StatisticsCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, name: str, item_list: list, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle(name)
|
||||||
|
|
||||||
|
self.Layout = QVBoxLayout()
|
||||||
|
self.viewLayout.addLayout(self.Layout)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
|
self.item_cards: List[QuantifiedItemCard] = []
|
||||||
|
|
||||||
|
for item in item_list:
|
||||||
|
|
||||||
|
self.item_cards.append(QuantifiedItemCard(item))
|
||||||
|
self.Layout.addWidget(self.item_cards[-1])
|
||||||
|
|
||||||
|
if len(item_list) == 0:
|
||||||
|
self.Layout.addWidget(QuantifiedItemCard(["暂无记录", ""]))
|
||||||
|
|
||||||
|
self.Layout.addStretch(1)
|
||||||
|
|
||||||
|
class LogCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("日志")
|
||||||
|
|
||||||
|
self.text = TextBrowser(self)
|
||||||
|
self.open_file = PushButton("打开日志文件", self)
|
||||||
|
self.open_file.clicked.connect(lambda: print("打开日志文件"))
|
||||||
|
self.open_dir = PushButton("打开所在目录", self)
|
||||||
|
self.open_dir.clicked.connect(lambda: print("打开所在文件"))
|
||||||
|
|
||||||
|
Layout = QVBoxLayout()
|
||||||
|
h_layout = QHBoxLayout()
|
||||||
|
h_layout.addWidget(self.open_file)
|
||||||
|
h_layout.addWidget(self.open_dir)
|
||||||
|
Layout.addWidget(self.text)
|
||||||
|
Layout.addLayout(h_layout)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
self.viewLayout.addLayout(Layout)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -26,7 +26,7 @@ v4.3
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from PySide6.QtWidgets import QSystemTrayIcon
|
from PySide6.QtWidgets import QApplication, QSystemTrayIcon
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
qconfig,
|
qconfig,
|
||||||
Action,
|
Action,
|
||||||
@@ -62,16 +62,22 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.setWindowIcon(QIcon(str(Config.app_path / "resources/icons/AUTO_MAA.ico")))
|
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.switch_theme()
|
||||||
|
|
||||||
self.splashScreen = SplashScreen(self.windowIcon(), self)
|
self.splashScreen = SplashScreen(self.windowIcon(), self)
|
||||||
self.show_ui("显示主窗口", if_quick=True)
|
self.show_ui("显示主窗口", if_quick=True)
|
||||||
|
|
||||||
TaskManager.main_window = self.window()
|
Config.main_window = self.window()
|
||||||
MainInfoBar.main_window = self.window()
|
|
||||||
System.main_window = self.window()
|
|
||||||
|
|
||||||
# 创建主窗口
|
# 创建主窗口
|
||||||
self.home = Home(self)
|
self.home = Home(self)
|
||||||
@@ -140,9 +146,6 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
self.dispatch_center.update_top_bar() if index == 3 else None
|
self.dispatch_center.update_top_bar() if index == 3 else None
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.stackedWidget.currentChanged.connect(
|
|
||||||
lambda index: (self.history.refresh() if index == 4 else None)
|
|
||||||
)
|
|
||||||
|
|
||||||
# 创建系统托盘及其菜单
|
# 创建系统托盘及其菜单
|
||||||
self.tray = QSystemTrayIcon(
|
self.tray = QSystemTrayIcon(
|
||||||
@@ -176,13 +179,19 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
|
|
||||||
# 退出主程序菜单项
|
# 退出主程序菜单项
|
||||||
self.tray_menu.addAction(
|
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.setContextMenu(self.tray_menu)
|
||||||
self.tray.activated.connect(self.on_tray_activated)
|
self.tray.activated.connect(self.on_tray_activated)
|
||||||
|
|
||||||
|
self.set_min_method()
|
||||||
|
|
||||||
Config.user_info_changed.connect(self.member_manager.refresh_dashboard)
|
Config.user_info_changed.connect(self.member_manager.refresh_dashboard)
|
||||||
TaskManager.create_gui.connect(self.dispatch_center.add_board)
|
TaskManager.create_gui.connect(self.dispatch_center.add_board)
|
||||||
TaskManager.connect_gui.connect(self.dispatch_center.connect_main_board)
|
TaskManager.connect_gui.connect(self.dispatch_center.connect_main_board)
|
||||||
@@ -258,11 +267,11 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
self.start_main_task()
|
self.start_main_task()
|
||||||
|
|
||||||
# 获取公告
|
# 获取公告
|
||||||
self.setting.show_notice(if_show=False)
|
self.setting.show_notice(if_first=True)
|
||||||
|
|
||||||
# 检查更新
|
# 检查更新
|
||||||
if Config.get(Config.update_IfAutoUpdate):
|
if Config.get(Config.update_IfAutoUpdate):
|
||||||
self.setting.check_update()
|
self.setting.check_update(if_first=True)
|
||||||
|
|
||||||
# 直接最小化
|
# 直接最小化
|
||||||
if Config.get(Config.start_IfMinimizeDirectly):
|
if Config.get(Config.start_IfMinimizeDirectly):
|
||||||
@@ -324,7 +333,7 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
logger.info("自动添加任务:调度队列_1")
|
logger.info("自动添加任务:调度队列_1")
|
||||||
TaskManager.add_task(
|
TaskManager.add_task(
|
||||||
"自动代理_主调度台",
|
"自动代理_主调度台",
|
||||||
"主任务队列",
|
"调度队列_1",
|
||||||
Config.queue_dict["调度队列_1"]["Config"].toDict(),
|
Config.queue_dict["调度队列_1"]["Config"].toDict(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -332,7 +341,7 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
|
|
||||||
logger.info("自动添加任务:脚本_1")
|
logger.info("自动添加任务:脚本_1")
|
||||||
TaskManager.add_task(
|
TaskManager.add_task(
|
||||||
"自动代理_主调度台", "主任务队列", {"Queue": {"Member_1": "脚本_1"}}
|
"自动代理_主调度台", "自定义队列", {"Queue": {"Member_1": "脚本_1"}}
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -350,27 +359,37 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
if mode == "显示主窗口":
|
if mode == "显示主窗口":
|
||||||
|
|
||||||
# 配置主窗口
|
# 配置主窗口
|
||||||
size = list(
|
if not self.window().isVisible():
|
||||||
map(
|
size = list(
|
||||||
int,
|
map(
|
||||||
Config.get(Config.ui_size).split("x"),
|
int,
|
||||||
|
Config.get(Config.ui_size).split("x"),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
location = list(
|
||||||
location = list(
|
map(
|
||||||
map(
|
int,
|
||||||
int,
|
Config.get(Config.ui_location).split("x"),
|
||||||
Config.get(Config.ui_location).split("x"),
|
)
|
||||||
)
|
)
|
||||||
)
|
if self.window().isMaximized():
|
||||||
self.window().setGeometry(location[0], location[1], size[0], size[1])
|
self.window().showNormal()
|
||||||
self.window().show()
|
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().raise_()
|
||||||
self.window().activateWindow()
|
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 == "配置托盘":
|
elif mode == "配置托盘":
|
||||||
|
|
||||||
@@ -392,6 +411,7 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
Config.ui_location,
|
Config.ui_location,
|
||||||
f"{self.geometry().x()}x{self.geometry().y()}",
|
f"{self.geometry().x()}x{self.geometry().y()}",
|
||||||
)
|
)
|
||||||
|
|
||||||
Config.set(Config.ui_maximized, self.window().isMaximized())
|
Config.set(Config.ui_maximized, self.window().isMaximized())
|
||||||
Config.save()
|
Config.save()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -35,6 +35,7 @@ from PySide6.QtWidgets import (
|
|||||||
QTableWidgetItem,
|
QTableWidgetItem,
|
||||||
QHeaderView,
|
QHeaderView,
|
||||||
)
|
)
|
||||||
|
from PySide6.QtGui import QIcon
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
Action,
|
Action,
|
||||||
Pivot,
|
Pivot,
|
||||||
@@ -69,6 +70,7 @@ from .Widget import (
|
|||||||
ComboBoxSettingCard,
|
ComboBoxSettingCard,
|
||||||
SwitchSettingCard,
|
SwitchSettingCard,
|
||||||
PushAndSwitchButtonSettingCard,
|
PushAndSwitchButtonSettingCard,
|
||||||
|
PushAndComboBoxSettingCard,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -313,68 +315,120 @@ class MemberManager(QWidget):
|
|||||||
def member_downloader(self):
|
def member_downloader(self):
|
||||||
"""脚本下载器"""
|
"""脚本下载器"""
|
||||||
|
|
||||||
|
if not Config.get(Config.update_MirrorChyanCDK):
|
||||||
|
|
||||||
|
logger.warning("脚本下载器未设置CDK")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning",
|
||||||
|
"未设置Mirror酱CDK",
|
||||||
|
"下载器依赖于Mirror酱,未设置CDK时无法使用",
|
||||||
|
5000,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
choice = ComboBoxMessageBox(
|
choice = ComboBoxMessageBox(
|
||||||
self.window(),
|
self.window(),
|
||||||
"选择一个脚本类型以下载相应脚本",
|
"选择一个脚本类型以下载相应脚本",
|
||||||
["选择脚本类型"],
|
["选择脚本类型"],
|
||||||
[["MAA"]],
|
[["MAA", "StarRailAssistant"]],
|
||||||
)
|
)
|
||||||
if choice.exec() and choice.input[0].currentIndex() != -1:
|
if choice.exec() and choice.input[0].currentIndex() != -1:
|
||||||
|
|
||||||
if choice.input[0].currentText() == "MAA":
|
app_name = choice.input[0].currentText()
|
||||||
|
|
||||||
(Config.app_path / "script/MAA").mkdir(parents=True, exist_ok=True)
|
(Config.app_path / f"script/{app_name}").mkdir(parents=True, exist_ok=True)
|
||||||
folder = QFileDialog.getExistingDirectory(
|
folder = QFileDialog.getExistingDirectory(
|
||||||
self, "选择MAA下载目录", str(Config.app_path / "script/MAA")
|
self,
|
||||||
|
f"选择{app_name}下载目录",
|
||||||
|
str(Config.app_path / f"script/{app_name}"),
|
||||||
|
)
|
||||||
|
if not folder:
|
||||||
|
logger.warning(f"选择{app_name}下载目录时未选择文件夹")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "警告", f"未选择{app_name}下载目录", 5000
|
||||||
)
|
)
|
||||||
if not folder:
|
return None
|
||||||
logger.warning("选择MAA下载目录时未选择文件夹")
|
|
||||||
MainInfoBar.push_info_bar(
|
if app_name in ["MAA"]:
|
||||||
"warning", "警告", "未选择MAA下载目录", 5000
|
|
||||||
)
|
url = f"https://mirrorchyan.com/api/resources/{app_name}/latest?user_agent=AutoMaaGui&cdk={Crypto.win_decryptor(Config.get(Config.update_MirrorChyanCDK))}&os=win&arch=x64&channel=stable"
|
||||||
return None
|
|
||||||
|
elif app_name in ["StarRailAssistant"]:
|
||||||
|
|
||||||
|
url = f"https://mirrorchyan.com/api/resources/{app_name}/latest?user_agent=AutoMaaGui&cdk={Crypto.win_decryptor(Config.get(Config.update_MirrorChyanCDK))}&channel=stable"
|
||||||
|
|
||||||
|
# 从mirrorc服务器获取最新版本信息
|
||||||
|
Network.set_info(mode="get", url=url)
|
||||||
|
Network.start()
|
||||||
|
Network.loop.exec()
|
||||||
|
if Network.stutus_code == 200:
|
||||||
|
app_info = Network.response_json
|
||||||
|
else:
|
||||||
|
|
||||||
|
if Network.response_json:
|
||||||
|
|
||||||
|
app_info = Network.response_json
|
||||||
|
|
||||||
|
if app_info["code"] != 0:
|
||||||
|
|
||||||
|
logger.error(f"获取版本信息时出错:{app_info["msg"]}")
|
||||||
|
|
||||||
|
error_remark_dict = {
|
||||||
|
1001: "获取版本信息的URL参数不正确",
|
||||||
|
7001: "填入的 CDK 已过期",
|
||||||
|
7002: "填入的 CDK 错误",
|
||||||
|
7003: "填入的 CDK 今日下载次数已达上限",
|
||||||
|
7004: "填入的 CDK 类型和待下载的资源不匹配",
|
||||||
|
7005: "填入的 CDK 已被封禁",
|
||||||
|
8001: "对应架构和系统下的资源不存在",
|
||||||
|
8002: "错误的系统参数",
|
||||||
|
8003: "错误的架构参数",
|
||||||
|
8004: "错误的更新通道参数",
|
||||||
|
1: app_info["msg"],
|
||||||
|
}
|
||||||
|
|
||||||
|
if app_info["code"] in error_remark_dict:
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"error",
|
||||||
|
"获取版本信息时出错",
|
||||||
|
error_remark_dict[app_info["code"]],
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"error",
|
||||||
|
"获取版本信息时出错",
|
||||||
|
"意料之外的错误,请及时联系项目组以获取来自 Mirror 酱的技术支持",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
|
||||||
# 从mirrorc服务器获取最新版本信息
|
|
||||||
Network.set_info(
|
|
||||||
mode="get",
|
|
||||||
url="https://mirrorchyan.com/api/resources/MAA/latest?user_agent=AutoMaaGui&os=win&arch=x64&channel=stable",
|
|
||||||
)
|
|
||||||
Network.start()
|
|
||||||
Network.loop.exec()
|
|
||||||
if Network.stutus_code == 200:
|
|
||||||
maa_info = Network.response_json
|
|
||||||
else:
|
|
||||||
choice = MessageBox(
|
|
||||||
"错误",
|
|
||||||
f"获取版本信息时出错:\n{Network.error_message}",
|
|
||||||
self.window(),
|
|
||||||
)
|
|
||||||
choice.cancelButton.hide()
|
|
||||||
choice.buttonLayout.insertStretch(1)
|
|
||||||
if choice.exec():
|
|
||||||
return None
|
return None
|
||||||
maa_version = list(
|
|
||||||
map(
|
|
||||||
int,
|
|
||||||
maa_info["data"]["version_name"][1:]
|
|
||||||
.replace("-beta", "")
|
|
||||||
.split("."),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
while len(maa_version) < 4:
|
|
||||||
maa_version.append(0)
|
|
||||||
|
|
||||||
self.downloader = DownloadManager(
|
logger.warning(f"获取版本信息时出错:{Network.error_message}")
|
||||||
Path(folder),
|
MainInfoBar.push_info_bar(
|
||||||
"MAA",
|
"warning",
|
||||||
maa_version,
|
"获取版本信息时出错",
|
||||||
{
|
f"网络错误:{Network.stutus_code}",
|
||||||
"mode": "Proxy",
|
5000,
|
||||||
"thread_numb": Config.get(Config.update_ThreadNumb),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
self.downloader.show()
|
return None
|
||||||
self.downloader.run()
|
|
||||||
|
self.downloader = DownloadManager(
|
||||||
|
Path(folder),
|
||||||
|
app_name,
|
||||||
|
None,
|
||||||
|
{
|
||||||
|
"mode": "MirrorChyan",
|
||||||
|
"thread_numb": 1,
|
||||||
|
"url": app_info["data"]["url"],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.downloader.setWindowTitle("AUTO_MAA下载器 - Mirror酱渠道")
|
||||||
|
self.downloader.setWindowIcon(
|
||||||
|
QIcon(str(Config.app_path / "resources/icons/MirrorChyan.ico"))
|
||||||
|
)
|
||||||
|
self.downloader.show()
|
||||||
|
self.downloader.run()
|
||||||
|
|
||||||
def show_password(self):
|
def show_password(self):
|
||||||
|
|
||||||
@@ -613,21 +667,7 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.RunSet_TaskTransitionMethod,
|
configItem=self.config.RunSet_TaskTransitionMethod,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_EnhanceTask = ComboBoxSettingCard(
|
self.card_ProxyTimesLimit = SpinBoxSettingCard(
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
|
||||||
title="自动代理增效任务",
|
|
||||||
content="自动代理时的额外操作,此操作无法区分多开模拟器,可能会干扰其他任务,也可能关闭您正在使用的模拟器",
|
|
||||||
texts=[
|
|
||||||
"禁用",
|
|
||||||
"强制关闭ADB",
|
|
||||||
"强制关闭所有模拟器",
|
|
||||||
"强制关闭ADB和所有模拟器",
|
|
||||||
],
|
|
||||||
qconfig=self.config,
|
|
||||||
configItem=self.config.RunSet_EnhanceTask,
|
|
||||||
parent=self,
|
|
||||||
)
|
|
||||||
self.ProxyTimesLimit = SpinBoxSettingCard(
|
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="用户单日代理次数上限",
|
title="用户单日代理次数上限",
|
||||||
content="当用户本日代理成功次数达到该阈值时跳过代理,阈值为“0”时视为无代理次数上限",
|
content="当用户本日代理成功次数达到该阈值时跳过代理,阈值为“0”时视为无代理次数上限",
|
||||||
@@ -636,25 +676,7 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.RunSet_ProxyTimesLimit,
|
configItem=self.config.RunSet_ProxyTimesLimit,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.AnnihilationTimeLimit = SpinBoxSettingCard(
|
self.card_RunTimesLimit = SpinBoxSettingCard(
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
|
||||||
title="剿灭代理超时限制",
|
|
||||||
content="MAA日志无变化时间超过该阈值视为超时,单位为分钟",
|
|
||||||
range=(1, 1024),
|
|
||||||
qconfig=self.config,
|
|
||||||
configItem=self.config.RunSet_AnnihilationTimeLimit,
|
|
||||||
parent=self,
|
|
||||||
)
|
|
||||||
self.RoutineTimeLimit = SpinBoxSettingCard(
|
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
|
||||||
title="自动代理超时限制",
|
|
||||||
content="MAA日志无变化时间超过该阈值视为超时,单位为分钟",
|
|
||||||
range=(1, 1024),
|
|
||||||
qconfig=self.config,
|
|
||||||
configItem=self.config.RunSet_RoutineTimeLimit,
|
|
||||||
parent=self,
|
|
||||||
)
|
|
||||||
self.RunTimesLimit = SpinBoxSettingCard(
|
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="代理重试次数限制",
|
title="代理重试次数限制",
|
||||||
content="若超过该次数限制仍未完成代理,视为代理失败",
|
content="若超过该次数限制仍未完成代理,视为代理失败",
|
||||||
@@ -663,7 +685,25 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.RunSet_RunTimesLimit,
|
configItem=self.config.RunSet_RunTimesLimit,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.AnnihilationWeeklyLimit = SwitchSettingCard(
|
self.card_AnnihilationTimeLimit = SpinBoxSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="剿灭代理超时限制",
|
||||||
|
content="MAA日志无变化时间超过该阈值视为超时,单位为分钟",
|
||||||
|
range=(1, 1024),
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.RunSet_AnnihilationTimeLimit,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_RoutineTimeLimit = SpinBoxSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="自动代理超时限制",
|
||||||
|
content="MAA日志无变化时间超过该阈值视为超时,单位为分钟",
|
||||||
|
range=(1, 1024),
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.RunSet_RoutineTimeLimit,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_AnnihilationWeeklyLimit = SwitchSettingCard(
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="每周剿灭仅执行到上限",
|
title="每周剿灭仅执行到上限",
|
||||||
content="每周剿灭模式执行到上限,本周剩下时间不再执行剿灭任务",
|
content="每周剿灭模式执行到上限,本周剩下时间不再执行剿灭任务",
|
||||||
@@ -671,16 +711,24 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.RunSet_AnnihilationWeeklyLimit,
|
configItem=self.config.RunSet_AnnihilationWeeklyLimit,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
self.card_AutoUpdateMaa = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="自动代理时自动更新MAA",
|
||||||
|
content="执行自动代理任务时自动更新MAA,关闭后仍会进行MAA版本检查",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.RunSet_AutoUpdateMaa,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
widget = QWidget()
|
widget = QWidget()
|
||||||
Layout = QVBoxLayout(widget)
|
Layout = QVBoxLayout(widget)
|
||||||
Layout.addWidget(self.card_TaskTransitionMethod)
|
Layout.addWidget(self.card_TaskTransitionMethod)
|
||||||
Layout.addWidget(self.card_EnhanceTask)
|
Layout.addWidget(self.card_ProxyTimesLimit)
|
||||||
Layout.addWidget(self.ProxyTimesLimit)
|
Layout.addWidget(self.card_RunTimesLimit)
|
||||||
Layout.addWidget(self.AnnihilationTimeLimit)
|
Layout.addWidget(self.card_AnnihilationTimeLimit)
|
||||||
Layout.addWidget(self.RoutineTimeLimit)
|
Layout.addWidget(self.card_RoutineTimeLimit)
|
||||||
Layout.addWidget(self.RunTimesLimit)
|
Layout.addWidget(self.card_AnnihilationWeeklyLimit)
|
||||||
Layout.addWidget(self.AnnihilationWeeklyLimit)
|
Layout.addWidget(self.card_AutoUpdateMaa)
|
||||||
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.viewLayout.setSpacing(0)
|
self.viewLayout.setSpacing(0)
|
||||||
self.addGroupWidget(widget)
|
self.addGroupWidget(widget)
|
||||||
@@ -1049,7 +1097,7 @@ class MemberManager(QWidget):
|
|||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
self.dashboard = TableWidget(self)
|
self.dashboard = TableWidget(self)
|
||||||
self.dashboard.setColumnCount(10)
|
self.dashboard.setColumnCount(11)
|
||||||
self.dashboard.setHorizontalHeaderLabels(
|
self.dashboard.setHorizontalHeaderLabels(
|
||||||
[
|
[
|
||||||
"用户名",
|
"用户名",
|
||||||
@@ -1059,8 +1107,9 @@ class MemberManager(QWidget):
|
|||||||
"代理情况",
|
"代理情况",
|
||||||
"给药量",
|
"给药量",
|
||||||
"关卡选择",
|
"关卡选择",
|
||||||
"备选关卡-1",
|
"备选 - 1",
|
||||||
"备选关卡-2",
|
"备选 - 2",
|
||||||
|
"剩余理智",
|
||||||
"详",
|
"详",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@@ -1070,14 +1119,14 @@ class MemberManager(QWidget):
|
|||||||
self.dashboard.horizontalHeader().setSectionResizeMode(
|
self.dashboard.horizontalHeader().setSectionResizeMode(
|
||||||
col, QHeaderView.ResizeMode.ResizeToContents
|
col, QHeaderView.ResizeMode.ResizeToContents
|
||||||
)
|
)
|
||||||
for col in range(6, 9):
|
for col in range(6, 10):
|
||||||
self.dashboard.horizontalHeader().setSectionResizeMode(
|
self.dashboard.horizontalHeader().setSectionResizeMode(
|
||||||
col, QHeaderView.ResizeMode.Stretch
|
col, QHeaderView.ResizeMode.Stretch
|
||||||
)
|
)
|
||||||
self.dashboard.horizontalHeader().setSectionResizeMode(
|
self.dashboard.horizontalHeader().setSectionResizeMode(
|
||||||
9, QHeaderView.ResizeMode.Fixed
|
10, QHeaderView.ResizeMode.Fixed
|
||||||
)
|
)
|
||||||
self.dashboard.setColumnWidth(9, 32)
|
self.dashboard.setColumnWidth(10, 32)
|
||||||
|
|
||||||
self.viewLayout.addWidget(self.dashboard)
|
self.viewLayout.addWidget(self.dashboard)
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
@@ -1099,7 +1148,7 @@ class MemberManager(QWidget):
|
|||||||
text_list.append("未通过人工排查")
|
text_list.append("未通过人工排查")
|
||||||
text_list.append(
|
text_list.append(
|
||||||
f"今日已代理{config.get(config.Data_ProxyTimes)}次"
|
f"今日已代理{config.get(config.Data_ProxyTimes)}次"
|
||||||
if Config.server_date()
|
if Config.server_date().strftime("%Y-%m-%d")
|
||||||
== config.get(config.Data_LastProxyDate)
|
== config.get(config.Data_LastProxyDate)
|
||||||
else "今日未进行代理"
|
else "今日未进行代理"
|
||||||
)
|
)
|
||||||
@@ -1109,9 +1158,7 @@ class MemberManager(QWidget):
|
|||||||
config.get(config.Data_LastAnnihilationDate),
|
config.get(config.Data_LastAnnihilationDate),
|
||||||
"%Y-%m-%d",
|
"%Y-%m-%d",
|
||||||
).isocalendar()[:2]
|
).isocalendar()[:2]
|
||||||
== datetime.strptime(
|
== Config.server_date().isocalendar()[:2]
|
||||||
Config.server_date(), "%Y-%m-%d"
|
|
||||||
).isocalendar()[:2]
|
|
||||||
else "本周剿灭未完成"
|
else "本周剿灭未完成"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1209,8 +1256,32 @@ class MemberManager(QWidget):
|
|||||||
else config.get(config.Info_GameId_2)
|
else config.get(config.Info_GameId_2)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
self.dashboard.setItem(
|
||||||
|
int(name[3:]) - 1,
|
||||||
|
9,
|
||||||
|
QTableWidgetItem(
|
||||||
|
"不使用"
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
self.dashboard.setCellWidget(
|
self.dashboard.setCellWidget(
|
||||||
int(name[3:]) - 1, 9, button
|
int(name[3:]) - 1, 10, button
|
||||||
)
|
)
|
||||||
|
|
||||||
class UserMemberSettingBox(HeaderCardWidget):
|
class UserMemberSettingBox(HeaderCardWidget):
|
||||||
@@ -1309,13 +1380,18 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_Routine,
|
configItem=self.config.Info_Routine,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_Infrastructure = PushAndSwitchButtonSettingCard(
|
self.card_InfrastMode = PushAndComboBoxSettingCard(
|
||||||
icon=FluentIcon.CAFE,
|
icon=FluentIcon.CAFE,
|
||||||
title="自定义基建",
|
title="基建模式",
|
||||||
content="自定义基建相关设置项",
|
content="配置文件仅在自定义基建中生效",
|
||||||
text="选择配置文件",
|
text="选择配置文件",
|
||||||
|
texts=[
|
||||||
|
"常规模式",
|
||||||
|
"一键轮休",
|
||||||
|
"自定义基建",
|
||||||
|
],
|
||||||
qconfig=self.config,
|
qconfig=self.config,
|
||||||
configItem=self.config.Info_Infrastructure,
|
configItem=self.config.Info_InfrastMode,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_Password = PasswordLineEditSettingCard(
|
self.card_Password = PasswordLineEditSettingCard(
|
||||||
@@ -1346,6 +1422,16 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_MedicineNumb,
|
configItem=self.config.Info_MedicineNumb,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
self.card_SeriesNumb = ComboBoxSettingCard(
|
||||||
|
icon=FluentIcon.GAME,
|
||||||
|
title="连战次数",
|
||||||
|
content="连战次数较大时建议搭配剩余理智关卡使用",
|
||||||
|
texts=["AUTO", "6", "5", "4", "3", "2", "1", "不选择"],
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Info_SeriesNumb,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_SeriesNumb.comboBox.setMinimumWidth(150)
|
||||||
self.card_GameId = EditableComboBoxSettingCard(
|
self.card_GameId = EditableComboBoxSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="关卡选择",
|
title="关卡选择",
|
||||||
@@ -1358,7 +1444,7 @@ class MemberManager(QWidget):
|
|||||||
)
|
)
|
||||||
self.card_GameId_1 = EditableComboBoxSettingCard(
|
self.card_GameId_1 = EditableComboBoxSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="备选关卡-1",
|
title="备选关卡 - 1",
|
||||||
content="按下回车以添加自定义关卡号",
|
content="按下回车以添加自定义关卡号",
|
||||||
value=Config.gameid_dict["ALL"]["value"],
|
value=Config.gameid_dict["ALL"]["value"],
|
||||||
texts=Config.gameid_dict["ALL"]["text"],
|
texts=Config.gameid_dict["ALL"]["text"],
|
||||||
@@ -1368,7 +1454,7 @@ class MemberManager(QWidget):
|
|||||||
)
|
)
|
||||||
self.card_GameId_2 = EditableComboBoxSettingCard(
|
self.card_GameId_2 = EditableComboBoxSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="备选关卡-2",
|
title="备选关卡 - 2",
|
||||||
content="按下回车以添加自定义关卡号",
|
content="按下回车以添加自定义关卡号",
|
||||||
value=Config.gameid_dict["ALL"]["value"],
|
value=Config.gameid_dict["ALL"]["value"],
|
||||||
texts=Config.gameid_dict["ALL"]["text"],
|
texts=Config.gameid_dict["ALL"]["text"],
|
||||||
@@ -1376,6 +1462,19 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_GameId_2,
|
configItem=self.config.Info_GameId_2,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
self.card_GameId_Remain = EditableComboBoxSettingCard(
|
||||||
|
icon=FluentIcon.GAME,
|
||||||
|
title="剩余理智关卡",
|
||||||
|
content="按下回车以添加自定义关卡号",
|
||||||
|
value=Config.gameid_dict["ALL"]["value"],
|
||||||
|
texts=[
|
||||||
|
"不使用" if _ == "当前/上次" else _
|
||||||
|
for _ in Config.gameid_dict["ALL"]["text"]
|
||||||
|
],
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Info_GameId_Remain,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
self.card_UserLable = UserLableSettingCard(
|
self.card_UserLable = UserLableSettingCard(
|
||||||
icon=FluentIcon.INFO,
|
icon=FluentIcon.INFO,
|
||||||
@@ -1404,16 +1503,19 @@ class MemberManager(QWidget):
|
|||||||
h4_layout = QHBoxLayout()
|
h4_layout = QHBoxLayout()
|
||||||
h4_layout.addWidget(self.card_Annihilation)
|
h4_layout.addWidget(self.card_Annihilation)
|
||||||
h4_layout.addWidget(self.card_Routine)
|
h4_layout.addWidget(self.card_Routine)
|
||||||
h4_layout.addWidget(self.card_Infrastructure)
|
h4_layout.addWidget(self.card_InfrastMode)
|
||||||
h5_layout = QHBoxLayout()
|
h5_layout = QHBoxLayout()
|
||||||
h5_layout.addWidget(self.card_Password)
|
h5_layout.addWidget(self.card_Password)
|
||||||
h5_layout.addWidget(self.card_Notes)
|
h5_layout.addWidget(self.card_Notes)
|
||||||
h6_layout = QHBoxLayout()
|
h6_layout = QHBoxLayout()
|
||||||
h6_layout.addWidget(self.card_MedicineNumb)
|
h6_layout.addWidget(self.card_MedicineNumb)
|
||||||
h6_layout.addWidget(self.card_GameId)
|
h6_layout.addWidget(self.card_SeriesNumb)
|
||||||
h7_layout = QHBoxLayout()
|
h7_layout = QHBoxLayout()
|
||||||
|
h7_layout.addWidget(self.card_GameId)
|
||||||
h7_layout.addWidget(self.card_GameId_1)
|
h7_layout.addWidget(self.card_GameId_1)
|
||||||
h7_layout.addWidget(self.card_GameId_2)
|
h8_layout = QHBoxLayout()
|
||||||
|
h8_layout.addWidget(self.card_GameId_2)
|
||||||
|
h8_layout.addWidget(self.card_GameId_Remain)
|
||||||
|
|
||||||
Layout = QVBoxLayout()
|
Layout = QVBoxLayout()
|
||||||
Layout.addLayout(h1_layout)
|
Layout.addLayout(h1_layout)
|
||||||
@@ -1424,6 +1526,7 @@ class MemberManager(QWidget):
|
|||||||
Layout.addLayout(h5_layout)
|
Layout.addLayout(h5_layout)
|
||||||
Layout.addLayout(h6_layout)
|
Layout.addLayout(h6_layout)
|
||||||
Layout.addLayout(h7_layout)
|
Layout.addLayout(h7_layout)
|
||||||
|
Layout.addLayout(h8_layout)
|
||||||
|
|
||||||
self.viewLayout.addLayout(Layout)
|
self.viewLayout.addLayout(Layout)
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
@@ -1437,7 +1540,7 @@ class MemberManager(QWidget):
|
|||||||
self.card_Routine.clicked.connect(
|
self.card_Routine.clicked.connect(
|
||||||
lambda: self.set_maa("Routine")
|
lambda: self.set_maa("Routine")
|
||||||
)
|
)
|
||||||
self.card_Infrastructure.clicked.connect(
|
self.card_InfrastMode.clicked.connect(
|
||||||
self.set_infrastructure
|
self.set_infrastructure
|
||||||
)
|
)
|
||||||
Config.gameid_refreshed.connect(self.refresh_gameid)
|
Config.gameid_refreshed.connect(self.refresh_gameid)
|
||||||
@@ -1452,12 +1555,12 @@ class MemberManager(QWidget):
|
|||||||
self.card_Routine.setVisible(False)
|
self.card_Routine.setVisible(False)
|
||||||
self.card_Server.setVisible(True)
|
self.card_Server.setVisible(True)
|
||||||
self.card_Annihilation.button.setVisible(False)
|
self.card_Annihilation.button.setVisible(False)
|
||||||
self.card_Infrastructure.setVisible(True)
|
self.card_InfrastMode.setVisible(True)
|
||||||
|
|
||||||
elif self.config.get(self.config.Info_Mode) == "详细":
|
elif self.config.get(self.config.Info_Mode) == "详细":
|
||||||
|
|
||||||
self.card_Server.setVisible(False)
|
self.card_Server.setVisible(False)
|
||||||
self.card_Infrastructure.setVisible(False)
|
self.card_InfrastMode.setVisible(False)
|
||||||
self.card_Annihilation.button.setVisible(True)
|
self.card_Annihilation.button.setVisible(True)
|
||||||
self.card_Routine.setVisible(True)
|
self.card_Routine.setVisible(True)
|
||||||
|
|
||||||
@@ -1475,6 +1578,13 @@ class MemberManager(QWidget):
|
|||||||
Config.gameid_dict["ALL"]["value"],
|
Config.gameid_dict["ALL"]["value"],
|
||||||
Config.gameid_dict["ALL"]["text"],
|
Config.gameid_dict["ALL"]["text"],
|
||||||
)
|
)
|
||||||
|
self.card_GameId_Remain.reLoadOptions(
|
||||||
|
Config.gameid_dict["ALL"]["value"],
|
||||||
|
[
|
||||||
|
"不使用" if _ == "当前/上次" else _
|
||||||
|
for _ in Config.gameid_dict["ALL"]["text"]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def refresh_password(self):
|
def refresh_password(self):
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -26,13 +26,12 @@ v4.3
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from PySide6.QtWidgets import QWidget, QVBoxLayout
|
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
FluentIcon,
|
FluentIcon,
|
||||||
MessageBox,
|
MessageBox,
|
||||||
Dialog,
|
|
||||||
HyperlinkCard,
|
HyperlinkCard,
|
||||||
HeaderCardWidget,
|
HeaderCardWidget,
|
||||||
ExpandGroupSettingCard,
|
ExpandGroupSettingCard,
|
||||||
@@ -42,13 +41,12 @@ from qfluentwidgets import (
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from packaging import version
|
from packaging import version
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Union
|
from typing import Dict, Union
|
||||||
|
|
||||||
from app.core import Config, MainInfoBar, Network
|
from app.core import Config, MainInfoBar, Network
|
||||||
from app.services import Crypto, System, Notify
|
from app.services import Crypto, System, Notify
|
||||||
@@ -89,9 +87,9 @@ class Setting(QWidget):
|
|||||||
self.start.card_IfSelfStart.checkedChanged.connect(System.set_SelfStart)
|
self.start.card_IfSelfStart.checkedChanged.connect(System.set_SelfStart)
|
||||||
self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD)
|
self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD)
|
||||||
self.updater.card_CheckUpdate.clicked.connect(
|
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.function)
|
||||||
content_layout.addWidget(self.start)
|
content_layout.addWidget(self.start)
|
||||||
@@ -179,10 +177,7 @@ class Setting(QWidget):
|
|||||||
while True:
|
while True:
|
||||||
|
|
||||||
choice = LineEditMessageBox(
|
choice = LineEditMessageBox(
|
||||||
self.window(),
|
self.window(), "请设置您的管理密钥", "管理密钥", "密码"
|
||||||
"未检测到管理密钥,请设置您的管理密钥",
|
|
||||||
"管理密钥",
|
|
||||||
"密码",
|
|
||||||
)
|
)
|
||||||
if choice.exec() and choice.input.text() != "":
|
if choice.exec() and choice.input.text() != "":
|
||||||
Crypto.get_PASSWORD(choice.input.text())
|
Crypto.get_PASSWORD(choice.input.text())
|
||||||
@@ -260,12 +255,12 @@ class Setting(QWidget):
|
|||||||
if choice.exec():
|
if choice.exec():
|
||||||
break
|
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(".")))
|
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(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "请求速度过快", "上个网络请求还未结束,请稍等片刻", 5000
|
"warning", "请求速度过快", "上个网络请求还未结束,请稍等片刻", 5000
|
||||||
)
|
)
|
||||||
@@ -282,6 +277,46 @@ class Setting(QWidget):
|
|||||||
Network.response_json
|
Network.response_json
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
if Network.response_json:
|
||||||
|
|
||||||
|
version_info = Network.response_json
|
||||||
|
|
||||||
|
if version_info["code"] != 0:
|
||||||
|
|
||||||
|
logger.error(f"获取版本信息时出错:{version_info["msg"]}")
|
||||||
|
|
||||||
|
error_remark_dict = {
|
||||||
|
1001: "获取版本信息的URL参数不正确",
|
||||||
|
7001: "填入的 CDK 已过期",
|
||||||
|
7002: "填入的 CDK 错误",
|
||||||
|
7003: "填入的 CDK 今日下载次数已达上限",
|
||||||
|
7004: "填入的 CDK 类型和待下载的资源不匹配",
|
||||||
|
7005: "填入的 CDK 已被封禁",
|
||||||
|
8001: "对应架构和系统下的资源不存在",
|
||||||
|
8002: "错误的系统参数",
|
||||||
|
8003: "错误的架构参数",
|
||||||
|
8004: "错误的更新通道参数",
|
||||||
|
1: version_info["msg"],
|
||||||
|
}
|
||||||
|
|
||||||
|
if version_info["code"] in error_remark_dict:
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"error",
|
||||||
|
"获取版本信息时出错",
|
||||||
|
error_remark_dict[version_info["code"]],
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"error",
|
||||||
|
"获取版本信息时出错",
|
||||||
|
"意料之外的错误,请及时联系项目组以获取来自 Mirror 酱的技术支持",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
logger.warning(f"获取版本信息时出错:{Network.error_message}")
|
logger.warning(f"获取版本信息时出错:{Network.error_message}")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning",
|
"warning",
|
||||||
@@ -291,41 +326,6 @@ class Setting(QWidget):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if version_info["code"] != 0:
|
|
||||||
|
|
||||||
logger.error(f"获取版本信息时出错:{version_info["msg"]}")
|
|
||||||
|
|
||||||
error_remark_dict = {
|
|
||||||
1001: "获取版本信息的URL参数不正确",
|
|
||||||
7001: "填入的 CDK 已过期",
|
|
||||||
7002: "填入的 CDK 错误",
|
|
||||||
7003: "填入的 CDK 今日下载次数已达上限",
|
|
||||||
7004: "填入的 CDK 类型和待下载的资源不匹配",
|
|
||||||
7005: "填入的 CDK 不合法",
|
|
||||||
8001: "对应架构和系统下的资源不存在",
|
|
||||||
8002: "错误的系统参数",
|
|
||||||
8003: "错误的架构参数",
|
|
||||||
8004: "错误的更新通道参数",
|
|
||||||
1: version_info["msg"],
|
|
||||||
}
|
|
||||||
|
|
||||||
if version_info["code"] in error_remark_dict:
|
|
||||||
MainInfoBar.push_info_bar(
|
|
||||||
"error",
|
|
||||||
"获取版本信息时出错",
|
|
||||||
error_remark_dict[version_info["code"]],
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
MainInfoBar.push_info_bar(
|
|
||||||
"error",
|
|
||||||
"获取版本信息时出错",
|
|
||||||
"意料之外的错误,请及时联系项目组以获取来自 Mirror 酱的技术支持",
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
remote_version = list(
|
remote_version = list(
|
||||||
map(
|
map(
|
||||||
int,
|
int,
|
||||||
@@ -335,8 +335,14 @@ class Setting(QWidget):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 有版本更新
|
if (
|
||||||
if version.parse(version_text(remote_version)) > version.parse(
|
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)
|
version_text(current_version)
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -405,15 +411,33 @@ class Setting(QWidget):
|
|||||||
|
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
[Config.app_path / "AUTO_Updater.active.exe"],
|
[Config.app_path / "AUTO_Updater.active.exe"],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
|
||||||
|
| subprocess.DETACHED_PROCESS
|
||||||
|
| subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
self.window().close()
|
self.window().close()
|
||||||
|
QApplication.quit()
|
||||||
|
|
||||||
# 无版本更新
|
elif (
|
||||||
else:
|
if_show
|
||||||
MainInfoBar.push_info_bar("success", "更新检查", "已是最新版本~", 3000)
|
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:
|
||||||
"""显示公告"""
|
"""显示公告"""
|
||||||
|
|
||||||
# 从远程服务器获取最新公告
|
# 从远程服务器获取最新公告
|
||||||
@@ -452,9 +476,11 @@ class Setting(QWidget):
|
|||||||
}
|
}
|
||||||
|
|
||||||
if if_show or (
|
if if_show or (
|
||||||
datetime.now()
|
if_first
|
||||||
|
and datetime.now()
|
||||||
> datetime.strptime(notice["time"], "%Y-%m-%d %H:%M")
|
> datetime.strptime(notice["time"], "%Y-%m-%d %H:%M")
|
||||||
> time_local
|
> time_local
|
||||||
|
and not Config.get(Config.function_UnattendedMode)
|
||||||
):
|
):
|
||||||
|
|
||||||
choice = NoticeMessageBox(self.window(), "公告", notice["notice_dict"])
|
choice = NoticeMessageBox(self.window(), "公告", notice["notice_dict"])
|
||||||
@@ -466,6 +492,17 @@ class Setting(QWidget):
|
|||||||
) as f:
|
) as f:
|
||||||
json.dump(notice, f, ensure_ascii=False, indent=4)
|
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):
|
class FunctionSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
@@ -486,7 +523,7 @@ class FunctionSettingCard(HeaderCardWidget):
|
|||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="历史记录保留时间",
|
title="历史记录保留时间",
|
||||||
content="选择历史记录的保留时间,超期自动清理",
|
content="选择历史记录的保留时间,超期自动清理",
|
||||||
texts=["7 天", "15 天", "30 天", "60 天", "永久"],
|
texts=["7 天", "15 天", "30 天", "60 天", "90 天", "半年", "一年", "永久"],
|
||||||
qconfig=Config,
|
qconfig=Config,
|
||||||
configItem=Config.function_HistoryRetentionTime,
|
configItem=Config.function_HistoryRetentionTime,
|
||||||
parent=self,
|
parent=self,
|
||||||
@@ -500,6 +537,14 @@ class FunctionSettingCard(HeaderCardWidget):
|
|||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_IfSilence = self.SilenceSettingCard(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(
|
self.card_IfAgreeBilibili = SwitchSettingCard(
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="托管bilibili游戏隐私政策",
|
title="托管bilibili游戏隐私政策",
|
||||||
@@ -522,6 +567,7 @@ class FunctionSettingCard(HeaderCardWidget):
|
|||||||
Layout.addWidget(self.card_HistoryRetentionTime)
|
Layout.addWidget(self.card_HistoryRetentionTime)
|
||||||
Layout.addWidget(self.card_IfAllowSleep)
|
Layout.addWidget(self.card_IfAllowSleep)
|
||||||
Layout.addWidget(self.card_IfSilence)
|
Layout.addWidget(self.card_IfSilence)
|
||||||
|
Layout.addWidget(self.card_UnattendedMode)
|
||||||
Layout.addWidget(self.card_IfAgreeBilibili)
|
Layout.addWidget(self.card_IfAgreeBilibili)
|
||||||
Layout.addWidget(self.card_IfSkipMumuSplashAds)
|
Layout.addWidget(self.card_IfSkipMumuSplashAds)
|
||||||
self.viewLayout.addLayout(Layout)
|
self.viewLayout.addLayout(Layout)
|
||||||
@@ -997,9 +1043,9 @@ class OtherSettingCard(HeaderCardWidget):
|
|||||||
)
|
)
|
||||||
self.card_UserDocs = HyperlinkCard(
|
self.card_UserDocs = HyperlinkCard(
|
||||||
url="https://clozya.github.io/AUTOMAA_docs",
|
url="https://clozya.github.io/AUTOMAA_docs",
|
||||||
text="访问",
|
text="查看指南",
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="AUTO_MAA官方文档站",
|
title="用户指南",
|
||||||
content="访问AUTO_MAA的官方文档站,获取使用指南和项目相关信息",
|
content="访问AUTO_MAA的官方文档站,获取使用指南和项目相关信息",
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
|||||||
89
app/utils/AUTO_MAA.iss
Normal file
89
app/utils/AUTO_MAA.iss
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
; Script generated by the Inno Setup Script Wizard.
|
||||||
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||||
|
|
||||||
|
#define MyAppName "AUTO_MAA"
|
||||||
|
#define MyAppVersion ""
|
||||||
|
#define MyAppPublisher "AUTO_MAA Team"
|
||||||
|
#define MyAppURL "https://doc.automaa.xyz/"
|
||||||
|
#define MyAppExeName "AUTO_MAA.exe"
|
||||||
|
#define MyAppPath ""
|
||||||
|
#define OutputDir ""
|
||||||
|
|
||||||
|
[Setup]
|
||||||
|
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
||||||
|
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||||
|
AppId={{D116A92A-E174-4699-B777-61C5FD837B19}
|
||||||
|
AppName={#MyAppName}
|
||||||
|
AppVersion={#MyAppVersion}
|
||||||
|
AppVerName={#MyAppName}
|
||||||
|
AppPublisher={#MyAppPublisher}
|
||||||
|
AppPublisherURL={#MyAppURL}
|
||||||
|
AppSupportURL={#MyAppURL}
|
||||||
|
AppUpdatesURL={#MyAppURL}
|
||||||
|
DefaultDirName=D:\{#MyAppName}
|
||||||
|
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||||
|
; "ArchitecturesAllowed=x64compatible" specifies that Setup cannot run
|
||||||
|
; on anything but x64 and Windows 11 on Arm.
|
||||||
|
ArchitecturesAllowed=x64compatible
|
||||||
|
; "ArchitecturesInstallIn64BitMode=x64compatible" requests that the
|
||||||
|
; install be done in "64-bit mode" on x64 or Windows 11 on Arm,
|
||||||
|
; meaning it should use the native 64-bit Program Files directory and
|
||||||
|
; the 64-bit view of the registry.
|
||||||
|
ArchitecturesInstallIn64BitMode=x64compatible
|
||||||
|
DisableProgramGroupPage=yes
|
||||||
|
LicenseFile={#MyAppPath}\LICENSE
|
||||||
|
; Remove the following line to run in administrative install mode (install for all users).
|
||||||
|
PrivilegesRequired=lowest
|
||||||
|
OutputDir={#OutputDir}
|
||||||
|
OutputBaseFilename=AUTO_MAA-Setup
|
||||||
|
SetupIconFile={#MyAppPath}\resources\icons\AUTO_MAA.ico
|
||||||
|
SolidCompression=yes
|
||||||
|
WizardStyle=modern
|
||||||
|
|
||||||
|
[Languages]
|
||||||
|
Name: "Chinese"; MessagesFile: "{#MyAppPath}\resources\docs\ChineseSimplified.isl"
|
||||||
|
Name: "English"; MessagesFile: "compiler:Default.isl"
|
||||||
|
|
||||||
|
[Tasks]
|
||||||
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||||
|
|
||||||
|
[Files]
|
||||||
|
Source: "{#MyAppPath}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "{#MyAppPath}\app\*"; DestDir: "{app}\app"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
Source: "{#MyAppPath}\resources\*"; DestDir: "{app}\resources"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
Source: "{#MyAppPath}\AUTO_Updater.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "{#MyAppPath}\main.py"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "{#MyAppPath}\requirements.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "{#MyAppPath}\README.md"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "{#MyAppPath}\LICENSE"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||||
|
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||||
|
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||||
|
|
||||||
|
[Code]
|
||||||
|
var
|
||||||
|
DeleteDataQuestion: Boolean;
|
||||||
|
|
||||||
|
function InitializeUninstall: Boolean;
|
||||||
|
begin
|
||||||
|
DeleteDataQuestion := MsgBox('您确认要完全移除 AUTO_MAA 的所有用户数据文件与子组件吗?', mbConfirmation, MB_YESNO) = IDYES;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||||
|
begin
|
||||||
|
if CurUninstallStep = usPostUninstall then
|
||||||
|
begin
|
||||||
|
DelTree(ExpandConstant('{app}\app'), True, True, True);
|
||||||
|
DelTree(ExpandConstant('{app}\resources'), True, True, True);
|
||||||
|
if DeleteDataQuestion then
|
||||||
|
begin
|
||||||
|
DelTree(ExpandConstant('{app}'), True, True, True);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -31,6 +31,7 @@ import zipfile
|
|||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
import psutil
|
||||||
import win32crypt
|
import win32crypt
|
||||||
import base64
|
import base64
|
||||||
from packaging import version
|
from packaging import version
|
||||||
@@ -180,7 +181,11 @@ class ZipExtractProcess(QThread):
|
|||||||
self.accomplish.emit()
|
self.accomplish.emit()
|
||||||
break
|
break
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
self.info.emit(f"解压出错:{self.name}正在运行,正在等待其关闭")
|
if self.name == "AUTO_MAA":
|
||||||
|
self.info.emit(f"解压出错:AUTO_MAA正在运行,正在尝试将其关闭")
|
||||||
|
self.kill_process(self.app_path / "AUTO_MAA.exe")
|
||||||
|
else:
|
||||||
|
self.info.emit(f"解压出错:{self.name}正在运行,正在等待其关闭")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -190,6 +195,30 @@ class ZipExtractProcess(QThread):
|
|||||||
self.info.emit(f"解压更新时出错:\n{e}")
|
self.info.emit(f"解压更新时出错:\n{e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def kill_process(self, path: Path) -> None:
|
||||||
|
"""根据路径中止进程"""
|
||||||
|
|
||||||
|
for pid in self.search_pids(path):
|
||||||
|
killprocess = subprocess.Popen(
|
||||||
|
f"taskkill /F /PID {pid}",
|
||||||
|
shell=True,
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
)
|
||||||
|
killprocess.wait()
|
||||||
|
|
||||||
|
def search_pids(self, path: Path) -> list:
|
||||||
|
"""根据路径查找进程PID"""
|
||||||
|
|
||||||
|
pids = []
|
||||||
|
for proc in psutil.process_iter(["pid", "exe"]):
|
||||||
|
try:
|
||||||
|
if proc.info["exe"] and proc.info["exe"].lower() == str(path).lower():
|
||||||
|
pids.append(proc.info["pid"])
|
||||||
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||||
|
# 进程可能在此期间已结束或无法访问,忽略这些异常
|
||||||
|
pass
|
||||||
|
return pids
|
||||||
|
|
||||||
|
|
||||||
class DownloadManager(QDialog):
|
class DownloadManager(QDialog):
|
||||||
"""下载管理器"""
|
"""下载管理器"""
|
||||||
@@ -200,18 +229,12 @@ class DownloadManager(QDialog):
|
|||||||
|
|
||||||
isInterruptionRequested = False
|
isInterruptionRequested = False
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, app_path: Path, name: str, version: list, config: dict) -> None:
|
||||||
self,
|
|
||||||
app_path: Path,
|
|
||||||
name: str,
|
|
||||||
main_version: list,
|
|
||||||
config: dict,
|
|
||||||
) -> None:
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.app_path = app_path
|
self.app_path = app_path
|
||||||
self.name = name
|
self.name = name
|
||||||
self.main_version = main_version
|
self.version = version
|
||||||
self.config = config
|
self.config = config
|
||||||
self.download_path = app_path / "DOWNLOAD_TEMP.zip" # 临时下载文件的路径
|
self.download_path = app_path / "DOWNLOAD_TEMP.zip" # 临时下载文件的路径
|
||||||
self.version_path = app_path / "resources/version.json"
|
self.version_path = app_path / "resources/version.json"
|
||||||
@@ -243,14 +266,14 @@ class DownloadManager(QDialog):
|
|||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
|
|
||||||
if self.name == "MAA":
|
if self.name == "AUTO_MAA":
|
||||||
self.download_task1()
|
|
||||||
elif self.name == "AUTO_MAA":
|
|
||||||
if self.config["mode"] == "Proxy":
|
if self.config["mode"] == "Proxy":
|
||||||
self.test_speed_task1()
|
self.test_speed_task1()
|
||||||
self.speed_test_accomplish.connect(self.download_task1)
|
self.speed_test_accomplish.connect(self.download_task1)
|
||||||
elif self.config["mode"] == "MirrorChyan":
|
elif self.config["mode"] == "MirrorChyan":
|
||||||
self.download_task1()
|
self.download_task1()
|
||||||
|
elif self.config["mode"] == "MirrorChyan":
|
||||||
|
self.download_task1()
|
||||||
|
|
||||||
def get_download_url(self, mode: str) -> Union[str, Dict[str, str]]:
|
def get_download_url(self, mode: str) -> Union[str, Dict[str, str]]:
|
||||||
"""获取下载链接"""
|
"""获取下载链接"""
|
||||||
@@ -260,26 +283,23 @@ class DownloadManager(QDialog):
|
|||||||
if mode == "测速":
|
if mode == "测速":
|
||||||
|
|
||||||
url_dict["GitHub站"] = (
|
url_dict["GitHub站"] = (
|
||||||
f"https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
f"https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.version)}/AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
)
|
)
|
||||||
url_dict["官方镜像站"] = (
|
url_dict["官方镜像站"] = (
|
||||||
f"https://gitee.com/DLmaster_361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
f"https://gitee.com/DLmaster_361/AUTO_MAA/releases/download/{version_text(self.version)}/AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
)
|
)
|
||||||
for name, download_url_head in self.config["download_dict"].items():
|
for name, download_url_head in self.config["download_dict"].items():
|
||||||
url_dict[name] = (
|
url_dict[name] = (
|
||||||
f"{download_url_head}AUTO_MAA_{version_text(self.main_version)}.zip"
|
f"{download_url_head}AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
)
|
)
|
||||||
for proxy_url in self.config["proxy_list"]:
|
for proxy_url in self.config["proxy_list"]:
|
||||||
url_dict[proxy_url] = (
|
url_dict[proxy_url] = (
|
||||||
f"{proxy_url}https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
f"{proxy_url}https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.version)}/AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
)
|
)
|
||||||
return url_dict
|
return url_dict
|
||||||
|
|
||||||
elif mode == "下载":
|
elif mode == "下载":
|
||||||
|
|
||||||
if self.name == "MAA":
|
|
||||||
return f"https://jp-download.fearr.xyz/MAA/MAA-{version_text(self.main_version)}-win-x64.zip"
|
|
||||||
|
|
||||||
if self.name == "AUTO_MAA":
|
if self.name == "AUTO_MAA":
|
||||||
|
|
||||||
if self.config["mode"] == "Proxy":
|
if self.config["mode"] == "Proxy":
|
||||||
@@ -293,15 +313,16 @@ class DownloadManager(QDialog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if selected_url == "GitHub站":
|
if selected_url == "GitHub站":
|
||||||
return f"https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
return f"https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.version)}/AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
elif selected_url == "官方镜像站":
|
elif selected_url == "官方镜像站":
|
||||||
return f"https://gitee.com/DLmaster_361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
return f"https://gitee.com/DLmaster_361/AUTO_MAA/releases/download/{version_text(self.version)}/AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
elif selected_url in self.config["download_dict"].keys():
|
elif selected_url in self.config["download_dict"].keys():
|
||||||
return f"{self.config["download_dict"][selected_url]}AUTO_MAA_{version_text(self.main_version)}.zip"
|
return f"{self.config["download_dict"][selected_url]}AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
else:
|
else:
|
||||||
return f"{selected_url}https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.main_version)}/AUTO_MAA_{version_text(self.main_version)}.zip"
|
return f"{selected_url}https://github.com/DLmaster361/AUTO_MAA/releases/download/{version_text(self.version)}/AUTO_MAA_{version_text(self.version)}.zip"
|
||||||
|
|
||||||
elif self.config["mode"] == "MirrorChyan":
|
elif self.config["mode"] == "MirrorChyan":
|
||||||
|
|
||||||
with requests.get(
|
with requests.get(
|
||||||
self.config["url"],
|
self.config["url"],
|
||||||
allow_redirects=True,
|
allow_redirects=True,
|
||||||
@@ -311,6 +332,14 @@ class DownloadManager(QDialog):
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.url
|
return response.url
|
||||||
|
|
||||||
|
elif self.config["mode"] == "MirrorChyan":
|
||||||
|
|
||||||
|
with requests.get(
|
||||||
|
self.config["url"], allow_redirects=True, timeout=10, stream=True
|
||||||
|
) as response:
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.url
|
||||||
|
|
||||||
def test_speed_task1(self) -> None:
|
def test_speed_task1(self) -> None:
|
||||||
|
|
||||||
if self.isInterruptionRequested:
|
if self.isInterruptionRequested:
|
||||||
@@ -517,8 +546,9 @@ class DownloadManager(QDialog):
|
|||||||
info: Dict[str, List[str]] = json.load(f)
|
info: Dict[str, List[str]] = json.load(f)
|
||||||
|
|
||||||
if "deleted" in info:
|
if "deleted" in info:
|
||||||
for file_path in info:
|
for file_path in info["deleted"]:
|
||||||
(self.app_path / file_path).unlink()
|
if (self.app_path / file_path).exists():
|
||||||
|
(self.app_path / file_path).unlink()
|
||||||
|
|
||||||
(self.app_path / "changes.json").unlink()
|
(self.app_path / "changes.json").unlink()
|
||||||
|
|
||||||
@@ -531,12 +561,16 @@ class DownloadManager(QDialog):
|
|||||||
if not self.isInterruptionRequested and self.name == "AUTO_MAA":
|
if not self.isInterruptionRequested and self.name == "AUTO_MAA":
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
[self.app_path / "AUTO_MAA.exe"],
|
[self.app_path / "AUTO_MAA.exe"],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
|
||||||
|
| subprocess.DETACHED_PROCESS
|
||||||
|
| subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
elif not self.isInterruptionRequested and self.name == "MAA":
|
elif not self.isInterruptionRequested and self.name == "MAA":
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
[self.app_path / "MAA.exe"],
|
[self.app_path / "MAA.exe"],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
|
||||||
|
| subprocess.DETACHED_PROCESS
|
||||||
|
| subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.update_info(f"{self.name}更新成功!")
|
self.update_info(f"{self.name}更新成功!")
|
||||||
@@ -585,11 +619,7 @@ class DownloadManager(QDialog):
|
|||||||
|
|
||||||
class AUTO_MAA_Downloader(QApplication):
|
class AUTO_MAA_Downloader(QApplication):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self, app_path: Path, name: str, main_version: list, config: dict
|
||||||
app_path: Path,
|
|
||||||
name: str,
|
|
||||||
main_version: list,
|
|
||||||
config: dict,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@@ -722,10 +752,5 @@ if __name__ == "__main__":
|
|||||||
if version.parse(version_text(remote_version)) > version.parse(
|
if version.parse(version_text(remote_version)) > version.parse(
|
||||||
version_text(current_version)
|
version_text(current_version)
|
||||||
):
|
):
|
||||||
app = AUTO_MAA_Downloader(
|
app = AUTO_MAA_Downloader(app_path, "AUTO_MAA", remote_version, download_config)
|
||||||
app_path,
|
|
||||||
"AUTO_MAA",
|
|
||||||
remote_version,
|
|
||||||
download_config,
|
|
||||||
)
|
|
||||||
sys.exit(app.exec())
|
sys.exit(app.exec())
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -79,7 +79,7 @@ if __name__ == "__main__":
|
|||||||
f" --file-version={version["main_version"]}"
|
f" --file-version={version["main_version"]}"
|
||||||
f" --product-version={version["main_version"]}"
|
f" --product-version={version["main_version"]}"
|
||||||
" --file-description='AUTO_MAA Component'"
|
" --file-description='AUTO_MAA Component'"
|
||||||
" --copyright='Copyright © 2024 DLmaster361'"
|
" --copyright='Copyright © 2024-2025 DLmaster361'"
|
||||||
" --assume-yes-for-downloads --output-filename=AUTO_MAA"
|
" --assume-yes-for-downloads --output-filename=AUTO_MAA"
|
||||||
" --remove-output main.py"
|
" --remove-output main.py"
|
||||||
)
|
)
|
||||||
@@ -98,7 +98,7 @@ if __name__ == "__main__":
|
|||||||
f" --file-version={version["updater_version"]}"
|
f" --file-version={version["updater_version"]}"
|
||||||
f" --product-version={version["main_version"]}"
|
f" --product-version={version["main_version"]}"
|
||||||
" --file-description='AUTO_MAA Component'"
|
" --file-description='AUTO_MAA Component'"
|
||||||
" --copyright='Copyright © 2024 DLmaster361'"
|
" --copyright='Copyright © 2024-2025 DLmaster361'"
|
||||||
" --assume-yes-for-downloads --output-filename=AUTO_Updater"
|
" --assume-yes-for-downloads --output-filename=AUTO_Updater"
|
||||||
" --remove-output downloader.py"
|
" --remove-output downloader.py"
|
||||||
)
|
)
|
||||||
@@ -146,3 +146,20 @@ if __name__ == "__main__":
|
|||||||
f"{version_text(main_version_numb)}\n{version_text(updater_version_numb)}\n<!--{json.dumps(version["version_info"], ensure_ascii=False)}-->\n{version_info_markdown(all_version_info)}",
|
f"{version_text(main_version_numb)}\n{version_text(updater_version_numb)}\n<!--{json.dumps(version["version_info"], ensure_ascii=False)}-->\n{version_info_markdown(all_version_info)}",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with (root_path / "app/utils/AUTO_MAA.iss").open(mode="r", encoding="utf-8") as f:
|
||||||
|
iss = f.read()
|
||||||
|
|
||||||
|
iss = (
|
||||||
|
iss.replace(
|
||||||
|
'#define MyAppVersion ""',
|
||||||
|
f'#define MyAppVersion "{version["main_version"]}"',
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
'#define MyAppPath ""', f'#define MyAppPath "{root_path / "AUTO_MAA"}"'
|
||||||
|
)
|
||||||
|
.replace('#define OutputDir ""', f'#define OutputDir "{root_path}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
with (root_path / "AUTO_MAA.iss").open(mode="w", encoding="utf-8") as f:
|
||||||
|
f.write(iss)
|
||||||
|
|||||||
8
main.py
8
main.py
@@ -1,5 +1,5 @@
|
|||||||
# <AUTO_MAA:A MAA Multi Account Management and Automation Tool>
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
# Copyright © <2024> <DLmaster361>
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
|
||||||
# This file is part of AUTO_MAA.
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# DLmaster_361@163.com
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
@@ -27,7 +27,6 @@ v4.3
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from PySide6.QtWidgets import QApplication
|
from PySide6.QtWidgets import QApplication
|
||||||
from PySide6.QtCore import Qt
|
|
||||||
from qfluentwidgets import FluentTranslator
|
from qfluentwidgets import FluentTranslator
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -36,7 +35,6 @@ import sys
|
|||||||
def main():
|
def main():
|
||||||
|
|
||||||
application = QApplication(sys.argv)
|
application = QApplication(sys.argv)
|
||||||
QApplication.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings)
|
|
||||||
|
|
||||||
translator = FluentTranslator()
|
translator = FluentTranslator()
|
||||||
application.installTranslator(translator)
|
application.installTranslator(translator)
|
||||||
|
|||||||
@@ -10,5 +10,4 @@ pycryptodome
|
|||||||
requests
|
requests
|
||||||
markdown
|
markdown
|
||||||
Jinja2
|
Jinja2
|
||||||
serverchan_sdk
|
|
||||||
nuitka
|
nuitka
|
||||||
403
resources/docs/ChineseSimplified.isl
Normal file
403
resources/docs/ChineseSimplified.isl
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
; *** Inno Setup version 6.4.0+ Chinese Simplified messages ***
|
||||||
|
;
|
||||||
|
; To download user-contributed translations of this file, go to:
|
||||||
|
; https://jrsoftware.org/files/istrans/
|
||||||
|
;
|
||||||
|
; Note: When translating this text, do not add periods (.) to the end of
|
||||||
|
; messages that didn't have them already, because on those messages Inno
|
||||||
|
; Setup adds the periods automatically (appending a period would result in
|
||||||
|
; two periods being displayed).
|
||||||
|
;
|
||||||
|
; Maintained by Zhenghan Yang
|
||||||
|
; Email: 847320916@QQ.com
|
||||||
|
; Translation based on network resource
|
||||||
|
; The latest Translation is on https://github.com/kira-96/Inno-Setup-Chinese-Simplified-Translation
|
||||||
|
;
|
||||||
|
|
||||||
|
[LangOptions]
|
||||||
|
; The following three entries are very important. Be sure to read and
|
||||||
|
; understand the '[LangOptions] section' topic in the help file.
|
||||||
|
LanguageName=简体中文
|
||||||
|
; If Language Name display incorrect, uncomment next line
|
||||||
|
; LanguageName=<7B80><4F53><4E2D><6587>
|
||||||
|
; About LanguageID, to reference link:
|
||||||
|
; https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c
|
||||||
|
LanguageID=$0804
|
||||||
|
; About CodePage, to reference link:
|
||||||
|
; https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
|
||||||
|
LanguageCodePage=936
|
||||||
|
; If the language you are translating to requires special font faces or
|
||||||
|
; sizes, uncomment any of the following entries and change them accordingly.
|
||||||
|
;DialogFontName=
|
||||||
|
;DialogFontSize=8
|
||||||
|
;WelcomeFontName=Verdana
|
||||||
|
;WelcomeFontSize=12
|
||||||
|
;TitleFontName=Arial
|
||||||
|
;TitleFontSize=29
|
||||||
|
;CopyrightFontName=Arial
|
||||||
|
;CopyrightFontSize=8
|
||||||
|
|
||||||
|
[Messages]
|
||||||
|
|
||||||
|
; *** 应用程序标题
|
||||||
|
SetupAppTitle=安装
|
||||||
|
SetupWindowTitle=安装 - %1
|
||||||
|
UninstallAppTitle=卸载
|
||||||
|
UninstallAppFullTitle=%1 卸载
|
||||||
|
|
||||||
|
; *** Misc. common
|
||||||
|
InformationTitle=信息
|
||||||
|
ConfirmTitle=确认
|
||||||
|
ErrorTitle=错误
|
||||||
|
|
||||||
|
; *** SetupLdr messages
|
||||||
|
SetupLdrStartupMessage=现在将安装 %1。您想要继续吗?
|
||||||
|
LdrCannotCreateTemp=无法创建临时文件。安装程序已中止
|
||||||
|
LdrCannotExecTemp=无法执行临时目录中的文件。安装程序已中止
|
||||||
|
HelpTextNote=
|
||||||
|
|
||||||
|
; *** 启动错误消息
|
||||||
|
LastErrorMessage=%1。%n%n错误 %2: %3
|
||||||
|
SetupFileMissing=安装目录中缺少文件 %1。请修正这个问题或者获取程序的新副本。
|
||||||
|
SetupFileCorrupt=安装文件已损坏。请获取程序的新副本。
|
||||||
|
SetupFileCorruptOrWrongVer=安装文件已损坏,或是与这个安装程序的版本不兼容。请修正这个问题或获取新的程序副本。
|
||||||
|
InvalidParameter=无效的命令行参数:%n%n%1
|
||||||
|
SetupAlreadyRunning=安装程序正在运行。
|
||||||
|
WindowsVersionNotSupported=此程序不支持当前计算机运行的 Windows 版本。
|
||||||
|
WindowsServicePackRequired=此程序需要 %1 服务包 %2 或更高版本。
|
||||||
|
NotOnThisPlatform=此程序不能在 %1 上运行。
|
||||||
|
OnlyOnThisPlatform=此程序只能在 %1 上运行。
|
||||||
|
OnlyOnTheseArchitectures=此程序只能安装到为下列处理器架构设计的 Windows 版本中:%n%n%1
|
||||||
|
WinVersionTooLowError=此程序需要 %1 版本 %2 或更高。
|
||||||
|
WinVersionTooHighError=此程序不能安装于 %1 版本 %2 或更高。
|
||||||
|
AdminPrivilegesRequired=在安装此程序时您必须以管理员身份登录。
|
||||||
|
PowerUserPrivilegesRequired=在安装此程序时您必须以管理员身份或有权限的用户组身份登录。
|
||||||
|
SetupAppRunningError=安装程序发现 %1 当前正在运行。%n%n请先关闭正在运行的程序,然后点击“确定”继续,或点击“取消”退出。
|
||||||
|
UninstallAppRunningError=卸载程序发现 %1 当前正在运行。%n%n请先关闭正在运行的程序,然后点击“确定”继续,或点击“取消”退出。
|
||||||
|
|
||||||
|
; *** 启动问题
|
||||||
|
PrivilegesRequiredOverrideTitle=选择安装程序模式
|
||||||
|
PrivilegesRequiredOverrideInstruction=选择安装模式
|
||||||
|
PrivilegesRequiredOverrideText1=%1 可以为所有用户安装(需要管理员权限),或仅为您安装。
|
||||||
|
PrivilegesRequiredOverrideText2=%1 只能为您安装,或为所有用户安装(需要管理员权限)。
|
||||||
|
PrivilegesRequiredOverrideAllUsers=为所有用户安装(&A)
|
||||||
|
PrivilegesRequiredOverrideAllUsersRecommended=为所有用户安装(&A) (建议选项)
|
||||||
|
PrivilegesRequiredOverrideCurrentUser=只为我安装(&M)
|
||||||
|
PrivilegesRequiredOverrideCurrentUserRecommended=只为我安装(&M) (建议选项)
|
||||||
|
|
||||||
|
; *** 其他错误
|
||||||
|
ErrorCreatingDir=安装程序无法创建目录“%1”
|
||||||
|
ErrorTooManyFilesInDir=无法在目录“%1”中创建文件,因为里面包含太多文件
|
||||||
|
|
||||||
|
; *** 安装程序公共消息
|
||||||
|
ExitSetupTitle=退出安装程序
|
||||||
|
ExitSetupMessage=安装程序尚未完成。如果现在退出,将不会安装该程序。%n%n您之后可以再次运行安装程序完成安装。%n%n现在退出安装程序吗?
|
||||||
|
AboutSetupMenuItem=关于安装程序(&A)...
|
||||||
|
AboutSetupTitle=关于安装程序
|
||||||
|
AboutSetupMessage=%1 版本 %2%n%3%n%n%1 主页:%n%4
|
||||||
|
AboutSetupNote=
|
||||||
|
TranslatorNote=简体中文翻译由Kira(847320916@qq.com)维护。项目地址:https://github.com/kira-96/Inno-Setup-Chinese-Simplified-Translation
|
||||||
|
|
||||||
|
; *** 按钮
|
||||||
|
ButtonBack=< 上一步(&B)
|
||||||
|
ButtonNext=下一步(&N) >
|
||||||
|
ButtonInstall=安装(&I)
|
||||||
|
ButtonOK=确定
|
||||||
|
ButtonCancel=取消
|
||||||
|
ButtonYes=是(&Y)
|
||||||
|
ButtonYesToAll=全是(&A)
|
||||||
|
ButtonNo=否(&N)
|
||||||
|
ButtonNoToAll=全否(&O)
|
||||||
|
ButtonFinish=完成(&F)
|
||||||
|
ButtonBrowse=浏览(&B)...
|
||||||
|
ButtonWizardBrowse=浏览(&R)...
|
||||||
|
ButtonNewFolder=新建文件夹(&M)
|
||||||
|
|
||||||
|
; *** “选择语言”对话框消息
|
||||||
|
SelectLanguageTitle=选择安装语言
|
||||||
|
SelectLanguageLabel=选择安装时使用的语言。
|
||||||
|
|
||||||
|
; *** 公共向导文字
|
||||||
|
ClickNext=点击“下一步”继续,或点击“取消”退出安装程序。
|
||||||
|
BeveledLabel=
|
||||||
|
BrowseDialogTitle=浏览文件夹
|
||||||
|
BrowseDialogLabel=在下面的列表中选择一个文件夹,然后点击“确定”。
|
||||||
|
NewFolderName=新建文件夹
|
||||||
|
|
||||||
|
; *** “欢迎”向导页
|
||||||
|
WelcomeLabel1=欢迎使用 [name] 安装向导
|
||||||
|
WelcomeLabel2=现在将安装 [name/ver] 到您的电脑中。%n%n建议您在继续安装前关闭所有其他应用程序。
|
||||||
|
|
||||||
|
; *** “密码”向导页
|
||||||
|
WizardPassword=密码
|
||||||
|
PasswordLabel1=这个安装程序有密码保护。
|
||||||
|
PasswordLabel3=请输入密码,然后点击“下一步”继续。密码区分大小写。
|
||||||
|
PasswordEditLabel=密码(&P):
|
||||||
|
IncorrectPassword=您输入的密码不正确,请重新输入。
|
||||||
|
|
||||||
|
; *** “许可协议”向导页
|
||||||
|
WizardLicense=许可协议
|
||||||
|
LicenseLabel=请在继续安装前阅读以下重要信息。
|
||||||
|
LicenseLabel3=请仔细阅读下列许可协议。在继续安装前您必须同意这些协议条款。
|
||||||
|
LicenseAccepted=我同意此协议(&A)
|
||||||
|
LicenseNotAccepted=我不同意此协议(&D)
|
||||||
|
|
||||||
|
; *** “信息”向导页
|
||||||
|
WizardInfoBefore=信息
|
||||||
|
InfoBeforeLabel=请在继续安装前阅读以下重要信息。
|
||||||
|
InfoBeforeClickLabel=准备好继续安装后,点击“下一步”。
|
||||||
|
WizardInfoAfter=信息
|
||||||
|
InfoAfterLabel=请在继续安装前阅读以下重要信息。
|
||||||
|
InfoAfterClickLabel=准备好继续安装后,点击“下一步”。
|
||||||
|
|
||||||
|
; *** “用户信息”向导页
|
||||||
|
WizardUserInfo=用户信息
|
||||||
|
UserInfoDesc=请输入您的信息。
|
||||||
|
UserInfoName=用户名(&U):
|
||||||
|
UserInfoOrg=组织(&O):
|
||||||
|
UserInfoSerial=序列号(&S):
|
||||||
|
UserInfoNameRequired=您必须输入用户名。
|
||||||
|
|
||||||
|
; *** “选择目标目录”向导页
|
||||||
|
WizardSelectDir=选择目标位置
|
||||||
|
SelectDirDesc=您想将 [name] 安装在哪里?
|
||||||
|
SelectDirLabel3=安装程序将安装 [name] 到下面的文件夹中。
|
||||||
|
SelectDirBrowseLabel=点击“下一步”继续。如果您想选择其他文件夹,点击“浏览”。
|
||||||
|
DiskSpaceGBLabel=至少需要有 [gb] GB 的可用磁盘空间。
|
||||||
|
DiskSpaceMBLabel=至少需要有 [mb] MB 的可用磁盘空间。
|
||||||
|
CannotInstallToNetworkDrive=安装程序无法安装到一个网络驱动器。
|
||||||
|
CannotInstallToUNCPath=安装程序无法安装到一个 UNC 路径。
|
||||||
|
InvalidPath=您必须输入一个带驱动器卷标的完整路径,例如:%n%nC:\APP%n%n或UNC路径:%n%n\\server\share
|
||||||
|
InvalidDrive=您选定的驱动器或 UNC 共享不存在或不能访问。请选择其他位置。
|
||||||
|
DiskSpaceWarningTitle=磁盘空间不足
|
||||||
|
DiskSpaceWarning=安装程序至少需要 %1 KB 的可用空间才能安装,但选定驱动器只有 %2 KB 的可用空间。%n%n您一定要继续吗?
|
||||||
|
DirNameTooLong=文件夹名称或路径太长。
|
||||||
|
InvalidDirName=文件夹名称无效。
|
||||||
|
BadDirName32=文件夹名称不能包含下列任何字符:%n%n%1
|
||||||
|
DirExistsTitle=文件夹已存在
|
||||||
|
DirExists=文件夹:%n%n%1%n%n已经存在。您一定要安装到这个文件夹中吗?
|
||||||
|
DirDoesntExistTitle=文件夹不存在
|
||||||
|
DirDoesntExist=文件夹:%n%n%1%n%n不存在。您想要创建此文件夹吗?
|
||||||
|
|
||||||
|
; *** “选择组件”向导页
|
||||||
|
WizardSelectComponents=选择组件
|
||||||
|
SelectComponentsDesc=您想安装哪些程序组件?
|
||||||
|
SelectComponentsLabel2=选中您想安装的组件;取消您不想安装的组件。然后点击“下一步”继续。
|
||||||
|
FullInstallation=完全安装
|
||||||
|
; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
|
||||||
|
CompactInstallation=简洁安装
|
||||||
|
CustomInstallation=自定义安装
|
||||||
|
NoUninstallWarningTitle=组件已存在
|
||||||
|
NoUninstallWarning=安装程序检测到下列组件已安装在您的电脑中:%n%n%1%n%n取消选中这些组件不会卸载它们。%n%n确定要继续吗?
|
||||||
|
ComponentSize1=%1 KB
|
||||||
|
ComponentSize2=%1 MB
|
||||||
|
ComponentsDiskSpaceGBLabel=当前选择的组件需要至少 [gb] GB 的磁盘空间。
|
||||||
|
ComponentsDiskSpaceMBLabel=当前选择的组件需要至少 [mb] MB 的磁盘空间。
|
||||||
|
|
||||||
|
; *** “选择附加任务”向导页
|
||||||
|
WizardSelectTasks=选择附加任务
|
||||||
|
SelectTasksDesc=您想要安装程序执行哪些附加任务?
|
||||||
|
SelectTasksLabel2=选择您想要安装程序在安装 [name] 时执行的附加任务,然后点击“下一步”。
|
||||||
|
|
||||||
|
; *** “选择开始菜单文件夹”向导页
|
||||||
|
WizardSelectProgramGroup=选择开始菜单文件夹
|
||||||
|
SelectStartMenuFolderDesc=安装程序应该在哪里放置程序的快捷方式?
|
||||||
|
SelectStartMenuFolderLabel3=安装程序将在下列“开始”菜单文件夹中创建程序的快捷方式。
|
||||||
|
SelectStartMenuFolderBrowseLabel=点击“下一步”继续。如果您想选择其他文件夹,点击“浏览”。
|
||||||
|
MustEnterGroupName=您必须输入一个文件夹名。
|
||||||
|
GroupNameTooLong=文件夹名或路径太长。
|
||||||
|
InvalidGroupName=无效的文件夹名字。
|
||||||
|
BadGroupName=文件夹名不能包含下列任何字符:%n%n%1
|
||||||
|
NoProgramGroupCheck2=不创建开始菜单文件夹(&D)
|
||||||
|
|
||||||
|
; *** “准备安装”向导页
|
||||||
|
WizardReady=准备安装
|
||||||
|
ReadyLabel1=安装程序准备就绪,现在可以开始安装 [name] 到您的电脑。
|
||||||
|
ReadyLabel2a=点击“安装”继续此安装程序。如果您想重新考虑或修改任何设置,点击“上一步”。
|
||||||
|
ReadyLabel2b=点击“安装”继续此安装程序。
|
||||||
|
ReadyMemoUserInfo=用户信息:
|
||||||
|
ReadyMemoDir=目标位置:
|
||||||
|
ReadyMemoType=安装类型:
|
||||||
|
ReadyMemoComponents=已选择组件:
|
||||||
|
ReadyMemoGroup=开始菜单文件夹:
|
||||||
|
ReadyMemoTasks=附加任务:
|
||||||
|
|
||||||
|
; *** TExtractionWizardPage wizard page and Extract7ZipArchive
|
||||||
|
ExtractionLabel=正在提取附加文件...
|
||||||
|
ButtonStopExtraction=停止提取(&S)
|
||||||
|
StopExtraction=您确定要停止提取吗?
|
||||||
|
ErrorExtractionAborted=提取已中止
|
||||||
|
ErrorExtractionFailed=提取失败:%1
|
||||||
|
|
||||||
|
; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
|
||||||
|
DownloadingLabel=正在下载附加文件...
|
||||||
|
ButtonStopDownload=停止下载(&S)
|
||||||
|
StopDownload=您确定要停止下载吗?
|
||||||
|
ErrorDownloadAborted=下载已中止
|
||||||
|
ErrorDownloadFailed=下载失败:%1 %2
|
||||||
|
ErrorDownloadSizeFailed=获取下载大小失败:%1 %2
|
||||||
|
ErrorFileHash1=校验文件哈希失败:%1
|
||||||
|
ErrorFileHash2=无效的文件哈希:预期 %1,实际 %2
|
||||||
|
ErrorProgress=无效的进度:%1 / %2
|
||||||
|
ErrorFileSize=文件大小错误:预期 %1,实际 %2
|
||||||
|
|
||||||
|
; *** “正在准备安装”向导页
|
||||||
|
WizardPreparing=正在准备安装
|
||||||
|
PreparingDesc=安装程序正在准备安装 [name] 到您的电脑。
|
||||||
|
PreviousInstallNotCompleted=先前的程序安装或卸载未完成,您需要重启您的电脑以完成。%n%n在重启电脑后,再次运行安装程序以完成 [name] 的安装。
|
||||||
|
CannotContinue=安装程序不能继续。请点击“取消”退出。
|
||||||
|
ApplicationsFound=以下应用程序正在使用将由安装程序更新的文件。建议您允许安装程序自动关闭这些应用程序。
|
||||||
|
ApplicationsFound2=以下应用程序正在使用将由安装程序更新的文件。建议您允许安装程序自动关闭这些应用程序。安装完成后,安装程序将尝试重新启动这些应用程序。
|
||||||
|
CloseApplications=自动关闭应用程序(&A)
|
||||||
|
DontCloseApplications=不要关闭应用程序(&D)
|
||||||
|
ErrorCloseApplications=安装程序无法自动关闭所有应用程序。建议您在继续之前,关闭所有在使用需要由安装程序更新的文件的应用程序。
|
||||||
|
PrepareToInstallNeedsRestart=安装程序必须重启您的计算机。计算机重启后,请再次运行安装程序以完成 [name] 的安装。%n%n是否立即重新启动?
|
||||||
|
|
||||||
|
; *** “正在安装”向导页
|
||||||
|
WizardInstalling=正在安装
|
||||||
|
InstallingLabel=安装程序正在安装 [name] 到您的电脑,请稍候。
|
||||||
|
|
||||||
|
; *** “安装完成”向导页
|
||||||
|
FinishedHeadingLabel=[name] 安装完成
|
||||||
|
FinishedLabelNoIcons=安装程序已在您的电脑中安装了 [name]。
|
||||||
|
FinishedLabel=安装程序已在您的电脑中安装了 [name]。您可以通过已安装的快捷方式运行此应用程序。
|
||||||
|
ClickFinish=点击“完成”退出安装程序。
|
||||||
|
FinishedRestartLabel=为完成 [name] 的安装,安装程序必须重新启动您的电脑。要立即重启吗?
|
||||||
|
FinishedRestartMessage=为完成 [name] 的安装,安装程序必须重新启动您的电脑。%n%n要立即重启吗?
|
||||||
|
ShowReadmeCheck=是,我想查阅自述文件
|
||||||
|
YesRadio=是,立即重启电脑(&Y)
|
||||||
|
NoRadio=否,稍后重启电脑(&N)
|
||||||
|
; used for example as 'Run MyProg.exe'
|
||||||
|
RunEntryExec=运行 %1
|
||||||
|
; used for example as 'View Readme.txt'
|
||||||
|
RunEntryShellExec=查阅 %1
|
||||||
|
|
||||||
|
; *** “安装程序需要下一张磁盘”提示
|
||||||
|
ChangeDiskTitle=安装程序需要下一张磁盘
|
||||||
|
SelectDiskLabel2=请插入磁盘 %1 并点击“确定”。%n%n如果这个磁盘中的文件可以在下列文件夹之外的文件夹中找到,请输入正确的路径或点击“浏览”。
|
||||||
|
PathLabel=路径(&P):
|
||||||
|
FileNotInDir2=“%2”中找不到文件“%1”。请插入正确的磁盘或选择其他文件夹。
|
||||||
|
SelectDirectoryLabel=请指定下一张磁盘的位置。
|
||||||
|
|
||||||
|
; *** 安装状态消息
|
||||||
|
SetupAborted=安装程序未完成安装。%n%n请修正这个问题并重新运行安装程序。
|
||||||
|
AbortRetryIgnoreSelectAction=选择操作
|
||||||
|
AbortRetryIgnoreRetry=重试(&T)
|
||||||
|
AbortRetryIgnoreIgnore=忽略错误并继续(&I)
|
||||||
|
AbortRetryIgnoreCancel=关闭安装程序
|
||||||
|
|
||||||
|
; *** 安装状态消息
|
||||||
|
StatusClosingApplications=正在关闭应用程序...
|
||||||
|
StatusCreateDirs=正在创建目录...
|
||||||
|
StatusExtractFiles=正在解压缩文件...
|
||||||
|
StatusCreateIcons=正在创建快捷方式...
|
||||||
|
StatusCreateIniEntries=正在创建 INI 条目...
|
||||||
|
StatusCreateRegistryEntries=正在创建注册表条目...
|
||||||
|
StatusRegisterFiles=正在注册文件...
|
||||||
|
StatusSavingUninstall=正在保存卸载信息...
|
||||||
|
StatusRunProgram=正在完成安装...
|
||||||
|
StatusRestartingApplications=正在重启应用程序...
|
||||||
|
StatusRollback=正在撤销更改...
|
||||||
|
|
||||||
|
; *** 其他错误
|
||||||
|
ErrorInternal2=内部错误:%1
|
||||||
|
ErrorFunctionFailedNoCode=%1 失败
|
||||||
|
ErrorFunctionFailed=%1 失败;错误代码 %2
|
||||||
|
ErrorFunctionFailedWithMessage=%1 失败;错误代码 %2.%n%3
|
||||||
|
ErrorExecutingProgram=无法执行文件:%n%1
|
||||||
|
|
||||||
|
; *** 注册表错误
|
||||||
|
ErrorRegOpenKey=打开注册表项时出错:%n%1\%2
|
||||||
|
ErrorRegCreateKey=创建注册表项时出错:%n%1\%2
|
||||||
|
ErrorRegWriteKey=写入注册表项时出错:%n%1\%2
|
||||||
|
|
||||||
|
; *** INI 错误
|
||||||
|
ErrorIniEntry=在文件“%1”中创建 INI 条目时出错。
|
||||||
|
|
||||||
|
; *** 文件复制错误
|
||||||
|
FileAbortRetryIgnoreSkipNotRecommended=跳过此文件(&S) (不推荐)
|
||||||
|
FileAbortRetryIgnoreIgnoreNotRecommended=忽略错误并继续(&I) (不推荐)
|
||||||
|
SourceIsCorrupted=源文件已损坏
|
||||||
|
SourceDoesntExist=源文件“%1”不存在
|
||||||
|
ExistingFileReadOnly2=无法替换现有文件,它是只读的。
|
||||||
|
ExistingFileReadOnlyRetry=移除只读属性并重试(&R)
|
||||||
|
ExistingFileReadOnlyKeepExisting=保留现有文件(&K)
|
||||||
|
ErrorReadingExistingDest=尝试读取现有文件时出错:
|
||||||
|
FileExistsSelectAction=选择操作
|
||||||
|
FileExists2=文件已经存在。
|
||||||
|
FileExistsOverwriteExisting=覆盖已存在的文件(&O)
|
||||||
|
FileExistsKeepExisting=保留现有的文件(&K)
|
||||||
|
FileExistsOverwriteOrKeepAll=为所有冲突文件执行此操作(&D)
|
||||||
|
ExistingFileNewerSelectAction=选择操作
|
||||||
|
ExistingFileNewer2=现有的文件比安装程序将要安装的文件还要新。
|
||||||
|
ExistingFileNewerOverwriteExisting=覆盖已存在的文件(&O)
|
||||||
|
ExistingFileNewerKeepExisting=保留现有的文件(&K) (推荐)
|
||||||
|
ExistingFileNewerOverwriteOrKeepAll=为所有冲突文件执行此操作(&D)
|
||||||
|
ErrorChangingAttr=尝试更改下列现有文件的属性时出错:
|
||||||
|
ErrorCreatingTemp=尝试在目标目录创建文件时出错:
|
||||||
|
ErrorReadingSource=尝试读取下列源文件时出错:
|
||||||
|
ErrorCopying=尝试复制下列文件时出错:
|
||||||
|
ErrorReplacingExistingFile=尝试替换现有文件时出错:
|
||||||
|
ErrorRestartReplace=重启并替换失败:
|
||||||
|
ErrorRenamingTemp=尝试重命名下列目标目录中的一个文件时出错:
|
||||||
|
ErrorRegisterServer=无法注册 DLL/OCX:%1
|
||||||
|
ErrorRegSvr32Failed=RegSvr32 失败;退出代码 %1
|
||||||
|
ErrorRegisterTypeLib=无法注册类库:%1
|
||||||
|
|
||||||
|
; *** 卸载显示名字标记
|
||||||
|
; used for example as 'My Program (32-bit)'
|
||||||
|
UninstallDisplayNameMark=%1 (%2)
|
||||||
|
; used for example as 'My Program (32-bit, All users)'
|
||||||
|
UninstallDisplayNameMarks=%1 (%2, %3)
|
||||||
|
UninstallDisplayNameMark32Bit=32 位
|
||||||
|
UninstallDisplayNameMark64Bit=64 位
|
||||||
|
UninstallDisplayNameMarkAllUsers=所有用户
|
||||||
|
UninstallDisplayNameMarkCurrentUser=当前用户
|
||||||
|
|
||||||
|
; *** 安装后错误
|
||||||
|
ErrorOpeningReadme=尝试打开自述文件时出错。
|
||||||
|
ErrorRestartingComputer=安装程序无法重启电脑,请手动重启。
|
||||||
|
|
||||||
|
; *** 卸载消息
|
||||||
|
UninstallNotFound=文件“%1”不存在。无法卸载。
|
||||||
|
UninstallOpenError=文件“%1”不能被打开。无法卸载。
|
||||||
|
UninstallUnsupportedVer=此版本的卸载程序无法识别卸载日志文件“%1”的格式。无法卸载
|
||||||
|
UninstallUnknownEntry=卸载日志中遇到一个未知条目 (%1)
|
||||||
|
ConfirmUninstall=您确认要完全移除 %1 及其所有组件吗?
|
||||||
|
UninstallOnlyOnWin64=仅允许在 64 位 Windows 中卸载此程序。
|
||||||
|
OnlyAdminCanUninstall=仅使用管理员权限的用户能完成此卸载。
|
||||||
|
UninstallStatusLabel=正在从您的电脑中移除 %1,请稍候。
|
||||||
|
UninstalledAll=已顺利从您的电脑中移除 %1。
|
||||||
|
UninstalledMost=%1 卸载完成。%n%n有部分内容未能被删除,但您可以手动删除它们。
|
||||||
|
UninstalledAndNeedsRestart=为完成 %1 的卸载,需要重启您的电脑。%n%n立即重启电脑吗?
|
||||||
|
UninstallDataCorrupted=文件“%1”已损坏。无法卸载
|
||||||
|
|
||||||
|
; *** 卸载状态消息
|
||||||
|
ConfirmDeleteSharedFileTitle=删除共享的文件吗?
|
||||||
|
ConfirmDeleteSharedFile2=系统表示下列共享的文件已不有其他程序使用。您希望卸载程序删除这些共享的文件吗?%n%n如果删除这些文件,但仍有程序在使用这些文件,则这些程序可能出现异常。如果您不能确定,请选择“否”,在系统中保留这些文件以免引发问题。
|
||||||
|
SharedFileNameLabel=文件名:
|
||||||
|
SharedFileLocationLabel=位置:
|
||||||
|
WizardUninstalling=卸载状态
|
||||||
|
StatusUninstalling=正在卸载 %1...
|
||||||
|
|
||||||
|
; *** Shutdown block reasons
|
||||||
|
ShutdownBlockReasonInstallingApp=正在安装 %1。
|
||||||
|
ShutdownBlockReasonUninstallingApp=正在卸载 %1。
|
||||||
|
|
||||||
|
; The custom messages below aren't used by Setup itself, but if you make
|
||||||
|
; use of them in your scripts, you'll want to translate them.
|
||||||
|
|
||||||
|
[CustomMessages]
|
||||||
|
|
||||||
|
NameAndVersion=%1 版本 %2
|
||||||
|
AdditionalIcons=附加快捷方式:
|
||||||
|
CreateDesktopIcon=创建桌面快捷方式(&D)
|
||||||
|
CreateQuickLaunchIcon=创建快速启动栏快捷方式(&Q)
|
||||||
|
ProgramOnTheWeb=%1 网站
|
||||||
|
UninstallProgram=卸载 %1
|
||||||
|
LaunchProgram=运行 %1
|
||||||
|
AssocFileExtension=将 %2 文件扩展名与 %1 建立关联(&A)
|
||||||
|
AssocingFileExtension=正在将 %2 文件扩展名与 %1 建立关联...
|
||||||
|
AutoStartProgramGroupDescription=启动:
|
||||||
|
AutoStartProgram=自动启动 %1
|
||||||
|
AddonHostProgramNotFound=您选择的文件夹中无法找到 %1。%n%n您要继续吗?
|
||||||
@@ -6,10 +6,18 @@
|
|||||||
"TaskQueue.Recruiting.IsChecked": "True" #自动公招
|
"TaskQueue.Recruiting.IsChecked": "True" #自动公招
|
||||||
"TaskQueue.Base.IsChecked": "True" #基建换班
|
"TaskQueue.Base.IsChecked": "True" #基建换班
|
||||||
"TaskQueue.Combat.IsChecked": "True" #刷理智
|
"TaskQueue.Combat.IsChecked": "True" #刷理智
|
||||||
"TaskQueue.Mission.IsChecked": "True" #领取奖励
|
|
||||||
"TaskQueue.Mall.IsChecked": "True" #获取信用及购物
|
"TaskQueue.Mall.IsChecked": "True" #获取信用及购物
|
||||||
|
"TaskQueue.Mission.IsChecked": "True" #领取奖励
|
||||||
"TaskQueue.AutoRoguelike.IsChecked": "False" #自动肉鸽
|
"TaskQueue.AutoRoguelike.IsChecked": "False" #自动肉鸽
|
||||||
"TaskQueue.Reclamation.IsChecked": "False" #生息演算
|
"TaskQueue.Reclamation.IsChecked": "False" #生息演算
|
||||||
|
"TaskQueue.Order.WakeUp": "0"
|
||||||
|
"TaskQueue.Order.Recruiting": "1"
|
||||||
|
"TaskQueue.Order.Base": "2"
|
||||||
|
"TaskQueue.Order.Combat": "3"
|
||||||
|
"TaskQueue.Order.Mall": "4"
|
||||||
|
"TaskQueue.Order.Mission": "5"
|
||||||
|
"TaskQueue.Order.AutoRoguelike": "6"
|
||||||
|
"TaskQueue.Order.Reclamation": "7"
|
||||||
#刷理智
|
#刷理智
|
||||||
"MainFunction.UseMedicine": "True" #吃理智药
|
"MainFunction.UseMedicine": "True" #吃理智药
|
||||||
"MainFunction.UseMedicine.Quantity": "999" #吃理智药数量
|
"MainFunction.UseMedicine.Quantity": "999" #吃理智药数量
|
||||||
@@ -30,8 +38,8 @@
|
|||||||
"Penguin.EnablePenguin": "True" #上报企鹅物流
|
"Penguin.EnablePenguin": "True" #上报企鹅物流
|
||||||
"Yituliu.EnableYituliu": "True" #上报一图流
|
"Yituliu.EnableYituliu": "True" #上报一图流
|
||||||
#基建换班
|
#基建换班
|
||||||
"Infrast.CustomInfrastEnabled": "True" #启用自定义基建配置
|
"Infrast.InfrastMode": "Normal"、"Rotation"、"Custom" #基建模式
|
||||||
"Infrast.CustomInfrastPlanIndex": "1" #自定义基建配置索引
|
"Infrast.CustomInfrastPlanIndex": "1" #自定义基建配置索引号
|
||||||
"Infrast.DefaultInfrast": "user_defined" #内置配置
|
"Infrast.DefaultInfrast": "user_defined" #内置配置
|
||||||
"Infrast.IsCustomInfrastFileReadOnly": "False" #自定义基建配置文件只读
|
"Infrast.IsCustomInfrastFileReadOnly": "False" #自定义基建配置文件只读
|
||||||
"Infrast.CustomInfrastFile": "" #自定义基建配置文件地址
|
"Infrast.CustomInfrastFile": "" #自定义基建配置文件地址
|
||||||
@@ -49,4 +57,5 @@ G"Start.MinimizeDirectly": "True" #启动MAA后直接最小化
|
|||||||
G"GUI.UseTray": "True" #显示托盘图标
|
G"GUI.UseTray": "True" #显示托盘图标
|
||||||
G"GUI.MinimizeToTray": "False" #最小化时隐藏至托盘
|
G"GUI.MinimizeToTray": "False" #最小化时隐藏至托盘
|
||||||
"Start.EmulatorPath" #模拟器路径
|
"Start.EmulatorPath" #模拟器路径
|
||||||
"Start.EmulatorAddCommand": "-v 2" #附加命令
|
"Start.EmulatorAddCommand": "-v 2" #附加命令
|
||||||
|
G"VersionUpdate.package": "MirrorChyanAppv5.15.6.zip" #更新包标识
|
||||||
BIN
resources/icons/MirrorChyan.ico
Normal file
BIN
resources/icons/MirrorChyan.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -1,44 +1,49 @@
|
|||||||
{
|
{
|
||||||
"main_version": "4.3.4.2",
|
"main_version": "4.3.6.0",
|
||||||
"updater_version": "1.0.0.0",
|
"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- 公告样式优化",
|
"announcement": "\n## 新增功能\n- 屏蔽MuMu模拟器开屏广告功能上线\n- 更新器支持多线程下载\n- 添加强制关闭ADB与模拟器等增强任务项\n## 修复BUG\n- 修复统计信息HTML模板公招匹配错误\n- 修复密码显示按钮动画异常\n- 修复`检测到MAA未能实际执行任务`报错被异常屏蔽\n- 修复MAA超时判定异常失效\n## 程序优化\n- 关机等电源操作添加100s倒计时\n- 人工排查弹窗方法优化\n- 人工排查时自动屏蔽静默操作\n- 公告样式优化",
|
||||||
"version_info": {
|
"version_info": {
|
||||||
"4.3.4.2": {
|
"4.3.6.0": {
|
||||||
"程序优化": [
|
|
||||||
"调度队列历史记录归入配置类管理",
|
|
||||||
"添加.gitignore",
|
|
||||||
"工作流删除冗余部分",
|
|
||||||
"自动代理与人工排查结束后MAA恢复到全局配置 #40",
|
|
||||||
"网络相关操作由子线程执行"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"4.3.4.1": {
|
|
||||||
"新增功能": [
|
"新增功能": [
|
||||||
"开始任务前自动释放ADB端口"
|
"适配MAA连战次数`AUTO`模式"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.6.5": {
|
||||||
|
"新增功能": [
|
||||||
|
"release中添加安装程序"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.6.4": {
|
||||||
|
"修复BUG": [
|
||||||
|
"修复详细模式下非定时自定义基建无法正常换班的问题"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.6.3": {
|
||||||
|
"新增功能": [
|
||||||
|
"下载器仅支持调用Mirror酱"
|
||||||
|
],
|
||||||
|
"修复BUG": [
|
||||||
|
"修复Mirror酱更新检查报错不显示详细信息的问题"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.6.2": {
|
||||||
|
"新增功能": [
|
||||||
|
"新增`无人值守模式`"
|
||||||
|
],
|
||||||
|
"修复BUG": [
|
||||||
|
"修复软件窗口最大化异常问题",
|
||||||
|
"修复异常操作导致窗口离开屏幕后难以复原的问题",
|
||||||
|
"修正剩余理智关卡文案",
|
||||||
|
"修复隐藏到托盘时,托盘无法退出主程序的问题",
|
||||||
|
"修复Server酱网络异常导致的卡死问题"
|
||||||
],
|
],
|
||||||
"程序优化": [
|
"程序优化": [
|
||||||
"request 添加超时限制",
|
"主窗口显示版本号"
|
||||||
"用户任务运行流程改进",
|
|
||||||
"自动代理中模拟器改由AUTO_MAA控制",
|
|
||||||
"修正部分配置项文案"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"4.3.3.0": {
|
"4.3.6.1": {
|
||||||
"修复BUG": [
|
"新增功能": [
|
||||||
"修复更新器无法下载MAA的异常"
|
"单次自动代理任务中,已完成的子任务在重复执行时不再启用"
|
||||||
],
|
|
||||||
"程序优化": [
|
|
||||||
"自动发版改为手动触发"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"4.3.2.0": {
|
|
||||||
"修复BUG": [
|
|
||||||
"修复更新器无法启动的异常"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"4.3.1.0": {
|
|
||||||
"修复BUG": [
|
|
||||||
"覆盖规避v4.3.0错误包"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -51,7 +56,6 @@
|
|||||||
"https://ghfast.top/"
|
"https://ghfast.top/"
|
||||||
],
|
],
|
||||||
"download_dict": {
|
"download_dict": {
|
||||||
"官方下载站-jp": "https://jp-download.fearr.xyz/AUTO_MAA/",
|
"官方下载站-jp": "https://jp-download.fearr.xyz/AUTO_MAA/"
|
||||||
"官方下载站-hw": "http://hwobs.fearr.xyz/releases/artifacts/"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user