Compare commits

..

17 Commits

Author SHA1 Message Date
DLmaster
44ee917d88 同步到MAA新版本的配置方法 2024-08-03 13:11:54 +08:00
DLmaster
669019c051 优化超时判定 2024-07-28 10:42:55 +08:00
DLmaster
4685c12570 Update python-app.yml
自动构建
2024-07-27 22:25:28 +08:00
DLmaster
d815529510 Update python-app.yml
自动构建
2024-07-27 22:03:02 +08:00
DLmaster
1da3620feb Update python-app.yml
自动构建
2024-07-27 22:00:23 +08:00
DLmaster
44d529c60f Update python-app.yml
自动构建
2024-07-27 21:53:49 +08:00
DLmaster
cdbcebd945 Update python-app.yml
自动构建
2024-07-27 21:51:37 +08:00
DLmaster
5bc2bf9397 Update python-app.yml
自动构建
2024-07-27 21:48:27 +08:00
DLmaster
d41419a579 Update python-app.yml
自动构建
2024-07-27 21:40:34 +08:00
DLmaster
a7e15e509e Create python-app.yml
自动构建
2024-07-27 21:30:41 +08:00
DLmaster
6518a378ac 修正v3.0_Beta版更新说明 2024-07-24 21:13:50 +08:00
DLmaster
ebb73182f7 添加开机自启与阻止休眠功能;优化配置文件处理方式 2024-07-24 20:57:15 +08:00
DLmaster
8fcc69165f 更新自述文件 2024-07-17 16:31:04 +08:00
DLmaster
5b98c58926 添加对自定义基建的支持 2024-07-17 16:19:38 +08:00
DLmaster
ce1534657b 修复禁用剿灭时的任务完成判定 2024-07-10 09:28:11 +08:00
DLmaster
e2f02ea616 修复定时判定;MAA路径运行检查 2024-07-09 11:48:58 +08:00
DLmaster
76134c2e2b 更新GUI相关自述文件 2024-07-07 14:26:47 +08:00
24 changed files with 462 additions and 321 deletions

44
.github/workflows/python-app.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python application
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v3
with:
python-version: "3.12"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install -r requirements.txt
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Built with pyinstaller
run: |
pyinstaller -F --version-file res/info.txt -w --icon=res/AUTO_MAA.ico AUTO_MAA.py
- name: Upload Artifact
uses: actions/upload-artifact@v2
with:
name: AUTO_MAA
path: ./

Binary file not shown.

View File

