Compare commits

...

15 Commits

Author SHA1 Message Date
DLmaster
73c3ec4820 修复深色模式下UI异常 2024-12-04 14:27:58 +08:00
DLmaster
fde5160d56 补充重要声明 2024-12-01 10:46:10 +08:00
DLmaster
13923705e5 修复窗口管理方面的部分问题 2024-12-01 00:16:49 +08:00
DLmaster
d3afc95261 启动时不显示托盘 2024-11-29 18:58:50 +08:00
DLmaster
326d7e474c 修复新用户无法设置MAA路径 2024-11-29 18:02:16 +08:00
DLmaster
537b5d9725 移除最小化启动模拟器选项 2024-11-29 11:01:55 +08:00
DLmaster
697c1b5b43 优化记忆窗口与最小化到托盘的体验 2024-11-28 20:43:12 +08:00
DLmaster
2b6057161e 更新时彻底关闭主程序 2024-11-27 21:17:05 +08:00
DLmaster
8e2a6444bd 修复设定时刻无法中止任务的问题 2024-11-27 20:36:51 +08:00
DLmaster
b04df40b7d 图标优化;添加最小化到托盘功能;更新器摆脱UI文件限制 2024-11-27 00:04:37 +08:00
DLmaster
3e17d94904 合并MAA启动器配置流程 2024-11-21 19:52:15 +08:00
DLmaster
29123054cc 3^3 2024-11-19 20:31:52 +08:00
DLmaster
530c038985 3^3 2024-11-19 20:25:53 +08:00
DLmaster
2e9d2f0491 添加软件介绍 2024-11-19 20:20:46 +08:00
DLmaster
69ab9b4f15 邮件通知功能上线 2024-11-16 10:42:56 +08:00
12 changed files with 433 additions and 212 deletions

View File

@@ -83,12 +83,10 @@ jobs:
- name: Create Zip
id: create_zip
run: |
move gui\ui\updater.ui .\
move gui\ico\AUTO_MAA_Updater.ico .\
Compress-Archive -Path gui,res,AUTO_MAA.py,Updater.py,package.py,dist/AUTO_MAA.exe,requirements.txt,README.md,LICENSE -DestinationPath AUTO_MAA_${{ env.AUTO_MAA_version }}.zip
del gui\ui\main.ui
del gui\ico\AUTO_MAA.ico
move updater.ui gui\ui
move AUTO_MAA_Updater.ico gui\ico
Compress-Archive -Path gui,dist/Updater.exe -DestinationPath Updater_${{ env.updater_version }}.zip
- name: Upload Artifact

View File

