Compare commits
21 Commits
v4.2.2-bet
...
v4.2.3-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e00676faf | ||
|
|
fb1895c4eb | ||
|
|
90d3dad8c8 | ||
|
|
de12339c3e | ||
|
|
f07cd2b44a | ||
|
|
c7fbbf6f50 | ||
|
|
de262ee6bd | ||
|
|
0c123e9389 | ||
|
|
d13fbb063d | ||
|
|
5c24eb7d56 | ||
|
|
6c2f19a884 | ||
|
|
4ff632ed2a | ||
|
|
d445c0054f | ||
|
|
748fa7a004 | ||
|
|
c3e710b5cf | ||
|
|
a93a60d125 | ||
|
|
07f24c6168 | ||
|
|
7f5478b098 | ||
|
|
fb7a429ff2 | ||
| 3307793a3d | |||
|
|
0da9f4b7ab |
13
.github/workflows/build-pre.yml
vendored
13
.github/workflows/build-pre.yml
vendored
@@ -150,4 +150,15 @@ jobs:
|
||||
gh release delete "$TAGNAME" --yes
|
||||
gh release create "$TAGNAME" --target "main" --title "$NAME" --notes "$NOTES" --prerelease artifacts/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||
|
||||
- name: Setup SSH Key
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan -H ${{ secrets.SERVER_IP }} >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Upload Release to Server
|
||||
run: |
|
||||
scp -r artifacts/* ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:/home/user/files/AUTO_MAA/
|
||||
|
||||
129
README.md
129
README.md
@@ -58,132 +58,9 @@ MAA多账号管理与自动化软件
|
||||
|
||||
# 使用方法
|
||||
|
||||
## 安装软件
|
||||
本项目已改用腾讯文档展示使用方法
|
||||
|
||||
```
|
||||
本软件是MAA的外部工具,需要安装MAA后才能使用。
|
||||
```
|
||||
|
||||
### 下载MAA
|
||||
|
||||
- 什么是MAA? [官网](https://maa.plus/)/[GitHub](https://github.com/MaaAssistantArknights/MaaAssistantArknights)
|
||||
- MAA下载地址 [GitHub下载](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases)
|
||||
|
||||
### 安装MAA
|
||||
|
||||
- 将MAA压缩包解压至任意普通文件夹即可。
|
||||
- 若为首次安装MAA,请双击`MAA.exe`启动MAA程序以生成MAA配置文件。
|
||||
|
||||
### 下载AUTO_MAA [](https://github.com/DLmaster361/AUTO_MAA/releases)
|
||||
|
||||
- GitHub下载地址 [GitHub下载](https://github.com/DLmaster361/AUTO_MAA/releases)
|
||||
|
||||
### 安装AUTO_MAA
|
||||
|
||||
- 将AUTO_MAA压缩包解压至任意普通文件夹即可。
|
||||
|
||||
## 配置AUTO_MAA
|
||||
|
||||
### 启动AUTO_MAA
|
||||
|
||||
- 双击`AUTO_MAA.exe`以启动软件。
|
||||
|
||||
```
|
||||
注意:
|
||||
|
||||
首次启动时会要求设置管理密钥。
|
||||
|
||||
管理密钥是解密用户密码的唯一凭证,与用户数据库绑定。
|
||||
密钥丢失或data/key/目录下任一文件损坏都将导致解密无法正常进行。
|
||||
|
||||
本项目采用自主开发的混合加密模式,项目组也无法找回您的管理密钥或修复data/key/目录下的文件。
|
||||
如果不幸的事发生,建议您删除data/key目录与config目录后重新录入信息。
|
||||
```
|
||||
|
||||
### 配置信息
|
||||
|
||||
#### 设置脚本实例
|
||||
|
||||
1. 单击`+`并选择`MAA`以添加MAA脚本实例。
|
||||
2. 在`MAA目录`选项卡中通过`选择文件夹`打开MAA软件目录以绑定MAA。
|
||||
3. 在`MAA全局配置`选项卡中通过`设置`进行MAA全局设置。在打开的MAA界面完成`性能设置`、`游戏设置`、`连接设置`、`启动设置`、`界面设置`、`软件更新`等基本配置以及代理任务的详细配置。
|
||||
4. 完成基本配置后,关闭MAA页面,AUTO_MAA会自动保存您的配置。
|
||||
|
||||
- 注意:在MAA的设置过程中,若MAA要求`立刻重启应用更改`,请选择`稍后`。否则,MAA重启后的一切更改都不会被程序记录。
|
||||
|
||||
- 特别的,在设置MAA过程中,您需要确保自己:
|
||||
- 在`切换配置`选项卡中选择了`Default`项。
|
||||
- 取消勾选`开机自启动MAA`。
|
||||
- 配置自己模拟器所在的位置并根据实际情况填写`等待模拟器启动时间`(建议预留10s以防意外)。
|
||||
- 如果是模拟器多开用户,还需要填写`附加命令`,具体填写值参见多开模拟器对应快捷方式路径(如`-v 1`)。
|
||||
|
||||

|
||||
|
||||
|
||||
#### 设置用户配置
|
||||
|
||||
每一个脚本实例都有独立的用户数据库,您可以直接在`用户列表`选项卡配置用户相关信息,页面简介如下:
|
||||
- `新建用户`、`删除用户`:新建一个用户到当前用户配置列表、删除当前所选第一行所对应的用户。
|
||||
- `向上移动`、`向下移动`:移动用户位置,用户位置即代理顺序。
|
||||
- `模式转换`:将当前所选第一行所对应的用户转为高级/简洁配置模式。
|
||||
- `用户选项配置`:选择用户与对应配置项目,执行对应配置流程。
|
||||
- `自定义基建`:选择自定义基建配置文件。
|
||||
- `日常`、`剿灭`:打开MAA界面进行设置,设置方法与MAA全局配置相同。
|
||||
- `显示密码`:输入管理密钥以显示用户密码,仅当管理密钥正确时能够修改`密码栏目`。
|
||||
- `简洁用户配置列表`:仅支持核心代理选项的设置,其它设置选项沿用MAA的全局设置,部分代理核心功能选项由程序托管。
|
||||
- `高级用户配置列表`:支持几乎所有代理选项的设置,通过`用户选项配置`进行MAA自定义,仅部分代理核心功能选项由程序托管。
|
||||
- `用户配置列表栏目`详解如下:
|
||||
- `用户名`:展示在执行界面的用户名,用于区分不同用户。
|
||||
- `账号ID`:MAA进行账号切换所需的凭据,官服用户请输入手机号码、B服请输入B站ID。
|
||||
- `服务器`:当前支持官服、B服。
|
||||
- `代理天数`:剩余需要进行代理的天数,输入`任意负数`可设置为无限代理天数,当剩余天数为0时不再代理或排查。
|
||||
- `状态`:用户的状态,禁用时将不再对其进行代理或排查。
|
||||
- `执行情况`:当日执行情况,不可编辑。
|
||||
- `关卡`、`备选关卡-1`、`备选关卡-2`:关卡号。
|
||||
- `日常`:单独设定是否进行自动代理的日常部分,可进一步配置MAA的具体代理任务,该配置与全局MAA配置相互独立。
|
||||
- `剿灭`:单独设定是否进行自动代理的剿灭部分,高级配置模式下可进一步配置MAA的具体代理任务,该配置与全局MAA配置相互独立。
|
||||
- `自定义基建`:是否启用自定义基建功能,需要进一步配置自定义基建文件,该配置与其他用户相互独立。
|
||||
- `密码`:仅用于登记用户的密码,可留空。
|
||||
- `备注`:用于备注用户信息。
|
||||
|
||||
- 特别的:
|
||||
- 对于`简洁用户配置列表的关卡、备选关卡-1、备选关卡-2栏目`您可以自定义关卡号替换方案。
|
||||
- 程序会读取`data/gameid.txt`中的数据,依据此进行关卡号的替换,便于常用关卡的使用。
|
||||
- `gameid.txt`会在程序首次运行时生成,其中将预置一些常用资源本的替换方案。
|
||||
|
||||

|
||||
|
||||
#### 设置调度队列
|
||||
|
||||
- 单个调度队列可包含至多10个定时与至多10个任务实例。
|
||||
- 调度队列状态为关闭时,将不会定时启动该调度队列,但仍能在主调度台直接运行该调度队列。
|
||||
- 同一调度队列内任务实例被依次挨个调起运行,非同一调度队列内的不同任务实例可被同时调起。
|
||||
- 同一时间内,任何脚本实例或调度队列都不会被重复调起,若某一任务运行时发现同一任务已在运行,将自动跳过。
|
||||
|
||||
#### 设置AUTO_MAA
|
||||
|
||||
- 详见软件中对应选项卡的注解。
|
||||
|
||||
## 运行代理任务
|
||||
|
||||
### 直接运行
|
||||
|
||||
- 在`调度中心`的`主调度台`选择对应任务与`自动代理`模式,单击`开始任务`即可开始代理。
|
||||
|
||||
### 定时运行
|
||||
|
||||
- 将调度队列状态设为开启,并在`定时`选项卡设置定时启动时间。
|
||||
- 保持软件开启,软件会在设定的时间自动运行。
|
||||
|
||||
## 人工排查代理结果
|
||||
|
||||
### 直接开始人工排查
|
||||
|
||||
- 在`调度中心`的`主调度台`选择对应任务与`人工排查`模式,单击`开始任务`即可开始人工排查。
|
||||
- 软件将调起MAA,依次登录各用户的账号。
|
||||
- 完成PRTS登录后,请人工检查代理情况,可以手动完成未代理的任务。
|
||||
- 在对话框中单击对应账号的代理情况。
|
||||
- 结束人工排查后,相应排查情况将被写入用户管理页的`备注栏目`。
|
||||
- [《AUTO_MAA用户指南》](https://docs.qq.com/aio/DQ2NwUHRiWGtMWHBy)
|
||||
|
||||
---
|
||||
|
||||
@@ -213,7 +90,7 @@ MAA多账号管理与自动化软件
|
||||
|
||||
欢迎加入AUTO_MAA项目组,欢迎反馈bug
|
||||
|
||||
- QQ群:[957750551](https://qm.qq.com/q/bd9fISNoME)
|
||||
- QQ交流群:[957750551](https://qm.qq.com/q/bd9fISNoME)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -127,6 +127,8 @@ class AppConfig:
|
||||
self.queue_config = QueueConfig()
|
||||
self.maa_config = MaaConfig()
|
||||
|
||||
qconfig.load(self.config_path, self.global_config)
|
||||
|
||||
config_list = self.search_config()
|
||||
for config in config_list:
|
||||
if config[0] == "Maa":
|
||||
@@ -499,6 +501,7 @@ class AppConfig:
|
||||
|
||||
self.queue_config.set(self.queue_config.queueSet_Name, "")
|
||||
self.queue_config.set(self.queue_config.queueSet_Enabled, False)
|
||||
self.queue_config.set(self.queue_config.queueSet_AfterAccomplish, "None")
|
||||
|
||||
self.queue_config.set(self.queue_config.time_TimeEnabled_0, False)
|
||||
self.queue_config.set(self.queue_config.time_TimeSet_0, "00:00")
|
||||
@@ -541,6 +544,9 @@ class GlobalConfig(QConfig):
|
||||
)
|
||||
function_IfSilence = ConfigItem("Function", "IfSilence", False, BoolValidator())
|
||||
function_BossKey = ConfigItem("Function", "BossKey", "")
|
||||
function_IfAgreeBilibili = ConfigItem(
|
||||
"Function", "IfAgreeBilibili", False, BoolValidator()
|
||||
)
|
||||
|
||||
start_IfSelfStart = ConfigItem("Start", "IfSelfStart", False, BoolValidator())
|
||||
start_IfRunDirectly = ConfigItem("Start", "IfRunDirectly", False, BoolValidator())
|
||||
@@ -556,7 +562,10 @@ class GlobalConfig(QConfig):
|
||||
notify_IfSendErrorOnly = ConfigItem(
|
||||
"Notify", "IfSendErrorOnly", False, BoolValidator()
|
||||
)
|
||||
notify_MailAddress = ConfigItem("Notify", "MailAddress", "")
|
||||
notify_SMTPServerAddress = ConfigItem("Notify", "SMTPServerAddress", "")
|
||||
notify_AuthorizationCode = ConfigItem("Notify", "AuthorizationCode", "")
|
||||
notify_FromAddress = ConfigItem("Notify", "FromAddress", "")
|
||||
notify_ToAddress = ConfigItem("Notify", "ToAddress", "")
|
||||
notify_IfServerChan = ConfigItem("Notify", "IfServerChan", False, BoolValidator())
|
||||
notify_ServerChanKey = ConfigItem("Notify", "ServerChanKey", "")
|
||||
notify_ServerChanChannel = ConfigItem("Notify", "ServerChanChannel", "")
|
||||
@@ -579,6 +588,12 @@ class QueueConfig(QConfig):
|
||||
|
||||
queueSet_Name = ConfigItem("QueueSet", "Name", "")
|
||||
queueSet_Enabled = ConfigItem("QueueSet", "Enabled", False, BoolValidator())
|
||||
queueSet_AfterAccomplish = OptionsConfigItem(
|
||||
"QueueSet",
|
||||
"AfterAccomplish",
|
||||
"None",
|
||||
OptionsValidator(["None", "KillSelf", "Sleep", "Hibernate", "Shutdown"]),
|
||||
)
|
||||
|
||||
time_TimeEnabled_0 = ConfigItem("Time", "TimeEnabled_0", False, BoolValidator())
|
||||
time_TimeSet_0 = ConfigItem("Time", "TimeSet_0", "00:00")
|
||||
|
||||
@@ -36,14 +36,14 @@ from qfluentwidgets import (
|
||||
class _MainInfoBar:
|
||||
"""信息通知栏"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, main_window=None):
|
||||
|
||||
self.parent = parent
|
||||
self.main_window = main_window
|
||||
|
||||
def push_info_bar(self, mode: str, title: str, content: str, time: int):
|
||||
"""推送到信息通知栏"""
|
||||
|
||||
if self.parent is None:
|
||||
if self.main_window is None:
|
||||
logger.error("信息通知栏未设置父窗口")
|
||||
return None
|
||||
|
||||
@@ -55,7 +55,7 @@ class _MainInfoBar:
|
||||
isClosable=True,
|
||||
position=InfoBarPosition.TOP_RIGHT,
|
||||
duration=time,
|
||||
parent=self.parent,
|
||||
parent=self.main_window,
|
||||
)
|
||||
elif mode == "warning":
|
||||
InfoBar.warning(
|
||||
@@ -65,7 +65,7 @@ class _MainInfoBar:
|
||||
isClosable=True,
|
||||
position=InfoBarPosition.TOP_RIGHT,
|
||||
duration=time,
|
||||
parent=self.parent,
|
||||
parent=self.main_window,
|
||||
)
|
||||
elif mode == "error":
|
||||
InfoBar.error(
|
||||
@@ -75,7 +75,7 @@ class _MainInfoBar:
|
||||
isClosable=True,
|
||||
position=InfoBarPosition.TOP_RIGHT,
|
||||
duration=time,
|
||||
parent=self.parent,
|
||||
parent=self.main_window,
|
||||
)
|
||||
elif mode == "info":
|
||||
InfoBar.info(
|
||||
@@ -85,7 +85,7 @@ class _MainInfoBar:
|
||||
isClosable=True,
|
||||
position=InfoBarPosition.TOP_RIGHT,
|
||||
duration=time,
|
||||
parent=self.parent,
|
||||
parent=self.main_window,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ v4.2
|
||||
from loguru import logger
|
||||
from PySide6.QtCore import QThread, QObject, Signal
|
||||
from qfluentwidgets import Dialog
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from typing import Dict, Union
|
||||
@@ -35,6 +36,7 @@ from typing import Dict, Union
|
||||
from .config import Config
|
||||
from .main_info_bar import MainInfoBar
|
||||
from app.models import MaaManager
|
||||
from app.services import System
|
||||
|
||||
|
||||
class Task(QThread):
|
||||
@@ -52,10 +54,7 @@ class Task(QThread):
|
||||
accomplish = Signal(list)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mode: str,
|
||||
name: str,
|
||||
info: Dict[str, Dict[str, Union[str, int, bool]]],
|
||||
self, mode: str, name: str, info: Dict[str, Dict[str, Union[str, int, bool]]]
|
||||
):
|
||||
super(Task, self).__init__()
|
||||
|
||||
@@ -92,41 +91,41 @@ class Task(QThread):
|
||||
else:
|
||||
|
||||
self.member_dict = self.search_member()
|
||||
self.task_list = [
|
||||
self.task_dict = [
|
||||
[value, "等待"]
|
||||
for _, value in self.info["Queue"].items()
|
||||
if value != "禁用"
|
||||
]
|
||||
|
||||
self.create_task_list.emit(self.task_list)
|
||||
self.create_task_list.emit(self.task_dict)
|
||||
|
||||
for i in range(len(self.task_list)):
|
||||
for i in range(len(self.task_dict)):
|
||||
|
||||
if self.isInterruptionRequested():
|
||||
break
|
||||
|
||||
self.task_list[i][1] = "运行"
|
||||
self.update_task_list.emit(self.task_list)
|
||||
self.task_dict[i][1] = "运行"
|
||||
self.update_task_list.emit(self.task_dict)
|
||||
|
||||
if self.task_list[i][0] in Config.running_list:
|
||||
if self.task_dict[i][0] in Config.running_list:
|
||||
|
||||
self.task_list[i][1] = "跳过"
|
||||
self.update_task_list.emit(self.task_list)
|
||||
logger.info(f"跳过任务:{self.task_list[i][0]}")
|
||||
self.task_dict[i][1] = "跳过"
|
||||
self.update_task_list.emit(self.task_dict)
|
||||
logger.info(f"跳过任务:{self.task_dict[i][0]}")
|
||||
self.push_info_bar.emit(
|
||||
"info", "跳过任务", self.task_list[i][0], 3000
|
||||
"info", "跳过任务", self.task_dict[i][0], 3000
|
||||
)
|
||||
continue
|
||||
|
||||
Config.running_list.append(self.task_list[i][0])
|
||||
logger.info(f"任务开始:{self.task_list[i][0]}")
|
||||
self.push_info_bar.emit("info", "任务开始", self.task_list[i][0], 3000)
|
||||
Config.running_list.append(self.task_dict[i][0])
|
||||
logger.info(f"任务开始:{self.task_dict[i][0]}")
|
||||
self.push_info_bar.emit("info", "任务开始", self.task_dict[i][0], 3000)
|
||||
|
||||
if self.member_dict[self.task_list[i][0]][0] == "Maa":
|
||||
if self.member_dict[self.task_dict[i][0]][0] == "Maa":
|
||||
|
||||
self.task = MaaManager(
|
||||
self.mode[0:4],
|
||||
self.member_dict[self.task_list[i][0]][1],
|
||||
self.member_dict[self.task_dict[i][0]][1],
|
||||
)
|
||||
|
||||
self.task.question.connect(self.question.emit)
|
||||
@@ -138,7 +137,7 @@ class Task(QThread):
|
||||
self.task.update_log_text.connect(self.update_log_text.emit)
|
||||
self.task.update_user_info.connect(
|
||||
lambda modes, uids, days, lasts, notes, numbs: self.update_user_info.emit(
|
||||
self.member_dict[self.task_list[i][0]][1],
|
||||
self.member_dict[self.task_dict[i][0]][1],
|
||||
modes,
|
||||
uids,
|
||||
days,
|
||||
@@ -148,16 +147,16 @@ class Task(QThread):
|
||||
)
|
||||
)
|
||||
self.task.accomplish.connect(
|
||||
lambda log: self.save_log(self.task_list[i][0], log)
|
||||
lambda log: self.save_log(self.task_dict[i][0], log)
|
||||
)
|
||||
|
||||
self.task.run()
|
||||
|
||||
Config.running_list.remove(self.task_list[i][0])
|
||||
Config.running_list.remove(self.task_dict[i][0])
|
||||
|
||||
self.task_list[i][1] = "完成"
|
||||
logger.info(f"任务完成:{self.task_list[i][0]}")
|
||||
self.push_info_bar.emit("info", "任务完成", self.task_list[i][0], 3000)
|
||||
self.task_dict[i][1] = "完成"
|
||||
logger.info(f"任务完成:{self.task_dict[i][0]}")
|
||||
self.push_info_bar.emit("info", "任务完成", self.task_dict[i][0], 3000)
|
||||
|
||||
self.accomplish.emit(self.logs)
|
||||
|
||||
@@ -190,14 +189,14 @@ class TaskManager(QObject):
|
||||
def __init__(self):
|
||||
super(TaskManager, self).__init__()
|
||||
|
||||
self.task_list: Dict[str, Task] = {}
|
||||
self.task_dict: Dict[str, Task] = {}
|
||||
|
||||
def add_task(
|
||||
self, mode: str, name: str, info: Dict[str, Dict[str, Union[str, int, bool]]]
|
||||
):
|
||||
"""添加任务"""
|
||||
|
||||
if name in Config.running_list or name in self.task_list:
|
||||
if name in Config.running_list or name in self.task_dict:
|
||||
|
||||
logger.warning(f"任务已存在:{name}")
|
||||
MainInfoBar.push_info_bar("warning", "任务已存在", name, 5000)
|
||||
@@ -207,23 +206,23 @@ class TaskManager(QObject):
|
||||
MainInfoBar.push_info_bar("info", "任务开始", name, 3000)
|
||||
|
||||
Config.running_list.append(name)
|
||||
self.task_list[name] = Task(mode, name, info)
|
||||
self.task_list[name].question.connect(
|
||||
self.task_dict[name] = Task(mode, name, info)
|
||||
self.task_dict[name].question.connect(
|
||||
lambda title, content: self.push_dialog(name, title, content)
|
||||
)
|
||||
self.task_list[name].push_info_bar.connect(MainInfoBar.push_info_bar)
|
||||
self.task_list[name].update_user_info.connect(Config.change_user_info)
|
||||
self.task_list[name].accomplish.connect(
|
||||
lambda logs: self.remove_task(name, logs)
|
||||
self.task_dict[name].push_info_bar.connect(MainInfoBar.push_info_bar)
|
||||
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)
|
||||
)
|
||||
|
||||
if "新调度台" in mode:
|
||||
self.create_gui.emit(self.task_list[name])
|
||||
self.create_gui.emit(self.task_dict[name])
|
||||
|
||||
elif "主调度台" in mode:
|
||||
self.connect_gui.emit(self.task_list[name])
|
||||
self.connect_gui.emit(self.task_dict[name])
|
||||
|
||||
self.task_list[name].start()
|
||||
self.task_dict[name].start()
|
||||
|
||||
def stop_task(self, name: str):
|
||||
"""中止任务"""
|
||||
@@ -233,22 +232,22 @@ class TaskManager(QObject):
|
||||
|
||||
if name == "ALL":
|
||||
|
||||
for name in self.task_list:
|
||||
for name in self.task_dict:
|
||||
|
||||
self.task_list[name].task.requestInterruption()
|
||||
self.task_list[name].requestInterruption()
|
||||
self.task_list[name].quit()
|
||||
self.task_list[name].wait()
|
||||
self.task_dict[name].task.requestInterruption()
|
||||
self.task_dict[name].requestInterruption()
|
||||
self.task_dict[name].quit()
|
||||
self.task_dict[name].wait()
|
||||
|
||||
elif name in self.task_list:
|
||||
elif name in self.task_dict:
|
||||
|
||||
self.task_list[name].task.requestInterruption()
|
||||
self.task_list[name].requestInterruption()
|
||||
self.task_list[name].quit()
|
||||
self.task_list[name].wait()
|
||||
self.task_dict[name].task.requestInterruption()
|
||||
self.task_dict[name].requestInterruption()
|
||||
self.task_dict[name].quit()
|
||||
self.task_dict[name].wait()
|
||||
|
||||
def remove_task(self, name: str, logs: str):
|
||||
"""移除任务标记"""
|
||||
def remove_task(self, mode: str, name: str, logs: str):
|
||||
"""任务结束后的处理"""
|
||||
|
||||
logger.info(f"任务结束:{name}")
|
||||
MainInfoBar.push_info_bar("info", "任务结束", name, 3000)
|
||||
@@ -271,9 +270,16 @@ class TaskManager(QObject):
|
||||
},
|
||||
)
|
||||
|
||||
self.task_list.pop(name)
|
||||
self.task_dict.pop(name)
|
||||
Config.running_list.remove(name)
|
||||
|
||||
if "调度队列" in name and "人工排查" not in mode:
|
||||
with (Config.app_path / f"config/QueueConfig/{name}.json").open(
|
||||
"r", encoding="utf-8"
|
||||
) as f:
|
||||
info = json.load(f)
|
||||
System.set_power(info["QueueSet"]["AfterAccomplish"])
|
||||
|
||||
def push_dialog(self, name: str, title: str, content: str):
|
||||
"""推送对话框"""
|
||||
|
||||
@@ -281,7 +287,7 @@ class TaskManager(QObject):
|
||||
choice.yesButton.setText("是")
|
||||
choice.cancelButton.setText("否")
|
||||
|
||||
self.task_list[name].question_response.emit(bool(choice.exec_()))
|
||||
self.task_dict[name].question_response.emit(bool(choice.exec_()))
|
||||
|
||||
|
||||
Task_manager = TaskManager()
|
||||
|
||||
@@ -86,25 +86,30 @@ class MainTimer(QWidget):
|
||||
def set_silence(self):
|
||||
"""设置静默模式"""
|
||||
|
||||
windows = System.get_window_info()
|
||||
if any(
|
||||
str(emulator_path) in window
|
||||
for window in windows
|
||||
for emulator_path in Config.silence_list
|
||||
if (
|
||||
Config.global_config.get(Config.global_config.function_IfSilence)
|
||||
and Config.global_config.get(Config.global_config.function_BossKey) != ""
|
||||
):
|
||||
try:
|
||||
pyautogui.hotkey(
|
||||
*[
|
||||
_.strip().lower()
|
||||
for _ in Config.global_config.get(
|
||||
Config.global_config.function_BossKey
|
||||
).split("+")
|
||||
]
|
||||
)
|
||||
except pyautogui.FailSafeException as e:
|
||||
if not self.if_FailSafeException:
|
||||
logger.warning(f"FailSafeException: {e}")
|
||||
self.if_FailSafeException = True
|
||||
|
||||
windows = System.get_window_info()
|
||||
if any(
|
||||
str(emulator_path) in window
|
||||
for window in windows
|
||||
for emulator_path in Config.silence_list
|
||||
):
|
||||
try:
|
||||
pyautogui.hotkey(
|
||||
*[
|
||||
_.strip().lower()
|
||||
for _ in Config.global_config.get(
|
||||
Config.global_config.function_BossKey
|
||||
).split("+")
|
||||
]
|
||||
)
|
||||
except pyautogui.FailSafeException as e:
|
||||
if not self.if_FailSafeException:
|
||||
logger.warning(f"FailSafeException: {e}")
|
||||
self.if_FailSafeException = True
|
||||
|
||||
def search_queue(self) -> list:
|
||||
"""搜索所有调度队列实例"""
|
||||
|
||||
@@ -89,6 +89,7 @@ class MaaManager(QObject):
|
||||
self.maa_set_path = self.maa_root_path / "config/gui.json"
|
||||
self.maa_log_path = self.maa_root_path / "debug/gui.log"
|
||||
self.maa_exe_path = self.maa_root_path / "MAA.exe"
|
||||
self.maa_tasks_path = self.maa_root_path / "resource/tasks.json"
|
||||
|
||||
def run(self):
|
||||
"""主进程,运行MAA代理进程"""
|
||||
@@ -187,17 +188,12 @@ class MaaManager(QObject):
|
||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||
)
|
||||
# 添加静默进程标记
|
||||
if Config.global_config.get(
|
||||
Config.global_config.function_IfSilence
|
||||
):
|
||||
with self.maa_set_path.open(
|
||||
mode="r", encoding="utf-8"
|
||||
) as f:
|
||||
set = json.load(f)
|
||||
self.emulator_path = Path(
|
||||
set["Configurations"]["Default"]["Start.EmulatorPath"]
|
||||
)
|
||||
Config.silence_list.append(self.emulator_path)
|
||||
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
||||
set = json.load(f)
|
||||
self.emulator_path = Path(
|
||||
set["Configurations"]["Default"]["Start.EmulatorPath"]
|
||||
)
|
||||
Config.silence_list.append(self.emulator_path)
|
||||
# 记录是否超时的标记
|
||||
self.if_time_out = False
|
||||
|
||||
@@ -253,10 +249,7 @@ class MaaManager(QObject):
|
||||
"检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
||||
)
|
||||
# 移除静默进程标记
|
||||
if Config.global_config.get(
|
||||
Config.global_config.function_IfSilence
|
||||
):
|
||||
Config.silence_list.remove(self.emulator_path)
|
||||
Config.silence_list.remove(self.emulator_path)
|
||||
for _ in range(10):
|
||||
if self.isInterruptionRequested:
|
||||
break
|
||||
@@ -277,10 +270,7 @@ class MaaManager(QObject):
|
||||
)
|
||||
killprocess.wait()
|
||||
# 移除静默进程标记
|
||||
if Config.global_config.get(
|
||||
Config.global_config.function_IfSilence
|
||||
):
|
||||
Config.silence_list.remove(self.emulator_path)
|
||||
Config.silence_list.remove(self.emulator_path)
|
||||
# 推送异常通知
|
||||
Notify.push_notification(
|
||||
"用户自动代理出现异常!",
|
||||
@@ -513,9 +503,14 @@ class MaaManager(QObject):
|
||||
f"{"\n".join([self.data[_][0] for _ in wait_index])}\n"
|
||||
)
|
||||
|
||||
title = (
|
||||
f"{self.set["MaaSet"]["Name"]}的{self.mode[:4]}任务报告"
|
||||
if self.set["MaaSet"]["Name"] != ""
|
||||
else f"{self.mode[:4]}任务报告"
|
||||
)
|
||||
# 推送代理结果通知
|
||||
Notify.push_notification(
|
||||
f"{self.mode[2:4]}任务已完成!",
|
||||
title.replace("报告", "已完成!"),
|
||||
f"已完成用户数:{len(over_index)},未完成用户数:{len(error_index) + len(wait_index)}",
|
||||
f"已完成用户数:{len(over_index)},未完成用户数:{len(error_index) + len(wait_index)}",
|
||||
10,
|
||||
@@ -527,18 +522,13 @@ class MaaManager(QObject):
|
||||
and len(error_index) + len(wait_index) != 0
|
||||
):
|
||||
Notify.send_mail(
|
||||
f"{self.mode[:4]}任务报告",
|
||||
title,
|
||||
f"{end_log}\n\nAUTO_MAA 敬上\n\n我们根据您在 AUTO_MAA 中的设置发送了这封电子邮件,本邮件无需回复\n",
|
||||
)
|
||||
Notify.ServerChanPush(
|
||||
f"{self.mode[:4]}任务报告",
|
||||
f"{end_log}\n\nAUTO_MAA 敬上",
|
||||
)
|
||||
Notify.CompanyWebHookBotPush(
|
||||
f"{self.mode[:4]}任务报告",
|
||||
f"{end_log}AUTO_MAA 敬上",
|
||||
)
|
||||
Notify.ServerChanPush(title, f"{end_log}\n\nAUTO_MAA 敬上")
|
||||
Notify.CompanyWebHookBotPush(title, f"{end_log}AUTO_MAA 敬上")
|
||||
|
||||
self.agree_bilibili(False)
|
||||
self.accomplish.emit({"Time": begin_time, "History": end_log})
|
||||
|
||||
def requestInterruption(self) -> None:
|
||||
@@ -660,6 +650,17 @@ class MaaManager(QObject):
|
||||
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if "设置MAA" not in mode and (
|
||||
(self.data[index][15] == "simple" and self.data[index][2] == "Bilibili")
|
||||
or (
|
||||
self.data[index][15] == "beta"
|
||||
and data["Configurations"]["Default"]["Start.ClientType"] == "Bilibili"
|
||||
)
|
||||
):
|
||||
self.agree_bilibili(True)
|
||||
else:
|
||||
self.agree_bilibili(False)
|
||||
|
||||
# 自动代理配置
|
||||
if "自动代理" in mode:
|
||||
|
||||
@@ -1021,6 +1022,34 @@ class MaaManager(QObject):
|
||||
|
||||
return True
|
||||
|
||||
def agree_bilibili(self, if_agree):
|
||||
"""向MAA写入Bilibili协议相关任务"""
|
||||
|
||||
with self.maa_tasks_path.open(mode="r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if if_agree and Config.global_config.get(
|
||||
Config.global_config.function_IfAgreeBilibili
|
||||
):
|
||||
data["BilibiliAgreement_AUTO"] = {
|
||||
"algorithm": "OcrDetect",
|
||||
"action": "ClickSelf",
|
||||
"text": ["同意"],
|
||||
"maxTimes": 5,
|
||||
"Doc": "关闭B服用户协议",
|
||||
"next": ["StartUpThemes#next"],
|
||||
}
|
||||
if "BilibiliAgreement_AUTO" not in data["StartUpThemes"]["next"]:
|
||||
data["StartUpThemes"]["next"].insert(0, "BilibiliAgreement_AUTO")
|
||||
else:
|
||||
if "BilibiliAgreement_AUTO" in data:
|
||||
data.pop("BilibiliAgreement_AUTO")
|
||||
if "BilibiliAgreement_AUTO" in data["StartUpThemes"]["next"]:
|
||||
data["StartUpThemes"]["next"].remove("BilibiliAgreement_AUTO")
|
||||
|
||||
with self.maa_tasks_path.open(mode="w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
def get_emulator_path(self):
|
||||
"""获取模拟器路径"""
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ from email.utils import formataddr
|
||||
|
||||
from serverchan_sdk import sc_send
|
||||
|
||||
from app.core import Config
|
||||
from app.core import Config, MainInfoBar
|
||||
from app.services.security import Crypto
|
||||
|
||||
|
||||
class Notification:
|
||||
@@ -57,73 +58,99 @@ class Notification:
|
||||
return True
|
||||
|
||||
def send_mail(self, title, content):
|
||||
"""使用官方专用邮箱推送邮件通知"""
|
||||
|
||||
# 声明:此邮箱为AUTO_MAA项目组资产,未经授权不得私自使用
|
||||
# 注意:此声明注释只有使用者更换发信邮箱时才能删除,本条规则优先级高于GPLv3
|
||||
"""推送邮件通知"""
|
||||
|
||||
if Config.global_config.get(Config.global_config.notify_IfSendMail):
|
||||
|
||||
# 第三方 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(),
|
||||
Config.global_config.get(Config.global_config.notify_MailAddress),
|
||||
)
|
||||
) # 收件人显示的名字
|
||||
message["Subject"] = Header(title, "utf-8")
|
||||
|
||||
try:
|
||||
smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 465为SMTP_SSL默认端口
|
||||
smtpObj.login(mail_sender, mail_key)
|
||||
# 定义邮件正文
|
||||
message = MIMEText(content, "plain", "utf-8")
|
||||
message["From"] = formataddr(
|
||||
(
|
||||
Header("AUTO_MAA通知服务", "utf-8").encode(),
|
||||
Config.global_config.get(
|
||||
Config.global_config.notify_FromAddress
|
||||
),
|
||||
)
|
||||
) # 发件人显示的名字
|
||||
message["To"] = formataddr(
|
||||
(
|
||||
Header("AUTO_MAA用户", "utf-8").encode(),
|
||||
Config.global_config.get(Config.global_config.notify_ToAddress),
|
||||
)
|
||||
) # 收件人显示的名字
|
||||
message["Subject"] = Header(title, "utf-8")
|
||||
|
||||
smtpObj = smtplib.SMTP_SSL(
|
||||
Config.global_config.get(
|
||||
Config.global_config.notify_SMTPServerAddress
|
||||
),
|
||||
465,
|
||||
)
|
||||
smtpObj.login(
|
||||
Config.global_config.get(Config.global_config.notify_FromAddress),
|
||||
Crypto.win_decryptor(
|
||||
Config.global_config.get(
|
||||
Config.global_config.notify_AuthorizationCode
|
||||
)
|
||||
),
|
||||
)
|
||||
smtpObj.sendmail(
|
||||
mail_sender,
|
||||
Config.global_config.get(Config.global_config.notify_MailAddress),
|
||||
Config.global_config.get(Config.global_config.notify_FromAddress),
|
||||
Config.global_config.get(Config.global_config.notify_ToAddress),
|
||||
message.as_string(),
|
||||
)
|
||||
return True
|
||||
except smtplib.SMTPException as e:
|
||||
return f"发送邮件时出错:\n{e}"
|
||||
finally:
|
||||
smtpObj.quit()
|
||||
logger.success("邮件发送成功")
|
||||
except Exception as e:
|
||||
logger.error(f"发送邮件时出错:\n{e}")
|
||||
MainInfoBar.push_info_bar("error", "发送邮件时出错", f"{e}", -1)
|
||||
|
||||
def ServerChanPush(self, title, content):
|
||||
"""使用Server酱推送通知"""
|
||||
|
||||
if Config.global_config.get(Config.global_config.notify_IfServerChan):
|
||||
send_key = Config.global_config.get(Config.global_config.notify_ServerChanKey)
|
||||
send_key = Config.global_config.get(
|
||||
Config.global_config.notify_ServerChanKey
|
||||
)
|
||||
option = {}
|
||||
is_valid = lambda s: s == "" or (s == '|'.join(s.split('|')) and (s.count('|') == 0 or all(s.split('|'))))
|
||||
is_valid = lambda s: s == "" or (
|
||||
s == "|".join(s.split("|")) and (s.count("|") == 0 or all(s.split("|")))
|
||||
)
|
||||
"""
|
||||
is_valid => True, 如果启用的话需要正确设置Tag和Channel。
|
||||
允许空的Tag和Channel即不启用,但不允许例如a||b,|a|b,a|b|,||||
|
||||
"""
|
||||
send_tag = Config.global_config.get(Config.global_config.notify_ServerChanTag)
|
||||
send_channel = Config.global_config.get(Config.global_config.notify_ServerChanChannel)
|
||||
send_tag = Config.global_config.get(
|
||||
Config.global_config.notify_ServerChanTag
|
||||
)
|
||||
send_channel = Config.global_config.get(
|
||||
Config.global_config.notify_ServerChanChannel
|
||||
)
|
||||
|
||||
if is_valid(send_tag):
|
||||
option['tags'] = send_tag
|
||||
option["tags"] = send_tag
|
||||
else:
|
||||
option['tags'] = ''
|
||||
logger.warning('请正确设置Auto_MAA中ServerChan的Tag。')
|
||||
option["tags"] = ""
|
||||
logger.warning("请正确设置Auto_MAA中ServerChan的Tag。")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"Server酱通知推送异常",
|
||||
"请正确设置Auto_MAA中ServerChan的Tag。",
|
||||
-1,
|
||||
)
|
||||
|
||||
if is_valid(send_channel):
|
||||
option['channel'] = send_channel
|
||||
option["channel"] = send_channel
|
||||
else:
|
||||
option['channel'] = ''
|
||||
logger.warning('请正确设置Auto_MAA中ServerChan的Channel。')
|
||||
option["channel"] = ""
|
||||
logger.warning("请正确设置Auto_MAA中ServerChan的Channel。")
|
||||
MainInfoBar.push_info_bar(
|
||||
"warning",
|
||||
"Server酱通知推送异常",
|
||||
"请正确设置Auto_MAA中ServerChan的Channel。",
|
||||
-1,
|
||||
)
|
||||
|
||||
response = sc_send(send_key, title, content, option)
|
||||
if response["code"] == 0:
|
||||
@@ -132,21 +159,24 @@ class Notification:
|
||||
else:
|
||||
logger.info("Server酱推送通知失败")
|
||||
logger.error(response)
|
||||
MainInfoBar.push_info_bar(
|
||||
"error",
|
||||
"Server酱通知推送失败",
|
||||
f'使用Server酱推送通知时出错:\n{response["data"]['error']}',
|
||||
-1,
|
||||
)
|
||||
return f'使用Server酱推送通知时出错:\n{response["data"]['error']}'
|
||||
|
||||
def CompanyWebHookBotPush(self, title, content):
|
||||
"""使用企业微信群机器人推送通知"""
|
||||
if Config.global_config.get(Config.global_config.notify_IfCompanyWebHookBot):
|
||||
content = f'{title}\n{content}'
|
||||
data = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": content
|
||||
}
|
||||
}
|
||||
content = f"{title}\n{content}"
|
||||
data = {"msgtype": "text", "text": {"content": content}}
|
||||
response = requests.post(
|
||||
url=Config.global_config.get(Config.global_config.notify_CompanyWebHookBotUrl),
|
||||
json=data
|
||||
url=Config.global_config.get(
|
||||
Config.global_config.notify_CompanyWebHookBotUrl
|
||||
),
|
||||
json=data,
|
||||
)
|
||||
if response.json()["errcode"] == 0:
|
||||
logger.info("企业微信群机器人推送通知成功")
|
||||
@@ -154,7 +184,15 @@ class Notification:
|
||||
else:
|
||||
logger.info("企业微信群机器人推送通知失败")
|
||||
logger.error(response.json())
|
||||
return f'使用企业微信群机器人推送通知时出错:\n{response.json()["errmsg"]}'
|
||||
MainInfoBar.push_info_bar(
|
||||
"error",
|
||||
"企业微信群机器人通知推送失败",
|
||||
f'使用企业微信群机器人推送通知时出错:\n{response.json()["errmsg"]}',
|
||||
-1,
|
||||
)
|
||||
return (
|
||||
f'使用企业微信群机器人推送通知时出错:\n{response.json()["errmsg"]}'
|
||||
)
|
||||
|
||||
|
||||
Notify = Notification()
|
||||
|
||||
@@ -30,6 +30,8 @@ import sqlite3
|
||||
import hashlib
|
||||
import random
|
||||
import secrets
|
||||
import base64
|
||||
import win32crypt
|
||||
from pathlib import Path
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.PublicKey import RSA
|
||||
@@ -83,8 +85,8 @@ class CryptoHandler:
|
||||
private_key_local = AES_key.encrypt(pad(private_key.exportKey(), 32))
|
||||
(Config.app_path / "data/key/private_key.bin").write_bytes(private_key_local)
|
||||
|
||||
def encryptx(self, note: str) -> bytes:
|
||||
"""加密数据"""
|
||||
def AUTO_encryptor(self, note: str) -> bytes:
|
||||
"""使用AUTO_MAA的算法加密数据"""
|
||||
|
||||
# 读取RSA公钥
|
||||
public_key_local = RSA.import_key(
|
||||
@@ -95,8 +97,8 @@ class CryptoHandler:
|
||||
encrypted = cipher.encrypt(note.encode("utf-8"))
|
||||
return encrypted
|
||||
|
||||
def decryptx(self, note: bytes, PASSWORD: str) -> str:
|
||||
"""解密数据"""
|
||||
def AUTO_decryptor(self, note: bytes, PASSWORD: str) -> str:
|
||||
"""使用AUTO_MAA的算法解密数据"""
|
||||
|
||||
# 读入RSA私钥密文、盐与校验哈希值
|
||||
private_key_local = (
|
||||
@@ -150,7 +152,9 @@ class CryptoHandler:
|
||||
# 使用旧管理密钥解密
|
||||
user_data["Password"] = []
|
||||
for i in range(len(data)):
|
||||
user_data["Password"].append(self.decryptx(data[i][12], PASSWORD_old))
|
||||
user_data["Password"].append(
|
||||
self.AUTO_decryptor(data[i][12], PASSWORD_old)
|
||||
)
|
||||
cur.close()
|
||||
db.close()
|
||||
|
||||
@@ -169,7 +173,7 @@ class CryptoHandler:
|
||||
cur.execute(
|
||||
"UPDATE adminx SET password = ? WHERE mode = ? AND uid = ?",
|
||||
(
|
||||
self.encryptx(user_data["Password"][i]),
|
||||
self.AUTO_encryptor(user_data["Password"][i]),
|
||||
data[i][15],
|
||||
data[i][16],
|
||||
),
|
||||
@@ -181,6 +185,27 @@ class CryptoHandler:
|
||||
cur.close()
|
||||
db.close()
|
||||
|
||||
def win_encryptor(
|
||||
self, note: str, description: str = None, entropy: bytes = None
|
||||
) -> str:
|
||||
"""使用Windows DPAPI加密数据"""
|
||||
|
||||
encrypted = win32crypt.CryptProtectData(
|
||||
note.encode("utf-8"), description, entropy, None, None, 0
|
||||
)
|
||||
return base64.b64encode(encrypted).decode("utf-8")
|
||||
|
||||
def win_decryptor(self, note: str, entropy: bytes = None) -> str:
|
||||
"""使用Windows DPAPI解密数据"""
|
||||
|
||||
if note == "":
|
||||
return ""
|
||||
|
||||
decrypted = win32crypt.CryptUnprotectData(
|
||||
base64.b64decode(note), entropy, None, None, 0
|
||||
)
|
||||
return decrypted[1].decode("utf-8")
|
||||
|
||||
def search_member(self) -> List[Dict[str, Union[Path, list]]]:
|
||||
"""搜索所有脚本实例及其用户数据库路径"""
|
||||
|
||||
@@ -197,7 +222,9 @@ class CryptoHandler:
|
||||
def check_PASSWORD(self, PASSWORD: str) -> bool:
|
||||
"""验证管理密钥"""
|
||||
|
||||
return bool(self.decryptx(self.encryptx(""), PASSWORD) != "管理密钥错误")
|
||||
return bool(
|
||||
self.AUTO_decryptor(self.AUTO_encryptor(""), PASSWORD) != "管理密钥错误"
|
||||
)
|
||||
|
||||
|
||||
Crypto = CryptoHandler()
|
||||
|
||||
@@ -25,21 +25,27 @@ v4.2
|
||||
作者:DLmaster_361
|
||||
"""
|
||||
|
||||
from loguru import logger
|
||||
from PySide6.QtWidgets import QWidget
|
||||
import sys
|
||||
import ctypes
|
||||
import win32gui
|
||||
import win32process
|
||||
import winreg
|
||||
import psutil
|
||||
import subprocess
|
||||
|
||||
from app.core import Config
|
||||
|
||||
|
||||
class SystemHandler:
|
||||
class _SystemHandler:
|
||||
|
||||
ES_CONTINUOUS = 0x80000000
|
||||
ES_SYSTEM_REQUIRED = 0x00000001
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, main_window: QWidget = None):
|
||||
|
||||
self.main_window = main_window
|
||||
|
||||
self.set_Sleep()
|
||||
self.set_SelfStart()
|
||||
@@ -84,6 +90,60 @@ class SystemHandler:
|
||||
winreg.DeleteValue(key, "AUTO_MAA")
|
||||
winreg.CloseKey(key)
|
||||
|
||||
def set_power(self, mode):
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
|
||||
if mode == "None":
|
||||
|
||||
logger.info("不执行系统电源操作")
|
||||
|
||||
elif mode == "Shutdown":
|
||||
|
||||
logger.info("执行关机操作")
|
||||
subprocess.run(["shutdown", "/s", "/t", "0"])
|
||||
|
||||
elif mode == "Hibernate":
|
||||
|
||||
logger.info("执行休眠操作")
|
||||
subprocess.run(["shutdown", "/h"])
|
||||
|
||||
elif mode == "Sleep":
|
||||
|
||||
logger.info("执行睡眠操作")
|
||||
subprocess.run(
|
||||
["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"]
|
||||
)
|
||||
|
||||
elif mode == "KillSelf":
|
||||
|
||||
self.main_window.close()
|
||||
|
||||
elif sys.platform.startswith("linux"):
|
||||
|
||||
if mode == "None":
|
||||
|
||||
logger.info("不执行系统电源操作")
|
||||
|
||||
elif mode == "Shutdown":
|
||||
|
||||
logger.info("执行关机操作")
|
||||
subprocess.run(["shutdown", "-h", "now"])
|
||||
|
||||
elif mode == "Hibernate":
|
||||
|
||||
logger.info("执行休眠操作")
|
||||
subprocess.run(["systemctl", "hibernate"])
|
||||
|
||||
elif mode == "Sleep":
|
||||
|
||||
logger.info("执行睡眠操作")
|
||||
subprocess.run(["systemctl", "suspend"])
|
||||
|
||||
elif mode == "KillSelf":
|
||||
|
||||
self.main_window.close()
|
||||
|
||||
def is_startup(self):
|
||||
"""判断程序是否已经开机自启"""
|
||||
|
||||
@@ -117,4 +177,4 @@ class SystemHandler:
|
||||
return window_info
|
||||
|
||||
|
||||
System = SystemHandler()
|
||||
System = _SystemHandler()
|
||||
|
||||
@@ -44,14 +44,15 @@ from qfluentwidgets import (
|
||||
TimeEdit,
|
||||
OptionsConfigItem,
|
||||
)
|
||||
|
||||
from typing import Union, List
|
||||
|
||||
from app.services import Crypto
|
||||
|
||||
class InputMessageBox(MessageBoxBase):
|
||||
|
||||
class LineEditMessageBox(MessageBoxBase):
|
||||
"""输入对话框"""
|
||||
|
||||
def __init__(self, parent, title: str, content: str, mode: str, list: list = None):
|
||||
def __init__(self, parent, title: str, content: str, mode: str):
|
||||
super().__init__(parent)
|
||||
self.title = SubtitleLabel(title)
|
||||
|
||||
@@ -60,10 +61,6 @@ class InputMessageBox(MessageBoxBase):
|
||||
self.input.setClearButtonEnabled(True)
|
||||
elif mode == "密码":
|
||||
self.input = PasswordLineEdit()
|
||||
elif mode == "选择":
|
||||
self.input = ComboBox()
|
||||
self.input.addItems(list)
|
||||
self.input.setCurrentIndex(-1)
|
||||
|
||||
self.input.setPlaceholderText(content)
|
||||
|
||||
@@ -72,8 +69,8 @@ class InputMessageBox(MessageBoxBase):
|
||||
self.viewLayout.addWidget(self.input)
|
||||
|
||||
|
||||
class SetMessageBox(MessageBoxBase):
|
||||
"""输入对话框"""
|
||||
class ComboBoxMessageBox(MessageBoxBase):
|
||||
"""选择对话框"""
|
||||
|
||||
def __init__(self, parent, title: str, content: List[str], list: List[List[str]]):
|
||||
super().__init__(parent)
|
||||
@@ -98,7 +95,7 @@ class SetMessageBox(MessageBoxBase):
|
||||
|
||||
|
||||
class LineEditSettingCard(SettingCard):
|
||||
"""Setting card with switch button"""
|
||||
"""Setting card with LineEdit"""
|
||||
|
||||
textChanged = Signal(str)
|
||||
|
||||
@@ -138,7 +135,49 @@ class LineEditSettingCard(SettingCard):
|
||||
self.LineEdit.setText(content)
|
||||
|
||||
|
||||
class PasswordLineEditSettingCard(SettingCard):
|
||||
"""Setting card with PasswordLineEdit"""
|
||||
|
||||
textChanged = Signal(str)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
text,
|
||||
icon: Union[str, QIcon, FluentIconBase],
|
||||
title,
|
||||
content=None,
|
||||
configItem: ConfigItem = None,
|
||||
parent=None,
|
||||
):
|
||||
|
||||
super().__init__(icon, title, content, parent)
|
||||
self.configItem = configItem
|
||||
self.LineEdit = PasswordLineEdit(self)
|
||||
self.LineEdit.setMinimumWidth(250)
|
||||
self.LineEdit.setPlaceholderText(text)
|
||||
|
||||
if configItem:
|
||||
self.setValue(qconfig.get(configItem))
|
||||
configItem.valueChanged.connect(self.setValue)
|
||||
|
||||
self.hBoxLayout.addWidget(self.LineEdit, 0, Qt.AlignRight)
|
||||
self.hBoxLayout.addSpacing(16)
|
||||
|
||||
self.LineEdit.textChanged.connect(self.__textChanged)
|
||||
|
||||
def __textChanged(self, content: str):
|
||||
self.setValue(Crypto.win_encryptor(content))
|
||||
self.textChanged.emit(content)
|
||||
|
||||
def setValue(self, content: str):
|
||||
if self.configItem:
|
||||
qconfig.set(self.configItem, content)
|
||||
|
||||
self.LineEdit.setText(Crypto.win_decryptor(content))
|
||||
|
||||
|
||||
class SpinBoxSettingCard(SettingCard):
|
||||
"""Setting card with SpinBox"""
|
||||
|
||||
textChanged = Signal(int)
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ class DispatchBox(QWidget):
|
||||
|
||||
logger.info(f"用户添加任务:{name}")
|
||||
Task_manager.add_task(
|
||||
f"{self.mode.currentText()}_主调度台", "用户自定义队列", info
|
||||
f"{self.mode.currentText()}_主调度台", "自定义队列", info
|
||||
)
|
||||
|
||||
class DispatchInfoCard(HeaderCardWidget):
|
||||
|
||||
@@ -68,7 +68,8 @@ class AUTO_MAA(MSFluentWindow):
|
||||
self.splashScreen = SplashScreen(self.windowIcon(), self)
|
||||
self.show_ui("显示主窗口", if_quick=True)
|
||||
|
||||
MainInfoBar.parent = self
|
||||
MainInfoBar.main_window = self.window()
|
||||
System.main_window = self.window()
|
||||
|
||||
# 创建主窗口
|
||||
self.setting = Setting(self)
|
||||
@@ -161,7 +162,7 @@ class AUTO_MAA(MSFluentWindow):
|
||||
|
||||
# 退出主程序菜单项
|
||||
self.tray_menu.addAction(
|
||||
Action(FluentIcon.POWER_BUTTON, "退出主程序", triggered=self.kill_main)
|
||||
Action(FluentIcon.POWER_BUTTON, "退出主程序", triggered=self.window().close)
|
||||
)
|
||||
|
||||
# 设置托盘菜单
|
||||
@@ -222,7 +223,7 @@ class AUTO_MAA(MSFluentWindow):
|
||||
else:
|
||||
|
||||
self.titleBar.minBtn.clicked.disconnect()
|
||||
self.titleBar.minBtn.clicked.connect(self.showMinimized)
|
||||
self.titleBar.minBtn.clicked.connect(self.window().showMinimized)
|
||||
|
||||
def on_tray_activated(self, reason):
|
||||
"""双击返回主界面"""
|
||||
@@ -264,11 +265,6 @@ class AUTO_MAA(MSFluentWindow):
|
||||
# 3,
|
||||
# )
|
||||
|
||||
def kill_main(self) -> None:
|
||||
"""退出主程序"""
|
||||
self.close()
|
||||
QApplication.quit()
|
||||
|
||||
def show_ui(self, mode: str, if_quick: bool = False) -> None:
|
||||
"""配置窗口状态"""
|
||||
|
||||
@@ -289,11 +285,11 @@ class AUTO_MAA(MSFluentWindow):
|
||||
),
|
||||
)
|
||||
)
|
||||
self.setGeometry(location[0], location[1], size[0], size[1])
|
||||
self.show()
|
||||
self.window().setGeometry(location[0], location[1], size[0], size[1])
|
||||
self.window().show()
|
||||
if not if_quick:
|
||||
if Config.global_config.get(Config.global_config.ui_maximized):
|
||||
self.showMaximized()
|
||||
self.window().showMaximized()
|
||||
self.set_min_method()
|
||||
self.show_ui("配置托盘")
|
||||
|
||||
@@ -307,7 +303,7 @@ class AUTO_MAA(MSFluentWindow):
|
||||
elif mode == "隐藏到托盘":
|
||||
|
||||
# 保存窗口相关属性
|
||||
if not self.isMaximized():
|
||||
if not self.window().isMaximized():
|
||||
|
||||
Config.global_config.set(
|
||||
Config.global_config.ui_size,
|
||||
@@ -318,14 +314,14 @@ class AUTO_MAA(MSFluentWindow):
|
||||
f"{self.geometry().x()}x{self.geometry().y()}",
|
||||
)
|
||||
Config.global_config.set(
|
||||
Config.global_config.ui_maximized, self.isMaximized()
|
||||
Config.global_config.ui_maximized, self.window().isMaximized()
|
||||
)
|
||||
Config.global_config.save()
|
||||
|
||||
# 隐藏主窗口
|
||||
if not if_quick:
|
||||
|
||||
self.hide()
|
||||
self.window().hide()
|
||||
self.tray.show()
|
||||
|
||||
def closeEvent(self, event: QCloseEvent):
|
||||
@@ -342,6 +338,6 @@ class AUTO_MAA(MSFluentWindow):
|
||||
Config.close_database()
|
||||
|
||||
logger.info("AUTO_MAA主程序关闭")
|
||||
logger.info("===================================")
|
||||
logger.info("----------------END----------------")
|
||||
|
||||
event.accept()
|
||||
|
||||
@@ -59,10 +59,10 @@ import shutil
|
||||
from app.core import Config, MainInfoBar, Task_manager
|
||||
from app.services import Crypto
|
||||
from .Widget import (
|
||||
InputMessageBox,
|
||||
LineEditMessageBox,
|
||||
LineEditSettingCard,
|
||||
SpinBoxSettingCard,
|
||||
SetMessageBox,
|
||||
ComboBoxMessageBox,
|
||||
)
|
||||
|
||||
|
||||
@@ -123,16 +123,15 @@ class MemberManager(QWidget):
|
||||
def add_setting_box(self):
|
||||
"""添加一个脚本实例"""
|
||||
|
||||
choice = InputMessageBox(
|
||||
self,
|
||||
"选择一个脚本类型并添加相应脚本实例",
|
||||
"选择脚本类型",
|
||||
"选择",
|
||||
["MAA"],
|
||||
choice = ComboBoxMessageBox(
|
||||
self.window(),
|
||||
"选择一个脚本类型以添加相应脚本实例",
|
||||
["选择脚本类型"],
|
||||
[["MAA"]],
|
||||
)
|
||||
if choice.exec() and choice.input.currentIndex() != -1:
|
||||
if choice.exec() and choice.input[0].currentIndex() != -1:
|
||||
|
||||
if choice.input.currentText() == "MAA":
|
||||
if choice.input[0].currentText() == "MAA":
|
||||
|
||||
index = len(self.member_manager.search_member()) + 1
|
||||
|
||||
@@ -170,7 +169,7 @@ class MemberManager(QWidget):
|
||||
choice = MessageBox(
|
||||
"确认",
|
||||
f"确定要删除 {name} 实例吗?",
|
||||
self,
|
||||
self.window(),
|
||||
)
|
||||
if choice.exec():
|
||||
|
||||
@@ -295,8 +294,8 @@ class MemberManager(QWidget):
|
||||
def show_password(self):
|
||||
|
||||
if Config.PASSWORD == "":
|
||||
choice = InputMessageBox(
|
||||
self,
|
||||
choice = LineEditMessageBox(
|
||||
self.window(),
|
||||
"请输入管理密钥",
|
||||
"管理密钥",
|
||||
"密码",
|
||||
@@ -535,7 +534,11 @@ class MaaSettingBox(QWidget):
|
||||
|
||||
def PathClicked(self):
|
||||
|
||||
folder = QFileDialog.getExistingDirectory(self, "选择MAA目录", "./")
|
||||
folder = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
"选择MAA目录",
|
||||
Config.maa_config.get(Config.maa_config.MaaSet_Path),
|
||||
)
|
||||
if (
|
||||
not folder
|
||||
or Config.maa_config.get(Config.maa_config.MaaSet_Path) == folder
|
||||
@@ -690,8 +693,8 @@ class MaaSettingBox(QWidget):
|
||||
user_list = [_[0] for _ in data if _[15] == "simple"]
|
||||
set_list = ["自定义基建"]
|
||||
|
||||
choice = SetMessageBox(
|
||||
self.parent().parent().parent().parent().parent().parent().parent(),
|
||||
choice = ComboBoxMessageBox(
|
||||
self.window(),
|
||||
"用户选项配置",
|
||||
["选择要配置的用户", "选择要配置的选项"],
|
||||
[user_list, set_list],
|
||||
@@ -730,8 +733,8 @@ class MaaSettingBox(QWidget):
|
||||
user_list = [_[0] for _ in data if _[15] == "beta"]
|
||||
set_list = ["MAA日常配置", "MAA剿灭配置"]
|
||||
|
||||
choice = SetMessageBox(
|
||||
self.parent().parent().parent().parent().parent().parent().parent(),
|
||||
choice = ComboBoxMessageBox(
|
||||
self.window(),
|
||||
"用户选项配置",
|
||||
["选择要配置的用户", "选择要配置的选项"],
|
||||
[user_list, set_list],
|
||||
@@ -985,7 +988,7 @@ class MaaSettingBox(QWidget):
|
||||
item = QTableWidgetItem("******")
|
||||
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
else:
|
||||
result = Crypto.decryptx(value, Config.PASSWORD)
|
||||
result = Crypto.AUTO_decryptor(value, Config.PASSWORD)
|
||||
item = QTableWidgetItem(result)
|
||||
if result == "管理密钥错误":
|
||||
item.setFlags(
|
||||
@@ -1052,7 +1055,7 @@ class MaaSettingBox(QWidget):
|
||||
item = QTableWidgetItem("******")
|
||||
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
else:
|
||||
result = Crypto.decryptx(value, Config.PASSWORD)
|
||||
result = Crypto.AUTO_decryptor(value, Config.PASSWORD)
|
||||
item = QTableWidgetItem(result)
|
||||
if result == "管理密钥错误":
|
||||
item.setFlags(
|
||||
@@ -1123,7 +1126,7 @@ class MaaSettingBox(QWidget):
|
||||
games[game_in.strip()] = game_out.strip()
|
||||
text = games.get(text, text)
|
||||
if item.column() == 11: # 密码
|
||||
text = Crypto.encryptx(text)
|
||||
text = Crypto.AUTO_encryptor(text)
|
||||
|
||||
# 保存至本地数据库
|
||||
if text != "":
|
||||
@@ -1141,7 +1144,7 @@ class MaaSettingBox(QWidget):
|
||||
self.update_user_info("normal")
|
||||
return None
|
||||
if item.column() == 6: # 密码
|
||||
text = Crypto.encryptx(text)
|
||||
text = Crypto.AUTO_encryptor(text)
|
||||
|
||||
# 保存至本地数据库
|
||||
if text != "":
|
||||
@@ -1223,7 +1226,7 @@ class MaaSettingBox(QWidget):
|
||||
Config.cur.execute(
|
||||
"INSERT INTO adminx VALUES('新用户','手机号码(官服)/B站ID(B服)','Official',-1,'y','2000-01-01','1-7','-','-','n','n','n',?,'无',0,?,?)",
|
||||
(
|
||||
Crypto.encryptx("未设置"),
|
||||
Crypto.AUTO_encryptor("未设置"),
|
||||
set_book[0],
|
||||
set_book[1],
|
||||
),
|
||||
@@ -1273,15 +1276,7 @@ class MaaSettingBox(QWidget):
|
||||
choice = MessageBox(
|
||||
"确认",
|
||||
f"确定要删除用户 {data[0][0]} 吗?",
|
||||
self.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent(),
|
||||
self.window(),
|
||||
)
|
||||
|
||||
# 删除用户
|
||||
@@ -1570,15 +1565,7 @@ class MaaSettingBox(QWidget):
|
||||
choice = MessageBox(
|
||||
"确认",
|
||||
f"确定要将用户 {data[0][0]} 转为{mode_list[1 - mode]}配置模式吗?",
|
||||
self.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent(),
|
||||
self.window(),
|
||||
)
|
||||
|
||||
# 切换用户
|
||||
|
||||
@@ -43,6 +43,7 @@ from qfluentwidgets import (
|
||||
TextBrowser,
|
||||
CommandBar,
|
||||
SwitchSettingCard,
|
||||
ComboBoxSettingCard,
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
from typing import List
|
||||
@@ -138,7 +139,7 @@ class QueueManager(QWidget):
|
||||
choice = MessageBox(
|
||||
"确认",
|
||||
f"确定要删除 {name} 吗?",
|
||||
self,
|
||||
self.window(),
|
||||
)
|
||||
if choice.exec():
|
||||
|
||||
@@ -412,9 +413,23 @@ class QueueMemberSettingBox(QWidget):
|
||||
"调度队列状态",
|
||||
Config.queue_config.queueSet_Enabled,
|
||||
)
|
||||
self.card_AfterAccomplish = ComboBoxSettingCard(
|
||||
configItem=Config.queue_config.queueSet_AfterAccomplish,
|
||||
icon=FluentIcon.POWER_BUTTON,
|
||||
title="调度队列结束后",
|
||||
content="选择调度队列结束后的操作",
|
||||
texts=[
|
||||
"无动作",
|
||||
"退出AUTO_MAA",
|
||||
"睡眠(win系统需禁用休眠)",
|
||||
"休眠",
|
||||
"关机",
|
||||
],
|
||||
)
|
||||
|
||||
Layout.addWidget(self.card_Name)
|
||||
Layout.addWidget(self.card_Enable)
|
||||
Layout.addWidget(self.card_AfterAccomplish)
|
||||
|
||||
self.viewLayout.addLayout(Layout)
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ import requests
|
||||
from app.core import Config, MainInfoBar
|
||||
from app.services import Crypto, System
|
||||
from app.utils import Updater
|
||||
from .Widget import InputMessageBox, LineEditSettingCard
|
||||
from .Widget import LineEditMessageBox, LineEditSettingCard, PasswordLineEditSettingCard
|
||||
|
||||
|
||||
class Setting(QWidget):
|
||||
@@ -83,6 +83,7 @@ class Setting(QWidget):
|
||||
self.other = OtherSettingCard(self)
|
||||
|
||||
self.function.card_IfAllowSleep.checkedChanged.connect(System.set_Sleep)
|
||||
self.function.card_IfAgreeBilibili.checkedChanged.connect(self.agree_bilibili)
|
||||
self.start.card_IfSelfStart.checkedChanged.connect(System.set_SelfStart)
|
||||
self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD)
|
||||
self.updater.card_CheckUpdate.clicked.connect(self.get_update)
|
||||
@@ -102,6 +103,31 @@ class Setting(QWidget):
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def agree_bilibili(self) -> None:
|
||||
"""授权bilibili游戏隐私政策"""
|
||||
|
||||
if not Config.global_config.get(Config.global_config.function_IfAgreeBilibili):
|
||||
logger.info("取消授权bilibili游戏隐私政策")
|
||||
MainInfoBar.push_info_bar(
|
||||
"info", "操作成功", "已取消授权bilibili游戏隐私政策", 3000
|
||||
)
|
||||
return None
|
||||
|
||||
choice = MessageBox(
|
||||
"授权声明",
|
||||
"开启“托管bilibili游戏隐私政策”功能,即代表您已完整阅读并同意《哔哩哔哩弹幕网用户使用协议》、《哔哩哔哩隐私政策》和《哔哩哔哩游戏中心用户协议》,并授权AUTO_MAA在其认定需要时以其认定合适的方法替您处理相关弹窗\n\n是否同意授权?",
|
||||
self.window(),
|
||||
)
|
||||
if choice.exec():
|
||||
logger.success("确认授权bilibili游戏隐私政策")
|
||||
MainInfoBar.push_info_bar(
|
||||
"success", "操作成功", "已确认授权bilibili游戏隐私政策", 3000
|
||||
)
|
||||
else:
|
||||
Config.global_config.set(
|
||||
Config.global_config.function_IfAgreeBilibili, False
|
||||
)
|
||||
|
||||
def check_PASSWORD(self) -> None:
|
||||
"""检查并配置管理密钥"""
|
||||
|
||||
@@ -110,8 +136,8 @@ class Setting(QWidget):
|
||||
|
||||
while True:
|
||||
|
||||
choice = InputMessageBox(
|
||||
self.parent().parent().parent(),
|
||||
choice = LineEditMessageBox(
|
||||
self.window(),
|
||||
"未检测到管理密钥,请设置您的管理密钥",
|
||||
"管理密钥",
|
||||
"密码",
|
||||
@@ -123,12 +149,11 @@ class Setting(QWidget):
|
||||
choice = MessageBox(
|
||||
"警告",
|
||||
"您没有设置管理密钥,无法使用本软件,请先设置管理密钥",
|
||||
self.parent().parent().parent(),
|
||||
self.window(),
|
||||
)
|
||||
choice.cancelButton.hide()
|
||||
choice.buttonLayout.insertStretch(1)
|
||||
if choice.exec():
|
||||
pass
|
||||
choice.exec()
|
||||
|
||||
def change_PASSWORD(self) -> None:
|
||||
"""修改管理密钥"""
|
||||
@@ -137,8 +162,8 @@ class Setting(QWidget):
|
||||
|
||||
while if_change:
|
||||
|
||||
choice = InputMessageBox(
|
||||
self,
|
||||
choice = LineEditMessageBox(
|
||||
self.window(),
|
||||
"请输入旧的管理密钥",
|
||||
"旧管理密钥",
|
||||
"密码",
|
||||
@@ -152,8 +177,8 @@ class Setting(QWidget):
|
||||
# 获取新的管理密钥
|
||||
while True:
|
||||
|
||||
choice = InputMessageBox(
|
||||
self,
|
||||
choice = LineEditMessageBox(
|
||||
self.window(),
|
||||
"请输入新的管理密钥",
|
||||
"新管理密钥",
|
||||
"密码",
|
||||
@@ -173,23 +198,22 @@ class Setting(QWidget):
|
||||
choice = MessageBox(
|
||||
"确认",
|
||||
"您没有输入新的管理密钥,是否取消修改管理密钥?",
|
||||
self,
|
||||
self.window(),
|
||||
)
|
||||
if choice.exec():
|
||||
if_change = False
|
||||
break
|
||||
|
||||
else:
|
||||
choice = MessageBox("错误", "管理密钥错误", self)
|
||||
choice = MessageBox("错误", "管理密钥错误", self.window())
|
||||
choice.cancelButton.hide()
|
||||
choice.buttonLayout.insertStretch(1)
|
||||
if choice.exec():
|
||||
pass
|
||||
choice.exec()
|
||||
else:
|
||||
choice = MessageBox(
|
||||
"确认",
|
||||
"您没有输入管理密钥,是否取消修改管理密钥?",
|
||||
self,
|
||||
self.window(),
|
||||
)
|
||||
if choice.exec():
|
||||
break
|
||||
@@ -261,7 +285,7 @@ class Setting(QWidget):
|
||||
choice = MessageBox(
|
||||
"错误",
|
||||
f"获取版本信息时出错:\n{err}",
|
||||
self,
|
||||
self.window(),
|
||||
)
|
||||
choice.cancelButton.hide()
|
||||
choice.buttonLayout.insertStretch(1)
|
||||
@@ -297,7 +321,7 @@ class Setting(QWidget):
|
||||
choice = MessageBox(
|
||||
"版本更新",
|
||||
f"发现新版本:\n{main_version_info}{updater_version_info} 更新说明:\n{version_remote['announcement'].replace("\n# ","\n !").replace("\n## ","\n - ").replace("\n- ","\n · ")}\n\n是否开始更新?\n\n 注意:主程序更新时AUTO_MAA将自动关闭",
|
||||
self,
|
||||
self.window(),
|
||||
)
|
||||
if not choice.exec():
|
||||
return None
|
||||
@@ -400,10 +424,17 @@ class FunctionSettingCard(HeaderCardWidget):
|
||||
configItem=Config.global_config.function_IfAllowSleep,
|
||||
)
|
||||
self.card_IfSilence = self.SilenceSettingCard(self)
|
||||
self.card_IfAgreeBilibili = SwitchSettingCard(
|
||||
icon=FluentIcon.PAGE_RIGHT,
|
||||
title="托管bilibili游戏隐私政策",
|
||||
content="授权AUTO_MAA同意bilibili游戏隐私政策",
|
||||
configItem=Config.global_config.function_IfAgreeBilibili,
|
||||
)
|
||||
|
||||
Layout = QVBoxLayout()
|
||||
Layout.addWidget(self.card_IfAllowSleep)
|
||||
Layout.addWidget(self.card_IfSilence)
|
||||
Layout.addWidget(self.card_IfAgreeBilibili)
|
||||
self.viewLayout.addLayout(Layout)
|
||||
|
||||
class SilenceSettingCard(ExpandGroupSettingCard):
|
||||
@@ -526,7 +557,7 @@ class NotifySettingCard(HeaderCardWidget):
|
||||
super().__init__(
|
||||
FluentIcon.SETTING,
|
||||
"推送邮件通知",
|
||||
"通过AUTO_MAA官方通知服务邮箱推送任务结果",
|
||||
"通过电子邮箱推送任务结果",
|
||||
parent,
|
||||
)
|
||||
|
||||
@@ -536,18 +567,42 @@ class NotifySettingCard(HeaderCardWidget):
|
||||
content="是否启用邮件通知功能",
|
||||
configItem=Config.global_config.notify_IfSendMail,
|
||||
)
|
||||
self.card_MailAddress = LineEditSettingCard(
|
||||
text="请输入邮箱地址",
|
||||
self.card_SMTPServerAddress = LineEditSettingCard(
|
||||
text="请输入SMTP服务器地址",
|
||||
icon=FluentIcon.PAGE_RIGHT,
|
||||
title="邮箱地址",
|
||||
title="SMTP服务器地址",
|
||||
content="发信邮箱的SMTP服务器地址",
|
||||
configItem=Config.global_config.notify_SMTPServerAddress,
|
||||
)
|
||||
self.card_FromAddress = LineEditSettingCard(
|
||||
text="请输入发信邮箱地址",
|
||||
icon=FluentIcon.PAGE_RIGHT,
|
||||
title="发信邮箱地址",
|
||||
content="发送通知的邮箱地址",
|
||||
configItem=Config.global_config.notify_FromAddress,
|
||||
)
|
||||
self.card_AuthorizationCode = PasswordLineEditSettingCard(
|
||||
text="请输入发信邮箱授权码",
|
||||
icon=FluentIcon.PAGE_RIGHT,
|
||||
title="发信邮箱授权码",
|
||||
content="发送通知的邮箱授权码",
|
||||
configItem=Config.global_config.notify_AuthorizationCode,
|
||||
)
|
||||
self.card_ToAddress = LineEditSettingCard(
|
||||
text="请输入收信邮箱地址",
|
||||
icon=FluentIcon.PAGE_RIGHT,
|
||||
title="收信邮箱地址",
|
||||
content="接收通知的邮箱地址",
|
||||
configItem=Config.global_config.notify_MailAddress,
|
||||
configItem=Config.global_config.notify_ToAddress,
|
||||
)
|
||||
|
||||
widget = QWidget()
|
||||
Layout = QVBoxLayout(widget)
|
||||
Layout.addWidget(self.card_IfSendMail)
|
||||
Layout.addWidget(self.card_MailAddress)
|
||||
Layout.addWidget(self.card_SMTPServerAddress)
|
||||
Layout.addWidget(self.card_FromAddress)
|
||||
Layout.addWidget(self.card_AuthorizationCode)
|
||||
Layout.addWidget(self.card_ToAddress)
|
||||
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.viewLayout.setSpacing(0)
|
||||
self.addGroupWidget(widget)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"main_version": "4.2.2.2",
|
||||
"main_version": "4.2.3.0",
|
||||
"updater_version": "1.1.1.3",
|
||||
"announcement": "\n## 新增功能\n- 添加用户每日代理次数上限功能 #15\n- 新增代理成功消息推送渠道Server酱与企业微信群机器人推送\n- 添加更新类别可选项\n## 修复BUG\n- 修复自定义基建无法正常使用的问题\n- 修正人工排查文案\n- 修复高级MAA配置序号错位\n- 修复高级用户列表无法配置问题\n- 修复主调度台选项乱动问题\n- 修复更新器文件夹定位问题\n## 程序优化\n- 无",
|
||||
"announcement": "\n## 新增功能\n- 添加用户每日代理次数上限功能 #15\n- 新增代理成功消息推送渠道Server酱与企业微信群机器人推送\n- 添加更新类别可选项\n- 添加调度队列完成任务后行为选项\n- 初步完成`托管bilibili游戏隐私政策`功能\n## 修复BUG\n- 修复自定义基建无法正常使用的问题\n- 修正人工排查文案\n- 修复高级MAA配置序号错位\n- 修复高级用户列表无法配置问题\n- 修复主调度台选项乱动问题\n- 修复更新器文件夹定位问题\n- 修复窗口记忆功能失效问题\n## 程序优化\n- 优化弹窗逻辑\n- 优化静默判定逻辑\n- 调整MAA设置目录时打开当前已配置的目录位置\n- 邮箱推送功能调整,改由用户提供发信邮箱",
|
||||
"proxy_list": [
|
||||
"",
|
||||
"https://gitproxy.click/",
|
||||
|
||||
Reference in New Issue
Block a user