Compare commits

..

15 Commits

Author SHA1 Message Date
DLmaster361
21e7df7c3e Merge branch 'dev' 2025-06-01 20:04:16 +08:00
DLmaster361
2d72ca66a4 fix(core): 修复网络模块子线程未及时销毁导致的程序崩溃 2025-06-01 19:52:22 +08:00
DLmaster361
4725a30165 fix(ui): 修复语音包禁忌二重奏 2025-06-01 04:31:29 +08:00
DLmaster361
f3c977f1b3 Merge branch 'main' into dev 2025-06-01 03:18:39 +08:00
DLmaster361
9a0e7265c6 feat(core): 语音功能上线 2025-06-01 03:16:56 +08:00
DLmaster361
3f8e2fbe6b Merge branch 'dev' 2025-05-31 13:37:06 +08:00
DLmaster361
590b13e916 ci: 移除测试打包流程 2025-05-31 13:36:09 +08:00
DLmaster361
0f6aee56e5 ci: 修正测试工作流名称 2025-05-31 11:21:13 +08:00
DLmaster361
daf18e7295 Merge branch 'dev' 2025-05-31 11:20:04 +08:00
DLmaster361
9bcc87f663 ci: 添加引入打包action的测试工作流 2025-05-31 11:19:36 +08:00
DLmaster361
e7205ce0aa fix(services): 非UI组件转为QObject类 2025-05-30 21:06:39 +08:00
DLmaster361
e3c4b2edc8 fix(core): 网络模块支持并发请求 2025-05-30 20:30:23 +08:00
DLmaster361
222a3b35a2 fix(maa): 修复ADB与模拟器相关日志信息报错时不显示 2025-05-29 21:06:09 +08:00
DLmaster361
cd5dfd56b2 Merge branch 'dev' 2025-05-28 23:13:15 +08:00
DLmaster361
7d5c6b8222 docs: 添加DeepWiki徽章 2025-05-28 23:12:56 +08:00
61 changed files with 347 additions and 184 deletions

View File

@@ -13,6 +13,7 @@
<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>
<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>
<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>
<a href="https://deepwiki.com/DLmaster361/AUTO_MAA"><img alt="DeepWiki" src="https://deepwiki.com/badge.svg"></a>
<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>

View File