@@ -29,10 +29,13 @@ from PySide6.QtWidgets import (
QWidget,
QMainWindow,
QApplication,
QSystemTrayIcon,
QMenu,
QInputDialog,
QFileDialog,
QMessageBox,
QLineEdit,
QTabWidget,
QToolBox,
QTableWidget,
QTableWidgetItem,
@@ -45,7 +48,7 @@ from PySide6.QtWidgets import (
QTextBrowser,
)
from PySide6.QtUiTools import QUiLoader
from PySide6.QtGui import QIcon
from PySide6.QtGui import QIcon, QCloseEvent
from PySide6 import QtCore
from functools import partial
from plyer import notification
@@ -63,6 +66,10 @@ import random
import secrets
import winreg
import requests
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
@@ -77,6 +84,7 @@ class MaaRunner(QtCore.QThread):
question = QtCore.Signal()
push_notification = QtCore.Signal(str, str, str, int)
send_mail = QtCore.Signal(str, str)
update_gui = QtCore.Signal(str, str, str, str, str)
update_user_info = QtCore.Signal(list, list, list, list, list, list)
accomplish = QtCore.Signal()
@@ -85,27 +93,34 @@ class MaaRunner(QtCore.QThread):
"\\", "/"
) # 获取软件自身的路径
def __init__(
self, set_path, log_path, maa_path, routine, annihilation, num, data, mode
):
def __init__(self):
super(MaaRunner, self).__init__()
self.set_path = set_path
self.log_path = log_path
self.maa_path = maa_path
self.json_path = f"{self.app_path}/data/MAAconfig"
self.routine = routine
self.annihilation = annihilation
self.num = num
self.data = data
self.mode = mode
self.config = None
self.data = None
self.mode = None
self.get_json_path = [0, 0, 0]
def configure(self):
"""提取配置信息"""
self.set_path = f"{self.config["Default"]["MaaSet.path"]}/config/gui.json"
self.log_path = f"{self.config["Default"]["MaaSet.path"]}/debug/gui.log"
self.maa_path = f"{self.config["Default"]["MaaSet.path"]}/MAA.exe"
self.json_path = f"{self.app_path}/data/MAAconfig"
self.routine = self.config["Default"]["TimeLimit.routine"]
self.annihilation = self.config["Default"]["TimeLimit.annihilation"]
self.num = self.config["Default"]["TimesLimit.run"]
self.if_send_mail = bool(self.config["Default"]["SelfSet.IfSendMail"] == "True")
def run(self):
"""主进程运行MAA代理进程"""
curdate = server_date()
begin_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.configure()
# 整理用户数据,筛选需代理的用户
self.data = sorted(self.data, key=lambda x: (-len(x[15]), x[16]))
wait_index = []
@@ -160,7 +175,11 @@ class MaaRunner(QtCore.QThread):
# 记录当前时间
start_time = datetime.datetime.now()
# 创建MAA任务
maa = subprocess.Popen([self.maa_path])
maa = subprocess.Popen(
[self.maa_path],
shell=True,
creationflags=subprocess.CREATE_NO_WINDOW,
)
# 记录是否超时的标记
self.if_time_out = False
# 更新运行信息
@@ -315,7 +334,11 @@ class MaaRunner(QtCore.QThread):
# 记录当前时间
start_time = datetime.datetime.now()
# 创建MAA任务
maa = subprocess.Popen([self.maa_path])
maa = subprocess.Popen(
[self.maa_path],
shell=True,
creationflags=subprocess.CREATE_NO_WINDOW,
)
# 更新运行信息
wait_index = [
_
@@ -427,7 +450,11 @@ class MaaRunner(QtCore.QThread):
# 配置MAA
self.set_maa(self.mode, "")
# 创建MAA任务
maa = subprocess.Popen([self.maa_path])
maa = subprocess.Popen(
[self.maa_path],
shell=True,
creationflags=subprocess.CREATE_NO_WINDOW,
)
# 记录当前时间
start_time = datetime.datetime.now()
@@ -506,6 +533,11 @@ class MaaRunner(QtCore.QThread):
f"已完成用户数:{len(over_index)},未完成用户数:{len(error_index) + len(wait_index)}",
10,
)
if self.if_send_mail:
self.send_mail.emit(
f"{self.mode[:4]}任务报告",
f"{end_log}\n\nAUTO_MAA 敬上\n\n我们根据您在 AUTO_MAA 中的设置发送了这封电子邮件,本邮件无需回复\n",
)
self.accomplish.emit()
@@ -635,9 +667,6 @@ class MaaRunner(QtCore.QThread):
data["Configurations"]["Default"][
"Start.OpenEmulatorAfterLaunch"
] = "False"
data["Configurations"]["Default"][
"Start.MinimizingStartup"
] = "False" # 最小化启动模拟器
if self.data[index][15] == "simple":
@@ -992,6 +1021,7 @@ class MainTimer(QtCore.QThread):
def __init__(self, config):
super(MainTimer, self).__init__()
self.config = config
self.last_time = "0000-00-00 00:00"
def run(self):
"""主功能代码,实现定时执行以及相关配置信息的实时同步"""
@@ -1011,8 +1041,13 @@ class MainTimer(QtCore.QThread):
if self.config["Default"][f"TimeSet.set{_ + 1}"] == "True"
]
# 按时间调起代理任务
curtime = datetime.datetime.now().strftime("%H:%M")
if (curtime in time_set) and not self.is_maa_run:
curtime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
if (
curtime[11:16] in time_set
and curtime != self.last_time
and not self.is_maa_run
):
self.last_time = curtime
self.start_for_timer.emit()
# 同步时间间隔
@@ -1167,6 +1202,9 @@ class Main(QWidget):
self.cur = self.db.cursor()
# 初始化控件
self.main_tab = self.ui.findChild(QTabWidget, "tabWidget_main")
self.main_tab.currentChanged.connect(self.change_config)
self.user_set = self.ui.findChild(QToolBox, "toolBox_userset")
self.user_set.currentChanged.connect(self.change_userlist_method)
@@ -1176,7 +1214,6 @@ class Main(QWidget):
self.user_list_simple.itemChanged.connect(
lambda item: self.change_user_Item(item, "simple")
)
self.user_list_simple.setStyleSheet("background-color: rgb(255, 255, 255);")
self.user_list_beta = self.ui.findChild(
QTableWidget, "tableWidget_userlist_beta"
@@ -1184,7 +1221,6 @@ class Main(QWidget):
self.user_list_beta.itemChanged.connect(
lambda item: self.change_user_Item(item, "beta")
)
self.user_list_beta.setStyleSheet("background-color: rgb(255, 255, 255);")
self.user_add = self.ui.findChild(QPushButton, "pushButton_new")
self.user_add.clicked.connect(self.add_user)
@@ -1205,10 +1241,10 @@ class Main(QWidget):
self.refresh.clicked.connect(lambda: self.update_user_info("clear"))
self.run_now = self.ui.findChild(QPushButton, "pushButton_runnow")
self.run_now.clicked.connect(self.routine_starter)
self.run_now.clicked.connect(lambda: self.maa_starter("日常代理"))
self.check_start = self.ui.findChild(QPushButton, "pushButton_checkstart")
self.check_start.clicked.connect(self.check_starter)
self.check_start.clicked.connect(lambda: self.maa_starter("人工排查"))
self.maa_path = self.ui.findChild(QLineEdit, "lineEdit_MAApath")
self.maa_path.textChanged.connect(self.change_config)
@@ -1218,7 +1254,7 @@ class Main(QWidget):
self.get_maa_path.clicked.connect(lambda: self.read("file_path_maa"))
self.set_maa = self.ui.findChild(QPushButton, "pushButton_setMAA")
self.set_maa.clicked.connect(lambda: self.maa_set_starter("设置MAA_全局"))
self.set_maa.clicked.connect(lambda: self.maa_starter("设置MAA_全局"))
self.routine = self.ui.findChild(QSpinBox, "spinBox_routine")
self.routine.valueChanged.connect(self.change_config)
@@ -1240,6 +1276,15 @@ class Main(QWidget):
)
self.if_proxy_directly.stateChanged.connect(self.change_config)
self.if_send_mail = self.ui.findChild(QCheckBox, "checkBox_ifsendmail")
self.if_send_mail.stateChanged.connect(self.change_config)
self.mail_address = self.ui.findChild(QLineEdit, "lineEdit_mailaddress")
self.mail_address.textChanged.connect(self.change_config)
self.if_to_tray = self.ui.findChild(QCheckBox, "checkBox_iftotray")
self.if_to_tray.stateChanged.connect(self.change_config)
self.check_update = self.ui.findChild(QPushButton, "pushButton_check_update")
self.check_update.clicked.connect(self.check_version)
@@ -1267,36 +1312,18 @@ class Main(QWidget):
self.change_password.clicked.connect(self.change_PASSWORD)
# 初始化线程
self.set_path_ = f"{self.config["Default"]["MaaSet.path"]}/config/gui.json"
self.log_path_ = f"{self.config["Default"]["MaaSet.path"]}/debug/gui.log"
self.maa_path_ = f"{self.config["Default"]["MaaSet.path"]}/MAA.exe"
self.routine_ = self.config["Default"]["TimeLimit.routine"]
self.annihilation_ = self.config["Default"]["TimeLimit.annihilation"]
self.num_ = self.config["Default"]["TimesLimit.run"]
self.cur.execute("SELECT * FROM adminx WHERE True")
self.data_ = self.cur.fetchall()
self.data_ = [list(row) for row in self.data_]
self.MaaRunner = MaaRunner(
self.set_path_,
self.log_path_,
self.maa_path_,
self.routine_,
self.annihilation_,
self.num_,
self.data_,
"未知",
)
self.MaaRunner = MaaRunner()
self.MaaRunner.question.connect(lambda: self.read("question_runner"))
self.MaaRunner.update_gui.connect(self.update_board)
self.MaaRunner.update_user_info.connect(self.change_user_info)
self.MaaRunner.push_notification.connect(self.push_notification)
self.MaaRunner.send_mail.connect(self.send_mail)
self.MaaRunner.accomplish.connect(lambda: self.maa_ender("日常代理_结束"))
self.MaaRunner.get_json.connect(self.get_maa_config)
self.MainTimer = MainTimer(self.config)
self.MainTimer.get_config.connect(self.give_config)
self.MainTimer.start_for_timer.connect(self.routine_starter)
self.MainTimer.start_for_timer.connect(lambda: self.maa_starter("日常代理"))
self.MainTimer.start()
# 载入GUI数据
@@ -1306,7 +1333,7 @@ class Main(QWidget):
# 启动后直接开始代理
if self.config["Default"]["SelfSet.IfProxyDirectly"] == "True":
self.routine_starter()
self.maa_starter("日常代理")
def initialize(self):
"""初始化程序的配置文件"""
@@ -1392,8 +1419,13 @@ class Main(QWidget):
["SelfSet.IfSelfStart", "False"],
["SelfSet.IfSleep", "False"],
["SelfSet.IfProxyDirectly", "False"],
["SelfSet.IfSendMail", "False"],
["SelfSet.MailAddress", ""],
["SelfSet.IfToTray", "False"],
["SelfSet.UIsize", "1200x700"],
["SelfSet.UIlocation", "100x100"],
["SelfSet.UImaximized", "False"],
["SelfSet.MainIndex", 2],
]
# 导入配置文件
@@ -1832,10 +1864,13 @@ class Main(QWidget):
# 阻止GUI程序配置被立即读入程序形成死循环
self.if_update_config = False
self.main_tab.setCurrentIndex(self.config["Default"]["SelfSet.MainIndex"])
self.maa_path.setText(self.config["Default"]["MaaSet.path"].replace("\\", "/"))
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.mail_address.setText(self.config["Default"]["SelfSet.MailAddress"])
self.if_self_start.setChecked(
bool(self.config["Default"]["SelfSet.IfSelfStart"] == "True")
@@ -1849,6 +1884,18 @@ class Main(QWidget):
bool(self.config["Default"]["SelfSet.IfProxyDirectly"] == "True")
)
self.if_send_mail.setChecked(
bool(self.config["Default"]["SelfSet.IfSendMail"] == "True")
)
self.mail_address.setVisible(
bool(self.config["Default"]["SelfSet.IfSendMail"] == "True")
)
self.if_to_tray.setChecked(
bool(self.config["Default"]["SelfSet.IfToTray"] == "True")
)
for i in range(10):
self.start_time[i][0].setChecked(
bool(self.config["Default"][f"TimeSet.set{i + 1}"] == "True")
@@ -2070,7 +2117,7 @@ class Main(QWidget):
self.user_list_beta.currentRow(),
self.user_list_beta.currentColumn() - 4,
]
self.maa_set_starter("设置MAA_用户")
self.maa_starter("设置MAA_用户")
else:
QMessageBox.critical(self.ui, "错误", "该项目无法进一步配置")
@@ -2267,9 +2314,12 @@ class Main(QWidget):
)
return None
self.config["Default"]["SelfSet.MainIndex"] = self.main_tab.currentIndex()
self.config["Default"]["TimeLimit.routine"] = self.routine.value()
self.config["Default"]["TimeLimit.annihilation"] = self.annihilation.value()
self.config["Default"]["TimesLimit.run"] = self.num.value()
self.config["Default"]["SelfSet.MailAddress"] = self.mail_address.text()
if self.if_sleep.isChecked():
self.config["Default"]["SelfSet.IfSleep"] = "True"
@@ -2286,6 +2336,16 @@ class Main(QWidget):
else:
self.config["Default"]["SelfSet.IfProxyDirectly"] = "False"
if self.if_send_mail.isChecked():
self.config["Default"]["SelfSet.IfSendMail"] = "True"
else:
self.config["Default"]["SelfSet.IfSendMail"] = "False"
if self.if_to_tray.isChecked():
self.config["Default"]["SelfSet.IfToTray"] = "True"
else:
self.config["Default"]["SelfSet.IfToTray"] = "False"
for i in range(10):
if self.start_time[i][0].isChecked():
self.config["Default"][f"TimeSet.set{i + 1}"] = "True"
@@ -2373,81 +2433,21 @@ class Main(QWidget):
else:
return False
def routine_starter(self):
"""启动MaaRunner线程运行日常代理任务"""
def maa_starter(self, mode):
"""启动MaaRunner线程运行任务"""
# 检查MAA路径是否可用
if not self.check_maa_path():
QMessageBox.critical(self.ui, "错误", "您还未正确配置MAA路径")
return None
self.maa_running_set("日常代理_开始")
self.maa_running_set(f"{mode}_开始")
# 配置参数
self.MaaRunner.set_path = (
f"{self.config["Default"]["MaaSet.path"]}/config/gui.json"
)
self.MaaRunner.log_path = (
f"{self.config["Default"]["MaaSet.path"]}/debug/gui.log"
)
self.MaaRunner.maa_path = f"{self.config["Default"]["MaaSet.path"]}/MAA.exe"
self.MaaRunner.routine = self.config["Default"]["TimeLimit.routine"]
self.MaaRunner.annihilation = self.config["Default"]["TimeLimit.annihilation"]
self.MaaRunner.num = self.config["Default"]["TimesLimit.run"]
self.MaaRunner.config = self.config
self.cur.execute("SELECT * FROM adminx WHERE True")
self.data_ = self.cur.fetchall()
self.MaaRunner.data = [list(row) for row in self.data_]
self.MaaRunner.mode = "日常代理"
# 启动执行线程
self.MainTimer.is_maa_run = True
self.MaaRunner.start()
def check_starter(self):
"""启动MaaRunner线程运行人工排查任务"""
# 检查MAA路径是否可用
if not self.check_maa_path():
QMessageBox.critical(self.ui, "错误", "您还未正确配置MAA路径")
return None
self.maa_running_set("人工排查_开始")
# 配置参数
self.MaaRunner.set_path = (
f"{self.config["Default"]["MaaSet.path"]}/config/gui.json"
)
self.MaaRunner.log_path = (
f"{self.config["Default"]["MaaSet.path"]}/debug/gui.log"
)
self.MaaRunner.maa_path = f"{self.config["Default"]["MaaSet.path"]}/MAA.exe"
self.cur.execute("SELECT * FROM adminx WHERE True")
self.data_ = self.cur.fetchall()
self.MaaRunner.data = [list(row) for row in self.data_]
self.MaaRunner.mode = "人工排查"
# 启动执行线程
self.MainTimer.is_maa_run = True
self.MaaRunner.start()
def maa_set_starter(self, mode):
"""启动MaaRunner线程进行MAA设置"""
# 检查MAA路径是否可用
if not self.check_maa_path():
QMessageBox.critical(self.ui, "错误", "您还未正确配置MAA路径")
return None
self.maa_running_set("设置MAA_开始")
# 配置参数
self.MaaRunner.set_path = (
f"{self.config["Default"]["MaaSet.path"]}/config/gui.json"
)
self.MaaRunner.log_path = (
f"{self.config["Default"]["MaaSet.path"]}/debug/gui.log"
)
self.MaaRunner.maa_path = f"{self.config["Default"]["MaaSet.path"]}/MAA.exe"
self.MaaRunner.mode = mode
# 启动执行线程
@@ -2457,7 +2457,6 @@ class Main(QWidget):
def maa_ender(self, mode):
"""中止MAA线程"""
self.MainTimer.quit()
self.MaaRunner.requestInterruption()
self.MaaRunner.wait()
@@ -2498,7 +2497,7 @@ class Main(QWidget):
lambda: self.maa_ender("人工排查_结束")
)
elif mode == "设置MAA_开始":
elif mode == "设置MAA_全局_开始" or mode == "设置MAA_用户_开始":
self.MaaRunner.accomplish.connect(
lambda: self.maa_ender("设置MAA_结束")
)
@@ -2518,22 +2517,24 @@ class Main(QWidget):
self.set_maa.setEnabled(True)
# self.update_user_info("editable")
if mode == "设置MAA_结束":
self.run_now.setEnabled(True)
if mode == "日常代理_结束":
self.check_start.setEnabled(True)
self.run_now.clicked.disconnect()
self.run_now.setText("立即执行")
self.run_now.clicked.connect(lambda: self.maa_starter("日常代理"))
elif mode == "人工排查_结束":
self.run_now.setEnabled(True)
self.check_start.clicked.disconnect()
self.check_start.setText("开始排查")
self.check_start.clicked.connect(self.check_starter)
self.check_start.clicked.connect(lambda: self.maa_starter("人工排查"))
elif mode == "日常代理_结束":
elif mode == "设置MAA_结束":
self.run_now.setEnabled(True)
self.check_start.setEnabled(True)
self.run_now.clicked.disconnect()
self.run_now.setText("立即执行")
self.run_now.clicked.connect(self.routine_starter)
def check_version(self):
"""检查版本更新,调起文件下载进程"""
@@ -2613,7 +2614,8 @@ class Main(QWidget):
shell=True,
creationflags=subprocess.CREATE_NO_WINDOW,
)
sys.exit()
self.close()
app.quit()
def version_text(self, version_numb):
"""将版本号列表转为可读的文本信息"""
@@ -2637,6 +2639,40 @@ class Main(QWidget):
toast=True,
)
def send_mail(self, title, content):
"""使用官方专用邮箱推送邮件通知"""
# 第三方 SMTP 服务配置
mail_host = "smtp.163.com" # 设置服务器
mail_sender = "AUTO_MAA_server@163.com" # 用户名
mail_key = "SYrq87nDLD4RNB5T" # 授权码 24/11/15
# 定义邮件正文
message = MIMEText(content, "plain", "utf-8")
message["From"] = formataddr(
(Header("AUTO_MAA通知服务", "utf-8").encode(), "AUTO_MAA_server@163.com")
) # 发件人显示的名字
message["To"] = formataddr(
(
Header("AUTO_MAA用户", "utf-8").encode(),
self.config["Default"]["SelfSet.MailAddress"],
)
) # 收件人显示的名字
message["Subject"] = Header(title, "utf-8")
try:
smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 465为SMTP_SSL默认端口
smtpObj.login(mail_sender, mail_key)
smtpObj.sendmail(
mail_sender,
self.config["Default"]["SelfSet.MailAddress"],
message.as_string(),
)
except smtplib.SMTPException as e:
QMessageBox.critical(self.ui, "错误", f"发送邮件时出错:\n{e}")
finally:
smtpObj.quit()
def give_config(self):
"""同步配置文件到子线程"""
@@ -2644,42 +2680,148 @@ class Main(QWidget):
class AUTO_MAA(QMainWindow):
def __init__(self):
super().__init__()
if_save = True
def __init__(self):
super(AUTO_MAA, self).__init__()
# 创建主窗口
self.main = Main()
self.setCentralWidget(self.main.ui)
self.setWindowIcon(QIcon(f"{self.main.app_path}/gui/ico/AUTO_MAA.ico"))
self.setWindowTitle("AUTO_MAA")
# 设置窗口初始大小与位置
size = list(map(int, self.main.config["Default"]["SelfSet.UIsize"].split("x")))
location = list(
map(int, self.main.config["Default"]["SelfSet.UIlocation"].split("x"))
# 创建系统托盘及其菜单
self.tray = QSystemTrayIcon(
QIcon(f"{self.main.app_path}/gui/ico/AUTO_MAA.ico"), self
)
self.setGeometry(location[0], location[1], size[0], size[1])
self.tray_menu = QMenu()
def closeEvent(self, event):
# 显示主界面菜单项
show_main = self.tray_menu.addAction("显示主界面")
show_main.triggered.connect(self.show_main)
# 开始任务菜单项
start_task_1 = self.tray_menu.addAction("运行日常代理")
start_task_1.triggered.connect(lambda: self.start_task("日常代理"))
start_task_2 = self.tray_menu.addAction("运行人工排查")
start_task_2.triggered.connect(lambda: self.start_task("人工排查"))
# 退出主程序菜单项
kill = self.tray_menu.addAction("退出主程序")
kill.triggered.connect(self.kill_main)
# 设置托盘菜单
self.tray.setContextMenu(self.tray_menu)
self.tray.activated.connect(self.on_tray_activated)
self.show_main()
def show_tray(self):
"""最小化到托盘"""
if self.if_save:
self.set_ui("保存")
self.hide()
self.tray.show()
def show_main(self):
"""显示主界面"""
self.set_ui("配置")
self.tray.hide()
def on_tray_activated(self, reason):
"""双击返回主界面"""
if reason == QSystemTrayIcon.DoubleClick:
self.show_main()
def start_task(self, mode):
"""调起对应任务"""
if self.main.MainTimer.is_maa_run:
self.main.push_notification(
f"无法运行{mode}",
"当前已有任务正在运行,请在该任务结束后重试",
"当前已有任务正在运行,请在该任务结束后重试",
10,
)
else:
self.main.maa_starter(mode)
def kill_main(self):
"""退出主程序"""
self.close()
app.quit()
def set_ui(self, mode):
"""设置窗口相关属性"""
# 保存窗口相关属性
if mode == "保存":
self.main.config["Default"][
"SelfSet.UIsize"
] = f"{self.geometry().width()}x{self.geometry().height()}"
self.main.config["Default"][
"SelfSet.UIlocation"
] = f"{self.geometry().x()}x{self.geometry().y()}"
if self.isMaximized():
self.main.config["Default"]["SelfSet.UImaximized"] = "True"
else:
self.main.config["Default"]["SelfSet.UImaximized"] = "False"
with open(self.main.config_path, "w", encoding="utf-8") as f:
json.dump(self.main.config, f, indent=4)
# 配置窗口相关属性
elif mode == "配置":
self.if_save = False
size = list(
map(int, self.main.config["Default"]["SelfSet.UIsize"].split("x"))
)
location = list(
map(int, self.main.config["Default"]["SelfSet.UIlocation"].split("x"))
)
self.setGeometry(location[0], location[1], size[0], size[1])
if self.main.config["Default"]["SelfSet.UImaximized"] == "True":
self.showMinimized()
self.showMaximized()
else:
self.showMinimized()
self.showNormal()
self.if_save = True
def changeEvent(self, event: QtCore.QEvent):
"""重写后的 changeEvent"""
# 最小化到托盘功能实现
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
if self.main.config["Default"]["SelfSet.IfToTray"] == "True":
self.show_tray()
# 保留其它 changeEvent 方法
return super().changeEvent(event)
def closeEvent(self, event: QCloseEvent):
"""清理残余进程"""
# 保存窗口最终大小与位置
self.main.config["Default"][
"SelfSet.UIsize"
] = f"{self.geometry().width()}x{self.geometry().height()}"
self.main.config["Default"][
"SelfSet.UIlocation"
] = f"{self.geometry().x()}x{self.geometry().y()}"
with open(self.main.config_path, "w", encoding="utf-8") as f:
json.dump(self.main.config, f, indent=4)
self.set_ui("保存")
# 清理各功能线程
self.main.MainTimer.requestInterruption()
self.main.MainTimer.quit()
self.main.MainTimer.wait()
self.main.MaaRunner.requestInterruption()
self.main.MaaRunner.quit()
self.main.MaaRunner.wait()
# 关闭数据库连接
self.main.cur.close()
self.main.db.close()
event.accept()
@@ -2696,5 +2838,4 @@ if __name__ == "__main__":
app = QApplication(sys.argv)
window = AUTO_MAA()
window.show()
sys.exit(app.exec())

View File

@@ -15,16 +15,35 @@ MAA多账号管理与自动化软件
[![GitHub License](https://img.shields.io/github/license/DLmaster361/AUTO_MAA?style=flat-square)](https://github.com/DLmaster361/AUTO_MAA/blob/main/LICENSE)
</div>
## 软件介绍
### 性质
本软件是明日方舟第三方软件`MAA`的第三方工具即第3<sup>3</sup>方软件。旨在优化MAA多账号功能体验并通过一些方法解决MAA项目未能解决的部分问题提高代理的稳定性。
### 原理
本软件可以存储多个明日方舟账号数据,并通过以下流程实现代理功能:
1. **配置:** 根据对应用户的配置信息生成配置文件并将其导入MAA。
2. **监测:** 在MAA开始代理后持续读取MAA的日志以判断其运行状态。当软件认定MAA出现异常时通过重启MAA使之仍能继续完成任务。
3. **循环:** 重复上述步骤使MAA依次完成各个用户的日常代理任务。
### 优势
- **节省运行开销:** 只需要一份MAA软件与一个模拟器无需多开就能完成多账号代理羸弱的电脑也能代理日常。
- **自定义空间大:** 依靠高级用户配置模式支持MAA几乎所有设置选项自定义同时保留对模拟器多开的支持。
- **一键代理无忧:** 无须中途手动修改MAA配置将繁琐交给AUTO_MAA把游戏留给自己。
- **代理结果复核:** 通过人工排查功能核实各用户代理情况,堵住日常代理的最后一丝风险。
## 重要声明
本软件是一个外部工具旨在优化MAA多账号功能体验并通过一些方法解决MAA项目未能解决的部分问题改善代理的稳定性。该软件包可以存储明日方舟多账号数据并通过修改MAA配置文件、读取MAA日志等行为自动完成多账号代理。本开发团队承诺,不会修改明日方舟游戏本体与相关配置文件。
本项目使用GPL开源相关细则如下
本开发团队承诺,不会修改明日方舟游戏本体与相关配置文件。本项目使用GPL开源相关细则如下
- **作者:** AUTO_MAA软件作者为DLmaster、DLmaster361或DLmaster_361以上均指代同一人。
- **使用:** AUTO_MAA使用者可以按自己的意愿自由使用本软件。依据GPL对于由此可能产生的损失AUTO_MAA项目组不负任何责任。
- **分发:** AUTO_MAA允许任何人自由分发本软件包括进行商业活动牟利。但所有分发者必须遵循GPL向接收者提供本软件项目地址、完整软件源码与GPL协议原文违反者可能会被追究法律责任。
- **传播:** AUTO_MAA原则上允许传播者自由传播本软件。由于软件性质项目组不希望发现任何人在明日方舟官方媒体包括官方媒体账号与森空岛社区等或明日方舟游戏相关内容包括同好群、线下活动与游戏内容讨论等下提及AUTO_MAA或MAA希望各位理解。
- **分发:** AUTO_MAA允许任何人自由分发本软件包括进行商业活动牟利。若为直接分发本软件必须遵循GPL向接收者提供本软件项目地址、完整的软件源码与GPL协议原文若为修改软件后进行分发必须遵循GPL向接收者提供本软件项目地址、修改前的完整软件源码副本与GPL协议原文违反者可能会被追究法律责任。
- **传播:** AUTO_MAA原则上允许传播者自由传播本软件,但无论在何种传播过程中,不得删除项目作者与开发者所留版权声明,不得隐瞒项目作者与相关开发者的存在。由于软件性质项目组不希望发现任何人在明日方舟官方媒体包括官方媒体账号与森空岛社区等或明日方舟游戏相关内容包括同好群、线下活动与游戏内容讨论等下提及AUTO_MAA或MAA希望各位理解。
- **衍生:** AUTO_MAA允许任何人对软件本体或软件部分代码进行二次开发或利用。但依据GPL相关成果也必须使用GPL开源。
- **授权:** 如果希望在使用AUTO_MAA的相关成果后仍保持自己的项目闭源请在Issues中说明来意。得到项目组认可后我们可以提供另一份使用不同协议的代码此协议主要内容如下被授权者可以自由使用该代码并维持闭源被授权者必须定期为AUTO_MAA作出贡献。
- **贡献:** 不论是直接参与软件的维护编写或是撰写文档、测试、反馈BUG、给出建议、参与讨论都为AUTO_MAA项目的发展完善做出了不可忽视的贡献。项目组提倡各位贡献者遵照GitHub开源社区惯例发布Issues参与项目。避免私信或私发邮件安全性漏洞或敏感问题除外以帮助更多用户。
@@ -114,6 +133,7 @@ MAA多账号管理与自动化软件
- `开机自动启动AUTO_MAA`实现AUTO_MAA的自启动。
- `AUTO_MAA启动时禁止电脑休眠`:仅阻止电脑自动休眠,不会影响屏幕是否熄灭。
- `启动AUTO_MAA后直接代理`在AUTO_MAA启动后立即执行代理任务。
- `通过邮件通知结果`在AUTO_MAA完成任务后将结果发送至用户指定邮箱。
- `检查版本更新`从GitHub上获取版本更新要求网络能够访问GitHub。获取版本信息时若遇网络不稳定主程序有概率未响应稍等片刻后恢复。
- `修改管理密钥`:修改管理密钥,当用户列表中无用户时,将跳过验证旧管理密钥。
@@ -182,12 +202,10 @@ MAA多账号管理与自动化软件
## 未来开发方向
- [x] 支持B服
- [x] 支持完全自定义MAA配置
- [x] 支持程序版本更新
- [ ] 尝试接入更多开源社区成果
- [ ] 支持对MAA运行状况的进一步识别
- [ ] 支持宽幅ADB连接适配
- [ ] 添加更多通知手段
- [x] 添加更多通知手段
- [ ] GUI界面美化
## 贡献者

View File

@@ -34,14 +34,13 @@ import subprocess
from PySide6.QtWidgets import (
QApplication,
QDialog,
QVBoxLayout,
QLabel,
QProgressBar,
)
from PySide6.QtGui import QIcon
from PySide6.QtCore import QObject, QThread, Signal
from PySide6.QtUiTools import QUiLoader
uiLoader = QUiLoader()
class UpdateProcess(QThread):
@@ -136,15 +135,20 @@ class Updater(QObject):
def __init__(self, app_path, name, download_url, version):
super().__init__()
self.ui = uiLoader.load(f"{app_path}/gui/ui/updater.ui")
self.ui = QDialog()
self.ui.setWindowTitle("AUTO_MAA更新器")
self.ui.resize(500, 70)
self.ui.setWindowIcon(QIcon(f"{app_path}/gui/ico/AUTO_MAA_Updater.ico"))
self.info = self.ui.findChild(QLabel, "label")
self.info.setText("正在初始化")
# 创建垂直布局
self.Layout_v = QVBoxLayout(self.ui)
self.progress = self.ui.findChild(QProgressBar, "progressBar")
self.info = QLabel("正在初始化", self.ui)
self.Layout_v.addWidget(self.info)
self.progress = QProgressBar(self.ui)
self.progress.setRange(0, 0)
self.Layout_v.addWidget(self.progress)
self.update_process = UpdateProcess(app_path, name, download_url, version)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -15,7 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<widget class="QTabWidget" name="tabWidget">
<widget class="QTabWidget" name="tabWidget_main">
<property name="currentIndex">
<number>0</number>
</property>
@@ -919,6 +919,12 @@
<height>0</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item>
@@ -968,6 +974,12 @@
<height>0</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item>
@@ -1017,6 +1029,12 @@
<height>0</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item>
@@ -1037,7 +1055,7 @@
<property name="title">
<string>AUTO_MAA设置</string>
</property>
<layout class="QGridLayout" name="gridLayout_4" columnstretch="1,1,1,1">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QFrame" name="frame_routine_3">
<property name="frameShape">
@@ -1173,7 +1191,87 @@
</property>
</spacer>
</item>
<item row="1" column="2">
<item row="1" column="2" colspan="2">
<widget class="QFrame" name="frame_routine_5">
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_22" stretch="0,1,3">
<item>
<widget class="QCheckBox" name="checkBox_ifsendmail">
<property name="text">
<string>通过邮件通知结果</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_16">
<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="QLineEdit" name="lineEdit_mailaddress"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QFrame" name="frame_iftotray">
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_23">
<item>
<widget class="QCheckBox" name="checkBox_iftotray">
<property name="text">
<string>最小化到托盘</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_17">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>149</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>311</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QFrame" name="frame_check_update">
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
@@ -1218,14 +1316,14 @@
</layout>
</widget>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer_12">
<item row="2" column="3">
<spacer name="horizontalSpacer_19">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>311</width>
<width>40</width>
<height>20</height>
</size>
</property>
@@ -1270,13 +1368,11 @@ li.checked::marker { content: &quot;\2612&quot;; }
&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; 使用本程序前请先仔细阅读README.md。&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定时执行并勾选最小化到托盘同时勾选MAA的启动MAA后直接最小化与最小化时隐藏至托盘来减少日常代理对电脑使用的影响但此时设置MAA时需要自行前往托盘区打开MAA界面。&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; 对于B服用户由于我们无权替您同意用户协议若出现用户协议弹窗您需要自行完成确认否则可能造成MAA卡死代理任务失败。&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;/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;/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;/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;/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;

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>61</height>
</rect>
</property>
<property name="windowTitle">
<string>AUTO_MAA更新器</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -36,5 +36,4 @@
"VersionUpdate.AutoInstallUpdatePackage": "True" #自动安装更新包
"Start.RunDirectly": "True" #启动MAA后直接运行
"Start.MinimizeDirectly": "True" #启动MAA后直接最小化
"Start.OpenEmulatorAfterLaunch": "True" #启动MAA后自动开启模拟器
"Start.MinimizingStartup": "True" #最小化启动模拟器
"Start.OpenEmulatorAfterLaunch": "True" #启动MAA后自动开启模拟器

View File

@@ -1,7 +1,7 @@
{
"main_version": "4.1.2.1",
"main_download_url": "https://ghp.ci/https://github.com/DLmaster361/AUTO_MAA/releases/download/v4.1.2_beta/AUTO_MAA_v4.1.2_beta.zip",
"updater_version": "1.0.4.0",
"updater_download_url": "https://ghp.ci/https://github.com/DLmaster361/AUTO_MAA/releases/download/v4.1.2_beta/Updater_v1.0.4.zip",
"announcement": "\n## 新增功能\n- 记忆窗口位置\n## 修复BUG\n- 暂无\n## 程序优化\n- 暂无"
"main_version": "4.1.3.1",
"main_download_url": "https://ghp.ci/https://github.com/DLmaster361/AUTO_MAA/releases/download/v4.1.3_beta/AUTO_MAA_v4.1.3_beta.zip",
"updater_version": "1.0.5.0",
"updater_download_url": "https://ghp.ci/https://github.com/DLmaster361/AUTO_MAA/releases/download/v4.1.3_beta/Updater_v1.0.5.zip",
"announcement": "\n## 新增功能\n- 暂无\n## 修复BUG\n- 修复深色模式下UI异常 #10\n## 程序优化\n- 暂无"
}