@@ -42,11 +42,14 @@ import sqlite3
import json
import datetime
import os
import sys
import ctypes
import hashlib
import subprocess
import time
import random
import secrets
import winreg
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
@@ -60,6 +63,9 @@ class MaaRunner(QtCore.QThread):
UpGui = QtCore.Signal(str, str, str, str, str)
UpUserInfo = QtCore.Signal(list, list, list, list)
Accomplish = QtCore.Signal()
AppPath = os.path.dirname(os.path.realpath(sys.argv[0])).replace(
"\\", "/"
) # 获取软件自身的路径
ifRun = False
def __init__(self, SetPath, LogPath, MaaPath, Routine, Annihilation, Num, data):
@@ -102,7 +108,10 @@ class MaaRunner(QtCore.QThread):
for j in range(2):
if not self.ifRun:
break
if (j == 0 and self.data[uid][8] == "n") or runbook[j]:
if j == 0 and self.data[uid][8] == "n":
runbook[0] = True
continue
if runbook[j]:
continue
# 配置MAA
self.SetMaa(j + 1, uid)
@@ -110,21 +119,17 @@ class MaaRunner(QtCore.QThread):
maa = subprocess.Popen([self.MaaPath])
# 记录当前时间
StartTime = datetime.datetime.now()
# 初始化log记录列表
if j == 0:
logx = [k for k in range(self.Annihilation * 60)]
elif j == 1:
logx = [k for k in range(self.Routine * 60)]
logi = 0
# 记录是否超时的标记
self.TimeOut = False
# 更新运行信息
WaitUid = [
idx for idx in AllUid if (not idx in OverUid + ErrorUid + [uid])
]
# 监测MAA运行状态
while True:
# 更新MAA日志
# 获取MAA日志
logs = []
with open(self.LogPath, "r", encoding="utf-8") as f:
logs = []
for entry in f:
try:
entry_time = datetime.datetime.strptime(
@@ -134,26 +139,41 @@ class MaaRunner(QtCore.QThread):
logs.append(entry)
except ValueError:
pass
log = "".join(logs)
if j == 0:
self.UpGui.emit(
self.data[uid][0] + "_第" + str(i + 1) + "次_剿灭",
"\n".join([self.data[k][0] for k in WaitUid]),
"\n".join([self.data[k][0] for k in OverUid]),
"\n".join([self.data[k][0] for k in ErrorUid]),
log,
)
elif j == 1:
self.UpGui.emit(
self.data[uid][0] + "_第" + str(i + 1) + "次_日常",
"\n".join([self.data[k][0] for k in WaitUid]),
"\n".join([self.data[k][0] for k in OverUid]),
"\n".join([self.data[k][0] for k in ErrorUid]),
log,
)
if len(logs) != 0:
logx[logi] = logs[-1]
logi = (logi + 1) % len(logx)
# 判断是否超时
if len(logs) > 0:
LastTime = datetime.datetime.strptime(
logs[-1][1:20], "%Y-%m-%d %H:%M:%S"
)
NowTime = datetime.datetime.now()
if (
j == 0
and NowTime - LastTime
> datetime.timedelta(minutes=self.Annihilation)
) or (
j == 1
and NowTime - LastTime
> datetime.timedelta(minutes=self.Routine)
):
self.TimeOut = True
# 合并日志
log = "".join(logs)
# 更新MAA日志
if j == 0:
self.UpGui.emit(
self.data[uid][0] + "_第" + str(i + 1) + "次_剿灭",
"\n".join([self.data[k][0] for k in WaitUid]),
"\n".join([self.data[k][0] for k in OverUid]),
"\n".join([self.data[k][0] for k in ErrorUid]),
log,
)
elif j == 1:
self.UpGui.emit(
self.data[uid][0] + "_第" + str(i + 1) + "次_日常",
"\n".join([self.data[k][0] for k in WaitUid]),
"\n".join([self.data[k][0] for k in OverUid]),
"\n".join([self.data[k][0] for k in ErrorUid]),
log,
)
# 判断MAA程序运行状态
if "任务已全部完成!" in log:
runbook[j] = True
@@ -164,17 +184,17 @@ class MaaRunner(QtCore.QThread):
"\n".join([self.data[k][0] for k in ErrorUid]),
"检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s",
)
maa.wait()
time.sleep(10)
break
elif (
("请检查连接设置或尝试重启模拟器与 ADB 或重启电脑" in log)
or ("已停止" in log)
or ("MaaAssistantArknights GUI exited" in log)
or self.TimeOut(logx)
or self.TimeOut
or not self.ifRun
):
# 打印中止信息
# 此时log变量内存储的就是出现异常的日志信息可以保存或发送用于问题排查
if (
(
"请检查连接设置或尝试重启模拟器与 ADB 或重启电脑"
@@ -184,7 +204,7 @@ class MaaRunner(QtCore.QThread):
or ("MaaAssistantArknights GUI exited" in log)
):
info = "检测到MAA进程异常\n正在中止相关程序\n请等待10s"
elif self.TimeOut(logx):
elif self.TimeOut:
info = "检测到MAA进程超时\n正在中止相关程序\n请等待10s"
elif not self.ifRun:
info = "您中止了本次任务\n正在中止相关程序\n请等待"
@@ -196,7 +216,6 @@ class MaaRunner(QtCore.QThread):
info,
)
os.system("taskkill /F /T /PID " + str(maa.pid))
maa.wait()
if self.ifRun:
time.sleep(10)
break
@@ -217,7 +236,7 @@ class MaaRunner(QtCore.QThread):
self.UpUserInfo.emit(AllUid, days, lasts, numbs)
# 保存运行日志
endtime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open("log.txt", "w", encoding="utf-8") as f:
with open(self.AppPath + "log.txt", "w", encoding="utf-8") as f:
print("任务开始时间:" + begintime + ",结束时间:" + endtime, file=f)
print(
"已完成数:" + str(len(OverUid)) + ",未完成数:" + str(len(ErrorUid)),
@@ -231,7 +250,7 @@ class MaaRunner(QtCore.QThread):
if len(WaitUid) != 0:
print("未代理的用户:", file=f)
print("\n".join([self.data[k][0] for k in WaitUid]), file=f)
with open("log.txt", "r", encoding="utf-8") as f:
with open(self.AppPath + "log.txt", "r", encoding="utf-8") as f:
EndLog = f.read()
# 恢复GUI运行面板
self.UpGui.emit("", "", "", "", EndLog)
@@ -244,8 +263,8 @@ class MaaRunner(QtCore.QThread):
data = json.load(f)
if s == 0:
data["Configurations"]["Default"][
"MainFunction.ActionAfterCompleted"
] = "ExitEmulatorAndSelf" # 完成后退出MAA和模拟器
"MainFunction.PostActions"
] = "12" # 完成后退出MAA和模拟器
data["Configurations"]["Default"][
"Start.RunDirectly"
] = "True" # 启动MAA后直接运行
@@ -322,92 +341,172 @@ class MaaRunner(QtCore.QThread):
data["Configurations"]["Default"][
"TaskQueue.Mall.IsChecked"
] = "True" # 获取信用及购物
data["Configurations"]["Default"]["MainFunction.Stage1"] = self.data[uid][
5
] # 主关卡
data["Configurations"]["Default"]["MainFunction.Stage2"] = self.data[uid][
6
] # 备选关卡1
data["Configurations"]["Default"]["MainFunction.Stage3"] = self.data[uid][
7
] # 备选关卡2
# 主关卡
if self.data[uid][5] == "-":
data["Configurations"]["Default"]["MainFunction.Stage1"] = ""
else:
data["Configurations"]["Default"]["MainFunction.Stage1"] = self.data[
uid
][5]
# 备选关卡1
if self.data[uid][6] == "-":
data["Configurations"]["Default"]["MainFunction.Stage2"] = ""
else:
data["Configurations"]["Default"]["MainFunction.Stage2"] = self.data[
uid
][6]
# 备选关卡2
if self.data[uid][7] == "-":
data["Configurations"]["Default"]["MainFunction.Stage3"] = ""
else:
data["Configurations"]["Default"]["MainFunction.Stage3"] = self.data[
uid
][7]
data["Configurations"]["Default"][
"Fight.RemainingSanityStage"
] = "" # 剩余理智关卡
# 连战次数
if self.data[uid][5] == "1-7":
data["Configurations"]["Default"][
"MainFunction.Series.Quantity"
] = "6" # 连战次数
data["Configurations"]["Default"]["MainFunction.Series.Quantity"] = "6"
else:
data["Configurations"]["Default"][
"MainFunction.Series.Quantity"
] = "1" # 连战次数
data["Configurations"]["Default"]["MainFunction.Series.Quantity"] = "1"
data["Configurations"]["Default"][
"Penguin.IsDrGrandet"
] = "False" # 博朗台模式
data["Configurations"]["Default"][
"GUI.CustomStageCode"
] = "True" # 手动输入关卡名
# 备选关卡
if self.data[uid][6] == "-" and self.data[uid][7] == "-":
data["Configurations"]["Default"][
"GUI.UseAlternateStage"
] = "False" # 不使用备选关卡
data["Configurations"]["Default"]["GUI.UseAlternateStage"] = "False"
else:
data["Configurations"]["Default"][
"GUI.UseAlternateStage"
] = "True" # 使用备选关卡
data["Configurations"]["Default"]["GUI.UseAlternateStage"] = "True"
data["Configurations"]["Default"][
"Fight.UseRemainingSanityStage"
] = "False" # 使用剩余理智
data["Configurations"]["Default"][
"Fight.UseExpiringMedicine"
] = "True" # 无限吃48小时内过期的理智药
# 自定义基建配置
if self.data[uid][9] == "-":
data["Configurations"]["Default"][
"Infrast.CustomInfrastEnabled"
] = "False" # 禁用自定义基建配置
else:
data["Configurations"]["Default"][
"Infrast.CustomInfrastEnabled"
] = "True" # 启用自定义基建配置
data["Configurations"]["Default"][
"Infrast.DefaultInfrast"
] = "user_defined" # 内置配置
data["Configurations"]["Default"][
"Infrast.IsCustomInfrastFileReadOnly"
] = "False" # 自定义基建配置文件只读
data["Configurations"]["Default"][
"Infrast.CustomInfrastFile"
] = self.data[uid][
9
] # 自定义基建配置文件地址
with open(self.SetPath, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4)
return True
# 超时判断
def TimeOut(self, logx):
log0 = logx[0]
for i in logx:
if i != log0:
return False
return True
class MaaTimer(QtCore.QThread):
class MainTimer(QtCore.QThread):
GetConfig = QtCore.Signal()
StartForTimer = QtCore.Signal()
AppPath = os.path.realpath(sys.argv[0]) # 获取软件自身的路径
AppName = os.path.basename(AppPath) # 获取软件自身的名称
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
isMaaRun = False
def __init__(self, config):
super(MaaTimer, self).__init__()
super(MainTimer, self).__init__()
self.config = config
def run(self):
while True:
self.GetConfig.emit()
self.setSystem()
TimeSet = [
self.config["Default"]["TimeSet.run" + str(k + 1)]
for k in range(10)
if self.config["Default"]["TimeSet.set" + str(k + 1)]
if self.config["Default"]["TimeSet.set" + str(k + 1)] == "True"
]
curtime = datetime.datetime.now().strftime("%H:%M")
if (curtime in TimeSet) and not self.isMaaRun:
self.StartForTimer.emit()
time.sleep(1)
def setSystem(self):
# 同步系统休眠状态
if self.config["Default"]["SelfSet.IfSleep"] == "True":
# 设置系统电源状态
ctypes.windll.kernel32.SetThreadExecutionState(
self.ES_CONTINUOUS | self.ES_SYSTEM_REQUIRED
)
elif self.config["Default"]["SelfSet.IfSleep"] == "False":
# 恢复系统电源状态
ctypes.windll.kernel32.SetThreadExecutionState(self.ES_CONTINUOUS)
# 同步开机自启
if (
self.config["Default"]["SelfSet.IfSelfStart"] == "True"
and not self.IsStartup()
):
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
winreg.KEY_SET_VALUE,
winreg.KEY_ALL_ACCESS | winreg.KEY_WRITE | winreg.KEY_CREATE_SUB_KEY,
)
winreg.SetValueEx(key, self.AppName, 0, winreg.REG_SZ, self.AppPath)
winreg.CloseKey(key)
elif (
self.config["Default"]["SelfSet.IfSelfStart"] == "False"
and self.IsStartup()
):
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
winreg.KEY_SET_VALUE,
winreg.KEY_ALL_ACCESS | winreg.KEY_WRITE | winreg.KEY_CREATE_SUB_KEY,
)
winreg.DeleteValue(key, self.AppName)
winreg.CloseKey(key)
def IsStartup(self):
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
0,
winreg.KEY_READ,
)
try:
value, _ = winreg.QueryValueEx(key, self.AppName)
return True
except FileNotFoundError:
return False
finally:
winreg.CloseKey(key)
class Main(QWidget):
AppPath = os.path.dirname(os.path.realpath(sys.argv[0])).replace(
"\\", "/"
) # 获取软件自身的路径
def __init__(self, PASSWARD=""):
super().__init__()
self.DatabasePath = "data/data.db"
self.ConfigPath = "config/gui.json"
self.KeyPath = "data/key"
self.GameidPath = "data/gameid.txt"
self.DatabasePath = self.AppPath + "/data/data.db"
self.ConfigPath = self.AppPath + "/config/gui.json"
self.KeyPath = self.AppPath + "/data/key"
self.GameidPath = self.AppPath + "/data/gameid.txt"
self.PASSWORD = PASSWARD
self.ifUpDatabase = True
self.ifUpConfig = True
@@ -428,12 +527,13 @@ class Main(QWidget):
"uid",
]
self.ui = uiLoader.load("gui/ui/main.ui")
self.ui = uiLoader.load(self.AppPath + "/gui/ui/main.ui")
self.ui.setWindowTitle("AUTO_MAA")
self.ui.setWindowIcon(QIcon("res/AUTO_MAA.ico"))
self.ui.setWindowIcon(QIcon(self.AppPath + "/res/AUTO_MAA.ico"))
# 检查文件完整性
if not os.path.exists(self.DatabasePath) or not os.path.exists(self.ConfigPath):
self.initialize()
self.CheckConfig()
with open(self.ConfigPath, "r") as f:
self.config = json.load(f)
if not os.path.exists(self.KeyPath):
@@ -488,6 +588,12 @@ class Main(QWidget):
self.num = self.ui.findChild(QSpinBox, "spinBox_numt")
self.num.valueChanged.connect(self.ChangeConfig)
self.IfSelfStart = self.ui.findChild(QCheckBox, "checkBox_ifselfstart")
self.IfSelfStart.stateChanged.connect(self.ChangeConfig)
self.IfSleep = self.ui.findChild(QCheckBox, "checkBox_ifsleep")
self.IfSleep.stateChanged.connect(self.ChangeConfig)
self.RunText = self.ui.findChild(QTextBrowser, "textBrowser_run")
self.WaitText = self.ui.findChild(QTextBrowser, "textBrowser_wait")
self.OverText = self.ui.findChild(QTextBrowser, "textBrowser_over")
@@ -531,10 +637,10 @@ class Main(QWidget):
self.MaaRunner.UpUserInfo.connect(self.ChangeUserInfo)
self.MaaRunner.Accomplish.connect(self.end)
self.MaaTimer = MaaTimer(self.config)
self.MaaTimer.GetConfig.connect(self.GiveConfig)
self.MaaTimer.StartForTimer.connect(self.RunStarter)
self.MaaTimer.start()
self.MainTimer = MainTimer(self.config)
self.MainTimer.GetConfig.connect(self.GiveConfig)
self.MainTimer.StartForTimer.connect(self.RunStarter)
self.MainTimer.start()
# 载入GUI数据
self.UpdateTable("normal")
@@ -543,10 +649,10 @@ class Main(QWidget):
# 初始化
def initialize(self):
# 检查目录
if not os.path.exists("data"):
os.makedirs("data")
if not os.path.exists("config"):
os.makedirs("config")
if not os.path.exists(self.AppPath + "/data"):
os.makedirs(self.AppPath + "/data")
if not os.path.exists(self.AppPath + "/config"):
os.makedirs(self.AppPath + "/config")
# 生成用户数据库
if not os.path.exists(self.DatabasePath):
db = sqlite3.connect(self.DatabasePath)
@@ -561,55 +667,74 @@ class Main(QWidget):
db.close()
# 生成配置文件
if not os.path.exists(self.ConfigPath):
config = {
"Default": {
"TimeSet.set1": "False",
"TimeSet.run1": "00:00",
"TimeSet.set2": "False",
"TimeSet.run2": "00:00",
"TimeSet.set3": "False",
"TimeSet.run3": "00:00",
"TimeSet.set4": "False",
"TimeSet.run4": "00:00",
"TimeSet.set5": "False",
"TimeSet.run5": "00:00",
"TimeSet.set6": "False",
"TimeSet.run6": "00:00",
"TimeSet.set7": "False",
"TimeSet.run7": "00:00",
"TimeSet.set8": "False",
"TimeSet.run8": "00:00",
"TimeSet.set9": "False",
"TimeSet.run9": "00:00",
"TimeSet.set10": "False",
"TimeSet.run10": "00:00",
"MaaSet.path": "",
"TimeLimit.routine": 10,
"TimeLimit.annihilation": 40,
"TimesLimit.run": 3,
}
}
config = {"Default": {}}
with open(self.ConfigPath, "w") as f:
json.dump(config, f, indent=4)
# 检查配置文件字段
def CheckConfig(self):
ConfigList = [
["TimeSet.set1", "False"],
["TimeSet.run1", "00:00"],
["TimeSet.set2", "False"],
["TimeSet.run2", "00:00"],
["TimeSet.set3", "False"],
["TimeSet.run3", "00:00"],
["TimeSet.set4", "False"],
["TimeSet.run4", "00:00"],
["TimeSet.set5", "False"],
["TimeSet.run5", "00:00"],
["TimeSet.set6", "False"],
["TimeSet.run6", "00:00"],
["TimeSet.set7", "False"],
["TimeSet.run7", "00:00"],
["TimeSet.set8", "False"],
["TimeSet.run8", "00:00"],
["TimeSet.set9", "False"],
["TimeSet.run9", "00:00"],
["TimeSet.set10", "False"],
["TimeSet.run10", "00:00"],
["MaaSet.path", ""],
["TimeLimit.routine", 10],
["TimeLimit.annihilation", 40],
["TimesLimit.run", 3],
["SelfSet.IfSelfStart", "False"],
["SelfSet.IfSleep", "False"],
]
# 导入配置文件
with open(self.ConfigPath, "r") as f:
config = json.load(f)
# 检查并补充缺失的字段
for i in range(len(ConfigList)):
if not ConfigList[i][0] in config["Default"]:
config["Default"][ConfigList[i][0]] = ConfigList[i][1]
# 导出配置文件
with open(self.ConfigPath, "w") as f:
json.dump(config, f, indent=4)
# 配置密钥
def getPASSWORD(self):
# 检查目录
if not os.path.exists("data/key"):
os.makedirs("data/key")
if not os.path.exists(self.AppPath + "/data/key"):
os.makedirs(self.AppPath + "/data/key")
# 生成RSA密钥对
key = RSA.generate(2048)
public_key_local = key.publickey()
private_key = key
# 保存RSA公钥
with open("data/key/public_key.pem", "wb") as f:
with open(self.AppPath + "/data/key/public_key.pem", "wb") as f:
f.write(public_key_local.exportKey())
# 生成密钥转换与校验随机盐
PASSWORDsalt = secrets.token_hex(random.randint(32, 1024))
with open("data/key/PASSWORDsalt.txt", "w", encoding="utf-8") as f:
with open(
self.AppPath + "/data/key/PASSWORDsalt.txt", "w", encoding="utf-8"
) as f:
print(PASSWORDsalt, file=f)
verifysalt = secrets.token_hex(random.randint(32, 1024))
with open("data/key/verifysalt.txt", "w", encoding="utf-8") as f:
with open(
self.AppPath + "/data/key/verifysalt.txt", "w", encoding="utf-8"
) as f:
print(verifysalt, file=f)
# 将管理密钥转化为AES-256密钥
AES_password = hashlib.sha256(
@@ -619,18 +744,18 @@ class Main(QWidget):
AES_password_verify = hashlib.sha256(
AES_password + verifysalt.encode("utf-8")
).digest()
with open("data/key/AES_password_verify.bin", "wb") as f:
with open(self.AppPath + "/data/key/AES_password_verify.bin", "wb") as f:
f.write(AES_password_verify)
# AES-256加密RSA私钥并保存密文
AES_key = AES.new(AES_password, AES.MODE_ECB)
private_key_local = AES_key.encrypt(pad(private_key.exportKey(), 32))
with open("data/key/private_key.bin", "wb") as f:
with open(self.AppPath + "/data/key/private_key.bin", "wb") as f:
f.write(private_key_local)
# 加密
def encryptx(self, note):
# 读取RSA公钥
with open("data/key/public_key.pem", "rb") as f:
with open(self.AppPath + "/data/key/public_key.pem", "rb") as f:
public_key_local = RSA.import_key(f.read())
# 使用RSA公钥对数据进行加密
cipher = PKCS1_OAEP.new(public_key_local)
@@ -640,13 +765,17 @@ class Main(QWidget):
# 解密
def decryptx(self, note):
# 读入RSA私钥密文、盐与校验哈希值
with open("data/key/private_key.bin", "rb") as f:
with open(self.AppPath + "/data/key/private_key.bin", "rb") as f:
private_key_local = f.read().strip()
with open("data/key/PASSWORDsalt.txt", "r", encoding="utf-8") as f:
with open(
self.AppPath + "/data/key/PASSWORDsalt.txt", "r", encoding="utf-8"
) as f:
PASSWORDsalt = f.read().strip()
with open("data/key/verifysalt.txt", "r", encoding="utf-8") as f:
with open(
self.AppPath + "/data/key/verifysalt.txt", "r", encoding="utf-8"
) as f:
verifysalt = f.read().strip()
with open("data/key/AES_password_verify.bin", "rb") as f:
with open(self.AppPath + "/data/key/AES_password_verify.bin", "rb") as f:
AES_password_verify = f.read().strip()
# 将管理密钥转化为AES-256密钥并验证
AES_password = hashlib.sha256(
@@ -769,8 +898,7 @@ class Main(QWidget):
item = QTableWidgetItem("今日已代理" + str(data[i][12]) + "")
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
elif j == 9:
item = QTableWidgetItem(str(value))
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
item = QTableWidgetItem(str(value).replace("\\", "/"))
elif j == 10:
if self.PASSWORD == "":
item = QTableWidgetItem("******")
@@ -804,6 +932,15 @@ class Main(QWidget):
self.routine.setValue(self.config["Default"]["TimeLimit.routine"])
self.annihilation.setValue(self.config["Default"]["TimeLimit.annihilation"])
self.num.setValue(self.config["Default"]["TimesLimit.run"])
self.IfSelfStart.setChecked(
bool(self.config["Default"]["SelfSet.IfSelfStart"] == "True")
)
self.IfSleep.setChecked(
bool(self.config["Default"]["SelfSet.IfSleep"] == "True")
)
for i in range(10):
self.StartTime[i][0].setChecked(
bool(self.config["Default"]["TimeSet.set" + str(i + 1)] == "True")
@@ -837,7 +974,7 @@ class Main(QWidget):
"1-7",
"-",
"-",
"暂不支持",
"-",
self.encryptx("未设置"),
self.userlist.rowCount(),
),
@@ -879,15 +1016,13 @@ class Main(QWidget):
if os.path.exists(self.GameidPath):
with open(self.GameidPath, encoding="utf-8") as f:
gameids = f.readlines()
for i in range(len(gameids)):
for j in range(len(gameids[i])):
if gameids[i][j] == "" or gameids[i][j] == ":":
gamein = gameids[i][:j]
gameout = gameids[i][j + 1 :]
break
games[gamein.strip()] = gameout.strip()
if text in games:
text = games[text]
for line in gameids:
if "" in line:
gamein, gameout = line.split("", 1)
games[gamein.strip()] = gameout.strip()
text = games.get(text, text)
if item.column() == 9:
text = text.replace("\\", "/")
if item.column() == 10:
text = self.encryptx(text)
if text != "":
@@ -939,6 +1074,17 @@ class Main(QWidget):
self.config["Default"]["TimeLimit.routine"] = self.routine.value()
self.config["Default"]["TimeLimit.annihilation"] = self.annihilation.value()
self.config["Default"]["TimesLimit.run"] = self.num.value()
if self.IfSleep.isChecked():
self.config["Default"]["SelfSet.IfSleep"] = "True"
else:
self.config["Default"]["SelfSet.IfSleep"] = "False"
if self.IfSelfStart.isChecked():
self.config["Default"]["SelfSet.IfSelfStart"] = "True"
else:
self.config["Default"]["SelfSet.IfSelfStart"] = "False"
for i in range(10):
if self.StartTime[i][0].isChecked():
self.config["Default"]["TimeSet.set" + str(i + 1)] = "True"
@@ -977,7 +1123,7 @@ class Main(QWidget):
return 0
def closeEvent(self, event):
self.MaaTimer.quit()
self.MainTimer.quit()
self.MaaRunner.ifRun = False
self.MaaRunner.wait()
self.cur.close()
@@ -988,13 +1134,16 @@ class Main(QWidget):
def end(self):
self.MaaRunner.ifRun = False
self.MaaRunner.wait()
self.MaaTimer.isMaaRun = False
self.MainTimer.isMaaRun = False
self.runnow.clicked.disconnect()
self.runnow.setText("立即执行")
self.runnow.clicked.connect(self.RunStarter)
# 启动MaaRunner线程
def RunStarter(self):
if self.config["Default"]["MaaSet.path"] == "":
QMessageBox.critical(self.ui, "错误", "MAA路径未设置")
return None
# 运行过程中修改部分组件
self.runnow.clicked.disconnect()
self.runnow.setText("结束运行")
@@ -1014,11 +1163,12 @@ class Main(QWidget):
self.data_ = self.cur.fetchall()
self.MaaRunner.data = [list(row) for row in self.data_]
# 启动执行线程
self.MaaTimer.isMaaRun = True
self.MainTimer.isMaaRun = True
self.MaaRunner.start()
# 同步配置文件到子线程
def GiveConfig(self):
self.MaaTimer.config = self.config
self.MainTimer.config = self.config
class AUTO_MAA(QApplication):

206
README.md
View File

@@ -18,21 +18,25 @@ MAA多账号管理与自动化软件
- **授权:** 如果希望在使用AUTO_MAA的相关成果后仍保持自己的项目闭源请在Issues中说明来意。得到项目组认可后我们可以提供另一份使用不同协议的代码此协议主要内容如下被授权者可以自由使用该代码并维持闭源被授权者必须定期为AUTO_MAA作出贡献
- **贡献:** 不论是直接参与软件的维护编写或是撰写文档、测试、反馈BUG、给出建议、参与讨论都为AUTO_MAA项目的发展完善做出了不可忽视的贡献。项目组提倡各位贡献者遵照GitHub开源社区惯例发布Issues参与项目。避免私信或私发邮件安全性漏洞或敏感问题除外以帮助更多用户
以上细则是本项目对GPL的相关补充与强调。未提及的以GPL为准发生冲突的以GPL为准。如有不清楚的部分请发Issues询问。若发生纠纷相关内容也没有在Issues上提及的项目组拥有最终解释权
以上细则是本项目对GPL的相关补充与强调。未提及的以GPL为准发生冲突的以本细则为准。如有不清楚的部分请发Issues询问。若发生纠纷相关内容也没有在Issues上提及的项目组拥有最终解释权
**注意**
- 由于本软件有修改其它目录JSON文件等行为使用前请将AUTO_MAA添加入Windows Defender信任区以及防病毒软件的信任区或开发者目录避免被误杀
- 如程序无法正常启动,请删除`state`目录下所有文件后重试
---
# 使用方法
## 安装与配置MAA
```
本软件是MAA的外部工具需要安装配置MAA后才能使用。
```
### MAA安装
什么是MAA [官网](https://maa.plus/)/[GitHub](https://github.com/CHNZYX/Auto_Simulated_Universe/archive/refs/heads/main.zip)
- 什么是MAA [官网](https://maa.plus/)/[GitHub](https://github.com/CHNZYX/Auto_Simulated_Universe/archive/refs/heads/main.zip)
MAA下载地址 [GitHub下载](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases)
- MAA下载地址 [GitHub下载](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases)
### MAA配置
@@ -50,197 +54,57 @@ MAA下载地址 [GitHub下载](https://github.com/MaaAssistantArknights/MaaAs
![MAA配置3](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/MAA配置3.png "MAA配置3")
## 下载AUTO_MAA软件包 [![](https://img.shields.io/github/downloads/DLmaster361/AUTO_MAA/total?color=66ccff)](https://github.com/DLmaster361/AUTO_MAA/releases)
## 下载AUTO_MAA [![](https://img.shields.io/github/downloads/DLmaster361/AUTO_MAA/total?color=66ccff)](https://github.com/DLmaster361/AUTO_MAA/releases)
GitHub下载地址 [GitHub下载](https://github.com/DLmaster361/AUTO_MAA/releases)
- GitHub下载地址 [GitHub下载](https://github.com/DLmaster361/AUTO_MAA/releases)
## 配置用户信息与相关参数
## 配置AUTO_MAA
**注意:** 当前所有的密码输入部分都存在一点“小问题”请在输入密码时避免输入Delete、F12、Tab等功能键。
-------------------------------------------------
### 启动AUTO_MAA
### 第一次启动
双击启动`manage.exe`输入MAA所在文件夹路径并回车注意使用斜杠的种类不要使用反斜杠然后设置管理密钥密钥可以包含字母大小写与特殊字符
![信息配置1](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置1.png "信息配置1")
管理密钥是解密用户密码的唯一凭证,与数据库绑定。密钥丢失或`data/key/`目录下任一文件损坏都将导致解密无法正常进行。
本项目采用自主开发的混合加密模式,项目组也无法找回您的管理密钥或修复`data/key/`目录下的文件。如果不幸的事发生,建议您删除`data/data.db`重新录入信息。
### 添加用户
输入“+”以开始添加用户。依次输入:
**用户名:** 管理用户的惟一凭证
**手机号码:** 允许隐去中间四位以“****”代替
**代理天数:** 这个还要我解释吗?
![信息配置2](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置2.png "信息配置2")
### 删除用户
输入用户名+“-”以删除用户。格式:
- 双击`AUTO_MAA.exe`以启动软件
```
用户名 -
注意:
首次启动时会要求设置管理密钥。
管理密钥是解密用户密码的唯一凭证,与数据库绑定。
密钥丢失或data/key/目录下任一文件损坏都将导致解密无法正常进行。
本项目采用自主开发的混合加密模式项目组也无法找回您的管理密钥或修复data/key/目录下的文件。
如果不幸的事发生建议您删除data/key/目录与data/data.db文件后重新录入信息。
```
![信息配置3](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置3.png "信息配置3")
### 配置信息
### 配置用户状态
**启用代理:** 输入用户名+“y”以启用该用户的代理。格式
- 本项目已初步完成GUI开发您可以在用户管理页与设置页配置信息。
```
用户名 y
特别的:
你可以自定义关卡号替换方案。
程序会读取data/gameid.txt中的数据依据此进行关卡号的替换便于常用关卡的使用。
gameid.txt在初始已经存储了一些常用资源本的替代方案。
```
![信息配置4](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置4.png "信息配置4")
**禁用代理:** 输入用户名+“n”以禁用该用户的代理。格式
```
用户名 n
```
![信息配置5](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置5.png "信息配置5")
### 续期
输入用户名+续期天数+“+”以延长该用户的代理天数。格式:
```
用户名 续期天数 +
```
![信息配置6](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置6.png "信息配置6")
### 修改刷取关卡
输入用户名+关卡号+“~”以更改该用户的代理关卡。格式:
```
用户名 关卡号 ~
```
![信息配置7](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置7.png "信息配置7")
**特别的:**
你可以自定义关卡号替换方案。程序会读取`gameid.txt`中的数据,依据此进行关卡号的替换,便于常用关卡的使用。`gameid.txt`在初始已经存储了一些常用资源本的替代方案。
![gameid](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/gameid.png "gameid")
### 设置MAA路径
输入“/”+新的MAA文件夹路径以修改MAA安装位置的配置。格式
```
/新的MAA文件夹路径
```
**注意:** /’与路径间没有空格,路径同样不能使用反斜杠
![信息配置8](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置8.png "信息配置8")
### 设置启动时间
**添加启动时间:** 输入“:+”+时间以添加定时启动时间。格式:
```
:+小时:分钟
```
**注意:** 所有输入间没有空格
![信息配置9](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置9.png "信息配置9")
**删除启动时间:** 输入“:-”+时间以删除定时启动时间。格式:
```
:-小时:分钟
```
**注意:** 所有输入间没有空格
![信息配置10](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置10.png "信息配置10")
### 检索信息
**检索所有信息:** `manage.exe`打开时会打印所有用户与配置信息。除此之外你可以通过输入“all ?”以打印所有信息,如下:
```
all ?
```
![信息配置11](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置11.png "信息配置11")
**检索MAA路径** 输入“maa ?”以检索MAA安装路径如下
```
maa ?
```
![信息配置12](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置12.png "信息配置12")
**检索启动时间:** 输入“time ?”以检索定时启动的时间,如下:
```
time ?
```
![信息配置13](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置13.png "信息配置13")
**检索指定用户:** 输入用户名+“?”以检索指定用户信息,如下:
```
用户名 ?
```
**注意:** 由于需要检索用户密码,每一次`manage.exe`启动后的首次查询需要验证管理密钥。为了方便操作,之后的查询不会再要求重复验证。因此,完成密码查询后,请及时关闭`manage.exe`
![信息配置14](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置14.png "信息配置14")
### 修改管理密钥
输入“*”以开始修改管理密钥。依次输入:
**旧管理密钥:** 当数据库中没有存储用户信息时,允许跳过验证直接配置新管理密钥
**新管理密钥:** 请妥善保管,丢失无法找回。
![信息配置15](https://github.com/DLmaster361/AUTO_MAA/blob/main/res/README/信息配置15.png "信息配置15")
### 退出
输入“-”以退出`manage.exe`,如下:
```
-
```
## 运行代理
## 运行代理任务
### 直接运行
双击`run.exe`直接运行
- 在执行页单击`立即执行`直接运行
### 定时运行
双击`AUTO_MAA.exe`打开,不要关闭。它会读取设定时间,在该时刻自动运行
- 在执行页的`定时执行`栏设置时间
**注意:** 将优先进行剿灭代理
- 保持软件打开,软件会在设定的时间自动运行
## 关于
项目图标由文心一格AI生成
----------------------------------------------------------------------------------------------
---
# 关于
欢迎加入AUTO_MAA项目组欢迎反馈bug

View File

@@ -745,7 +745,7 @@
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>时间限制</string>
<string>执行限制</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
@@ -898,6 +898,79 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>AUTO_MAA设置</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_20">
<item>
<widget class="QFrame" name="frame_routine_3">
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_19">
<item>
<widget class="QCheckBox" name="checkBox_ifselfstart">
<property name="text">
<string>开机自动启动AUTO_MAA</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame_routine_2">
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_18">
<item>
<widget class="QCheckBox" name="checkBox_ifsleep">
<property name="text">
<string>AUTO_MAA启动时禁止电脑休眠</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
@@ -932,9 +1005,9 @@ li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;致用户:&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; 这是AUTO_MAA_v3.0_Beta,项目初步完成可视化。&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; 这是AUTO_MAA_v3.1.1,项目基本完成可视化。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; 这个版本可能出现各种各样的BUG因此不会去除命令行窗口。当程序出现异常时,您可以在命令行窗口中获取报错信息,以便向项目组求助。&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; 正式版去除命令行窗口但这不意味着BUG不会出现。由于用户与项目贡献者的稀缺我们无法确保正式版足够完善还望谅解。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; 您可以通过官方仓库 &lt;a href=&quot;https://github.com/DLmaster361/AUTO_MAA/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007ad6;&quot;&gt;DLmaster361/AUTO_MAA&lt;/span&gt;&lt;/a&gt; 发布Issues求助。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -4,7 +4,7 @@ VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
filevers=(3, 0, 0, 0),
filevers=(3, 1, 2, 0),
prodvers=(0, 0, 0, 0),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
@@ -31,13 +31,13 @@ VSVersionInfo(
[StringStruct('Comments', 'https://github.com/DLmaster361/AUTO_MAA/'),
StringStruct('CompanyName', 'AUTO_MAA Team'),
StringStruct('FileDescription', 'AUTO_MAA Component'),
StringStruct('FileVersion', '3.0'),
StringStruct('FileVersion', '3.1.2'),
StringStruct('InternalName', 'AUTO_MAA'),
StringStruct('LegalCopyright', 'Copyright © 2024 DLmaster361'),
StringStruct('OriginalFilename', 'AUTO_MAA'),
StringStruct('OriginalFilename', 'AUTO_MAA.py'),
StringStruct('ProductName', 'AUTO_MAA'),
StringStruct('ProductVersion', 'v3.0_Beta'),
StringStruct('Assembly Version', 'v3.0_Beta')])
StringStruct('ProductVersion', 'v3.1.2'),
StringStruct('Assembly Version', 'v3.1.2')])
])
]
)

View File

@@ -1,5 +1,6 @@
#主界面
"MainFunction.ActionAfterCompleted": "ExitEmulatorAndSelf" #完成后
"MainFunction.ActionAfterCompleted": "ExitEmulatorAndSelf" #完成后(旧)
"MainFunction.PostActions": "12" #完成后(新)
"TaskQueue.WakeUp.IsChecked": "True" #开始唤醒
"TaskQueue.Recruiting.IsChecked": "True" #自动公招
"TaskQueue.Base.IsChecked": "True" #基建换班
@@ -21,6 +22,11 @@
"Infrast.CustomInfrastPlanShowInFightSettings": "False" #显示基建计划
"Penguin.EnablePenguin": "True" #上报企鹅物流
"Yituliu.EnableYituliu": "True" #上报一图流
#基建换班
"Infrast.CustomInfrastEnabled": "True" #启用自定义基建配置
"Infrast.DefaultInfrast": "user_defined" #内置配置
"Infrast.IsCustomInfrastFileReadOnly": "False" #自定义基建配置文件只读
"Infrast.CustomInfrastFile": "" #自定义基建配置文件地址
#设置
"Start.RunDirectly": "True" #启动MAA后直接运行
"Start.StartEmulator": "True" #启动MAA后自动开启模拟器

View File

@@ -20,4 +20,6 @@
import os
os.system("pyinstaller -F --version-file res/info.txt --icon=res/AUTO_MAA.ico gui.py")
os.system(
"pyinstaller -F --version-file res/info.txt -w --icon=res/AUTO_MAA.ico AUTO_MAA.py"
)

View File

@@ -1,3 +1,5 @@
项目初始阶段,不会提供专门的版本更新程序,您需要手动更新程序。
v3.0_Beta版本采用全新的架构,您需要手动输入之前的信息。
v2.1.5及以前的用户,由于新版本采用全新的架构,您需要手动输入之前的信息。
v3.0_Beta版用户直接用AUTO_MAA.exe替代gui.exe后将原文件夹下的gui文件夹用新版本对应文件替换重新设置每个用户的“自定义基建”选项输入“-”以关闭该功能,输入自定义基建配置文件地址以开启该功能)。
v3.1~v3.1.1版用户将原文件夹下的AUTO_MAA.exe文件和gui文件夹用新版本对应文件替换即可。
新用户请忽略本说明。