@@ -32,6 +32,7 @@ __license__ = "GPL-3.0 license"
from .config import QueueConfig, MaaConfig, MaaUserConfig, MaaPlanConfig, Config
from .main_info_bar import MainInfoBar
from .network import Network
from .sound_player import SoundPlayer
from .task_manager import Task, TaskManager
from .timer import MainTimer
@@ -43,6 +44,7 @@ __all__ = [
"MaaPlanConfig",
"MainInfoBar",
"Network",
"SoundPlayer",
"Task",
"TaskManager",
"MainTimer",

View File

@@ -185,6 +185,11 @@ class GlobalConfig(LQConfig):
"Function", "IfSkipMumuSplashAds", False, BoolValidator()
)
self.voice_Enabled = ConfigItem("Voice", "Enabled", False, BoolValidator())
self.voice_Type = OptionsConfigItem(
"Voice", "Type", "simple", OptionsValidator(["simple", "noisy"])
)
self.start_IfSelfStart = ConfigItem(
"Start", "IfSelfStart", False, BoolValidator()
)
@@ -567,7 +572,7 @@ class MaaPlanConfig(LQConfig):
class AppConfig(GlobalConfig):
VERSION = "4.3.8.0"
VERSION = "4.3.9.0"
gameid_refreshed = Signal()
PASSWORD_refreshed = Signal()
@@ -652,18 +657,20 @@ class AppConfig(GlobalConfig):
def get_gameid(self) -> None:
# 从MAA服务器获取活动关卡信息
Network.set_info(
network = Network.add_task(
mode="get",
url="https://api.maa.plus/MaaAssistantArknights/api/gui/StageActivity.json",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
gameid_infos: List[Dict[str, Union[str, Dict[str, Union[str, int]]]]] = (
Network.response_json["Official"]["sideStoryStage"]
network_result["response_json"]["Official"]["sideStoryStage"]
)
else:
logger.warning(f"无法从MAA服务器获取活动关卡信息:{Network.error_message}")
logger.warning(
f"无法从MAA服务器获取活动关卡信息:{network_result['error_message']}"
)
gameid_infos = []
ss_gameid_dict = {"value": [], "text": []}

View File

@@ -30,6 +30,7 @@ from PySide6.QtCore import Qt
from qfluentwidgets import InfoBar, InfoBarPosition
from .config import Config
from .sound_player import SoundPlayer
class _MainInfoBar:
@@ -79,5 +80,10 @@ class _MainInfoBar:
if info_bar_item not in Config.info_bar_list:
Config.info_bar_list.append(info_bar_item)
if mode == "warning":
SoundPlayer.play("发生异常")
if mode == "error":
SoundPlayer.play("发生错误")
MainInfoBar = _MainInfoBar()

View File

@@ -26,55 +26,46 @@ v4.3
"""
from loguru import logger
from PySide6.QtCore import QThread, QEventLoop, QTimer
from PySide6.QtCore import QObject, QThread, QEventLoop
import re
import time
import requests
from pathlib import Path
class _Network(QThread):
class NetworkThread(QThread):
"""网络请求线程类"""
max_retries = 3
timeout = 10
backoff_factor = 0.1
def __init__(self) -> None:
def __init__(self, mode: str, url: str, path: Path = None) -> None:
super().__init__()
self.if_running = False
self.mode = None
self.url = None
self.loop = QEventLoop()
self.wait_loop = QEventLoop()
@logger.catch
def run(self) -> None:
"""运行网络请求线程"""
self.if_running = True
if self.mode == "get":
self.get_json(self.url)
elif self.mode == "get_file":
self.get_file(self.url, self.path)
self.if_running = False
def set_info(self, mode: str, url: str, path: Path = None) -> None:
"""设置网络请求信息"""
while self.if_running:
QTimer.singleShot(self.backoff_factor * 1000, self.wait_loop.quit)
self.wait_loop.exec()
self.setObjectName(
f"NetworkThread-{mode}-{re.sub(r'(&cdk=)[^&]+(&)', r'\1******\2', url)}"
)
self.mode = mode
self.url = url
self.path = path
self.stutus_code = None
self.status_code = None
self.response_json = None
self.error_message = None
self.loop = QEventLoop()
@logger.catch
def run(self) -> None:
"""运行网络请求线程"""
if self.mode == "get":
self.get_json(self.url)
elif self.mode == "get_file":
self.get_file(self.url, self.path)
def get_json(self, url: str) -> None:
"""通过get方法获取json数据"""
@@ -83,12 +74,12 @@ class _Network(QThread):
for _ in range(self.max_retries):
try:
response = requests.get(url, timeout=self.timeout)
self.stutus_code = response.status_code
self.status_code = response.status_code
self.response_json = response.json()
self.error_message = None
break
except Exception as e:
self.stutus_code = response.status_code if response else None
self.status_code = response.status_code if response else None
self.response_json = None
self.error_message = str(e)
time.sleep(self.backoff_factor)
@@ -105,16 +96,56 @@ class _Network(QThread):
if response.status_code == 200:
with open(path, "wb") as file:
file.write(response.content)
self.stutus_code = response.status_code
self.status_code = response.status_code
else:
self.stutus_code = response.status_code
self.status_code = response.status_code
self.error_message = "下载失败"
except Exception as e:
self.stutus_code = response.status_code if response else None
self.status_code = response.status_code if response else None
self.error_message = str(e)
self.loop.quit()
class _Network(QObject):
"""网络请求线程类"""
def __init__(self) -> None:
super().__init__()
self.task_queue = []
def add_task(self, mode: str, url: str, path: Path = None) -> NetworkThread:
"""添加网络请求任务"""
network_thread = NetworkThread(mode, url, path)
self.task_queue.append(network_thread)
network_thread.start()
return network_thread
def get_result(self, network_thread: NetworkThread) -> dict:
"""获取网络请求结果"""
result = {
"status_code": network_thread.status_code,
"response_json": network_thread.response_json,
"error_message": (
re.sub(r"(&cdk=)[^&]+(&)", r"\1******\2", network_thread.error_message)
if network_thread.error_message
else None
),
}
network_thread.quit()
network_thread.wait()
self.task_queue.remove(network_thread)
network_thread.deleteLater()
return result
Network = _Network()

69
app/core/sound_player.py Normal file
View File

@@ -0,0 +1,69 @@
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
# Copyright © 2024-2025 DLmaster361
# This file is part of AUTO_MAA.
# AUTO_MAA is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
# AUTO_MAA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
# the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
# Contact: DLmaster_361@163.com
"""
AUTO_MAA
AUTO_MAA音效播放器
v4.3
作者DLmaster_361
"""
from loguru import logger
from PySide6.QtCore import QObject, QUrl
from PySide6.QtMultimedia import QSoundEffect
from pathlib import Path
from .config import Config
class _SoundPlayer(QObject):
def __init__(self):
super().__init__()
self.sounds_path = Config.app_path / "resources/sounds"
def play(self, sound_name: str):
if not Config.get(Config.voice_Enabled):
return
if (self.sounds_path / f"both/{sound_name}.wav").exists():
self.play_voice(self.sounds_path / f"both/{sound_name}.wav")
elif (
self.sounds_path / Config.get(Config.voice_Type) / f"{sound_name}.wav"
).exists():
self.play_voice(
self.sounds_path / Config.get(Config.voice_Type) / f"{sound_name}.wav"
)
def play_voice(self, sound_path: Path):
effect = QSoundEffect(self)
effect.setVolume(1)
effect.setSource(QUrl.fromLocalFile(sound_path))
effect.play()
SoundPlayer = _SoundPlayer()

View File

@@ -35,6 +35,7 @@ from typing import Dict, Union
from .config import Config
from .main_info_bar import MainInfoBar
from .network import Network
from .sound_player import SoundPlayer
from app.models import MaaManager
from app.services import System
@@ -44,6 +45,7 @@ class Task(QThread):
check_maa_version = Signal(str)
push_info_bar = Signal(str, str, str, int)
play_sound = Signal(str)
question = Signal(str, str)
question_response = Signal(bool)
update_user_info = Signal(str, dict)
@@ -59,6 +61,8 @@ class Task(QThread):
):
super(Task, self).__init__()
self.setObjectName(f"Task-{mode}-{name}")
self.mode = mode
self.name = name
self.info = info
@@ -82,6 +86,7 @@ class Task(QThread):
)
self.task.check_maa_version.connect(self.check_maa_version.emit)
self.task.push_info_bar.connect(self.push_info_bar.emit)
self.task.play_sound.connect(self.play_sound.emit)
self.task.accomplish.connect(lambda: self.accomplish.emit([]))
self.task.run()
@@ -141,6 +146,7 @@ class Task(QThread):
self.question_response.disconnect()
self.question_response.connect(self.task.question_response.emit)
self.task.push_info_bar.connect(self.push_info_bar.emit)
self.task.play_sound.connect(self.play_sound.emit)
self.task.create_user_list.connect(self.create_user_list.emit)
self.task.update_user_list.connect(self.update_user_list.emit)
self.task.update_log_text.connect(self.update_log_text.emit)
@@ -191,6 +197,7 @@ class _TaskManager(QObject):
logger.info(f"任务开始:{name}")
MainInfoBar.push_info_bar("info", "任务开始", name, 3000)
SoundPlayer.play("任务开始")
Config.running_list.append(name)
self.task_dict[name] = Task(mode, name, info)
@@ -199,6 +206,7 @@ class _TaskManager(QObject):
lambda title, content: self.push_dialog(name, title, content)
)
self.task_dict[name].push_info_bar.connect(MainInfoBar.push_info_bar)
self.task_dict[name].play_sound.connect(SoundPlayer.play)
self.task_dict[name].update_user_info.connect(Config.change_user_info)
self.task_dict[name].accomplish.connect(
lambda logs: self.remove_task(mode, name, logs)
@@ -239,6 +247,7 @@ class _TaskManager(QObject):
logger.info(f"任务结束:{name}")
MainInfoBar.push_info_bar("info", "任务结束", name, 3000)
SoundPlayer.play("任务结束")
self.task_dict[name].deleteLater()
self.task_dict.pop(name)
@@ -277,20 +286,20 @@ class _TaskManager(QObject):
def check_maa_version(self, v: str):
"""检查MAA版本"""
Network.set_info(
network = Network.add_task(
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
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
maa_info = network_result["response_json"]
else:
logger.warning(f"获取MAA版本信息时出错{Network.error_message}")
logger.warning(f"获取MAA版本信息时出错{network_result['error_message']}")
MainInfoBar.push_info_bar(
"warning",
"获取MAA版本信息时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None

View File

@@ -26,8 +26,7 @@ v4.3
"""
from loguru import logger
from PySide6.QtWidgets import QWidget
from PySide6.QtCore import QTimer
from PySide6.QtCore import QObject, QTimer
from datetime import datetime
from pathlib import Path
import pyautogui
@@ -37,7 +36,7 @@ from .task_manager import TaskManager
from app.services import System
class _MainTimer(QWidget):
class _MainTimer(QObject):
def __init__(self, parent=None):
super().__init__(parent)

View File

@@ -50,6 +50,7 @@ class MaaManager(QObject):
question_response = Signal(bool)
update_user_info = Signal(str, dict)
push_info_bar = Signal(str, str, str, int)
play_sound = Signal(str)
create_user_list = Signal(list)
update_user_list = Signal(list)
update_log_text = Signal(str)
@@ -88,6 +89,8 @@ class MaaManager(QObject):
self.question_response.connect(self.__capture_response)
self.question_response.connect(self.question_loop.quit)
self.wait_loop = QEventLoop()
self.interrupt.connect(self.quit_monitor)
self.maa_version = None
@@ -426,11 +429,11 @@ class MaaManager(QObject):
# 任务开始前释放ADB
try:
logger.info(f"{self.name} | 释放ADB{self.ADB_address}")
subprocess.run(
[self.ADB_path, "disconnect", self.ADB_address],
creationflags=subprocess.CREATE_NO_WINDOW,
)
logger.info(f"{self.name} | 释放ADB{self.ADB_address}")
except subprocess.CalledProcessError as e:
# 忽略错误,因为可能本来就没有连接
logger.warning(f"{self.name} | 释放ADB时出现异常{e}")
@@ -445,13 +448,13 @@ class MaaManager(QObject):
if self.if_open_emulator_process:
try:
logger.info(
f"{self.name} | 启动模拟器:{self.emulator_path},参数:{self.emulator_arguments}"
)
self.emulator_process = subprocess.Popen(
[self.emulator_path, *self.emulator_arguments],
creationflags=subprocess.CREATE_NO_WINDOW,
)
logger.info(
f"{self.name} | 启动模拟器:{self.emulator_path},参数:{self.emulator_arguments}"
)
except Exception as e:
logger.error(f"{self.name} | 启动模拟器时出现异常:{e}")
self.push_info_bar.emit(
@@ -511,10 +514,7 @@ class MaaManager(QObject):
"检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
)
for _ in range(10):
if self.isInterruptionRequested:
break
time.sleep(1)
self.sleep(10)
else:
logger.error(
f"{self.name} | 用户: {user[0]} - 代理任务异常: {self.maa_result}"
@@ -564,18 +564,19 @@ class MaaManager(QObject):
f"{user[0].replace("_", " ")}{mode_book[mode][5:7]}出现异常",
1,
)
for _ in range(10):
if self.isInterruptionRequested:
break
time.sleep(1)
if i == self.set["RunSet"]["RunTimesLimit"] - 1:
self.play_sound.emit("子任务失败")
else:
self.play_sound.emit(self.maa_result)
self.sleep(10)
# 任务结束后释放ADB
try:
logger.info(f"{self.name} | 释放ADB{self.ADB_address}")
subprocess.run(
[self.ADB_path, "disconnect", self.ADB_address],
creationflags=subprocess.CREATE_NO_WINDOW,
)
logger.info(f"{self.name} | 释放ADB{self.ADB_address}")
except subprocess.CalledProcessError as e:
# 忽略错误,因为可能本来就没有连接
logger.warning(f"{self.name} | 释放ADB时出现异常{e}")
@@ -619,6 +620,7 @@ class MaaManager(QObject):
},
user_data,
)
self.play_sound.emit("六星喜报")
# 执行MAA解压更新动作
if self.maa_update_package:
@@ -630,15 +632,13 @@ class MaaManager(QObject):
self.update_log_text.emit(
f"检测到MAA存在更新\nMAA正在执行更新动作\n请等待10s"
)
self.play_sound.emit("MAA更新")
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)
self.sleep(10)
System.kill_process(self.maa_exe_path)
logger.info(f"{self.name} | 更新动作结束")
@@ -745,10 +745,7 @@ class MaaManager(QObject):
# 无命令行中止MAA与其子程序
System.kill_process(self.maa_exe_path)
self.if_open_emulator = True
for _ in range(10):
if self.isInterruptionRequested:
break
time.sleep(1)
self.sleep(10)
# 登录成功,结束循环
if run_book[0]:
@@ -756,6 +753,7 @@ class MaaManager(QObject):
# 登录失败,询问是否结束循环
elif not self.isInterruptionRequested:
self.play_sound.emit("排查重试")
if not self.push_question(
"操作提示", "MAA未能正确登录到PRTS是否重试"
):
@@ -764,6 +762,7 @@ class MaaManager(QObject):
# 登录成功,录入人工排查情况
if run_book[0] and not self.isInterruptionRequested:
self.play_sound.emit("排查录入")
if self.push_question(
"操作提示", "请检查用户代理情况,该用户是否正确完成代理任务?"
):
@@ -885,6 +884,7 @@ class MaaManager(QObject):
self.maa_result = "任务被手动中止"
self.isInterruptionRequested = True
self.wait_loop.quit()
def push_question(self, title: str, message: str) -> bool:
@@ -895,6 +895,12 @@ class MaaManager(QObject):
def __capture_response(self, response: bool) -> None:
self.response = response
def sleep(self, time: int) -> None:
"""非阻塞型等待"""
QTimer.singleShot(time * 1000, self.wait_loop.quit)
self.wait_loop.exec()
def search_ADB_address(self) -> None:
"""搜索ADB实际地址"""
@@ -902,10 +908,7 @@ class MaaManager(QObject):
f"即将搜索ADB实际地址\n正在等待模拟器完成启动\n请等待{self.wait_time}s"
)
for _ in range(self.wait_time):
if self.isInterruptionRequested:
break
time.sleep(1)
self.sleep(self.wait_time)
# 移除静默进程标记
Config.silence_list.remove(self.emulator_path)
@@ -968,6 +971,7 @@ class MaaManager(QObject):
with self.maa_set_path.open(mode="w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
self.play_sound.emit("ADB成功")
return None
else:
@@ -975,6 +979,8 @@ class MaaManager(QObject):
else:
logger.info(f"{self.name} | 无法连接到ADB地址{ADB_address}")
self.play_sound.emit("ADB失败")
def refresh_maa_log(self) -> None:
"""刷新MAA日志"""

View File

@@ -34,8 +34,7 @@ from email.mime.text import MIMEText
from email.utils import formataddr
import requests
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QWidget
from PySide6.QtCore import QObject, Signal
from loguru import logger
from plyer import notification
@@ -43,7 +42,7 @@ from app.core import Config
from app.services.security import Crypto
class Notification(QWidget):
class Notification(QObject):
push_info_bar = Signal(str, str, str, int)

View File

@@ -48,7 +48,7 @@ from PySide6.QtGui import QTextCursor
from typing import List, Dict
from app.core import Config, TaskManager, Task, MainInfoBar
from app.core import Config, TaskManager, Task, MainInfoBar, SoundPlayer
from .Widget import StatefulItemCard, ComboBoxMessageBox, PivotArea

View File

@@ -78,6 +78,8 @@ class DownloadProcess(QThread):
) -> None:
super(DownloadProcess, self).__init__()
self.setObjectName(f"DownloadProcess-{url}-{start_byte}-{end_byte}")
self.url = url
self.start_byte = start_byte
self.end_byte = end_byte
@@ -157,6 +159,8 @@ class ZipExtractProcess(QThread):
def __init__(self, name: str, app_path: Path, download_path: Path) -> None:
super(ZipExtractProcess, self).__init__()
self.setObjectName(f"ZipExtractProcess-{name}")
self.name = name
self.app_path = app_path
self.download_path = download_path

View File

@@ -51,7 +51,7 @@ from pathlib import Path
from typing import Union, List, Dict
from app.core import Config
from app.core import Config, SoundPlayer
from .Widget import StatefulItemCard, QuantifiedItemCard, QuickExpandGroupCard
@@ -83,6 +83,8 @@ class History(QWidget):
def reload_history(self, mode: str, start_date: QDate, end_date: QDate) -> None:
"""加载历史记录界面"""
SoundPlayer.play("历史记录查询")
while self.content_layout.count() > 0:
item = self.content_layout.takeAt(0)
if item.spacerItem():

View File

@@ -199,20 +199,22 @@ class Home(QWidget):
elif Config.get(Config.function_HomeImageMode) == "主题图像":
# 从远程服务器获取最新主题图像
Network.set_info(
network = Network.add_task(
mode="get",
url="https://gitee.com/DLmaster_361/AUTO_MAA/raw/server/theme_image.json",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
theme_image = Network.response_json
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
theme_image = network_result["response_json"]
else:
logger.warning(f"获取最新主题图像时出错:{Network.error_message}")
logger.warning(
f"获取最新主题图像时出错:{network_result['error_message']}"
)
MainInfoBar.push_info_bar(
"warning",
"获取最新主题图像时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None
@@ -236,15 +238,15 @@ class Home(QWidget):
> time_local
):
Network.set_info(
network = Network.add_task(
mode="get_file",
url=theme_image["url"],
path=Config.app_path / "resources/images/Home/BannerTheme.jpg",
)
Network.start()
Network.loop.exec()
network.loop.exec()
network_result = Network.get_result(network)
if Network.stutus_code == 200:
if network_result["status_code"] == 200:
with (Config.app_path / "resources/theme_image.json").open(
mode="w", encoding="utf-8"
@@ -261,11 +263,13 @@ class Home(QWidget):
else:
logger.warning(f"下载最新主题图像时出错:{Network.error_message}")
logger.warning(
f"下载最新主题图像时出错:{network_result['error_message']}"
)
MainInfoBar.push_info_bar(
"warning",
"下载最新主题图像时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)

View File

@@ -45,7 +45,7 @@ from datetime import datetime, timedelta
import shutil
import darkdetect
from app.core import Config, TaskManager, MainTimer, MainInfoBar
from app.core import Config, TaskManager, MainTimer, MainInfoBar, SoundPlayer
from app.services import Notify, Crypto, System
from .home import Home
from .member_manager import MemberManager
@@ -285,6 +285,7 @@ class AUTO_MAA(MSFluentWindow):
and not self.window().isMaximized()
):
self.titleBar.maxBtn.click()
SoundPlayer.play("欢迎回来")
self.show_ui("配置托盘")
elif if_start:
if Config.get(Config.ui_maximized) and not self.window().isMaximized():

View File

@@ -58,7 +58,15 @@ from typing import List
import shutil
import json
from app.core import Config, MainInfoBar, TaskManager, MaaConfig, MaaUserConfig, Network
from app.core import (
Config,
MainInfoBar,
TaskManager,
MaaConfig,
MaaUserConfig,
Network,
SoundPlayer,
)
from app.services import Crypto
from .downloader import DownloadManager
from .Widget import (
@@ -181,6 +189,7 @@ class MemberManager(QWidget):
MainInfoBar.push_info_bar(
"success", "操作成功", f"添加脚本实例 脚本_{index}", 3000
)
SoundPlayer.play("添加脚本实例")
def del_setting_box(self):
"""删除一个脚本实例"""
@@ -221,6 +230,7 @@ class MemberManager(QWidget):
MainInfoBar.push_info_bar(
"success", "操作成功", f"删除脚本实例 {name}", 3000
)
SoundPlayer.play("删除脚本实例")
def left_setting_box(self):
"""向左移动脚本实例"""
@@ -333,20 +343,20 @@ class MemberManager(QWidget):
return None
# 从远程服务器获取应用列表
Network.set_info(
network = Network.add_task(
mode="get",
url="https://gitee.com/DLmaster_361/AUTO_MAA/raw/server/apps_info.json",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
apps_info = Network.response_json
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
apps_info = network_result["response_json"]
else:
logger.warning(f"获取应用列表时出错:{Network.error_message}")
logger.warning(f"获取应用列表时出错:{network_result['error_message']}")
MainInfoBar.push_info_bar(
"warning",
"获取应用列表时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None
@@ -376,19 +386,19 @@ class MemberManager(QWidget):
return None
# 从mirrorc服务器获取最新版本信息
Network.set_info(
network = Network.add_task(
mode="get",
url=f"https://mirrorchyan.com/api/resources/{app_rid}/latest?user_agent=AutoMaaGui&cdk={Crypto.win_decryptor(Config.get(Config.update_MirrorChyanCDK))}&os={apps_info[app_name]["os"]}&arch={apps_info[app_name]["arch"]}&channel=stable",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
app_info = Network.response_json
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
app_info = network_result["response_json"]
else:
if Network.response_json:
if network_result["response_json"]:
app_info = Network.response_json
app_info = network_result["response_json"]
if app_info["code"] != 0:
@@ -425,11 +435,11 @@ class MemberManager(QWidget):
return None
logger.warning(f"获取版本信息时出错:{Network.error_message}")
logger.warning(f"获取版本信息时出错:{network_result['error_message']}")
MainInfoBar.push_info_bar(
"warning",
"获取版本信息时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None
@@ -885,6 +895,7 @@ class MemberManager(QWidget):
MainInfoBar.push_info_bar(
"success", "操作成功", f"{self.name} 添加 用户_{index}", 3000
)
SoundPlayer.play("添加用户")
def del_user(self):
"""删除一个用户"""
@@ -944,6 +955,7 @@ class MemberManager(QWidget):
MainInfoBar.push_info_bar(
"success", "操作成功", f"{self.name} 删除 {name}", 3000
)
SoundPlayer.play("删除用户")
def left_user(self):
"""向前移动用户"""

View File

@@ -43,7 +43,7 @@ from qfluentwidgets import (
from typing import List, Dict, Union
import shutil
from app.core import Config, MainInfoBar, MaaPlanConfig
from app.core import Config, MainInfoBar, MaaPlanConfig, SoundPlayer
from .Widget import (
ComboBoxMessageBox,
LineEditSettingCard,
@@ -129,6 +129,7 @@ class PlanManager(QWidget):
MainInfoBar.push_info_bar(
"success", "操作成功", f"添加计划表 计划_{index}", 3000
)
SoundPlayer.play("添加计划表")
def del_setting_box(self):
"""删除一个计划表"""
@@ -167,6 +168,7 @@ class PlanManager(QWidget):
logger.success(f"计划表 {name} 删除成功")
MainInfoBar.push_info_bar("success", "操作成功", f"删除计划表 {name}", 3000)
SoundPlayer.play("删除计划表")
def left_setting_box(self):
"""向左移动计划表"""

View File

@@ -42,7 +42,7 @@ from qfluentwidgets import (
)
from typing import List
from app.core import QueueConfig, Config, MainInfoBar
from app.core import QueueConfig, Config, MainInfoBar, SoundPlayer
from .Widget import (
SwitchSettingCard,
ComboBoxSettingCard,
@@ -116,6 +116,7 @@ class QueueManager(QWidget):
logger.success(f"调度队列_{index} 添加成功")
MainInfoBar.push_info_bar("success", "操作成功", f"添加 调度队列_{index}", 3000)
SoundPlayer.play("添加调度队列")
def del_setting_box(self):
"""删除一个调度队列实例"""
@@ -154,6 +155,7 @@ class QueueManager(QWidget):
logger.success(f"{name} 删除成功")
MainInfoBar.push_info_bar("success", "操作成功", f"删除 {name}", 3000)
SoundPlayer.play("删除调度队列")
def left_setting_box(self):
"""向左移动调度队列实例"""

View File

@@ -49,7 +49,7 @@ from packaging import version
from pathlib import Path
from typing import Dict, Union
from app.core import Config, MainInfoBar, Network
from app.core import Config, MainInfoBar, Network, SoundPlayer
from app.services import Crypto, System, Notify
from .downloader import DownloadManager
from .Widget import (
@@ -71,6 +71,7 @@ class Setting(QWidget):
self.setObjectName("设置")
self.function = FunctionSettingCard(self)
self.voice = VoiceSettingCard(self)
self.start = StartSettingCard(self)
self.ui = UiSettingCard(self)
self.notification = NotifySettingCard(self)
@@ -94,6 +95,7 @@ class Setting(QWidget):
content_layout = QVBoxLayout(content_widget)
content_layout.setContentsMargins(0, 0, 11, 0)
content_layout.addWidget(self.function)
content_layout.addWidget(self.voice)
content_layout.addWidget(self.start)
content_layout.addWidget(self.ui)
content_layout.addWidget(self.notification)
@@ -262,31 +264,26 @@ class Setting(QWidget):
current_version = list(map(int, Config.VERSION.split(".")))
if Network.if_running and if_show:
MainInfoBar.push_info_bar(
"warning", "请求速度过快", "上个网络请求还未结束,请稍等片刻", 5000
)
return None
# 从远程服务器获取最新版本信息
Network.set_info(
network = Network.add_task(
mode="get",
url=f"https://mirrorchyan.com/api/resources/AUTO_MAA/latest?user_agent=AutoMaaGui&current_version={version_text(current_version)}&cdk={Crypto.win_decryptor(Config.get(Config.update_MirrorChyanCDK))}&channel={Config.get(Config.update_UpdateType)}",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
version_info: Dict[str, Union[int, str, Dict[str, str]]] = (
Network.response_json
)
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
version_info: Dict[str, Union[int, str, Dict[str, str]]] = network_result[
"response_json"
]
else:
if Network.response_json:
if network_result["response_json"]:
version_info = Network.response_json
version_info = network_result["response_json"]
if version_info["code"] != 0:
logger.error(f"获取版本信息时出错:{version_info["msg"]}")
logger.error(f"获取版本信息时出错:{version_info['msg']}")
error_remark_dict = {
1001: "获取版本信息的URL参数不正确",
@@ -319,11 +316,11 @@ class Setting(QWidget):
return None
logger.warning(f"获取版本信息时出错:{Network.error_message}")
logger.warning(f"获取版本信息时出错:{network_result['error_message']}")
MainInfoBar.push_info_bar(
"warning",
"获取版本信息时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None
@@ -381,6 +378,7 @@ class Setting(QWidget):
all_version_info[key] = value.copy()
# 询问是否开始版本更新
SoundPlayer.play("有新版本")
choice = NoticeMessageBox(
self.window(),
"版本更新",
@@ -406,20 +404,22 @@ class Setting(QWidget):
else:
# 从远程服务器获取代理信息
Network.set_info(
network = Network.add_task(
mode="get",
url="https://gitee.com/DLmaster_361/AUTO_MAA/raw/server/download_info.json",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
download_info = Network.response_json
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
download_info = network_result["response_json"]
else:
logger.warning(f"获取应用列表时出错:{Network.error_message}")
logger.warning(
f"获取应用列表时出错:{network_result['error_message']}"
)
MainInfoBar.push_info_bar(
"warning",
"获取应用列表时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None
@@ -464,8 +464,10 @@ class Setting(QWidget):
3600000,
if_force=True,
)
SoundPlayer.play("有新版本")
else:
MainInfoBar.push_info_bar("success", "更新检查", "已是最新版本~", 3000)
SoundPlayer.play("无新版本")
def start_setup(self) -> None:
subprocess.Popen(
@@ -488,20 +490,20 @@ class Setting(QWidget):
"""显示公告"""
# 从远程服务器获取最新公告
Network.set_info(
network = Network.add_task(
mode="get",
url="https://gitee.com/DLmaster_361/AUTO_MAA/raw/server/notice.json",
)
Network.start()
Network.loop.exec()
if Network.stutus_code == 200:
notice = Network.response_json
network.loop.exec()
network_result = Network.get_result(network)
if network_result["status_code"] == 200:
notice = network_result["response_json"]
else:
logger.warning(f"获取最新公告时出错:{Network.error_message}")
logger.warning(f"获取最新公告时出错:{network_result['error_message']}")
MainInfoBar.push_info_bar(
"warning",
"获取最新公告时出错",
f"网络错误:{Network.stutus_code}",
f"网络错误:{network_result['status_code']}",
5000,
)
return None
@@ -533,6 +535,7 @@ class Setting(QWidget):
choice = NoticeMessageBox(self.window(), "公告", notice["notice_dict"])
choice.button_cancel.hide()
choice.button_layout.insertStretch(0, 1)
SoundPlayer.play("公告展示")
if choice.exec():
with (Config.app_path / "resources/notice.json").open(
mode="w", encoding="utf-8"
@@ -548,6 +551,7 @@ class Setting(QWidget):
MainInfoBar.push_info_bar(
"info", "有新公告", "请前往设置界面查看公告", 3600000, if_force=True
)
SoundPlayer.play("公告通知")
return None
@@ -656,6 +660,36 @@ class FunctionSettingCard(HeaderCardWidget):
self.addGroupWidget(widget)
class VoiceSettingCard(HeaderCardWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setTitle("音效")
self.card_Enabled = SwitchSettingCard(
icon=FluentIcon.PAGE_RIGHT,
title="音效开关",
content="是否启用音效",
qconfig=Config,
configItem=Config.voice_Enabled,
parent=self,
)
self.card_Type = ComboBoxSettingCard(
icon=FluentIcon.PAGE_RIGHT,
title="音效模式",
content="选择音效的播放模式",
texts=["简洁", "聒噪"],
qconfig=Config,
configItem=Config.voice_Type,
parent=self,
)
Layout = QVBoxLayout()
Layout.addWidget(self.card_Enabled)
Layout.addWidget(self.card_Type)
self.viewLayout.addLayout(Layout)
class StartSettingCard(HeaderCardWidget):
def __init__(self, parent=None):

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,53 +1,26 @@
{
"main_version": "4.3.8.0",
"main_version": "4.3.9.0",
"version_info": {
"4.3.8.0": {
"新增功能": [
"吐司通知在主窗口隐藏时不再弹出"
"4.3.9.0": {
"修复bug": [
"修复网络模块子线程未及时销毁导致的程序崩溃"
]
},
"4.3.8.4": {
"新增功能": [
"支持为每一个用户执行独立通知",
"输入文本框适配文本插入操作",
"计划表功能上线",
"静默控制时长从全任务内缩短至搜索ADB时段内",
"UI界面添加自动日常代理任务序列设置项"
],
"4.3.9.2": {
"修复bug": [
"修复雷电模拟器静默模式无法正常识别模拟器是否隐藏相关问题"
"修复语音包禁忌二重奏"
]
},
"4.3.8.3": {
"4.3.9.1": {
"新增功能": [
"用户仪表盘支持直接控制用户状态"
"语音功能上线"
],
"修复bug": [
"修复雷电ADB端口号相关问题"
]
},
"4.3.8.2": {
"新增功能": [
"添加ADB端口号宽幅适配能力"
],
"修复bug": [
"日志分析忽略MAA超时提示"
"网络模块支持并发请求",
"修复中止任务时程序异常卡顿"
],
"程序优化": [
"配置类定义方法优化"
]
},
"4.3.8.1": {
"新增功能": [
"自定义基建显示配置名称 #46",
"主调度台添加仅一次电源任务"
],
"修复bug": [
"电源相关选项改为所有任务完成后生效",
"适配MAAv5.16.3的ADB报错信息更改"
],
"程序优化": [
"UI样式优化进一步适配win10主题"
"非UI组件转为QObject类"
]
}
}