Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4dbf4736e4 | ||
|
|
d50504181e | ||
|
|
c7e94dfcd1 | ||
|
|
a752b67ca1 | ||
|
|
078736337d | ||
|
|
de1058a28c | ||
|
|
740797a689 | ||
|
|
26328920a2 | ||
|
|
9c447bbdf9 | ||
|
|
fac85a889f | ||
|
|
f5d898c89e | ||
| 974a4b634a | |||
| 3127c83603 | |||
|
|
8d69e43f72 | ||
|
|
86df9e7a50 | ||
| 59ff9bf818 | |||
|
|
1641e32e3d | ||
|
|
a482087abd | ||
| bc5b15cec2 | |||
| 3787c25a77 | |||
|
|
0b06b499e4 | ||
|
|
04079dd57b | ||
|
|
34ac0c5ab3 | ||
| 0d904b229e | |||
| c0f887ff9d | |||
|
|
cf95075d01 | ||
|
|
d78a764d87 | ||
|
|
a368f4b722 | ||
|
|
803fe4568f | ||
|
|
1162d5dcc1 | ||
|
|
aa83058e39 | ||
|
|
061f205224 | ||
|
|
5d966f98df | ||
|
|
0037914db8 | ||
|
|
13d0115475 | ||
|
|
5bdb5ad2bf | ||
| a5d733c8df | |||
|
|
0b038e2997 | ||
|
|
5e46040db6 | ||
|
|
f2b04dd0f6 | ||
|
|
2177c1b40e | ||
|
|
d1f4cffe8f | ||
|
|
74ce441b90 | ||
|
|
5893aa2426 |
9
.github/workflows/build-app.yml
vendored
9
.github/workflows/build-app.yml
vendored
@@ -73,8 +73,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
$MAIN_VERSION=(Get-Content -Path "version_info.txt" -TotalCount 1).Trim()
|
$MAIN_VERSION=(Get-Content -Path "version_info.txt" -TotalCount 1).Trim()
|
||||||
"AUTO_MAA_version=$MAIN_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
|
"AUTO_MAA_version=$MAIN_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||||
$UPDATER_VERSION=(Get-Content -Path "version_info.txt" -TotalCount 2 | Select-Object -Index 1).Trim()
|
|
||||||
"updater_version=$UPDATER_VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -111,8 +109,11 @@ jobs:
|
|||||||
NAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
NAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
||||||
TAGNAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
TAGNAME="$(sed 's/\r$//g' <(head -n 1 version_info.txt))"
|
||||||
NOTES_MAIN="$(sed 's/\r$//g' <(tail -n +3 version_info.txt))"
|
NOTES_MAIN="$(sed 's/\r$//g' <(tail -n +3 version_info.txt))"
|
||||||
NOTES_TAIL="\`\`\`本release通过GitHub Actions自动构建\`\`\`"
|
NOTES="$NOTES_MAIN
|
||||||
NOTES="$NOTES_MAIN<br><br>$NOTES_TAIL"
|
|
||||||
|
[已有 Mirror酱 CDK ?前往 Mirror酱 高速下载](https://mirrorchyan.com/zh/projects?rid=AUTO_MAA)
|
||||||
|
|
||||||
|
\`\`\`本release通过GitHub Actions自动构建\`\`\`"
|
||||||
if [ "${{ github.ref_name }}" == "main" ]; then
|
if [ "${{ github.ref_name }}" == "main" ]; then
|
||||||
PRERELEASE_FLAG=""
|
PRERELEASE_FLAG=""
|
||||||
else
|
else
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -22,6 +22,11 @@
|
|||||||
|
|
||||||
本软件是明日方舟第三方软件`MAA`的第三方工具,即第3<sup>3</sup>方软件。旨在优化MAA多账号功能体验,并通过一些方法解决MAA项目未能解决的部分问题,提高代理的稳定性。
|
本软件是明日方舟第三方软件`MAA`的第三方工具,即第3<sup>3</sup>方软件。旨在优化MAA多账号功能体验,并通过一些方法解决MAA项目未能解决的部分问题,提高代理的稳定性。
|
||||||
|
|
||||||
|
- **集中管理**:一站式管理多个MAA脚本与多个用户配置,和凌乱的散装脚本窗口说再见!
|
||||||
|
- **无人值守**:自动处理MAA相关报错,再也不用为代理任务卡死时自己不在电脑旁烦恼啦!
|
||||||
|
- **配置灵活**:通过调度队列与脚本的组合,自由实现您能想到的所有调度需求!
|
||||||
|
- **信息统计**:自动统计用户的公招与关卡掉落物,看看这个月您的收益是多少!
|
||||||
|
|
||||||
### 原理
|
### 原理
|
||||||
|
|
||||||
本软件可以存储多个明日方舟账号数据,并通过以下流程实现代理功能:
|
本软件可以存储多个明日方舟账号数据,并通过以下流程实现代理功能:
|
||||||
@@ -32,11 +37,9 @@
|
|||||||
|
|
||||||
### 优势
|
### 优势
|
||||||
|
|
||||||
- **节省运行开销:** 只需要一份MAA软件与一个模拟器,无需多开就能完成多账号代理,羸弱的电脑也能代理日常。
|
- **高效稳定**:通过日志监测、异常处理等机制,保障代理任务顺利完成。
|
||||||
- **自定义空间大:** 依靠高级用户配置模式,支持MAA几乎所有设置选项自定义,支持模拟器多开。
|
- **简洁易用**:无需手动修改配置文件,实现自动化调度与多开管理。
|
||||||
- **调度方法自由:** 通过调度队列功能,自由实现MAA多开等多种调度方式。
|
- **兼容扩展**:支持 MAA 几乎所有的配置选项,满足不同用户需求。
|
||||||
- **一键代理无忧:** 无须中途手动修改MAA配置,将繁琐交给AUTO_MAA,把游戏留给自己。
|
|
||||||
- **代理结果复核:** 通过人工排查功能核实各用户代理情况,堵住自动代理的最后一丝风险。
|
|
||||||
|
|
||||||
## 重要声明
|
## 重要声明
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ __version__ = "4.2.0"
|
|||||||
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
__license__ = "GPL-3.0 license"
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
from .config import QueueConfig, MaaConfig, MaaUserConfig, Config
|
from .config import QueueConfig, MaaConfig, MaaUserConfig, MaaPlanConfig, Config
|
||||||
from .main_info_bar import MainInfoBar
|
from .main_info_bar import MainInfoBar
|
||||||
from .network import Network
|
from .network import Network
|
||||||
from .task_manager import Task, TaskManager
|
from .task_manager import Task, TaskManager
|
||||||
@@ -40,6 +40,7 @@ __all__ = [
|
|||||||
"QueueConfig",
|
"QueueConfig",
|
||||||
"MaaConfig",
|
"MaaConfig",
|
||||||
"MaaUserConfig",
|
"MaaUserConfig",
|
||||||
|
"MaaPlanConfig",
|
||||||
"MainInfoBar",
|
"MainInfoBar",
|
||||||
"Network",
|
"Network",
|
||||||
"Task",
|
"Task",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import sys
|
|||||||
import shutil
|
import shutil
|
||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
|
import calendar
|
||||||
from datetime import datetime, timedelta, date
|
from datetime import datetime, timedelta, date
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -78,7 +79,78 @@ class UrlListValidator(ConfigValidator):
|
|||||||
return list(set([_ for _ in urls if self.validate(_)]))
|
return list(set([_ for _ in urls if self.validate(_)]))
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig(QConfig):
|
class LQConfig(QConfig):
|
||||||
|
"""局域配置类"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def toDict(self, serialize=True):
|
||||||
|
"""convert config items to `dict`"""
|
||||||
|
items = {}
|
||||||
|
for name in dir(self._cfg):
|
||||||
|
item = getattr(self._cfg, name)
|
||||||
|
if not isinstance(item, ConfigItem):
|
||||||
|
continue
|
||||||
|
|
||||||
|
value = item.serialize() if serialize else item.value
|
||||||
|
if not items.get(item.group):
|
||||||
|
if not item.name:
|
||||||
|
items[item.group] = value
|
||||||
|
else:
|
||||||
|
items[item.group] = {}
|
||||||
|
|
||||||
|
if item.name:
|
||||||
|
items[item.group][item.name] = value
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
||||||
|
@exceptionHandler()
|
||||||
|
def load(self, file=None, config=None):
|
||||||
|
"""load config
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
file: str or Path
|
||||||
|
the path of json config file
|
||||||
|
|
||||||
|
config: Config
|
||||||
|
config object to be initialized
|
||||||
|
"""
|
||||||
|
if isinstance(config, QConfig):
|
||||||
|
self._cfg = config
|
||||||
|
self._cfg.themeChanged.connect(self.themeChanged)
|
||||||
|
|
||||||
|
if isinstance(file, (str, Path)):
|
||||||
|
self._cfg.file = Path(file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(self._cfg.file, encoding="utf-8") as f:
|
||||||
|
cfg = json.load(f)
|
||||||
|
except:
|
||||||
|
cfg = {}
|
||||||
|
|
||||||
|
# map config items'key to item
|
||||||
|
items = {}
|
||||||
|
for name in dir(self._cfg):
|
||||||
|
item = getattr(self._cfg, name)
|
||||||
|
if isinstance(item, ConfigItem):
|
||||||
|
items[item.key] = item
|
||||||
|
|
||||||
|
# update the value of config item
|
||||||
|
for k, v in cfg.items():
|
||||||
|
if not isinstance(v, dict) and items.get(k) is not None:
|
||||||
|
items[k].deserializeFrom(v)
|
||||||
|
elif isinstance(v, dict):
|
||||||
|
for key, value in v.items():
|
||||||
|
key = k + "." + key
|
||||||
|
if items.get(key) is not None:
|
||||||
|
items[key].deserializeFrom(value)
|
||||||
|
|
||||||
|
self.theme = self.get(self._cfg.themeMode)
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalConfig(LQConfig):
|
||||||
"""全局配置"""
|
"""全局配置"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -163,10 +235,6 @@ class GlobalConfig(QConfig):
|
|||||||
self.notify_CompanyWebHookBotUrl = ConfigItem(
|
self.notify_CompanyWebHookBotUrl = ConfigItem(
|
||||||
"Notify", "CompanyWebHookBotUrl", ""
|
"Notify", "CompanyWebHookBotUrl", ""
|
||||||
)
|
)
|
||||||
self.notify_IfPushDeer = ConfigItem(
|
|
||||||
"Notify", "IfPushDeer", False, BoolValidator()
|
|
||||||
)
|
|
||||||
self.notify_IfPushDeerKey = ConfigItem("Notify", "PushDeerKey", "")
|
|
||||||
|
|
||||||
self.update_IfAutoUpdate = ConfigItem(
|
self.update_IfAutoUpdate = ConfigItem(
|
||||||
"Update", "IfAutoUpdate", False, BoolValidator()
|
"Update", "IfAutoUpdate", False, BoolValidator()
|
||||||
@@ -182,72 +250,8 @@ class GlobalConfig(QConfig):
|
|||||||
)
|
)
|
||||||
self.update_MirrorChyanCDK = ConfigItem("Update", "MirrorChyanCDK", "")
|
self.update_MirrorChyanCDK = ConfigItem("Update", "MirrorChyanCDK", "")
|
||||||
|
|
||||||
def toDict(self, serialize=True):
|
|
||||||
"""convert config items to `dict`"""
|
|
||||||
items = {}
|
|
||||||
for name in dir(self._cfg):
|
|
||||||
item = getattr(self._cfg, name)
|
|
||||||
if not isinstance(item, ConfigItem):
|
|
||||||
continue
|
|
||||||
|
|
||||||
value = item.serialize() if serialize else item.value
|
class QueueConfig(LQConfig):
|
||||||
if not items.get(item.group):
|
|
||||||
if not item.name:
|
|
||||||
items[item.group] = value
|
|
||||||
else:
|
|
||||||
items[item.group] = {}
|
|
||||||
|
|
||||||
if item.name:
|
|
||||||
items[item.group][item.name] = value
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
@exceptionHandler()
|
|
||||||
def load(self, file=None, config=None):
|
|
||||||
"""load config
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
file: str or Path
|
|
||||||
the path of json config file
|
|
||||||
|
|
||||||
config: Config
|
|
||||||
config object to be initialized
|
|
||||||
"""
|
|
||||||
if isinstance(config, QConfig):
|
|
||||||
self._cfg = config
|
|
||||||
self._cfg.themeChanged.connect(self.themeChanged)
|
|
||||||
|
|
||||||
if isinstance(file, (str, Path)):
|
|
||||||
self._cfg.file = Path(file)
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(self._cfg.file, encoding="utf-8") as f:
|
|
||||||
cfg = json.load(f)
|
|
||||||
except:
|
|
||||||
cfg = {}
|
|
||||||
|
|
||||||
# map config items'key to item
|
|
||||||
items = {}
|
|
||||||
for name in dir(self._cfg):
|
|
||||||
item = getattr(self._cfg, name)
|
|
||||||
if isinstance(item, ConfigItem):
|
|
||||||
items[item.key] = item
|
|
||||||
|
|
||||||
# update the value of config item
|
|
||||||
for k, v in cfg.items():
|
|
||||||
if not isinstance(v, dict) and items.get(k) is not None:
|
|
||||||
items[k].deserializeFrom(v)
|
|
||||||
elif isinstance(v, dict):
|
|
||||||
for key, value in v.items():
|
|
||||||
key = k + "." + key
|
|
||||||
if items.get(key) is not None:
|
|
||||||
items[key].deserializeFrom(value)
|
|
||||||
|
|
||||||
self.theme = self.get(self._cfg.themeMode)
|
|
||||||
|
|
||||||
|
|
||||||
class QueueConfig(QConfig):
|
|
||||||
"""队列配置"""
|
"""队列配置"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -260,8 +264,10 @@ class QueueConfig(QConfig):
|
|||||||
self.queueSet_AfterAccomplish = OptionsConfigItem(
|
self.queueSet_AfterAccomplish = OptionsConfigItem(
|
||||||
"QueueSet",
|
"QueueSet",
|
||||||
"AfterAccomplish",
|
"AfterAccomplish",
|
||||||
"None",
|
"NoAction",
|
||||||
OptionsValidator(["None", "KillSelf", "Sleep", "Hibernate", "Shutdown"]),
|
OptionsValidator(
|
||||||
|
["NoAction", "KillSelf", "Sleep", "Hibernate", "Shutdown"]
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.time_TimeEnabled_0 = ConfigItem(
|
self.time_TimeEnabled_0 = ConfigItem(
|
||||||
@@ -332,72 +338,8 @@ class QueueConfig(QConfig):
|
|||||||
"Data", "LastProxyHistory", "暂无历史运行记录"
|
"Data", "LastProxyHistory", "暂无历史运行记录"
|
||||||
)
|
)
|
||||||
|
|
||||||
def toDict(self, serialize=True):
|
|
||||||
"""convert config items to `dict`"""
|
|
||||||
items = {}
|
|
||||||
for name in dir(self._cfg):
|
|
||||||
item = getattr(self._cfg, name)
|
|
||||||
if not isinstance(item, ConfigItem):
|
|
||||||
continue
|
|
||||||
|
|
||||||
value = item.serialize() if serialize else item.value
|
class MaaConfig(LQConfig):
|
||||||
if not items.get(item.group):
|
|
||||||
if not item.name:
|
|
||||||
items[item.group] = value
|
|
||||||
else:
|
|
||||||
items[item.group] = {}
|
|
||||||
|
|
||||||
if item.name:
|
|
||||||
items[item.group][item.name] = value
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
@exceptionHandler()
|
|
||||||
def load(self, file=None, config=None):
|
|
||||||
"""load config
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
file: str or Path
|
|
||||||
the path of json config file
|
|
||||||
|
|
||||||
config: Config
|
|
||||||
config object to be initialized
|
|
||||||
"""
|
|
||||||
if isinstance(config, QConfig):
|
|
||||||
self._cfg = config
|
|
||||||
self._cfg.themeChanged.connect(self.themeChanged)
|
|
||||||
|
|
||||||
if isinstance(file, (str, Path)):
|
|
||||||
self._cfg.file = Path(file)
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(self._cfg.file, encoding="utf-8") as f:
|
|
||||||
cfg = json.load(f)
|
|
||||||
except:
|
|
||||||
cfg = {}
|
|
||||||
|
|
||||||
# map config items'key to item
|
|
||||||
items = {}
|
|
||||||
for name in dir(self._cfg):
|
|
||||||
item = getattr(self._cfg, name)
|
|
||||||
if isinstance(item, ConfigItem):
|
|
||||||
items[item.key] = item
|
|
||||||
|
|
||||||
# update the value of config item
|
|
||||||
for k, v in cfg.items():
|
|
||||||
if not isinstance(v, dict) and items.get(k) is not None:
|
|
||||||
items[k].deserializeFrom(v)
|
|
||||||
elif isinstance(v, dict):
|
|
||||||
for key, value in v.items():
|
|
||||||
key = k + "." + key
|
|
||||||
if items.get(key) is not None:
|
|
||||||
items[key].deserializeFrom(value)
|
|
||||||
|
|
||||||
self.theme = self.get(self._cfg.themeMode)
|
|
||||||
|
|
||||||
|
|
||||||
class MaaConfig(QConfig):
|
|
||||||
"""MAA配置"""
|
"""MAA配置"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -415,6 +357,9 @@ class MaaConfig(QConfig):
|
|||||||
self.RunSet_ProxyTimesLimit = RangeConfigItem(
|
self.RunSet_ProxyTimesLimit = RangeConfigItem(
|
||||||
"RunSet", "ProxyTimesLimit", 0, RangeValidator(0, 1024)
|
"RunSet", "ProxyTimesLimit", 0, RangeValidator(0, 1024)
|
||||||
)
|
)
|
||||||
|
self.RunSet_ADBSearchRange = RangeConfigItem(
|
||||||
|
"RunSet", "ADBSearchRange", 0, RangeValidator(0, 3)
|
||||||
|
)
|
||||||
self.RunSet_RunTimesLimit = RangeConfigItem(
|
self.RunSet_RunTimesLimit = RangeConfigItem(
|
||||||
"RunSet", "RunTimesLimit", 3, RangeValidator(1, 1024)
|
"RunSet", "RunTimesLimit", 3, RangeValidator(1, 1024)
|
||||||
)
|
)
|
||||||
@@ -431,72 +376,8 @@ class MaaConfig(QConfig):
|
|||||||
"RunSet", "AutoUpdateMaa", False, BoolValidator()
|
"RunSet", "AutoUpdateMaa", False, BoolValidator()
|
||||||
)
|
)
|
||||||
|
|
||||||
def toDict(self, serialize=True):
|
|
||||||
"""convert config items to `dict`"""
|
|
||||||
items = {}
|
|
||||||
for name in dir(self._cfg):
|
|
||||||
item = getattr(self._cfg, name)
|
|
||||||
if not isinstance(item, ConfigItem):
|
|
||||||
continue
|
|
||||||
|
|
||||||
value = item.serialize() if serialize else item.value
|
class MaaUserConfig(LQConfig):
|
||||||
if not items.get(item.group):
|
|
||||||
if not item.name:
|
|
||||||
items[item.group] = value
|
|
||||||
else:
|
|
||||||
items[item.group] = {}
|
|
||||||
|
|
||||||
if item.name:
|
|
||||||
items[item.group][item.name] = value
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
@exceptionHandler()
|
|
||||||
def load(self, file=None, config=None):
|
|
||||||
"""load config
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
file: str or Path
|
|
||||||
the path of json config file
|
|
||||||
|
|
||||||
config: Config
|
|
||||||
config object to be initialized
|
|
||||||
"""
|
|
||||||
if isinstance(config, QConfig):
|
|
||||||
self._cfg = config
|
|
||||||
self._cfg.themeChanged.connect(self.themeChanged)
|
|
||||||
|
|
||||||
if isinstance(file, (str, Path)):
|
|
||||||
self._cfg.file = Path(file)
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(self._cfg.file, encoding="utf-8") as f:
|
|
||||||
cfg = json.load(f)
|
|
||||||
except:
|
|
||||||
cfg = {}
|
|
||||||
|
|
||||||
# map config items'key to item
|
|
||||||
items = {}
|
|
||||||
for name in dir(self._cfg):
|
|
||||||
item = getattr(self._cfg, name)
|
|
||||||
if isinstance(item, ConfigItem):
|
|
||||||
items[item.key] = item
|
|
||||||
|
|
||||||
# update the value of config item
|
|
||||||
for k, v in cfg.items():
|
|
||||||
if not isinstance(v, dict) and items.get(k) is not None:
|
|
||||||
items[k].deserializeFrom(v)
|
|
||||||
elif isinstance(v, dict):
|
|
||||||
for key, value in v.items():
|
|
||||||
key = k + "." + key
|
|
||||||
if items.get(key) is not None:
|
|
||||||
items[key].deserializeFrom(value)
|
|
||||||
|
|
||||||
self.theme = self.get(self._cfg.themeMode)
|
|
||||||
|
|
||||||
|
|
||||||
class MaaUserConfig(QConfig):
|
|
||||||
"""MAA用户配置"""
|
"""MAA用户配置"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -507,9 +388,7 @@ class MaaUserConfig(QConfig):
|
|||||||
self.Info_Mode = OptionsConfigItem(
|
self.Info_Mode = OptionsConfigItem(
|
||||||
"Info", "Mode", "简洁", OptionsValidator(["简洁", "详细"])
|
"Info", "Mode", "简洁", OptionsValidator(["简洁", "详细"])
|
||||||
)
|
)
|
||||||
self.Info_GameIdMode = OptionsConfigItem(
|
self.Info_GameIdMode = ConfigItem("Info", "GameIdMode", "固定")
|
||||||
"Info", "GameIdMode", "固定", OptionsValidator(["固定"])
|
|
||||||
)
|
|
||||||
self.Info_Server = OptionsConfigItem(
|
self.Info_Server = OptionsConfigItem(
|
||||||
"Info", "Server", "Official", OptionsValidator(["Official", "Bilibili"])
|
"Info", "Server", "Official", OptionsValidator(["Official", "Bilibili"])
|
||||||
)
|
)
|
||||||
@@ -535,8 +414,8 @@ class MaaUserConfig(QConfig):
|
|||||||
self.Info_SeriesNumb = OptionsConfigItem(
|
self.Info_SeriesNumb = OptionsConfigItem(
|
||||||
"Info",
|
"Info",
|
||||||
"SeriesNumb",
|
"SeriesNumb",
|
||||||
"1",
|
"0",
|
||||||
OptionsValidator(["1000", "6", "5", "4", "3", "2", "1", "-1"]),
|
OptionsValidator(["0", "6", "5", "4", "3", "2", "1", "-1"]),
|
||||||
)
|
)
|
||||||
self.Info_GameId = ConfigItem("Info", "GameId", "-")
|
self.Info_GameId = ConfigItem("Info", "GameId", "-")
|
||||||
self.Info_GameId_1 = ConfigItem("Info", "GameId_1", "-")
|
self.Info_GameId_1 = ConfigItem("Info", "GameId_1", "-")
|
||||||
@@ -555,78 +434,145 @@ class MaaUserConfig(QConfig):
|
|||||||
"Data", "CustomInfrastPlanIndex", "0"
|
"Data", "CustomInfrastPlanIndex", "0"
|
||||||
)
|
)
|
||||||
|
|
||||||
def toDict(self, serialize=True):
|
self.Task_IfWakeUp = ConfigItem("Task", "IfWakeUp", True, BoolValidator())
|
||||||
"""convert config items to `dict`"""
|
self.Task_IfRecruiting = ConfigItem(
|
||||||
items = {}
|
"Task", "IfRecruiting", True, BoolValidator()
|
||||||
for name in dir(self._cfg):
|
)
|
||||||
item = getattr(self._cfg, name)
|
self.Task_IfBase = ConfigItem("Task", "IfBase", True, BoolValidator())
|
||||||
if not isinstance(item, ConfigItem):
|
self.Task_IfCombat = ConfigItem("Task", "IfCombat", True, BoolValidator())
|
||||||
continue
|
self.Task_IfMall = ConfigItem("Task", "IfMall", True, BoolValidator())
|
||||||
|
self.Task_IfMission = ConfigItem("Task", "IfMission", True, BoolValidator())
|
||||||
|
self.Task_IfAutoRoguelike = ConfigItem(
|
||||||
|
"Task", "IfAutoRoguelike", False, BoolValidator()
|
||||||
|
)
|
||||||
|
self.Task_IfReclamation = ConfigItem(
|
||||||
|
"Task", "IfReclamation", False, BoolValidator()
|
||||||
|
)
|
||||||
|
|
||||||
value = item.serialize() if serialize else item.value
|
self.Notify_Enabled = ConfigItem("Notify", "Enabled", False, BoolValidator())
|
||||||
if not items.get(item.group):
|
self.Notify_IfSendStatistic = ConfigItem(
|
||||||
if not item.name:
|
"Notify", "IfSendStatistic", False, BoolValidator()
|
||||||
items[item.group] = value
|
)
|
||||||
else:
|
self.Notify_IfSendSixStar = ConfigItem(
|
||||||
items[item.group] = {}
|
"Notify", "IfSendSixStar", False, BoolValidator()
|
||||||
|
)
|
||||||
|
self.Notify_IfSendMail = ConfigItem(
|
||||||
|
"Notify", "IfSendMail", False, BoolValidator()
|
||||||
|
)
|
||||||
|
self.Notify_ToAddress = ConfigItem("Notify", "ToAddress", "")
|
||||||
|
self.Notify_IfServerChan = ConfigItem(
|
||||||
|
"Notify", "IfServerChan", False, BoolValidator()
|
||||||
|
)
|
||||||
|
self.Notify_ServerChanKey = ConfigItem("Notify", "ServerChanKey", "")
|
||||||
|
self.Notify_ServerChanChannel = ConfigItem("Notify", "ServerChanChannel", "")
|
||||||
|
self.Notify_ServerChanTag = ConfigItem("Notify", "ServerChanTag", "")
|
||||||
|
self.Notify_IfCompanyWebHookBot = ConfigItem(
|
||||||
|
"Notify", "IfCompanyWebHookBot", False, BoolValidator()
|
||||||
|
)
|
||||||
|
self.Notify_CompanyWebHookBotUrl = ConfigItem(
|
||||||
|
"Notify", "CompanyWebHookBotUrl", ""
|
||||||
|
)
|
||||||
|
|
||||||
if item.name:
|
def get_plan_info(self) -> Dict[str, Union[str, int]]:
|
||||||
items[item.group][item.name] = value
|
"""获取当前的计划下信息"""
|
||||||
|
|
||||||
return items
|
if self.get(self.Info_GameIdMode) == "固定":
|
||||||
|
return {
|
||||||
|
"MedicineNumb": self.get(self.Info_MedicineNumb),
|
||||||
|
"SeriesNumb": self.get(self.Info_SeriesNumb),
|
||||||
|
"GameId": self.get(self.Info_GameId),
|
||||||
|
"GameId_1": self.get(self.Info_GameId_1),
|
||||||
|
"GameId_2": self.get(self.Info_GameId_2),
|
||||||
|
"GameId_Remain": self.get(self.Info_GameId_Remain),
|
||||||
|
}
|
||||||
|
elif "计划" in self.get(self.Info_GameIdMode):
|
||||||
|
plan = Config.plan_dict[self.get(self.Info_GameIdMode)]["Config"]
|
||||||
|
return {
|
||||||
|
"MedicineNumb": plan.get(plan.get_current_info("MedicineNumb")),
|
||||||
|
"SeriesNumb": plan.get(plan.get_current_info("SeriesNumb")),
|
||||||
|
"GameId": plan.get(plan.get_current_info("GameId")),
|
||||||
|
"GameId_1": plan.get(plan.get_current_info("GameId_1")),
|
||||||
|
"GameId_2": plan.get(plan.get_current_info("GameId_2")),
|
||||||
|
"GameId_Remain": plan.get(plan.get_current_info("GameId_Remain")),
|
||||||
|
}
|
||||||
|
|
||||||
@exceptionHandler()
|
|
||||||
def load(self, file=None, config=None):
|
|
||||||
"""load config
|
|
||||||
|
|
||||||
Parameters
|
class MaaPlanConfig(LQConfig):
|
||||||
----------
|
"""MAA计划表配置"""
|
||||||
file: str or Path
|
|
||||||
the path of json config file
|
|
||||||
|
|
||||||
config: Config
|
def __init__(self) -> None:
|
||||||
config object to be initialized
|
super().__init__()
|
||||||
"""
|
|
||||||
if isinstance(config, QConfig):
|
|
||||||
self._cfg = config
|
|
||||||
self._cfg.themeChanged.connect(self.themeChanged)
|
|
||||||
|
|
||||||
if isinstance(file, (str, Path)):
|
self.Info_Name = ConfigItem("Info", "Name", "")
|
||||||
self._cfg.file = Path(file)
|
self.Info_Mode = OptionsConfigItem(
|
||||||
|
"Info", "Mode", "ALL", OptionsValidator(["ALL", "Weekly"])
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
self.config_item_dict: dict[str, Dict[str, ConfigItem]] = {}
|
||||||
with open(self._cfg.file, encoding="utf-8") as f:
|
|
||||||
cfg = json.load(f)
|
|
||||||
except:
|
|
||||||
cfg = {}
|
|
||||||
|
|
||||||
# map config items'key to item
|
for group in [
|
||||||
items = {}
|
"ALL",
|
||||||
for name in dir(self._cfg):
|
"Monday",
|
||||||
item = getattr(self._cfg, name)
|
"Tuesday",
|
||||||
if isinstance(item, ConfigItem):
|
"Wednesday",
|
||||||
items[item.key] = item
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday",
|
||||||
|
"Sunday",
|
||||||
|
]:
|
||||||
|
self.config_item_dict[group] = {}
|
||||||
|
|
||||||
# update the value of config item
|
self.config_item_dict[group]["MedicineNumb"] = ConfigItem(
|
||||||
for k, v in cfg.items():
|
group, "MedicineNumb", 0, RangeValidator(0, 1024)
|
||||||
if not isinstance(v, dict) and items.get(k) is not None:
|
)
|
||||||
items[k].deserializeFrom(v)
|
self.config_item_dict[group]["SeriesNumb"] = OptionsConfigItem(
|
||||||
elif isinstance(v, dict):
|
group,
|
||||||
for key, value in v.items():
|
"SeriesNumb",
|
||||||
key = k + "." + key
|
"0",
|
||||||
if items.get(key) is not None:
|
OptionsValidator(["0", "6", "5", "4", "3", "2", "1", "-1"]),
|
||||||
items[key].deserializeFrom(value)
|
)
|
||||||
|
self.config_item_dict[group]["GameId"] = ConfigItem(group, "GameId", "-")
|
||||||
|
self.config_item_dict[group]["GameId_1"] = ConfigItem(
|
||||||
|
group, "GameId_1", "-"
|
||||||
|
)
|
||||||
|
self.config_item_dict[group]["GameId_2"] = ConfigItem(
|
||||||
|
group, "GameId_2", "-"
|
||||||
|
)
|
||||||
|
self.config_item_dict[group]["GameId_Remain"] = ConfigItem(
|
||||||
|
group, "GameId_Remain", "-"
|
||||||
|
)
|
||||||
|
|
||||||
self.theme = self.get(self._cfg.themeMode)
|
for name in [
|
||||||
|
"MedicineNumb",
|
||||||
|
"SeriesNumb",
|
||||||
|
"GameId",
|
||||||
|
"GameId_1",
|
||||||
|
"GameId_2",
|
||||||
|
"GameId_Remain",
|
||||||
|
]:
|
||||||
|
setattr(self, f"{group}_{name}", self.config_item_dict[group][name])
|
||||||
|
|
||||||
|
def get_current_info(self, name: str) -> ConfigItem:
|
||||||
|
"""获取当前的计划表配置项"""
|
||||||
|
|
||||||
|
if self.get(self.Info_Mode) == "ALL":
|
||||||
|
return self.config_item_dict["ALL"][name]
|
||||||
|
elif self.get(self.Info_Mode) == "Weekly":
|
||||||
|
today = datetime.now().strftime("%A")
|
||||||
|
if today in self.config_item_dict:
|
||||||
|
return self.config_item_dict[today][name]
|
||||||
|
else:
|
||||||
|
return self.config_item_dict["ALL"][name]
|
||||||
|
|
||||||
|
|
||||||
class AppConfig(GlobalConfig):
|
class AppConfig(GlobalConfig):
|
||||||
|
|
||||||
VERSION = "4.3.7.0"
|
VERSION = "4.3.8.0"
|
||||||
|
|
||||||
gameid_refreshed = Signal()
|
gameid_refreshed = Signal()
|
||||||
PASSWORD_refreshed = Signal()
|
PASSWORD_refreshed = Signal()
|
||||||
user_info_changed = Signal()
|
user_info_changed = Signal()
|
||||||
|
power_sign_changed = Signal()
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -645,10 +591,18 @@ class AppConfig(GlobalConfig):
|
|||||||
self.PASSWORD = ""
|
self.PASSWORD = ""
|
||||||
self.running_list = []
|
self.running_list = []
|
||||||
self.silence_list = []
|
self.silence_list = []
|
||||||
|
self.info_bar_list = []
|
||||||
self.gameid_dict = {
|
self.gameid_dict = {
|
||||||
"ALL": {"value": [], "text": []},
|
"ALL": {"value": [], "text": []},
|
||||||
"Today": {"value": [], "text": []},
|
"Monday": {"value": [], "text": []},
|
||||||
|
"Tuesday": {"value": [], "text": []},
|
||||||
|
"Wednesday": {"value": [], "text": []},
|
||||||
|
"Thursday": {"value": [], "text": []},
|
||||||
|
"Friday": {"value": [], "text": []},
|
||||||
|
"Saturday": {"value": [], "text": []},
|
||||||
|
"Sunday": {"value": [], "text": []},
|
||||||
}
|
}
|
||||||
|
self.power_sign = "NoAction"
|
||||||
self.if_ignore_silence = False
|
self.if_ignore_silence = False
|
||||||
self.if_database_opened = False
|
self.if_database_opened = False
|
||||||
|
|
||||||
@@ -700,7 +654,7 @@ class AppConfig(GlobalConfig):
|
|||||||
# 从MAA服务器获取活动关卡信息
|
# 从MAA服务器获取活动关卡信息
|
||||||
Network.set_info(
|
Network.set_info(
|
||||||
mode="get",
|
mode="get",
|
||||||
url="https://ota.maa.plus/MaaAssistantArknights/api/gui/StageActivity.json",
|
url="https://api.maa.plus/MaaAssistantArknights/api/gui/StageActivity.json",
|
||||||
)
|
)
|
||||||
Network.start()
|
Network.start()
|
||||||
Network.loop.exec()
|
Network.loop.exec()
|
||||||
@@ -712,7 +666,7 @@ class AppConfig(GlobalConfig):
|
|||||||
logger.warning(f"无法从MAA服务器获取活动关卡信息:{Network.error_message}")
|
logger.warning(f"无法从MAA服务器获取活动关卡信息:{Network.error_message}")
|
||||||
gameid_infos = []
|
gameid_infos = []
|
||||||
|
|
||||||
gameid_dict = {"value": [], "text": []}
|
ss_gameid_dict = {"value": [], "text": []}
|
||||||
|
|
||||||
for gameid_info in gameid_infos:
|
for gameid_info in gameid_infos:
|
||||||
|
|
||||||
@@ -725,53 +679,11 @@ class AppConfig(GlobalConfig):
|
|||||||
gameid_info["Activity"]["UtcExpireTime"], "%Y/%m/%d %H:%M:%S"
|
gameid_info["Activity"]["UtcExpireTime"], "%Y/%m/%d %H:%M:%S"
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
gameid_dict["value"].append(gameid_info["Value"])
|
ss_gameid_dict["value"].append(gameid_info["Value"])
|
||||||
gameid_dict["text"].append(gameid_info["Value"])
|
ss_gameid_dict["text"].append(gameid_info["Value"])
|
||||||
|
|
||||||
# 生成全部关卡信息
|
# 生成每日关卡信息
|
||||||
self.gameid_dict["ALL"]["value"] = gameid_dict["value"] + [
|
gameid_daily_info = [
|
||||||
"-",
|
|
||||||
"1-7",
|
|
||||||
"R8-11",
|
|
||||||
"12-17-HARD",
|
|
||||||
"CE-6",
|
|
||||||
"AP-5",
|
|
||||||
"CA-5",
|
|
||||||
"LS-6",
|
|
||||||
"SK-5",
|
|
||||||
"PR-A-1",
|
|
||||||
"PR-A-2",
|
|
||||||
"PR-B-1",
|
|
||||||
"PR-B-2",
|
|
||||||
"PR-C-1",
|
|
||||||
"PR-C-2",
|
|
||||||
"PR-D-1",
|
|
||||||
"PR-D-2",
|
|
||||||
]
|
|
||||||
self.gameid_dict["ALL"]["text"] = gameid_dict["text"] + [
|
|
||||||
"当前/上次",
|
|
||||||
"1-7",
|
|
||||||
"R8-11",
|
|
||||||
"12-17-HARD",
|
|
||||||
"龙门币-6/5",
|
|
||||||
"红票-5",
|
|
||||||
"技能-5",
|
|
||||||
"经验-6/5",
|
|
||||||
"碳-5",
|
|
||||||
"奶/盾芯片",
|
|
||||||
"奶/盾芯片组",
|
|
||||||
"术/狙芯片",
|
|
||||||
"术/狙芯片组",
|
|
||||||
"先/辅芯片",
|
|
||||||
"先/辅芯片组",
|
|
||||||
"近/特芯片",
|
|
||||||
"近/特芯片组",
|
|
||||||
]
|
|
||||||
|
|
||||||
# 生成本日关卡信息
|
|
||||||
days = self.server_date().isoweekday()
|
|
||||||
|
|
||||||
gameid_list = [
|
|
||||||
{"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]},
|
{"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||||
{"value": "1-7", "text": "1-7", "days": [1, 2, 3, 4, 5, 6, 7]},
|
{"value": "1-7", "text": "1-7", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||||
{"value": "R8-11", "text": "R8-11", "days": [1, 2, 3, 4, 5, 6, 7]},
|
{"value": "R8-11", "text": "R8-11", "days": [1, 2, 3, 4, 5, 6, 7]},
|
||||||
@@ -795,12 +707,20 @@ class AppConfig(GlobalConfig):
|
|||||||
{"value": "PR-D-2", "text": "近/特芯片组", "days": [2, 3, 6, 7]},
|
{"value": "PR-D-2", "text": "近/特芯片组", "days": [2, 3, 6, 7]},
|
||||||
]
|
]
|
||||||
|
|
||||||
for gameid_info in gameid_list:
|
for day in range(0, 8):
|
||||||
if days in gameid_info["days"]:
|
|
||||||
gameid_dict["value"].append(gameid_info["value"])
|
|
||||||
gameid_dict["text"].append(gameid_info["text"])
|
|
||||||
|
|
||||||
self.gameid_dict["Today"] = gameid_dict
|
today_gameid_dict = {"value": [], "text": []}
|
||||||
|
|
||||||
|
for gameid_info in gameid_daily_info:
|
||||||
|
|
||||||
|
if day in gameid_info["days"] or day == 0:
|
||||||
|
today_gameid_dict["value"].append(gameid_info["value"])
|
||||||
|
today_gameid_dict["text"].append(gameid_info["text"])
|
||||||
|
|
||||||
|
self.gameid_dict[calendar.day_name[day - 1] if day > 0 else "ALL"] = {
|
||||||
|
"value": today_gameid_dict["value"] + ss_gameid_dict["value"],
|
||||||
|
"text": today_gameid_dict["text"] + ss_gameid_dict["text"],
|
||||||
|
}
|
||||||
|
|
||||||
self.gameid_refreshed.emit()
|
self.gameid_refreshed.emit()
|
||||||
|
|
||||||
@@ -1231,6 +1151,28 @@ class AppConfig(GlobalConfig):
|
|||||||
sorted(user_dict.items(), key=lambda x: int(x[0][3:]))
|
sorted(user_dict.items(), key=lambda x: int(x[0][3:]))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def search_plan(self) -> None:
|
||||||
|
"""搜索所有计划表"""
|
||||||
|
|
||||||
|
self.plan_dict: Dict[str, Dict[str, Union[str, Path, MaaPlanConfig]]] = {}
|
||||||
|
if (self.app_path / "config/MaaPlanConfig").exists():
|
||||||
|
for maa_plan_dir in (self.app_path / "config/MaaPlanConfig").iterdir():
|
||||||
|
if maa_plan_dir.is_dir():
|
||||||
|
|
||||||
|
maa_plan_config = MaaPlanConfig()
|
||||||
|
maa_plan_config.load(maa_plan_dir / "config.json", maa_plan_config)
|
||||||
|
maa_plan_config.save()
|
||||||
|
|
||||||
|
self.plan_dict[maa_plan_dir.name] = {
|
||||||
|
"Type": "Maa",
|
||||||
|
"Path": maa_plan_dir,
|
||||||
|
"Config": maa_plan_config,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.plan_dict = dict(
|
||||||
|
sorted(self.plan_dict.items(), key=lambda x: int(x[0][3:]))
|
||||||
|
)
|
||||||
|
|
||||||
def search_queue(self):
|
def search_queue(self):
|
||||||
"""搜索所有调度队列实例"""
|
"""搜索所有调度队列实例"""
|
||||||
|
|
||||||
@@ -1278,6 +1220,16 @@ class AppConfig(GlobalConfig):
|
|||||||
if queue["Config"].get(queue["Config"].queue_Member_10) == old:
|
if queue["Config"].get(queue["Config"].queue_Member_10) == old:
|
||||||
queue["Config"].set(queue["Config"].queue_Member_10, new)
|
queue["Config"].set(queue["Config"].queue_Member_10, new)
|
||||||
|
|
||||||
|
def change_plan(self, old: str, new: str) -> None:
|
||||||
|
"""修改脚本管理所有下属用户的计划表配置参数"""
|
||||||
|
|
||||||
|
for member in self.member_dict.values():
|
||||||
|
|
||||||
|
for user in member["UserData"].values():
|
||||||
|
|
||||||
|
if user["Config"].get(user["Config"].Info_GameIdMode) == old:
|
||||||
|
user["Config"].set(user["Config"].Info_GameIdMode, new)
|
||||||
|
|
||||||
def change_user_info(
|
def change_user_info(
|
||||||
self, name: str, user_data: Dict[str, Dict[str, Union[str, Path, dict]]]
|
self, name: str, user_data: Dict[str, Dict[str, Union[str, Path, dict]]]
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -1310,6 +1262,12 @@ class AppConfig(GlobalConfig):
|
|||||||
|
|
||||||
self.user_info_changed.emit()
|
self.user_info_changed.emit()
|
||||||
|
|
||||||
|
def set_power_sign(self, sign: str) -> None:
|
||||||
|
"""设置当前电源状态"""
|
||||||
|
|
||||||
|
self.power_sign = sign
|
||||||
|
self.power_sign_changed.emit()
|
||||||
|
|
||||||
def save_history(self, key: str, content: dict) -> None:
|
def save_history(self, key: str, content: dict) -> None:
|
||||||
"""保存历史记录"""
|
"""保存历史记录"""
|
||||||
|
|
||||||
|
|||||||
@@ -35,23 +35,30 @@ from .config import Config
|
|||||||
class _MainInfoBar:
|
class _MainInfoBar:
|
||||||
"""信息通知栏"""
|
"""信息通知栏"""
|
||||||
|
|
||||||
def push_info_bar(self, mode: str, title: str, content: str, time: int):
|
# 模式到 InfoBar 方法的映射
|
||||||
|
mode_mapping = {
|
||||||
|
"success": InfoBar.success,
|
||||||
|
"warning": InfoBar.warning,
|
||||||
|
"error": InfoBar.error,
|
||||||
|
"info": InfoBar.info,
|
||||||
|
}
|
||||||
|
|
||||||
|
def push_info_bar(
|
||||||
|
self, mode: str, title: str, content: str, time: int, if_force: bool = False
|
||||||
|
):
|
||||||
"""推送到信息通知栏"""
|
"""推送到信息通知栏"""
|
||||||
if Config.main_window is None:
|
if Config.main_window is None:
|
||||||
logger.error("信息通知栏未设置父窗口")
|
logger.error("信息通知栏未设置父窗口")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 定义模式到 InfoBar 方法的映射
|
|
||||||
mode_mapping = {
|
|
||||||
"success": InfoBar.success,
|
|
||||||
"warning": InfoBar.warning,
|
|
||||||
"error": InfoBar.error,
|
|
||||||
"info": InfoBar.info,
|
|
||||||
}
|
|
||||||
|
|
||||||
# 根据 mode 获取对应的 InfoBar 方法
|
# 根据 mode 获取对应的 InfoBar 方法
|
||||||
info_bar_method = mode_mapping.get(mode)
|
info_bar_method = self.mode_mapping.get(mode)
|
||||||
if info_bar_method:
|
|
||||||
|
if not info_bar_method:
|
||||||
|
logger.error(f"未知的通知栏模式: {mode}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if Config.main_window.isVisible():
|
||||||
info_bar_method(
|
info_bar_method(
|
||||||
title=title,
|
title=title,
|
||||||
content=content,
|
content=content,
|
||||||
@@ -61,8 +68,16 @@ class _MainInfoBar:
|
|||||||
duration=time,
|
duration=time,
|
||||||
parent=Config.main_window,
|
parent=Config.main_window,
|
||||||
)
|
)
|
||||||
else:
|
elif if_force:
|
||||||
logger.error(f"未知的通知栏模式: {mode}")
|
# 如果主窗口不可见且强制推送,则录入消息队列等待窗口显示后推送
|
||||||
|
info_bar_item = {
|
||||||
|
"mode": mode,
|
||||||
|
"title": title,
|
||||||
|
"content": content,
|
||||||
|
"time": time,
|
||||||
|
}
|
||||||
|
if info_bar_item not in Config.info_bar_list:
|
||||||
|
Config.info_bar_list.append(info_bar_item)
|
||||||
|
|
||||||
|
|
||||||
MainInfoBar = _MainInfoBar()
|
MainInfoBar = _MainInfoBar()
|
||||||
|
|||||||
@@ -265,28 +265,14 @@ class _TaskManager(QObject):
|
|||||||
Config.queue_dict[name]["Config"].get(
|
Config.queue_dict[name]["Config"].get(
|
||||||
Config.queue_dict[name]["Config"].queueSet_AfterAccomplish
|
Config.queue_dict[name]["Config"].queueSet_AfterAccomplish
|
||||||
)
|
)
|
||||||
!= "None"
|
!= "NoAction"
|
||||||
|
and Config.power_sign == "NoAction"
|
||||||
):
|
):
|
||||||
|
Config.set_power_sign(
|
||||||
from app.ui import ProgressRingMessageBox
|
Config.queue_dict[name]["Config"].get(
|
||||||
|
Config.queue_dict[name]["Config"].queueSet_AfterAccomplish
|
||||||
mode_book = {
|
|
||||||
"Shutdown": "关机",
|
|
||||||
"Hibernate": "休眠",
|
|
||||||
"Sleep": "睡眠",
|
|
||||||
"KillSelf": "关闭AUTO_MAA",
|
|
||||||
}
|
|
||||||
|
|
||||||
choice = ProgressRingMessageBox(
|
|
||||||
Config.main_window,
|
|
||||||
f"{mode_book[Config.queue_dict[name]["Config"].get(Config.queue_dict[name]["Config"].queueSet_AfterAccomplish)]}倒计时",
|
|
||||||
)
|
|
||||||
if choice.exec():
|
|
||||||
System.set_power(
|
|
||||||
Config.queue_dict[name]["Config"].get(
|
|
||||||
Config.queue_dict[name]["Config"].queueSet_AfterAccomplish
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def check_maa_version(self, v: str):
|
def check_maa_version(self, v: str):
|
||||||
"""检查MAA版本"""
|
"""检查MAA版本"""
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ from loguru import logger
|
|||||||
from PySide6.QtWidgets import QWidget
|
from PySide6.QtWidgets import QWidget
|
||||||
from PySide6.QtCore import QTimer
|
from PySide6.QtCore import QTimer
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
import pyautogui
|
import pyautogui
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
@@ -46,6 +47,7 @@ class _MainTimer(QWidget):
|
|||||||
self.Timer = QTimer()
|
self.Timer = QTimer()
|
||||||
self.Timer.timeout.connect(self.timed_start)
|
self.Timer.timeout.connect(self.timed_start)
|
||||||
self.Timer.timeout.connect(self.set_silence)
|
self.Timer.timeout.connect(self.set_silence)
|
||||||
|
self.Timer.timeout.connect(self.check_power)
|
||||||
self.Timer.start(1000)
|
self.Timer.start(1000)
|
||||||
self.LongTimer = QTimer()
|
self.LongTimer = QTimer()
|
||||||
self.LongTimer.timeout.connect(self.long_timed_task)
|
self.LongTimer.timeout.connect(self.long_timed_task)
|
||||||
@@ -96,6 +98,16 @@ class _MainTimer(QWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
windows = System.get_window_info()
|
windows = System.get_window_info()
|
||||||
|
|
||||||
|
# 排除雷电名为新通知的窗口
|
||||||
|
windows = [
|
||||||
|
window
|
||||||
|
for window in windows
|
||||||
|
if not (
|
||||||
|
window[0] == "新通知" and Path(window[1]) in Config.silence_list
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
if any(
|
if any(
|
||||||
str(emulator_path) in window
|
str(emulator_path) in window
|
||||||
for window in windows
|
for window in windows
|
||||||
@@ -113,5 +125,27 @@ class _MainTimer(QWidget):
|
|||||||
logger.warning(f"FailSafeException: {e}")
|
logger.warning(f"FailSafeException: {e}")
|
||||||
self.if_FailSafeException = True
|
self.if_FailSafeException = True
|
||||||
|
|
||||||
|
def check_power(self):
|
||||||
|
|
||||||
|
if Config.power_sign != "NoAction" and not Config.running_list:
|
||||||
|
|
||||||
|
from app.ui import ProgressRingMessageBox
|
||||||
|
|
||||||
|
mode_book = {
|
||||||
|
"KillSelf": "退出软件",
|
||||||
|
"Sleep": "睡眠",
|
||||||
|
"Hibernate": "休眠",
|
||||||
|
"Shutdown": "关机",
|
||||||
|
}
|
||||||
|
|
||||||
|
choice = ProgressRingMessageBox(
|
||||||
|
Config.main_window, f"{mode_book[Config.power_sign]}倒计时"
|
||||||
|
)
|
||||||
|
if choice.exec():
|
||||||
|
System.set_power(Config.power_sign)
|
||||||
|
Config.set_power_sign("NoAction")
|
||||||
|
else:
|
||||||
|
Config.set_power_sign("NoAction")
|
||||||
|
|
||||||
|
|
||||||
MainTimer = _MainTimer()
|
MainTimer = _MainTimer()
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ class MaaManager(QObject):
|
|||||||
"Path": info["Path"],
|
"Path": info["Path"],
|
||||||
"Config": info["Config"].toDict(),
|
"Config": info["Config"].toDict(),
|
||||||
}
|
}
|
||||||
|
planed_info = info["Config"].get_plan_info()
|
||||||
|
for key, value in planed_info.items():
|
||||||
|
self.data[name]["Config"]["Info"][key] = value
|
||||||
|
|
||||||
self.data = dict(sorted(self.data.items(), key=lambda x: int(x[0][3:])))
|
self.data = dict(sorted(self.data.items(), key=lambda x: int(x[0][3:])))
|
||||||
|
|
||||||
@@ -114,10 +117,15 @@ class MaaManager(QObject):
|
|||||||
self.maa_log_path = self.maa_root_path / "debug/gui.log"
|
self.maa_log_path = self.maa_root_path / "debug/gui.log"
|
||||||
self.maa_exe_path = self.maa_root_path / "MAA.exe"
|
self.maa_exe_path = self.maa_root_path / "MAA.exe"
|
||||||
self.maa_tasks_path = self.maa_root_path / "resource/tasks/tasks.json"
|
self.maa_tasks_path = self.maa_root_path / "resource/tasks/tasks.json"
|
||||||
|
self.port_range = [0] + [
|
||||||
|
(i // 2 + 1) * (-1 if i % 2 else 1)
|
||||||
|
for i in range(0, 2 * self.set["RunSet"]["ADBSearchRange"])
|
||||||
|
]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""主进程,运行MAA代理进程"""
|
"""主进程,运行MAA代理进程"""
|
||||||
|
|
||||||
|
current_date = datetime.now().strftime("%m-%d")
|
||||||
curdate = Config.server_date().strftime("%Y-%m-%d")
|
curdate = Config.server_date().strftime("%Y-%m-%d")
|
||||||
begin_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
begin_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
@@ -266,9 +274,23 @@ class MaaManager(QObject):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 解析任务构成
|
# 解析任务构成
|
||||||
if user_data["Info"]["Mode"] == "简洁":
|
if mode == "Routine":
|
||||||
|
|
||||||
|
self.task_dict = {
|
||||||
|
"WakeUp": str(user_data["Task"]["IfWakeUp"]),
|
||||||
|
"Recruiting": str(user_data["Task"]["IfRecruiting"]),
|
||||||
|
"Base": str(user_data["Task"]["IfBase"]),
|
||||||
|
"Combat": str(user_data["Task"]["IfCombat"]),
|
||||||
|
"Mission": str(user_data["Task"]["IfMission"]),
|
||||||
|
"Mall": str(user_data["Task"]["IfMall"]),
|
||||||
|
"AutoRoguelike": str(user_data["Task"]["IfAutoRoguelike"]),
|
||||||
|
"Reclamation": str(user_data["Task"]["IfReclamation"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
elif mode == "Annihilation":
|
||||||
|
|
||||||
|
if user_data["Info"]["Mode"] == "简洁":
|
||||||
|
|
||||||
if mode == "Annihilation":
|
|
||||||
self.task_dict = {
|
self.task_dict = {
|
||||||
"WakeUp": "True",
|
"WakeUp": "True",
|
||||||
"Recruiting": "False",
|
"Recruiting": "False",
|
||||||
@@ -280,52 +302,40 @@ class MaaManager(QObject):
|
|||||||
"Reclamation": "False",
|
"Reclamation": "False",
|
||||||
}
|
}
|
||||||
|
|
||||||
elif mode == "Routine":
|
elif user_data["Info"]["Mode"] == "详细":
|
||||||
|
|
||||||
|
with (self.data[user[2]]["Path"] / f"{mode}/gui.json").open(
|
||||||
|
mode="r", encoding="utf-8"
|
||||||
|
) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
self.task_dict = {
|
self.task_dict = {
|
||||||
"WakeUp": "True",
|
"WakeUp": data["Configurations"]["Default"][
|
||||||
"Recruiting": "True",
|
"TaskQueue.WakeUp.IsChecked"
|
||||||
"Base": "True",
|
],
|
||||||
"Combat": "True",
|
"Recruiting": data["Configurations"]["Default"][
|
||||||
"Mission": "True",
|
"TaskQueue.Recruiting.IsChecked"
|
||||||
"Mall": "True",
|
],
|
||||||
"AutoRoguelike": "False",
|
"Base": data["Configurations"]["Default"][
|
||||||
"Reclamation": "False",
|
"TaskQueue.Base.IsChecked"
|
||||||
|
],
|
||||||
|
"Combat": data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Combat.IsChecked"
|
||||||
|
],
|
||||||
|
"Mission": data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Mission.IsChecked"
|
||||||
|
],
|
||||||
|
"Mall": data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Mall.IsChecked"
|
||||||
|
],
|
||||||
|
"AutoRoguelike": data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.AutoRoguelike.IsChecked"
|
||||||
|
],
|
||||||
|
"Reclamation": data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.Reclamation.IsChecked"
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
elif user_data["Info"]["Mode"] == "详细":
|
|
||||||
|
|
||||||
with (self.data[user[2]]["Path"] / f"{mode}/gui.json").open(
|
|
||||||
mode="r", encoding="utf-8"
|
|
||||||
) as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
self.task_dict = {
|
|
||||||
"WakeUp": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.WakeUp.IsChecked"
|
|
||||||
],
|
|
||||||
"Recruiting": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.Recruiting.IsChecked"
|
|
||||||
],
|
|
||||||
"Base": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.Base.IsChecked"
|
|
||||||
],
|
|
||||||
"Combat": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.Combat.IsChecked"
|
|
||||||
],
|
|
||||||
"Mission": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.Mission.IsChecked"
|
|
||||||
],
|
|
||||||
"Mall": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.Mall.IsChecked"
|
|
||||||
],
|
|
||||||
"AutoRoguelike": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.AutoRoguelike.IsChecked"
|
|
||||||
],
|
|
||||||
"Reclamation": data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.Reclamation.IsChecked"
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
# 尝试次数循环
|
# 尝试次数循环
|
||||||
for i in range(self.set["RunSet"]["RunTimesLimit"]):
|
for i in range(self.set["RunSet"]["RunTimesLimit"]):
|
||||||
|
|
||||||
@@ -386,6 +396,12 @@ class MaaManager(QObject):
|
|||||||
self.if_open_emulator = True
|
self.if_open_emulator = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
self.wait_time = int(
|
||||||
|
set["Configurations"]["Default"][
|
||||||
|
"Start.EmulatorWaitSeconds"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.ADB_path = Path(
|
self.ADB_path = Path(
|
||||||
set["Configurations"]["Default"]["Connect.AdbPath"]
|
set["Configurations"]["Default"]["Connect.AdbPath"]
|
||||||
)
|
)
|
||||||
@@ -414,6 +430,7 @@ class MaaManager(QObject):
|
|||||||
[self.ADB_path, "disconnect", self.ADB_address],
|
[self.ADB_path, "disconnect", self.ADB_address],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
|
logger.info(f"{self.name} | 释放ADB:{self.ADB_address}")
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
# 忽略错误,因为可能本来就没有连接
|
# 忽略错误,因为可能本来就没有连接
|
||||||
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||||
@@ -432,6 +449,9 @@ class MaaManager(QObject):
|
|||||||
[self.emulator_path, *self.emulator_arguments],
|
[self.emulator_path, *self.emulator_arguments],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
|
logger.info(
|
||||||
|
f"{self.name} | 启动模拟器:{self.emulator_path},参数:{self.emulator_arguments}"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.name} | 启动模拟器时出现异常:{e}")
|
logger.error(f"{self.name} | 启动模拟器时出现异常:{e}")
|
||||||
self.push_info_bar.emit(
|
self.push_info_bar.emit(
|
||||||
@@ -446,6 +466,8 @@ class MaaManager(QObject):
|
|||||||
# 添加静默进程标记
|
# 添加静默进程标记
|
||||||
Config.silence_list.append(self.emulator_path)
|
Config.silence_list.append(self.emulator_path)
|
||||||
|
|
||||||
|
self.search_ADB_address()
|
||||||
|
|
||||||
# 创建MAA任务
|
# 创建MAA任务
|
||||||
maa = subprocess.Popen(
|
maa = subprocess.Popen(
|
||||||
[self.maa_exe_path],
|
[self.maa_exe_path],
|
||||||
@@ -517,6 +539,12 @@ class MaaManager(QObject):
|
|||||||
) as f:
|
) as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
|
|
||||||
|
# 记录自定义基建索引
|
||||||
|
if self.task_dict["Base"] == "False":
|
||||||
|
user_data["Data"]["CustomInfrastPlanIndex"] = data[
|
||||||
|
"Configurations"
|
||||||
|
]["Default"]["Infrast.CustomInfrastPlanIndex"]
|
||||||
|
|
||||||
# 记录更新包路径
|
# 记录更新包路径
|
||||||
if (
|
if (
|
||||||
data["Global"]["VersionUpdate.package"]
|
data["Global"]["VersionUpdate.package"]
|
||||||
@@ -541,15 +569,13 @@ class MaaManager(QObject):
|
|||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# 移除静默进程标记
|
|
||||||
Config.silence_list.remove(self.emulator_path)
|
|
||||||
|
|
||||||
# 任务结束后释放ADB
|
# 任务结束后释放ADB
|
||||||
try:
|
try:
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[self.ADB_path, "disconnect", self.ADB_address],
|
[self.ADB_path, "disconnect", self.ADB_address],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
)
|
)
|
||||||
|
logger.info(f"{self.name} | 释放ADB:{self.ADB_address}")
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
# 忽略错误,因为可能本来就没有连接
|
# 忽略错误,因为可能本来就没有连接
|
||||||
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
logger.warning(f"{self.name} | 释放ADB时出现异常:{e}")
|
||||||
@@ -567,6 +593,33 @@ class MaaManager(QObject):
|
|||||||
self.emulator_process.wait()
|
self.emulator_process.wait()
|
||||||
self.if_open_emulator = True
|
self.if_open_emulator = True
|
||||||
|
|
||||||
|
# 记录剿灭情况
|
||||||
|
if (
|
||||||
|
mode == "Annihilation"
|
||||||
|
and self.weekly_annihilation_limit_reached
|
||||||
|
):
|
||||||
|
user_data["Data"]["LastAnnihilationDate"] = curdate
|
||||||
|
# 保存运行日志以及统计信息
|
||||||
|
if_six_star = Config.save_maa_log(
|
||||||
|
Config.app_path
|
||||||
|
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{start_time.strftime("%H-%M-%S")}.log",
|
||||||
|
self.check_maa_log(start_time, mode_book[mode]),
|
||||||
|
self.maa_result,
|
||||||
|
)
|
||||||
|
user_logs_list.append(
|
||||||
|
Config.app_path
|
||||||
|
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{start_time.strftime("%H-%M-%S")}.json",
|
||||||
|
)
|
||||||
|
if if_six_star:
|
||||||
|
self.push_notification(
|
||||||
|
"公招六星",
|
||||||
|
f"喜报:用户 {user[0]} 公招出六星啦!",
|
||||||
|
{
|
||||||
|
"user_name": user_data["Info"]["Name"],
|
||||||
|
},
|
||||||
|
user_data,
|
||||||
|
)
|
||||||
|
|
||||||
# 执行MAA解压更新动作
|
# 执行MAA解压更新动作
|
||||||
if self.maa_update_package:
|
if self.maa_update_package:
|
||||||
|
|
||||||
@@ -590,50 +643,23 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
logger.info(f"{self.name} | 更新动作结束")
|
logger.info(f"{self.name} | 更新动作结束")
|
||||||
|
|
||||||
# 记录剿灭情况
|
# 发送统计信息
|
||||||
if (
|
statistics = Config.merge_maa_logs("指定项", user_logs_list)
|
||||||
mode == "Annihilation"
|
statistics["user_index"] = user[2]
|
||||||
and self.weekly_annihilation_limit_reached
|
statistics["user_info"] = user[0]
|
||||||
):
|
statistics["start_time"] = user_start_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
user_data["Data"]["LastAnnihilationDate"] = curdate
|
statistics["end_time"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
# 保存运行日志以及统计信息
|
statistics["maa_result"] = (
|
||||||
if_six_star = Config.save_maa_log(
|
"代理任务全部完成"
|
||||||
Config.app_path
|
if (run_book["Annihilation"] and run_book["Routine"])
|
||||||
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{start_time.strftime("%H-%M-%S")}.log",
|
else "代理任务未全部完成"
|
||||||
self.check_maa_log(start_time, mode_book[mode]),
|
)
|
||||||
self.maa_result,
|
self.push_notification(
|
||||||
)
|
"统计信息",
|
||||||
user_logs_list.append(
|
f"{current_date} | 用户 {user[0]} 的自动代理统计报告",
|
||||||
Config.app_path
|
statistics,
|
||||||
/ f"history/{curdate}/{user_data["Info"]["Name"]}/{start_time.strftime("%H-%M-%S")}.json",
|
user_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
if Config.get(Config.notify_IfSendSixStar) and if_six_star:
|
|
||||||
|
|
||||||
self.push_notification(
|
|
||||||
"公招六星",
|
|
||||||
f"喜报:用户 {user[0]} 公招出六星啦!",
|
|
||||||
{"user_name": user_data["Info"]["Name"]},
|
|
||||||
)
|
|
||||||
|
|
||||||
if Config.get(Config.notify_IfSendStatistic):
|
|
||||||
|
|
||||||
statistics = Config.merge_maa_logs("指定项", user_logs_list)
|
|
||||||
statistics["user_info"] = user[0]
|
|
||||||
statistics["start_time"] = user_start_time.strftime(
|
|
||||||
"%Y-%m-%d %H:%M:%S"
|
|
||||||
)
|
|
||||||
statistics["end_time"] = datetime.now().strftime(
|
|
||||||
"%Y-%m-%d %H:%M:%S"
|
|
||||||
)
|
|
||||||
statistics["maa_result"] = (
|
|
||||||
"代理任务全部完成"
|
|
||||||
if (run_book["Annihilation"] and run_book["Routine"])
|
|
||||||
else "代理任务未全部完成"
|
|
||||||
)
|
|
||||||
self.push_notification(
|
|
||||||
"统计信息", f"用户 {user[0]} 的自动代理统计报告", statistics
|
|
||||||
)
|
|
||||||
|
|
||||||
if run_book["Annihilation"] and run_book["Routine"]:
|
if run_book["Annihilation"] and run_book["Routine"]:
|
||||||
# 成功完成代理的用户修改相关参数
|
# 成功完成代理的用户修改相关参数
|
||||||
@@ -804,9 +830,9 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
# 保存运行日志
|
# 保存运行日志
|
||||||
title = (
|
title = (
|
||||||
f"{self.set["MaaSet"]["Name"]}的{self.mode[:4]}任务报告"
|
f"{current_date} | {self.set["MaaSet"]["Name"]}的{self.mode[:4]}任务报告"
|
||||||
if self.set["MaaSet"]["Name"] != ""
|
if self.set["MaaSet"]["Name"] != ""
|
||||||
else f"{self.mode[:4]}任务报告"
|
else f"{current_date} | {self.mode[:4]}任务报告"
|
||||||
)
|
)
|
||||||
result = {
|
result = {
|
||||||
"title": f"{self.mode[:4]}任务报告",
|
"title": f"{self.mode[:4]}任务报告",
|
||||||
@@ -826,6 +852,17 @@ class MaaManager(QObject):
|
|||||||
self.data[_]["Config"]["Info"]["Name"] for _ in wait_index
|
self.data[_]["Config"]["Info"]["Name"] for _ in wait_index
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 生成结果文本
|
||||||
|
result_text = (
|
||||||
|
f"任务开始时间:{result["start_time"]},结束时间:{result["end_time"]}\n"
|
||||||
|
f"已完成数:{result["completed_count"]},未完成数:{result["uncompleted_count"]}\n\n"
|
||||||
|
)
|
||||||
|
if len(result["failed_user"]) > 0:
|
||||||
|
result_text += f"{self.mode[2:4]}未成功的用户:\n{"\n".join(result["failed_user"])}\n"
|
||||||
|
if len(result["waiting_user"]) > 0:
|
||||||
|
result_text += f"\n未开始{self.mode[2:4]}的用户:\n{"\n".join(result["waiting_user"])}\n"
|
||||||
|
|
||||||
# 推送代理结果通知
|
# 推送代理结果通知
|
||||||
Notify.push_plyer(
|
Notify.push_plyer(
|
||||||
title.replace("报告", "已完成!"),
|
title.replace("报告", "已完成!"),
|
||||||
@@ -833,15 +870,7 @@ class MaaManager(QObject):
|
|||||||
f"已完成用户数:{len(over_index)},未完成用户数:{len(error_index) + len(wait_index)}",
|
f"已完成用户数:{len(over_index)},未完成用户数:{len(error_index) + len(wait_index)}",
|
||||||
10,
|
10,
|
||||||
)
|
)
|
||||||
if Config.get(Config.notify_SendTaskResultTime) == "任何时刻" or (
|
self.push_notification("代理结果", title, result)
|
||||||
Config.get(Config.notify_SendTaskResultTime) == "仅失败时"
|
|
||||||
and len(error_index) + len(wait_index) != 0
|
|
||||||
):
|
|
||||||
result_text = self.push_notification("代理结果", title, result)
|
|
||||||
else:
|
|
||||||
result_text = self.push_notification(
|
|
||||||
"代理结果", title, result, if_get_text_only=True
|
|
||||||
)
|
|
||||||
|
|
||||||
self.agree_bilibili(False)
|
self.agree_bilibili(False)
|
||||||
self.log_monitor.deleteLater()
|
self.log_monitor.deleteLater()
|
||||||
@@ -866,6 +895,86 @@ class MaaManager(QObject):
|
|||||||
def __capture_response(self, response: bool) -> None:
|
def __capture_response(self, response: bool) -> None:
|
||||||
self.response = response
|
self.response = response
|
||||||
|
|
||||||
|
def search_ADB_address(self) -> None:
|
||||||
|
"""搜索ADB实际地址"""
|
||||||
|
|
||||||
|
self.update_log_text.emit(
|
||||||
|
f"即将搜索ADB实际地址\n正在等待模拟器完成启动\n请等待{self.wait_time}s"
|
||||||
|
)
|
||||||
|
|
||||||
|
for _ in range(self.wait_time):
|
||||||
|
if self.isInterruptionRequested:
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 移除静默进程标记
|
||||||
|
Config.silence_list.remove(self.emulator_path)
|
||||||
|
|
||||||
|
if "-" in self.ADB_address:
|
||||||
|
ADB_ip = f"{self.ADB_address.split("-")[0]}-"
|
||||||
|
ADB_port = int(self.ADB_address.split("-")[1])
|
||||||
|
|
||||||
|
elif ":" in self.ADB_address:
|
||||||
|
ADB_ip = f"{self.ADB_address.split(':')[0]}:"
|
||||||
|
ADB_port = int(self.ADB_address.split(":")[1])
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"{self.name} | 正在搜索ADB实际地址,ADB前缀:{ADB_ip},初始端口:{ADB_port},搜索范围:{self.port_range}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for port in self.port_range:
|
||||||
|
|
||||||
|
ADB_address = f"{ADB_ip}{ADB_port + port}"
|
||||||
|
|
||||||
|
# 尝试通过ADB连接到指定地址
|
||||||
|
connect_result = subprocess.run(
|
||||||
|
[self.ADB_path, "connect", ADB_address],
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
if "connected" in connect_result.stdout:
|
||||||
|
|
||||||
|
# 检查连接状态
|
||||||
|
devices_result = subprocess.run(
|
||||||
|
[self.ADB_path, "devices"],
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
if ADB_address in devices_result.stdout:
|
||||||
|
|
||||||
|
logger.info(f"{self.name} | ADB实际地址:{ADB_address}")
|
||||||
|
|
||||||
|
# 断开连接
|
||||||
|
subprocess.run(
|
||||||
|
[self.ADB_path, "disconnect", ADB_address],
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.ADB_address = ADB_address
|
||||||
|
|
||||||
|
# 覆写当前ADB地址
|
||||||
|
System.kill_process(self.maa_exe_path)
|
||||||
|
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"Connect.Address"
|
||||||
|
] = self.ADB_address
|
||||||
|
data["Configurations"]["Default"]["Start.EmulatorWaitSeconds"] = "0"
|
||||||
|
with self.maa_set_path.open(mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.info(f"{self.name} | 无法连接到ADB地址:{ADB_address}")
|
||||||
|
else:
|
||||||
|
logger.info(f"{self.name} | 无法连接到ADB地址:{ADB_address}")
|
||||||
|
|
||||||
def refresh_maa_log(self) -> None:
|
def refresh_maa_log(self) -> None:
|
||||||
"""刷新MAA日志"""
|
"""刷新MAA日志"""
|
||||||
|
|
||||||
@@ -923,6 +1032,8 @@ class MaaManager(QObject):
|
|||||||
latest_time = start_time
|
latest_time = start_time
|
||||||
for _ in logs[::-1]:
|
for _ in logs[::-1]:
|
||||||
try:
|
try:
|
||||||
|
if "如果长时间无进一步日志更新,可能需要手动干预。" in _:
|
||||||
|
continue
|
||||||
latest_time = datetime.strptime(_[1:20], "%Y-%m-%d %H:%M:%S")
|
latest_time = datetime.strptime(_[1:20], "%Y-%m-%d %H:%M:%S")
|
||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -965,7 +1076,7 @@ class MaaManager(QObject):
|
|||||||
else:
|
else:
|
||||||
self.maa_result = "MAA部分任务执行失败"
|
self.maa_result = "MAA部分任务执行失败"
|
||||||
|
|
||||||
elif "请「检查连接设置」或「尝试重启模拟器与 ADB」或「重启电脑」" in log:
|
elif "请 「检查连接设置」 → 「尝试重启模拟器与 ADB」 → 「重启电脑」" in log:
|
||||||
self.maa_result = "MAA的ADB连接异常"
|
self.maa_result = "MAA的ADB连接异常"
|
||||||
|
|
||||||
elif "未检测到任何模拟器" in log:
|
elif "未检测到任何模拟器" in log:
|
||||||
@@ -991,7 +1102,7 @@ class MaaManager(QObject):
|
|||||||
elif mode == "人工排查":
|
elif mode == "人工排查":
|
||||||
if "完成任务: StartUp" in log:
|
if "完成任务: StartUp" in log:
|
||||||
self.maa_result = "Success!"
|
self.maa_result = "Success!"
|
||||||
elif "请「检查连接设置」或「尝试重启模拟器与 ADB」或「重启电脑」" in log:
|
elif "请 「检查连接设置」 → 「尝试重启模拟器与 ADB」 → 「重启电脑」" in log:
|
||||||
self.maa_result = "MAA的ADB连接异常"
|
self.maa_result = "MAA的ADB连接异常"
|
||||||
elif "未检测到任何模拟器" in log:
|
elif "未检测到任何模拟器" in log:
|
||||||
self.maa_result = "MAA未检测到任何模拟器"
|
self.maa_result = "MAA未检测到任何模拟器"
|
||||||
@@ -1166,6 +1277,9 @@ class MaaManager(QObject):
|
|||||||
]["Id"]
|
]["Id"]
|
||||||
|
|
||||||
# 按预设设定任务
|
# 按预设设定任务
|
||||||
|
data["Configurations"]["Default"][
|
||||||
|
"TaskQueue.WakeUp.IsChecked"
|
||||||
|
] = "True" # 开始唤醒
|
||||||
data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = (
|
data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = (
|
||||||
self.task_dict["Recruiting"]
|
self.task_dict["Recruiting"]
|
||||||
) # 自动公招
|
) # 自动公招
|
||||||
@@ -1190,10 +1304,6 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
if user_data["Info"]["Mode"] == "简洁":
|
if user_data["Info"]["Mode"] == "简洁":
|
||||||
|
|
||||||
data["Configurations"]["Default"][
|
|
||||||
"TaskQueue.WakeUp.IsChecked"
|
|
||||||
] = "True" # 开始唤醒
|
|
||||||
|
|
||||||
data["Configurations"]["Default"]["Start.ClientType"] = user_data[
|
data["Configurations"]["Default"]["Start.ClientType"] = user_data[
|
||||||
"Info"
|
"Info"
|
||||||
][
|
][
|
||||||
@@ -1292,7 +1402,9 @@ class MaaManager(QObject):
|
|||||||
] = "True" # 备选关卡
|
] = "True" # 备选关卡
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Fight.UseRemainingSanityStage"
|
"Fight.UseRemainingSanityStage"
|
||||||
] = "True" # 使用剩余理智
|
] = (
|
||||||
|
"True" if user_data["Info"]["GameId_Remain"] != "-" else "False"
|
||||||
|
) # 使用剩余理智
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Fight.UseExpiringMedicine"
|
"Fight.UseExpiringMedicine"
|
||||||
] = "True" # 无限吃48小时内过期的理智药
|
] = "True" # 无限吃48小时内过期的理智药
|
||||||
@@ -1390,7 +1502,9 @@ class MaaManager(QObject):
|
|||||||
] = "True" # 备选关卡
|
] = "True" # 备选关卡
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Fight.UseRemainingSanityStage"
|
"Fight.UseRemainingSanityStage"
|
||||||
] = "True" # 使用剩余理智
|
] = (
|
||||||
|
"True" if user_data["Info"]["GameId_Remain"] != "-" else "False"
|
||||||
|
) # 使用剩余理智
|
||||||
|
|
||||||
# 基建模式
|
# 基建模式
|
||||||
if (
|
if (
|
||||||
@@ -1416,12 +1530,20 @@ class MaaManager(QObject):
|
|||||||
"Start.RunDirectly"
|
"Start.RunDirectly"
|
||||||
] = "True" # 启动MAA后直接运行
|
] = "True" # 启动MAA后直接运行
|
||||||
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
||||||
|
|
||||||
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
||||||
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
||||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = str(
|
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = str(
|
||||||
self.if_open_emulator
|
self.if_open_emulator
|
||||||
) # 启动MAA后自动开启模拟器
|
) # 启动MAA后自动开启模拟器
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.ScheduledUpdateCheck"
|
||||||
|
] = "False" # 定时检查更新
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||||
|
] = "False" # 自动下载更新包
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoInstallUpdatePackage"
|
||||||
|
] = "False" # 自动安装更新包
|
||||||
|
|
||||||
# 账号切换
|
# 账号切换
|
||||||
if user_data["Info"]["Server"] == "Official":
|
if user_data["Info"]["Server"] == "Official":
|
||||||
@@ -1437,15 +1559,6 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
if user_data["Info"]["Mode"] == "简洁":
|
if user_data["Info"]["Mode"] == "简洁":
|
||||||
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.ScheduledUpdateCheck"
|
|
||||||
] = "False" # 定时检查更新
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
|
||||||
] = "False" # 自动下载更新包
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.AutoInstallUpdatePackage"
|
|
||||||
] = "False" # 自动安装更新包
|
|
||||||
data["Configurations"]["Default"]["Start.ClientType"] = user_data[
|
data["Configurations"]["Default"]["Start.ClientType"] = user_data[
|
||||||
"Info"
|
"Info"
|
||||||
][
|
][
|
||||||
@@ -1492,6 +1605,15 @@ class MaaManager(QObject):
|
|||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Start.OpenEmulatorAfterLaunch"
|
"Start.OpenEmulatorAfterLaunch"
|
||||||
] = "False" # 启动MAA后自动开启模拟器
|
] = "False" # 启动MAA后自动开启模拟器
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.ScheduledUpdateCheck"
|
||||||
|
] = "False" # 定时检查更新
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||||
|
] = "False" # 自动下载更新包
|
||||||
|
data["Global"][
|
||||||
|
"VersionUpdate.AutoInstallUpdatePackage"
|
||||||
|
] = "False" # 自动安装更新包
|
||||||
|
|
||||||
if Config.get(Config.function_IfSilence):
|
if Config.get(Config.function_IfSilence):
|
||||||
data["Global"][
|
data["Global"][
|
||||||
@@ -1500,15 +1622,6 @@ class MaaManager(QObject):
|
|||||||
|
|
||||||
if "全局" in mode:
|
if "全局" in mode:
|
||||||
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.ScheduledUpdateCheck"
|
|
||||||
] = "False" # 定时检查更新
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
|
||||||
] = "False" # 自动下载更新包
|
|
||||||
data["Global"][
|
|
||||||
"VersionUpdate.AutoInstallUpdatePackage"
|
|
||||||
] = "False" # 自动安装更新包
|
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"TaskQueue.WakeUp.IsChecked"
|
"TaskQueue.WakeUp.IsChecked"
|
||||||
] = "False" # 开始唤醒
|
] = "False" # 开始唤醒
|
||||||
@@ -1633,16 +1746,21 @@ class MaaManager(QObject):
|
|||||||
mode: str,
|
mode: str,
|
||||||
title: str,
|
title: str,
|
||||||
message: Union[str, dict],
|
message: Union[str, dict],
|
||||||
if_get_text_only: bool = False,
|
user_data: Dict[str, Dict[str, Union[str, int, bool]]] = None,
|
||||||
) -> str:
|
) -> None:
|
||||||
"""通过所有渠道推送通知"""
|
"""通过所有渠道推送通知"""
|
||||||
|
|
||||||
env = Environment(
|
env = Environment(
|
||||||
loader=FileSystemLoader(str(Config.app_path / "resources/html"))
|
loader=FileSystemLoader(str(Config.app_path / "resources/html"))
|
||||||
)
|
)
|
||||||
|
|
||||||
if mode == "代理结果":
|
if mode == "代理结果" and (
|
||||||
|
Config.get(Config.notify_SendTaskResultTime) == "任何时刻"
|
||||||
|
or (
|
||||||
|
Config.get(Config.notify_SendTaskResultTime) == "仅失败时"
|
||||||
|
and message["uncompleted_count"] != 0
|
||||||
|
)
|
||||||
|
):
|
||||||
# 生成文本通知内容
|
# 生成文本通知内容
|
||||||
message_text = (
|
message_text = (
|
||||||
f"任务开始时间:{message["start_time"]},结束时间:{message["end_time"]}\n"
|
f"任务开始时间:{message["start_time"]},结束时间:{message["end_time"]}\n"
|
||||||
@@ -1654,9 +1772,6 @@ class MaaManager(QObject):
|
|||||||
if len(message["waiting_user"]) > 0:
|
if len(message["waiting_user"]) > 0:
|
||||||
message_text += f"\n未开始{self.mode[2:4]}的用户:\n{"\n".join(message["waiting_user"])}\n"
|
message_text += f"\n未开始{self.mode[2:4]}的用户:\n{"\n".join(message["waiting_user"])}\n"
|
||||||
|
|
||||||
if if_get_text_only:
|
|
||||||
return message_text
|
|
||||||
|
|
||||||
# 生成HTML通知内容
|
# 生成HTML通知内容
|
||||||
message["failed_user"] = "、".join(message["failed_user"])
|
message["failed_user"] = "、".join(message["failed_user"])
|
||||||
message["waiting_user"] = "、".join(message["waiting_user"])
|
message["waiting_user"] = "、".join(message["waiting_user"])
|
||||||
@@ -1664,11 +1779,31 @@ class MaaManager(QObject):
|
|||||||
template = env.get_template("MAA_result.html")
|
template = env.get_template("MAA_result.html")
|
||||||
message_html = template.render(message)
|
message_html = template.render(message)
|
||||||
|
|
||||||
Notify.send_mail("网页", title, message_html)
|
# ServerChan的换行是两个换行符。故而将\n替换为\n\n
|
||||||
Notify.ServerChanPush(title, f"{message_text}\n\nAUTO_MAA 敬上")
|
serverchan_message = message_text.replace("\n", "\n\n")
|
||||||
Notify.CompanyWebHookBotPush(title, f"{message_text}\n\nAUTO_MAA 敬上")
|
|
||||||
|
|
||||||
return message_text
|
# 发送全局通知
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfSendMail):
|
||||||
|
Notify.send_mail(
|
||||||
|
"网页", title, message_html, Config.get(Config.notify_ToAddress)
|
||||||
|
)
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfServerChan):
|
||||||
|
Notify.ServerChanPush(
|
||||||
|
title,
|
||||||
|
f"{serverchan_message}\n\nAUTO_MAA 敬上",
|
||||||
|
Config.get(Config.notify_ServerChanKey),
|
||||||
|
Config.get(Config.notify_ServerChanTag),
|
||||||
|
Config.get(Config.notify_ServerChanChannel),
|
||||||
|
)
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfCompanyWebHookBot):
|
||||||
|
Notify.CompanyWebHookBotPush(
|
||||||
|
title,
|
||||||
|
f"{message_text}\n\nAUTO_MAA 敬上",
|
||||||
|
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||||
|
)
|
||||||
|
|
||||||
elif mode == "统计信息":
|
elif mode == "统计信息":
|
||||||
|
|
||||||
@@ -1697,18 +1832,155 @@ class MaaManager(QObject):
|
|||||||
template = env.get_template("MAA_statistics.html")
|
template = env.get_template("MAA_statistics.html")
|
||||||
message_html = template.render(message)
|
message_html = template.render(message)
|
||||||
|
|
||||||
Notify.send_mail("网页", title, message_html)
|
|
||||||
# ServerChan的换行是两个换行符。故而将\n替换为\n\n
|
# ServerChan的换行是两个换行符。故而将\n替换为\n\n
|
||||||
serverchan_message = message_text.replace("\n", "\n\n")
|
serverchan_message = message_text.replace("\n", "\n\n")
|
||||||
Notify.ServerChanPush(title, f"{serverchan_message}\n\nAUTO_MAA 敬上")
|
|
||||||
Notify.CompanyWebHookBotPush(title, f"{message_text}\n\nAUTO_MAA 敬上")
|
# 发送全局通知
|
||||||
|
if Config.get(Config.notify_IfSendStatistic):
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfSendMail):
|
||||||
|
Notify.send_mail(
|
||||||
|
"网页", title, message_html, Config.get(Config.notify_ToAddress)
|
||||||
|
)
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfServerChan):
|
||||||
|
Notify.ServerChanPush(
|
||||||
|
title,
|
||||||
|
f"{serverchan_message}\n\nAUTO_MAA 敬上",
|
||||||
|
Config.get(Config.notify_ServerChanKey),
|
||||||
|
Config.get(Config.notify_ServerChanTag),
|
||||||
|
Config.get(Config.notify_ServerChanChannel),
|
||||||
|
)
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfCompanyWebHookBot):
|
||||||
|
Notify.CompanyWebHookBotPush(
|
||||||
|
title,
|
||||||
|
f"{message_text}\n\nAUTO_MAA 敬上",
|
||||||
|
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||||
|
)
|
||||||
|
|
||||||
|
# 发送用户单独通知
|
||||||
|
if (
|
||||||
|
user_data["Notify"]["Enabled"]
|
||||||
|
and user_data["Notify"]["IfSendStatistic"]
|
||||||
|
):
|
||||||
|
|
||||||
|
# 发送邮件通知
|
||||||
|
if user_data["Notify"]["IfSendMail"]:
|
||||||
|
if user_data["Notify"]["ToAddress"]:
|
||||||
|
Notify.send_mail(
|
||||||
|
"网页",
|
||||||
|
title,
|
||||||
|
message_html,
|
||||||
|
user_data["Notify"]["ToAddress"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} | 用户邮箱地址为空,无法发送用户单独的邮件通知"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 发送ServerChan通知
|
||||||
|
if user_data["Notify"]["IfServerChan"]:
|
||||||
|
if user_data["Notify"]["ServerChanKey"]:
|
||||||
|
Notify.ServerChanPush(
|
||||||
|
title,
|
||||||
|
f"{serverchan_message}\n\nAUTO_MAA 敬上",
|
||||||
|
user_data["Notify"]["ServerChanKey"],
|
||||||
|
user_data["Notify"]["ServerChanTag"],
|
||||||
|
user_data["Notify"]["ServerChanChannel"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} |用户ServerChan密钥为空,无法发送用户单独的ServerChan通知"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 推送CompanyWebHookBot通知
|
||||||
|
if user_data["Notify"]["IfCompanyWebHookBot"]:
|
||||||
|
if user_data["Notify"]["CompanyWebHookBotUrl"]:
|
||||||
|
Notify.CompanyWebHookBotPush(
|
||||||
|
title,
|
||||||
|
f"{message_text}\n\nAUTO_MAA 敬上",
|
||||||
|
user_data["Notify"]["CompanyWebHookBotUrl"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} |用户CompanyWebHookBot密钥为空,无法发送用户单独的CompanyWebHookBot通知"
|
||||||
|
)
|
||||||
|
|
||||||
elif mode == "公招六星":
|
elif mode == "公招六星":
|
||||||
|
|
||||||
# 生成HTML通知内容
|
# 生成HTML通知内容
|
||||||
template = env.get_template("MAA_six_star.html")
|
template = env.get_template("MAA_six_star.html")
|
||||||
|
|
||||||
message_html = template.render(message)
|
message_html = template.render(message)
|
||||||
|
|
||||||
Notify.send_mail("网页", title, message_html)
|
# 发送全局通知
|
||||||
Notify.ServerChanPush(title, "好羡慕~\n\nAUTO_MAA 敬上")
|
if Config.get(Config.notify_IfSendSixStar):
|
||||||
Notify.CompanyWebHookBotPush(title, "好羡慕~\n\nAUTO_MAA 敬上")
|
|
||||||
|
if Config.get(Config.notify_IfSendMail):
|
||||||
|
Notify.send_mail(
|
||||||
|
"网页", title, message_html, Config.get(Config.notify_ToAddress)
|
||||||
|
)
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfServerChan):
|
||||||
|
Notify.ServerChanPush(
|
||||||
|
title,
|
||||||
|
"好羡慕~\n\nAUTO_MAA 敬上",
|
||||||
|
Config.get(Config.notify_ServerChanKey),
|
||||||
|
Config.get(Config.notify_ServerChanTag),
|
||||||
|
Config.get(Config.notify_ServerChanChannel),
|
||||||
|
)
|
||||||
|
|
||||||
|
if Config.get(Config.notify_IfCompanyWebHookBot):
|
||||||
|
Notify.CompanyWebHookBotPush(
|
||||||
|
title,
|
||||||
|
"好羡慕~\n\nAUTO_MAA 敬上",
|
||||||
|
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||||
|
)
|
||||||
|
|
||||||
|
# 发送用户单独通知
|
||||||
|
if user_data["Notify"]["Enabled"] and user_data["Notify"]["IfSendSixStar"]:
|
||||||
|
|
||||||
|
# 发送邮件通知
|
||||||
|
if user_data["Notify"]["IfSendMail"]:
|
||||||
|
if user_data["Notify"]["ToAddress"]:
|
||||||
|
Notify.send_mail(
|
||||||
|
"网页",
|
||||||
|
title,
|
||||||
|
message_html,
|
||||||
|
user_data["Notify"]["ToAddress"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} | 用户邮箱地址为空,无法发送用户单独的邮件通知"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 发送ServerChan通知
|
||||||
|
if user_data["Notify"]["IfServerChan"]:
|
||||||
|
|
||||||
|
if user_data["Notify"]["ServerChanKey"]:
|
||||||
|
Notify.ServerChanPush(
|
||||||
|
title,
|
||||||
|
"好羡慕~\n\nAUTO_MAA 敬上",
|
||||||
|
user_data["Notify"]["ServerChanKey"],
|
||||||
|
user_data["Notify"]["ServerChanTag"],
|
||||||
|
user_data["Notify"]["ServerChanChannel"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} |用户ServerChan密钥为空,无法发送用户单独的ServerChan通知"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 推送CompanyWebHookBot通知
|
||||||
|
if user_data["Notify"]["IfCompanyWebHookBot"]:
|
||||||
|
if user_data["Notify"]["CompanyWebHookBotUrl"]:
|
||||||
|
Notify.CompanyWebHookBotPush(
|
||||||
|
title,
|
||||||
|
"好羡慕~\n\nAUTO_MAA 敬上",
|
||||||
|
user_data["Notify"]["CompanyWebHookBotUrl"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.name} |用户CompanyWebHookBot密钥为空,无法发送用户单独的CompanyWebHookBot通知"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|||||||
@@ -25,18 +25,20 @@ v4.3
|
|||||||
作者:DLmaster_361
|
作者:DLmaster_361
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from PySide6.QtWidgets import QWidget
|
|
||||||
from PySide6.QtCore import Signal
|
|
||||||
import requests
|
|
||||||
import time
|
|
||||||
from loguru import logger
|
|
||||||
from plyer import notification
|
|
||||||
import re
|
import re
|
||||||
import smtplib
|
import smtplib
|
||||||
from email.mime.text import MIMEText
|
import time
|
||||||
from email.mime.multipart import MIMEMultipart
|
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
from email.utils import formataddr
|
from email.utils import formataddr
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from PySide6.QtCore import Signal
|
||||||
|
from PySide6.QtWidgets import QWidget
|
||||||
|
from loguru import logger
|
||||||
|
from plyer import notification
|
||||||
|
|
||||||
from app.core import Config
|
from app.core import Config
|
||||||
from app.services.security import Crypto
|
from app.services.security import Crypto
|
||||||
|
|
||||||
@@ -65,218 +67,210 @@ class Notification(QWidget):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def send_mail(self, mode, title, content) -> None:
|
def send_mail(self, mode, title, content, to_address) -> None:
|
||||||
"""推送邮件通知"""
|
"""推送邮件通知"""
|
||||||
|
if (
|
||||||
if Config.get(Config.notify_IfSendMail):
|
Config.get(Config.notify_SMTPServerAddress) == ""
|
||||||
|
or Config.get(Config.notify_AuthorizationCode) == ""
|
||||||
if (
|
or not bool(
|
||||||
Config.get(Config.notify_SMTPServerAddress) == ""
|
re.match(
|
||||||
or Config.get(Config.notify_AuthorizationCode) == ""
|
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||||
or not bool(
|
|
||||||
re.match(
|
|
||||||
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
|
||||||
Config.get(Config.notify_FromAddress),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
or not bool(
|
|
||||||
re.match(
|
|
||||||
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
|
||||||
Config.get(Config.notify_ToAddress),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
):
|
|
||||||
logger.error(
|
|
||||||
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址"
|
|
||||||
)
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"error",
|
|
||||||
"邮件通知推送异常",
|
|
||||||
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址",
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 定义邮件正文
|
|
||||||
if mode == "文本":
|
|
||||||
message = MIMEText(content, "plain", "utf-8")
|
|
||||||
elif mode == "网页":
|
|
||||||
message = MIMEMultipart("alternative")
|
|
||||||
message["From"] = formataddr(
|
|
||||||
(
|
|
||||||
Header("AUTO_MAA通知服务", "utf-8").encode(),
|
|
||||||
Config.get(Config.notify_FromAddress),
|
|
||||||
)
|
|
||||||
) # 发件人显示的名字
|
|
||||||
message["To"] = formataddr(
|
|
||||||
(
|
|
||||||
Header("AUTO_MAA用户", "utf-8").encode(),
|
|
||||||
Config.get(Config.notify_ToAddress),
|
|
||||||
)
|
|
||||||
) # 收件人显示的名字
|
|
||||||
message["Subject"] = Header(title, "utf-8")
|
|
||||||
|
|
||||||
if mode == "网页":
|
|
||||||
message.attach(MIMEText(content, "html", "utf-8"))
|
|
||||||
|
|
||||||
smtpObj = smtplib.SMTP_SSL(
|
|
||||||
Config.get(Config.notify_SMTPServerAddress),
|
|
||||||
465,
|
|
||||||
)
|
|
||||||
smtpObj.login(
|
|
||||||
Config.get(Config.notify_FromAddress),
|
Config.get(Config.notify_FromAddress),
|
||||||
Crypto.win_decryptor(Config.get(Config.notify_AuthorizationCode)),
|
|
||||||
)
|
)
|
||||||
smtpObj.sendmail(
|
)
|
||||||
|
or not bool(
|
||||||
|
re.match(
|
||||||
|
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||||
|
to_address,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
logger.error(
|
||||||
|
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址"
|
||||||
|
)
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"邮件通知推送异常",
|
||||||
|
"请正确设置邮件通知的SMTP服务器地址、授权码、发件人地址和收件人地址",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 定义邮件正文
|
||||||
|
if mode == "文本":
|
||||||
|
message = MIMEText(content, "plain", "utf-8")
|
||||||
|
elif mode == "网页":
|
||||||
|
message = MIMEMultipart("alternative")
|
||||||
|
message["From"] = formataddr(
|
||||||
|
(
|
||||||
|
Header("AUTO_MAA通知服务", "utf-8").encode(),
|
||||||
Config.get(Config.notify_FromAddress),
|
Config.get(Config.notify_FromAddress),
|
||||||
Config.get(Config.notify_ToAddress),
|
|
||||||
message.as_string(),
|
|
||||||
)
|
)
|
||||||
smtpObj.quit()
|
) # 发件人显示的名字
|
||||||
logger.success("邮件发送成功")
|
message["To"] = formataddr(
|
||||||
except Exception as e:
|
(
|
||||||
logger.error(f"发送邮件时出错:\n{e}")
|
Header("AUTO_MAA用户", "utf-8").encode(),
|
||||||
self.push_info_bar.emit("error", "发送邮件时出错", f"{e}", -1)
|
to_address,
|
||||||
|
|
||||||
def ServerChanPush(self, title, content):
|
|
||||||
"""使用Server酱推送通知(支持 tag 和 channel,避免使用SDK)"""
|
|
||||||
if Config.get(Config.notify_IfServerChan):
|
|
||||||
send_key = Config.get(Config.notify_ServerChanKey)
|
|
||||||
|
|
||||||
if not send_key:
|
|
||||||
logger.error("请正确设置Server酱的SendKey")
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"error", "Server酱通知推送异常", "请正确设置Server酱的SendKey", -1
|
|
||||||
)
|
)
|
||||||
return None
|
) # 收件人显示的名字
|
||||||
|
message["Subject"] = Header(title, "utf-8")
|
||||||
|
|
||||||
try:
|
if mode == "网页":
|
||||||
# 构造 URL
|
message.attach(MIMEText(content, "html", "utf-8"))
|
||||||
if send_key.startswith("sctp"):
|
|
||||||
match = re.match(r"^sctp(\d+)t", send_key)
|
smtpObj = smtplib.SMTP_SSL(
|
||||||
if match:
|
Config.get(Config.notify_SMTPServerAddress),
|
||||||
url = f"https://{match.group(1)}.push.ft07.com/send/{send_key}.send"
|
465,
|
||||||
else:
|
)
|
||||||
raise ValueError("SendKey 格式错误(sctp)")
|
smtpObj.login(
|
||||||
|
Config.get(Config.notify_FromAddress),
|
||||||
|
Crypto.win_decryptor(Config.get(Config.notify_AuthorizationCode)),
|
||||||
|
)
|
||||||
|
smtpObj.sendmail(
|
||||||
|
Config.get(Config.notify_FromAddress),
|
||||||
|
to_address,
|
||||||
|
message.as_string(),
|
||||||
|
)
|
||||||
|
smtpObj.quit()
|
||||||
|
logger.success("邮件发送成功")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"发送邮件时出错:\n{e}")
|
||||||
|
self.push_info_bar.emit("error", "发送邮件时出错", f"{e}", -1)
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
def ServerChanPush(self, title, content, send_key, tag, channel):
|
||||||
|
"""使用Server酱推送通知"""
|
||||||
|
if not send_key:
|
||||||
|
logger.error("请正确设置Server酱的SendKey")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error", "Server酱通知推送异常", "请正确设置Server酱的SendKey", -1
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 构造 URL
|
||||||
|
if send_key.startswith("sctp"):
|
||||||
|
match = re.match(r"^sctp(\d+)t", send_key)
|
||||||
|
if match:
|
||||||
|
url = f"https://{match.group(1)}.push.ft07.com/send/{send_key}.send"
|
||||||
else:
|
else:
|
||||||
url = f"https://sctapi.ftqq.com/{send_key}.send"
|
raise ValueError("SendKey 格式错误(sctp)")
|
||||||
|
|
||||||
# 构建 tags 和 channel
|
|
||||||
def is_valid(s):
|
|
||||||
return s == "" or (
|
|
||||||
s == "|".join(s.split("|"))
|
|
||||||
and (s.count("|") == 0 or all(s.split("|")))
|
|
||||||
)
|
|
||||||
|
|
||||||
tags = "|".join(
|
|
||||||
_.strip()
|
|
||||||
for _ in Config.get(Config.notify_ServerChanTag).split("|")
|
|
||||||
)
|
|
||||||
channels = "|".join(
|
|
||||||
_.strip()
|
|
||||||
for _ in Config.get(Config.notify_ServerChanChannel).split("|")
|
|
||||||
)
|
|
||||||
|
|
||||||
options = {}
|
|
||||||
if is_valid(tags):
|
|
||||||
options["tags"] = tags
|
|
||||||
else:
|
|
||||||
logger.warning("Server酱 Tag 配置不正确,将被忽略")
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"warning",
|
|
||||||
"Server酱通知推送异常",
|
|
||||||
"请正确设置 ServerChan 的 Tag",
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_valid(channels):
|
|
||||||
options["channel"] = channels
|
|
||||||
else:
|
|
||||||
logger.warning("Server酱 Channel 配置不正确,将被忽略")
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"warning",
|
|
||||||
"Server酱通知推送异常",
|
|
||||||
"请正确设置 ServerChan 的 Channel",
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 请求发送
|
|
||||||
params = {"title": title, "desp": content, **options}
|
|
||||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
|
||||||
|
|
||||||
response = requests.post(url, json=params, headers=headers, timeout=10)
|
|
||||||
result = response.json()
|
|
||||||
|
|
||||||
if result.get("code") == 0:
|
|
||||||
logger.info("Server酱推送通知成功")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
error_code = result.get("code", "-1")
|
|
||||||
logger.error(f"Server酱通知推送失败:响应码:{error_code}")
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"error", "Server酱通知推送失败", f"响应码:{error_code}", -1
|
|
||||||
)
|
|
||||||
return f"Server酱通知推送失败:{error_code}"
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception("Server酱通知推送异常")
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"error", "Server酱通知推送异常", f"请检查相关设置,如还有问题可联系开发者", -1
|
|
||||||
)
|
|
||||||
return f"Server酱通知推送异常:{str(e)}"
|
|
||||||
|
|
||||||
def CompanyWebHookBotPush(self, title, content):
|
|
||||||
"""使用企业微信群机器人推送通知"""
|
|
||||||
if Config.get(Config.notify_IfCompanyWebHookBot):
|
|
||||||
|
|
||||||
if Config.get(Config.notify_CompanyWebHookBotUrl) == "":
|
|
||||||
logger.error("请正确设置企业微信群机器人的WebHook地址")
|
|
||||||
self.push_info_bar.emit(
|
|
||||||
"error",
|
|
||||||
"企业微信群机器人通知推送异常",
|
|
||||||
"请正确设置企业微信群机器人的WebHook地址",
|
|
||||||
-1,
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
content = f"{title}\n{content}"
|
|
||||||
data = {"msgtype": "text", "text": {"content": content}}
|
|
||||||
# 从远程服务器获取最新主题图像
|
|
||||||
for _ in range(3):
|
|
||||||
try:
|
|
||||||
response = requests.post(
|
|
||||||
url=Config.get(Config.notify_CompanyWebHookBotUrl),
|
|
||||||
json=data,
|
|
||||||
timeout=10,
|
|
||||||
)
|
|
||||||
info = response.json()
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
err = e
|
|
||||||
time.sleep(0.1)
|
|
||||||
else:
|
else:
|
||||||
logger.error(f"推送企业微信群机器人时出错:{err}")
|
url = f"https://sctapi.ftqq.com/{send_key}.send"
|
||||||
|
|
||||||
|
# 构建 tags 和 channel
|
||||||
|
def is_valid(s):
|
||||||
|
return s == "" or (
|
||||||
|
s == "|".join(s.split("|"))
|
||||||
|
and (s.count("|") == 0 or all(s.split("|")))
|
||||||
|
)
|
||||||
|
|
||||||
|
tags = "|".join(_.strip() for _ in tag.split("|"))
|
||||||
|
channels = "|".join(_.strip() for _ in channel.split("|"))
|
||||||
|
|
||||||
|
options = {}
|
||||||
|
if is_valid(tags):
|
||||||
|
options["tags"] = tags
|
||||||
|
else:
|
||||||
|
logger.warning("Server酱 Tag 配置不正确,将被忽略")
|
||||||
self.push_info_bar.emit(
|
self.push_info_bar.emit(
|
||||||
"error",
|
"warning",
|
||||||
"企业微信群机器人通知推送失败",
|
"Server酱通知推送异常",
|
||||||
f'使用企业微信群机器人推送通知时出错:{info["errmsg"]}',
|
"请正确设置 ServerChan 的 Tag",
|
||||||
-1,
|
-1,
|
||||||
)
|
)
|
||||||
return None
|
|
||||||
|
|
||||||
if info["errcode"] == 0:
|
if is_valid(channels):
|
||||||
logger.info("企业微信群机器人推送通知成功")
|
options["channel"] = channels
|
||||||
|
else:
|
||||||
|
logger.warning("Server酱 Channel 配置不正确,将被忽略")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"warning",
|
||||||
|
"Server酱通知推送异常",
|
||||||
|
"请正确设置 ServerChan 的 Channel",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 请求发送
|
||||||
|
params = {"title": title, "desp": content, **options}
|
||||||
|
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||||
|
|
||||||
|
response = requests.post(url, json=params, headers=headers, timeout=10)
|
||||||
|
result = response.json()
|
||||||
|
|
||||||
|
if result.get("code") == 0:
|
||||||
|
logger.info("Server酱推送通知成功")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.error(f"企业微信群机器人推送通知失败:{info}")
|
error_code = result.get("code", "-1")
|
||||||
|
logger.error(f"Server酱通知推送失败:响应码:{error_code}")
|
||||||
self.push_info_bar.emit(
|
self.push_info_bar.emit(
|
||||||
"error",
|
"error", "Server酱通知推送失败", f"响应码:{error_code}", -1
|
||||||
"企业微信群机器人通知推送失败",
|
|
||||||
f'使用企业微信群机器人推送通知时出错:{info["errmsg"]}',
|
|
||||||
-1,
|
|
||||||
)
|
)
|
||||||
return f'使用企业微信群机器人推送通知时出错:{info["errmsg"]}'
|
return f"Server酱通知推送失败:{error_code}"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Server酱通知推送异常")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"Server酱通知推送异常",
|
||||||
|
"请检查相关设置和网络连接。如全部配置正确,请稍后再试。",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
return f"Server酱通知推送异常:{str(e)}"
|
||||||
|
|
||||||
|
def CompanyWebHookBotPush(self, title, content, webhook_url):
|
||||||
|
"""使用企业微信群机器人推送通知"""
|
||||||
|
if webhook_url == "":
|
||||||
|
logger.error("请正确设置企业微信群机器人的WebHook地址")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"企业微信群机器人通知推送异常",
|
||||||
|
"请正确设置企业微信群机器人的WebHook地址",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
content = f"{title}\n{content}"
|
||||||
|
data = {"msgtype": "text", "text": {"content": content}}
|
||||||
|
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
url=webhook_url,
|
||||||
|
json=data,
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
info = response.json()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
err = e
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
logger.error(f"推送企业微信群机器人时出错:{err}")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"企业微信群机器人通知推送失败",
|
||||||
|
f"使用企业微信群机器人推送通知时出错:{err}",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if info["errcode"] == 0:
|
||||||
|
logger.info("企业微信群机器人推送通知成功")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.error(f"企业微信群机器人推送通知失败:{info}")
|
||||||
|
self.push_info_bar.emit(
|
||||||
|
"error",
|
||||||
|
"企业微信群机器人通知推送失败",
|
||||||
|
f"使用企业微信群机器人推送通知时出错:{err}",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
return f"使用企业微信群机器人推送通知时出错:{err}"
|
||||||
|
|
||||||
def send_test_notification(self):
|
def send_test_notification(self):
|
||||||
"""发送测试通知到所有已启用的通知渠道"""
|
"""发送测试通知到所有已启用的通知渠道"""
|
||||||
@@ -294,6 +288,7 @@ class Notification(QWidget):
|
|||||||
"文本",
|
"文本",
|
||||||
"AUTO_MAA测试通知",
|
"AUTO_MAA测试通知",
|
||||||
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容,说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
|
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容,说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
|
||||||
|
Config.get(Config.notify_ToAddress),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 发送Server酱通知
|
# 发送Server酱通知
|
||||||
@@ -301,6 +296,9 @@ class Notification(QWidget):
|
|||||||
self.ServerChanPush(
|
self.ServerChanPush(
|
||||||
"AUTO_MAA测试通知",
|
"AUTO_MAA测试通知",
|
||||||
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容,说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
|
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容,说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
|
||||||
|
Config.get(Config.notify_ServerChanKey),
|
||||||
|
Config.get(Config.notify_ServerChanTag),
|
||||||
|
Config.get(Config.notify_ServerChanChannel),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 发送企业微信机器人通知
|
# 发送企业微信机器人通知
|
||||||
@@ -308,6 +306,7 @@ class Notification(QWidget):
|
|||||||
self.CompanyWebHookBotPush(
|
self.CompanyWebHookBotPush(
|
||||||
"AUTO_MAA测试通知",
|
"AUTO_MAA测试通知",
|
||||||
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容,说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
|
"这是 AUTO_MAA 外部通知测试信息。如果你看到了这段内容,说明 AUTO_MAA 的通知功能已经正确配置且可以正常工作!",
|
||||||
|
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class _SystemHandler:
|
|||||||
|
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
|
|
||||||
if mode == "None":
|
if mode == "NoAction":
|
||||||
|
|
||||||
logger.info("不执行系统电源操作")
|
logger.info("不执行系统电源操作")
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ class _SystemHandler:
|
|||||||
|
|
||||||
elif sys.platform.startswith("linux"):
|
elif sys.platform.startswith("linux"):
|
||||||
|
|
||||||
if mode == "None":
|
if mode == "NoAction":
|
||||||
|
|
||||||
logger.info("不执行系统电源操作")
|
logger.info("不执行系统电源操作")
|
||||||
|
|
||||||
|
|||||||
822
app/ui/Widget.py
822
app/ui/Widget.py
@@ -25,17 +25,24 @@ v4.3
|
|||||||
作者:DLmaster_361
|
作者:DLmaster_361
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from datetime import datetime
|
||||||
|
from functools import partial
|
||||||
|
from typing import Optional, Union, List, Dict
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import markdown
|
||||||
|
from PySide6.QtCore import Qt, QTime, QTimer, QEvent, QSize
|
||||||
|
from PySide6.QtGui import QIcon, QPixmap, QPainter, QPainterPath
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QApplication,
|
QApplication,
|
||||||
QWidget,
|
QWidget,
|
||||||
QWidget,
|
|
||||||
QLabel,
|
QLabel,
|
||||||
QHBoxLayout,
|
QHBoxLayout,
|
||||||
QVBoxLayout,
|
QVBoxLayout,
|
||||||
QSizePolicy,
|
QSizePolicy,
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt, QTime, QTimer, QEvent, QSize
|
|
||||||
from PySide6.QtGui import QIcon, QPixmap, QPainter, QPainterPath
|
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
LineEdit,
|
LineEdit,
|
||||||
PasswordLineEdit,
|
PasswordLineEdit,
|
||||||
@@ -71,15 +78,13 @@ from qfluentwidgets import (
|
|||||||
SwitchButton,
|
SwitchButton,
|
||||||
IndicatorPosition,
|
IndicatorPosition,
|
||||||
Slider,
|
Slider,
|
||||||
|
ScrollArea,
|
||||||
|
Pivot,
|
||||||
|
PivotItem,
|
||||||
|
FlyoutViewBase,
|
||||||
|
PushSettingCard,
|
||||||
)
|
)
|
||||||
from qfluentwidgets.common.overload import singledispatchmethod
|
from qfluentwidgets.common.overload import singledispatchmethod
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import markdown
|
|
||||||
from datetime import datetime
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
from functools import partial
|
|
||||||
from typing import Optional, Union, List, Dict
|
|
||||||
|
|
||||||
from app.core import Config
|
from app.core import Config
|
||||||
from app.services import Crypto
|
from app.services import Crypto
|
||||||
@@ -105,6 +110,8 @@ class LineEditMessageBox(MessageBoxBase):
|
|||||||
self.viewLayout.addWidget(self.title)
|
self.viewLayout.addWidget(self.title)
|
||||||
self.viewLayout.addWidget(self.input)
|
self.viewLayout.addWidget(self.input)
|
||||||
|
|
||||||
|
self.input.setFocus()
|
||||||
|
|
||||||
|
|
||||||
class ComboBoxMessageBox(MessageBoxBase):
|
class ComboBoxMessageBox(MessageBoxBase):
|
||||||
"""选择对话框"""
|
"""选择对话框"""
|
||||||
@@ -268,6 +275,41 @@ class NoticeMessageBox(MessageBoxBase):
|
|||||||
self.Layout.addStretch(1)
|
self.Layout.addStretch(1)
|
||||||
|
|
||||||
|
|
||||||
|
class SettingFlyoutView(FlyoutViewBase):
|
||||||
|
"""设置卡二级菜单弹出组件"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
parent,
|
||||||
|
title: str,
|
||||||
|
setting_cards: List[Union[SettingCard, HeaderCardWidget]],
|
||||||
|
):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.title = SubtitleLabel(title)
|
||||||
|
|
||||||
|
content_widget = QWidget()
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setSpacing(0)
|
||||||
|
content_layout.setContentsMargins(0, 0, 11, 0)
|
||||||
|
for setting_card in setting_cards:
|
||||||
|
content_layout.addWidget(setting_card)
|
||||||
|
|
||||||
|
scrollArea = ScrollArea()
|
||||||
|
scrollArea.setWidgetResizable(True)
|
||||||
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
|
scrollArea.setWidget(content_widget)
|
||||||
|
|
||||||
|
self.viewLayout = QVBoxLayout(self)
|
||||||
|
self.viewLayout.setSpacing(12)
|
||||||
|
self.viewLayout.setContentsMargins(20, 16, 9, 16)
|
||||||
|
self.viewLayout.addWidget(self.title)
|
||||||
|
self.viewLayout.addWidget(scrollArea)
|
||||||
|
|
||||||
|
self.setVisible(False)
|
||||||
|
|
||||||
|
|
||||||
class SwitchSettingCard(SettingCard):
|
class SwitchSettingCard(SettingCard):
|
||||||
"""Setting card with switch button"""
|
"""Setting card with switch button"""
|
||||||
|
|
||||||
@@ -428,24 +470,27 @@ class LineEditSettingCard(SettingCard):
|
|||||||
self.LineEdit.setMinimumWidth(250)
|
self.LineEdit.setMinimumWidth(250)
|
||||||
self.LineEdit.setPlaceholderText(text)
|
self.LineEdit.setPlaceholderText(text)
|
||||||
|
|
||||||
if configItem:
|
|
||||||
self.setValue(self.qconfig.get(configItem))
|
|
||||||
configItem.valueChanged.connect(self.setValue)
|
|
||||||
|
|
||||||
self.hBoxLayout.addWidget(self.LineEdit, 0, Qt.AlignRight)
|
self.hBoxLayout.addWidget(self.LineEdit, 0, Qt.AlignRight)
|
||||||
self.hBoxLayout.addSpacing(16)
|
self.hBoxLayout.addSpacing(16)
|
||||||
|
|
||||||
|
self.configItem.valueChanged.connect(self.setValue)
|
||||||
self.LineEdit.textChanged.connect(self.__textChanged)
|
self.LineEdit.textChanged.connect(self.__textChanged)
|
||||||
|
|
||||||
|
self.setValue(self.qconfig.get(configItem))
|
||||||
|
|
||||||
def __textChanged(self, content: str):
|
def __textChanged(self, content: str):
|
||||||
self.setValue(content.strip())
|
|
||||||
|
self.configItem.valueChanged.disconnect(self.setValue)
|
||||||
|
self.qconfig.set(self.configItem, content.strip())
|
||||||
|
self.configItem.valueChanged.connect(self.setValue)
|
||||||
|
|
||||||
self.textChanged.emit(content.strip())
|
self.textChanged.emit(content.strip())
|
||||||
|
|
||||||
def setValue(self, content: str):
|
def setValue(self, content: str):
|
||||||
if self.configItem:
|
|
||||||
self.qconfig.set(self.configItem, content.strip())
|
|
||||||
|
|
||||||
|
self.LineEdit.textChanged.disconnect(self.__textChanged)
|
||||||
self.LineEdit.setText(content.strip())
|
self.LineEdit.setText(content.strip())
|
||||||
|
self.LineEdit.textChanged.connect(self.__textChanged)
|
||||||
|
|
||||||
|
|
||||||
class PasswordLineEditSettingCard(SettingCard):
|
class PasswordLineEditSettingCard(SettingCard):
|
||||||
@@ -474,35 +519,29 @@ class PasswordLineEditSettingCard(SettingCard):
|
|||||||
self.LineEdit.setPlaceholderText(text)
|
self.LineEdit.setPlaceholderText(text)
|
||||||
if algorithm == "AUTO":
|
if algorithm == "AUTO":
|
||||||
self.LineEdit.setViewPasswordButtonVisible(False)
|
self.LineEdit.setViewPasswordButtonVisible(False)
|
||||||
self.if_setValue = False
|
|
||||||
|
|
||||||
if configItem:
|
|
||||||
self.setValue(self.qconfig.get(configItem))
|
|
||||||
configItem.valueChanged.connect(self.setValue)
|
|
||||||
|
|
||||||
self.hBoxLayout.addWidget(self.LineEdit, 0, Qt.AlignRight)
|
self.hBoxLayout.addWidget(self.LineEdit, 0, Qt.AlignRight)
|
||||||
self.hBoxLayout.addSpacing(16)
|
self.hBoxLayout.addSpacing(16)
|
||||||
|
|
||||||
|
self.configItem.valueChanged.connect(self.setValue)
|
||||||
self.LineEdit.textChanged.connect(self.__textChanged)
|
self.LineEdit.textChanged.connect(self.__textChanged)
|
||||||
|
|
||||||
|
self.setValue(self.qconfig.get(configItem))
|
||||||
|
|
||||||
def __textChanged(self, content: str):
|
def __textChanged(self, content: str):
|
||||||
|
|
||||||
if self.if_setValue:
|
self.configItem.valueChanged.disconnect(self.setValue)
|
||||||
return None
|
|
||||||
|
|
||||||
if self.algorithm == "DPAPI":
|
if self.algorithm == "DPAPI":
|
||||||
self.setValue(Crypto.win_encryptor(content))
|
self.qconfig.set(self.configItem, Crypto.win_encryptor(content))
|
||||||
elif self.algorithm == "AUTO":
|
elif self.algorithm == "AUTO":
|
||||||
self.setValue(Crypto.AUTO_encryptor(content))
|
self.qconfig.set(self.configItem, Crypto.AUTO_encryptor(content))
|
||||||
|
self.configItem.valueChanged.connect(self.setValue)
|
||||||
|
|
||||||
self.textChanged.emit()
|
self.textChanged.emit()
|
||||||
|
|
||||||
def setValue(self, content: str):
|
def setValue(self, content: str):
|
||||||
|
|
||||||
self.if_setValue = True
|
self.LineEdit.textChanged.disconnect(self.__textChanged)
|
||||||
|
|
||||||
if self.configItem:
|
|
||||||
self.qconfig.set(self.configItem, content)
|
|
||||||
|
|
||||||
if self.algorithm == "DPAPI":
|
if self.algorithm == "DPAPI":
|
||||||
self.LineEdit.setText(Crypto.win_decryptor(content))
|
self.LineEdit.setText(Crypto.win_decryptor(content))
|
||||||
elif self.algorithm == "AUTO":
|
elif self.algorithm == "AUTO":
|
||||||
@@ -518,59 +557,7 @@ class PasswordLineEditSettingCard(SettingCard):
|
|||||||
self.LineEdit.setText("************")
|
self.LineEdit.setText("************")
|
||||||
self.LineEdit.setPasswordVisible(False)
|
self.LineEdit.setPasswordVisible(False)
|
||||||
self.LineEdit.setReadOnly(True)
|
self.LineEdit.setReadOnly(True)
|
||||||
|
self.LineEdit.textChanged.connect(self.__textChanged)
|
||||||
self.if_setValue = False
|
|
||||||
|
|
||||||
|
|
||||||
class UserLableSettingCard(SettingCard):
|
|
||||||
"""Setting card with User's Lable"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
icon: Union[str, QIcon, FluentIconBase],
|
|
||||||
title: str,
|
|
||||||
content: Union[str, None],
|
|
||||||
qconfig: QConfig,
|
|
||||||
configItems: Dict[str, ConfigItem],
|
|
||||||
parent=None,
|
|
||||||
):
|
|
||||||
|
|
||||||
super().__init__(icon, title, content, parent)
|
|
||||||
self.qconfig = qconfig
|
|
||||||
self.configItems = configItems
|
|
||||||
self.Lable = SubtitleLabel(self)
|
|
||||||
|
|
||||||
if configItems:
|
|
||||||
for configItem in configItems.values():
|
|
||||||
configItem.valueChanged.connect(self.setValue)
|
|
||||||
self.setValue()
|
|
||||||
|
|
||||||
self.hBoxLayout.addWidget(self.Lable, 0, Qt.AlignRight)
|
|
||||||
self.hBoxLayout.addSpacing(16)
|
|
||||||
|
|
||||||
def setValue(self):
|
|
||||||
if self.configItems:
|
|
||||||
|
|
||||||
text_list = []
|
|
||||||
if not self.qconfig.get(self.configItems["IfPassCheck"]):
|
|
||||||
text_list.append("未通过人工排查")
|
|
||||||
text_list.append(
|
|
||||||
f"今日已代理{self.qconfig.get(self.configItems["ProxyTimes"])}次"
|
|
||||||
if Config.server_date().strftime("%Y-%m-%d")
|
|
||||||
== self.qconfig.get(self.configItems["LastProxyDate"])
|
|
||||||
else "今日未进行代理"
|
|
||||||
)
|
|
||||||
text_list.append(
|
|
||||||
"本周剿灭已完成"
|
|
||||||
if datetime.strptime(
|
|
||||||
self.qconfig.get(self.configItems["LastAnnihilationDate"]),
|
|
||||||
"%Y-%m-%d",
|
|
||||||
).isocalendar()[:2]
|
|
||||||
== Config.server_date().isocalendar()[:2]
|
|
||||||
else "本周剿灭未完成"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.Lable.setText(" | ".join(text_list))
|
|
||||||
|
|
||||||
|
|
||||||
class PushAndSwitchButtonSettingCard(SettingCard):
|
class PushAndSwitchButtonSettingCard(SettingCard):
|
||||||
@@ -721,7 +708,7 @@ class NoOptionComboBoxSettingCard(SettingCard):
|
|||||||
value: List[str],
|
value: List[str],
|
||||||
texts: List[str],
|
texts: List[str],
|
||||||
qconfig: QConfig,
|
qconfig: QConfig,
|
||||||
configItem: OptionsConfigItem,
|
configItem: ConfigItem,
|
||||||
parent=None,
|
parent=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -754,7 +741,7 @@ class NoOptionComboBoxSettingCard(SettingCard):
|
|||||||
|
|
||||||
def reLoadOptions(self, value: List[str], texts: List[str]):
|
def reLoadOptions(self, value: List[str], texts: List[str]):
|
||||||
|
|
||||||
self.comboBox.currentIndexChanged.disconnect()
|
self.comboBox.currentIndexChanged.disconnect(self._onCurrentIndexChanged)
|
||||||
self.comboBox.clear()
|
self.comboBox.clear()
|
||||||
self.optionToText = {o: t for o, t in zip(value, texts)}
|
self.optionToText = {o: t for o, t in zip(value, texts)}
|
||||||
for text, option in zip(texts, value):
|
for text, option in zip(texts, value):
|
||||||
@@ -776,7 +763,7 @@ class EditableComboBoxSettingCard(SettingCard):
|
|||||||
value: List[str],
|
value: List[str],
|
||||||
texts: List[str],
|
texts: List[str],
|
||||||
qconfig: QConfig,
|
qconfig: QConfig,
|
||||||
configItem: OptionsConfigItem,
|
configItem: ConfigItem,
|
||||||
parent=None,
|
parent=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -826,7 +813,7 @@ class EditableComboBoxSettingCard(SettingCard):
|
|||||||
|
|
||||||
def reLoadOptions(self, value: List[str], texts: List[str]):
|
def reLoadOptions(self, value: List[str], texts: List[str]):
|
||||||
|
|
||||||
self.comboBox.currentIndexChanged.disconnect()
|
self.comboBox.currentIndexChanged.disconnect(self._onCurrentIndexChanged)
|
||||||
self.comboBox.clear()
|
self.comboBox.clear()
|
||||||
self.optionToText = {o: t for o, t in zip(value, texts)}
|
self.optionToText = {o: t for o, t in zip(value, texts)}
|
||||||
for text, option in zip(texts, value):
|
for text, option in zip(texts, value):
|
||||||
@@ -864,6 +851,169 @@ class EditableComboBoxSettingCard(SettingCard):
|
|||||||
self.currentIndexChanged.emit(self.count() - 1)
|
self.currentIndexChanged.emit(self.count() - 1)
|
||||||
|
|
||||||
|
|
||||||
|
class SpinBoxWithPlanSettingCard(SpinBoxSettingCard):
|
||||||
|
|
||||||
|
textChanged = Signal(int)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
range: tuple[int, int],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: ConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(icon, title, content, range, qconfig, configItem, parent)
|
||||||
|
|
||||||
|
self.configItem_plan = None
|
||||||
|
|
||||||
|
self.LineEdit = LineEdit(self)
|
||||||
|
self.LineEdit.setMinimumWidth(150)
|
||||||
|
self.LineEdit.setReadOnly(True)
|
||||||
|
self.LineEdit.setVisible(False)
|
||||||
|
|
||||||
|
self.hBoxLayout.insertWidget(5, self.LineEdit, 0, Qt.AlignRight)
|
||||||
|
|
||||||
|
def setText(self, value: int) -> None:
|
||||||
|
self.LineEdit.setText(str(value))
|
||||||
|
|
||||||
|
def switch_mode(self, mode: str) -> None:
|
||||||
|
"""切换模式"""
|
||||||
|
|
||||||
|
if mode == "固定":
|
||||||
|
|
||||||
|
self.LineEdit.setVisible(False)
|
||||||
|
self.SpinBox.setVisible(True)
|
||||||
|
|
||||||
|
elif mode == "计划":
|
||||||
|
|
||||||
|
self.SpinBox.setVisible(False)
|
||||||
|
self.LineEdit.setVisible(True)
|
||||||
|
|
||||||
|
def change_plan(self, configItem_plan: ConfigItem) -> None:
|
||||||
|
"""切换计划"""
|
||||||
|
|
||||||
|
if self.configItem_plan is not None:
|
||||||
|
self.configItem_plan.valueChanged.disconnect(self.setText)
|
||||||
|
self.configItem_plan = configItem_plan
|
||||||
|
self.configItem_plan.valueChanged.connect(self.setText)
|
||||||
|
self.setText(self.qconfig.get(self.configItem_plan))
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxWithPlanSettingCard(ComboBoxSettingCard):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
texts: List[str],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: OptionsConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(icon, title, content, texts, qconfig, configItem, parent)
|
||||||
|
|
||||||
|
self.configItem_plan = None
|
||||||
|
|
||||||
|
self.LineEdit = LineEdit(self)
|
||||||
|
self.LineEdit.setMinimumWidth(150)
|
||||||
|
self.LineEdit.setReadOnly(True)
|
||||||
|
self.LineEdit.setVisible(False)
|
||||||
|
|
||||||
|
self.hBoxLayout.insertWidget(5, self.LineEdit, 0, Qt.AlignRight)
|
||||||
|
|
||||||
|
def setText(self, value: str) -> None:
|
||||||
|
|
||||||
|
if value not in self.optionToText:
|
||||||
|
self.optionToText[value] = value
|
||||||
|
|
||||||
|
self.LineEdit.setText(self.optionToText[value])
|
||||||
|
|
||||||
|
def switch_mode(self, mode: str) -> None:
|
||||||
|
"""切换模式"""
|
||||||
|
|
||||||
|
if mode == "固定":
|
||||||
|
|
||||||
|
self.LineEdit.setVisible(False)
|
||||||
|
self.comboBox.setVisible(True)
|
||||||
|
|
||||||
|
elif mode == "计划":
|
||||||
|
|
||||||
|
self.comboBox.setVisible(False)
|
||||||
|
self.LineEdit.setVisible(True)
|
||||||
|
|
||||||
|
def change_plan(self, configItem_plan: ConfigItem) -> None:
|
||||||
|
"""切换计划"""
|
||||||
|
|
||||||
|
if self.configItem_plan is not None:
|
||||||
|
self.configItem_plan.valueChanged.disconnect(self.setText)
|
||||||
|
self.configItem_plan = configItem_plan
|
||||||
|
self.configItem_plan.valueChanged.connect(self.setText)
|
||||||
|
self.setText(self.qconfig.get(self.configItem_plan))
|
||||||
|
|
||||||
|
|
||||||
|
class EditableComboBoxWithPlanSettingCard(EditableComboBoxSettingCard):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
value: List[str],
|
||||||
|
texts: List[str],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: ConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
icon, title, content, value, texts, qconfig, configItem, parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self.configItem_plan = None
|
||||||
|
|
||||||
|
self.LineEdit = LineEdit(self)
|
||||||
|
self.LineEdit.setMinimumWidth(150)
|
||||||
|
self.LineEdit.setReadOnly(True)
|
||||||
|
self.LineEdit.setVisible(False)
|
||||||
|
|
||||||
|
self.hBoxLayout.insertWidget(5, self.LineEdit, 0, Qt.AlignRight)
|
||||||
|
|
||||||
|
def setText(self, value: str) -> None:
|
||||||
|
|
||||||
|
if value not in self.optionToText:
|
||||||
|
self.optionToText[value] = value
|
||||||
|
|
||||||
|
self.LineEdit.setText(self.optionToText[value])
|
||||||
|
|
||||||
|
def switch_mode(self, mode: str) -> None:
|
||||||
|
"""切换模式"""
|
||||||
|
|
||||||
|
if mode == "固定":
|
||||||
|
|
||||||
|
self.LineEdit.setVisible(False)
|
||||||
|
self.comboBox.setVisible(True)
|
||||||
|
|
||||||
|
elif mode == "计划":
|
||||||
|
|
||||||
|
self.comboBox.setVisible(False)
|
||||||
|
self.LineEdit.setVisible(True)
|
||||||
|
|
||||||
|
def change_plan(self, configItem_plan: ConfigItem) -> None:
|
||||||
|
"""切换计划"""
|
||||||
|
|
||||||
|
if self.configItem_plan is not None:
|
||||||
|
self.configItem_plan.valueChanged.disconnect(self.setText)
|
||||||
|
self.configItem_plan = configItem_plan
|
||||||
|
self.configItem_plan.valueChanged.connect(self.setText)
|
||||||
|
self.setText(self.qconfig.get(self.configItem_plan))
|
||||||
|
|
||||||
|
|
||||||
class TimeEditSettingCard(SettingCard):
|
class TimeEditSettingCard(SettingCard):
|
||||||
|
|
||||||
enabledChanged = Signal(bool)
|
enabledChanged = Signal(bool)
|
||||||
@@ -930,6 +1080,418 @@ class TimeEditSettingCard(SettingCard):
|
|||||||
self.TimeEdit.setTime(QTime.fromString(value, "HH:mm"))
|
self.TimeEdit.setTime(QTime.fromString(value, "HH:mm"))
|
||||||
|
|
||||||
|
|
||||||
|
class UserLableSettingCard(SettingCard):
|
||||||
|
"""Setting card with User's Lable"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItems: Dict[str, ConfigItem],
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(icon, title, content, parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItems = configItems
|
||||||
|
self.Lable = SubtitleLabel(self)
|
||||||
|
|
||||||
|
if configItems:
|
||||||
|
for configItem in configItems.values():
|
||||||
|
configItem.valueChanged.connect(self.setValue)
|
||||||
|
self.setValue()
|
||||||
|
|
||||||
|
self.hBoxLayout.addWidget(self.Lable, 0, Qt.AlignRight)
|
||||||
|
self.hBoxLayout.addSpacing(16)
|
||||||
|
|
||||||
|
def setValue(self):
|
||||||
|
|
||||||
|
text_list = []
|
||||||
|
|
||||||
|
if self.configItems:
|
||||||
|
|
||||||
|
if not self.qconfig.get(self.configItems["IfPassCheck"]):
|
||||||
|
text_list.append("未通过人工排查")
|
||||||
|
text_list.append(
|
||||||
|
f"今日已代理{self.qconfig.get(self.configItems["ProxyTimes"])}次"
|
||||||
|
if Config.server_date().strftime("%Y-%m-%d")
|
||||||
|
== self.qconfig.get(self.configItems["LastProxyDate"])
|
||||||
|
else "今日未进行代理"
|
||||||
|
)
|
||||||
|
text_list.append(
|
||||||
|
"本周剿灭已完成"
|
||||||
|
if datetime.strptime(
|
||||||
|
self.qconfig.get(self.configItems["LastAnnihilationDate"]),
|
||||||
|
"%Y-%m-%d",
|
||||||
|
).isocalendar()[:2]
|
||||||
|
== Config.server_date().isocalendar()[:2]
|
||||||
|
else "本周剿灭未完成"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.Lable.setText(" | ".join(text_list))
|
||||||
|
|
||||||
|
|
||||||
|
class UserTaskSettingCard(PushSettingCard):
|
||||||
|
"""Setting card with User's Task"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
text: str,
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItems: Dict[str, ConfigItem],
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(text, icon, title, content, parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItems = configItems
|
||||||
|
self.Lable = SubtitleLabel(self)
|
||||||
|
|
||||||
|
if configItems:
|
||||||
|
for config_item in configItems.values():
|
||||||
|
config_item.valueChanged.connect(self.setValues)
|
||||||
|
self.setValues()
|
||||||
|
|
||||||
|
self.hBoxLayout.addWidget(self.Lable, 0, Qt.AlignRight)
|
||||||
|
self.hBoxLayout.addSpacing(16)
|
||||||
|
|
||||||
|
def setValues(self):
|
||||||
|
|
||||||
|
text_list = []
|
||||||
|
|
||||||
|
if self.configItems:
|
||||||
|
|
||||||
|
if self.qconfig.get(self.configItems["IfWakeUp"]):
|
||||||
|
text_list.append("开始唤醒")
|
||||||
|
if self.qconfig.get(self.configItems["IfRecruiting"]):
|
||||||
|
text_list.append("自动公招")
|
||||||
|
if self.qconfig.get(self.configItems["IfBase"]):
|
||||||
|
text_list.append("基建换班")
|
||||||
|
if self.qconfig.get(self.configItems["IfCombat"]):
|
||||||
|
text_list.append("刷理智")
|
||||||
|
if self.qconfig.get(self.configItems["IfMall"]):
|
||||||
|
text_list.append("获取信用及购物")
|
||||||
|
if self.qconfig.get(self.configItems["IfMission"]):
|
||||||
|
text_list.append("领取奖励")
|
||||||
|
if self.qconfig.get(self.configItems["IfAutoRoguelike"]):
|
||||||
|
text_list.append("自动肉鸽")
|
||||||
|
if self.qconfig.get(self.configItems["IfReclamation"]):
|
||||||
|
text_list.append("生息演算")
|
||||||
|
|
||||||
|
if text_list:
|
||||||
|
self.setContent(f"任务序列:{" - ".join(text_list)}")
|
||||||
|
else:
|
||||||
|
self.setContent("未启用任何任务项")
|
||||||
|
|
||||||
|
|
||||||
|
class UserNoticeSettingCard(PushAndSwitchButtonSettingCard):
|
||||||
|
"""Setting card with User's Notice"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
icon: Union[str, QIcon, FluentIconBase],
|
||||||
|
title: str,
|
||||||
|
content: Union[str, None],
|
||||||
|
text: str,
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: ConfigItem,
|
||||||
|
configItems: Dict[str, ConfigItem],
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(icon, title, content, text, qconfig, configItem, parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItems = configItems
|
||||||
|
self.Lable = SubtitleLabel(self)
|
||||||
|
|
||||||
|
if configItems:
|
||||||
|
for config_item in configItems.values():
|
||||||
|
config_item.valueChanged.connect(self.setValues)
|
||||||
|
self.setValues()
|
||||||
|
|
||||||
|
self.hBoxLayout.addWidget(self.Lable, 0, Qt.AlignRight)
|
||||||
|
self.hBoxLayout.addSpacing(16)
|
||||||
|
|
||||||
|
def setValues(self):
|
||||||
|
|
||||||
|
def short_str(s: str) -> str:
|
||||||
|
if s.startswith(("SC", "sc")):
|
||||||
|
# SendKey:首4 + 末4
|
||||||
|
return f"{s[:4]}***{s[-4:]}" if len(s) > 8 else s
|
||||||
|
|
||||||
|
elif s.startswith(("http://", "https://")):
|
||||||
|
# Webhook URL:域名 + 路径尾3
|
||||||
|
parsed_url = urlparse(s)
|
||||||
|
domain = parsed_url.netloc
|
||||||
|
path_tail = (
|
||||||
|
parsed_url.path[-3:]
|
||||||
|
if len(parsed_url.path) > 3
|
||||||
|
else parsed_url.path
|
||||||
|
)
|
||||||
|
return f"{domain}***{path_tail}"
|
||||||
|
|
||||||
|
elif "@" in s:
|
||||||
|
# 邮箱:@前3/6 + 域名
|
||||||
|
username, domain = s.split("@", 1)
|
||||||
|
displayed_name = f"{username[:3]}***" if len(username) > 6 else username
|
||||||
|
return f"{displayed_name}@{domain}"
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 普通字符串:末尾3字符
|
||||||
|
return f"***{s[-3:]}" if len(s) > 3 else s
|
||||||
|
|
||||||
|
text_list = []
|
||||||
|
|
||||||
|
if self.configItems:
|
||||||
|
|
||||||
|
if not (
|
||||||
|
self.qconfig.get(self.configItems["IfSendStatistic"])
|
||||||
|
or self.qconfig.get(self.configItems["IfSendSixStar"])
|
||||||
|
):
|
||||||
|
text_list.append("未启用任何通知项")
|
||||||
|
|
||||||
|
if self.qconfig.get(self.configItems["IfSendStatistic"]):
|
||||||
|
text_list.append("统计信息已启用")
|
||||||
|
if self.qconfig.get(self.configItems["IfSendSixStar"]):
|
||||||
|
text_list.append("六星喜报已启用")
|
||||||
|
|
||||||
|
if self.qconfig.get(self.configItems["IfSendMail"]):
|
||||||
|
text_list.append(
|
||||||
|
f"邮箱通知:{short_str(self.qconfig.get(self.configItems["ToAddress"]))}"
|
||||||
|
)
|
||||||
|
if self.qconfig.get(self.configItems["IfServerChan"]):
|
||||||
|
text_list.append(
|
||||||
|
f"Server酱通知:{short_str(self.qconfig.get(self.configItems["ServerChanKey"]))}"
|
||||||
|
)
|
||||||
|
if self.qconfig.get(self.configItems["IfCompanyWebHookBot"]):
|
||||||
|
text_list.append(
|
||||||
|
f"企业微信通知:{short_str(self.qconfig.get(self.configItems["CompanyWebHookBotUrl"]))}"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.setContent(" | ".join(text_list))
|
||||||
|
|
||||||
|
|
||||||
|
class StatusSwitchSetting(SwitchButton):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem_check: ConfigItem,
|
||||||
|
configItem_enable: ConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItem_check = configItem_check
|
||||||
|
self.configItem_enable = configItem_enable
|
||||||
|
self.setOffText("")
|
||||||
|
self.setOnText("")
|
||||||
|
|
||||||
|
if configItem_check:
|
||||||
|
self.setValue(self.qconfig.get(configItem_check))
|
||||||
|
configItem_check.valueChanged.connect(self.setValue)
|
||||||
|
if configItem_enable:
|
||||||
|
self.setEnabled(self.qconfig.get(configItem_enable))
|
||||||
|
configItem_enable.valueChanged.connect(self.setEnabled)
|
||||||
|
|
||||||
|
self.checkedChanged.connect(self.setValue)
|
||||||
|
|
||||||
|
def setValue(self, isChecked: bool):
|
||||||
|
if self.configItem_check:
|
||||||
|
self.qconfig.set(self.configItem_check, isChecked)
|
||||||
|
|
||||||
|
self.setChecked(isChecked)
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxSetting(ComboBox):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
texts: List[str],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: OptionsConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItem = configItem
|
||||||
|
|
||||||
|
self.optionToText = {o: t for o, t in zip(configItem.options, texts)}
|
||||||
|
for text, option in zip(texts, configItem.options):
|
||||||
|
self.addItem(text, userData=option)
|
||||||
|
|
||||||
|
self.setCurrentText(self.optionToText[self.qconfig.get(configItem)])
|
||||||
|
self.currentIndexChanged.connect(self._onCurrentIndexChanged)
|
||||||
|
configItem.valueChanged.connect(self.setValue)
|
||||||
|
|
||||||
|
def _onCurrentIndexChanged(self, index: int):
|
||||||
|
|
||||||
|
self.qconfig.set(self.configItem, self.itemData(index))
|
||||||
|
|
||||||
|
def setValue(self, value):
|
||||||
|
if value not in self.optionToText:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.setCurrentText(self.optionToText[value])
|
||||||
|
self.qconfig.set(self.configItem, value)
|
||||||
|
|
||||||
|
|
||||||
|
class NoOptionComboBoxSetting(ComboBox):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
value: List[str],
|
||||||
|
texts: List[str],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: OptionsConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItem = configItem
|
||||||
|
|
||||||
|
self.optionToText = {o: t for o, t in zip(value, texts)}
|
||||||
|
for text, option in zip(texts, value):
|
||||||
|
self.addItem(text, userData=option)
|
||||||
|
|
||||||
|
self.setCurrentText(self.optionToText[self.qconfig.get(configItem)])
|
||||||
|
self.currentIndexChanged.connect(self._onCurrentIndexChanged)
|
||||||
|
configItem.valueChanged.connect(self.setValue)
|
||||||
|
|
||||||
|
def _onCurrentIndexChanged(self, index: int):
|
||||||
|
|
||||||
|
self.qconfig.set(self.configItem, self.itemData(index))
|
||||||
|
|
||||||
|
def setValue(self, value):
|
||||||
|
if value not in self.optionToText:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.setCurrentText(self.optionToText[value])
|
||||||
|
self.qconfig.set(self.configItem, value)
|
||||||
|
|
||||||
|
def reLoadOptions(self, value: List[str], texts: List[str]):
|
||||||
|
|
||||||
|
self.currentIndexChanged.disconnect(self._onCurrentIndexChanged)
|
||||||
|
self.clear()
|
||||||
|
self.optionToText = {o: t for o, t in zip(value, texts)}
|
||||||
|
for text, option in zip(texts, value):
|
||||||
|
self.addItem(text, userData=option)
|
||||||
|
self.setCurrentText(self.optionToText[self.qconfig.get(self.configItem)])
|
||||||
|
self.currentIndexChanged.connect(self._onCurrentIndexChanged)
|
||||||
|
|
||||||
|
|
||||||
|
class EditableComboBoxSetting(EditableComboBox):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
value: List[str],
|
||||||
|
texts: List[str],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: OptionsConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItem = configItem
|
||||||
|
|
||||||
|
self.optionToText = {o: t for o, t in zip(value, texts)}
|
||||||
|
for text, option in zip(texts, value):
|
||||||
|
self.addItem(text, userData=option)
|
||||||
|
|
||||||
|
if qconfig.get(configItem) not in self.optionToText:
|
||||||
|
self.optionToText[qconfig.get(configItem)] = qconfig.get(configItem)
|
||||||
|
self.addItem(qconfig.get(configItem), userData=qconfig.get(configItem))
|
||||||
|
|
||||||
|
self.setCurrentText(self.optionToText[qconfig.get(configItem)])
|
||||||
|
self.currentIndexChanged.connect(self._onCurrentIndexChanged)
|
||||||
|
configItem.valueChanged.connect(self.setValue)
|
||||||
|
|
||||||
|
def _onCurrentIndexChanged(self, index: int):
|
||||||
|
|
||||||
|
self.qconfig.set(
|
||||||
|
self.configItem,
|
||||||
|
(self.itemData(index) if self.itemData(index) else self.itemText(index)),
|
||||||
|
)
|
||||||
|
|
||||||
|
def setValue(self, value):
|
||||||
|
if value not in self.optionToText:
|
||||||
|
self.optionToText[value] = value
|
||||||
|
if self.findText(value) == -1:
|
||||||
|
self.addItem(value, userData=value)
|
||||||
|
else:
|
||||||
|
self.setItemData(self.findText(value), value)
|
||||||
|
|
||||||
|
self.setCurrentText(self.optionToText[value])
|
||||||
|
self.qconfig.set(self.configItem, value)
|
||||||
|
|
||||||
|
def reLoadOptions(self, value: List[str], texts: List[str]):
|
||||||
|
|
||||||
|
self.currentIndexChanged.disconnect(self._onCurrentIndexChanged)
|
||||||
|
self.clear()
|
||||||
|
self.optionToText = {o: t for o, t in zip(value, texts)}
|
||||||
|
for text, option in zip(texts, value):
|
||||||
|
self.addItem(text, userData=option)
|
||||||
|
if self.qconfig.get(self.configItem) not in self.optionToText:
|
||||||
|
self.optionToText[self.qconfig.get(self.configItem)] = self.qconfig.get(
|
||||||
|
self.configItem
|
||||||
|
)
|
||||||
|
self.addItem(
|
||||||
|
self.qconfig.get(self.configItem),
|
||||||
|
userData=self.qconfig.get(self.configItem),
|
||||||
|
)
|
||||||
|
self.setCurrentText(self.optionToText[self.qconfig.get(self.configItem)])
|
||||||
|
self.currentIndexChanged.connect(self._onCurrentIndexChanged)
|
||||||
|
|
||||||
|
def _onReturnPressed(self):
|
||||||
|
if not self.text():
|
||||||
|
return
|
||||||
|
|
||||||
|
index = self.findText(self.text())
|
||||||
|
if index >= 0 and index != self.currentIndex():
|
||||||
|
self._currentIndex = index
|
||||||
|
self.currentIndexChanged.emit(index)
|
||||||
|
elif index == -1:
|
||||||
|
self.addItem(self.text())
|
||||||
|
self.setCurrentIndex(self.count() - 1)
|
||||||
|
self.currentIndexChanged.emit(self.count() - 1)
|
||||||
|
|
||||||
|
|
||||||
|
class SpinBoxSetting(SpinBox):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
range: tuple[int, int],
|
||||||
|
qconfig: QConfig,
|
||||||
|
configItem: ConfigItem,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(parent)
|
||||||
|
self.qconfig = qconfig
|
||||||
|
self.configItem = configItem
|
||||||
|
self.setRange(range[0], range[1])
|
||||||
|
|
||||||
|
if configItem:
|
||||||
|
self.set_value(qconfig.get(configItem))
|
||||||
|
configItem.valueChanged.connect(self.set_value)
|
||||||
|
|
||||||
|
self.valueChanged.connect(self.set_value)
|
||||||
|
|
||||||
|
def set_value(self, value: int):
|
||||||
|
if self.configItem:
|
||||||
|
self.qconfig.set(self.configItem, value)
|
||||||
|
|
||||||
|
self.setValue(value)
|
||||||
|
|
||||||
|
|
||||||
class HistoryCard(HeaderCardWidget):
|
class HistoryCard(HeaderCardWidget):
|
||||||
|
|
||||||
def __init__(self, qconfig: QConfig, configItem: ConfigItem, parent=None):
|
def __init__(self, qconfig: QConfig, configItem: ConfigItem, parent=None):
|
||||||
@@ -1049,9 +1611,7 @@ class UrlListSettingCard(ExpandSettingCard):
|
|||||||
"""show confirm dialog"""
|
"""show confirm dialog"""
|
||||||
|
|
||||||
choice = MessageBox(
|
choice = MessageBox(
|
||||||
"确认",
|
"确认", f"确定要删除 {item.url} 代理网址吗?", self.window()
|
||||||
f"确定要删除 {item.url} 代理网址吗?",
|
|
||||||
self.window(),
|
|
||||||
)
|
)
|
||||||
if choice.exec():
|
if choice.exec():
|
||||||
self.__removeUrl(item)
|
self.__removeUrl(item)
|
||||||
@@ -1128,6 +1688,84 @@ class QuantifiedItemCard(CardWidget):
|
|||||||
self.Layout.addWidget(self.Numb)
|
self.Layout.addWidget(self.Numb)
|
||||||
|
|
||||||
|
|
||||||
|
class PivotArea(ScrollArea):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
# 创建中间容器并设置布局
|
||||||
|
self.center_container = QWidget()
|
||||||
|
self.center_layout = QHBoxLayout(self.center_container)
|
||||||
|
self.center_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.center_layout.setSpacing(0)
|
||||||
|
self.center_container.setStyleSheet("background: transparent; border: none;")
|
||||||
|
self.center_container.setFixedHeight(45)
|
||||||
|
|
||||||
|
self.pivot = self._Pivot(self)
|
||||||
|
self.pivot.ItemNumbChanged.connect(
|
||||||
|
lambda: QTimer.singleShot(
|
||||||
|
100,
|
||||||
|
lambda: (
|
||||||
|
self.center_container.setFixedWidth(
|
||||||
|
max(self.width() - 2, self.pivot.width())
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.center_layout.addStretch(1)
|
||||||
|
self.center_layout.addWidget(self.pivot)
|
||||||
|
self.center_layout.addStretch(1)
|
||||||
|
|
||||||
|
self.setWidgetResizable(False)
|
||||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
|
self.viewport().setCursor(Qt.ArrowCursor)
|
||||||
|
self.setStyleSheet("background: transparent; border: none;")
|
||||||
|
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||||
|
self.setWidget(self.center_container)
|
||||||
|
|
||||||
|
def wheelEvent(self, event):
|
||||||
|
scroll_bar = self.horizontalScrollBar()
|
||||||
|
if scroll_bar.maximum() > 0:
|
||||||
|
delta = event.angleDelta().y()
|
||||||
|
scroll_bar.setValue(scroll_bar.value() - delta // 15)
|
||||||
|
event.ignore()
|
||||||
|
|
||||||
|
def resizeEvent(self, event):
|
||||||
|
super().resizeEvent(event)
|
||||||
|
|
||||||
|
self.center_container.setFixedWidth(max(self.width() - 2, self.pivot.width()))
|
||||||
|
QTimer.singleShot(
|
||||||
|
100,
|
||||||
|
lambda: (
|
||||||
|
self.center_container.setFixedWidth(
|
||||||
|
max(self.width() - 2, self.pivot.width())
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
class _Pivot(Pivot):
|
||||||
|
|
||||||
|
ItemNumbChanged = Signal()
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
def insertWidget(
|
||||||
|
self, index: int, routeKey: str, widget: PivotItem, onClick=None
|
||||||
|
):
|
||||||
|
super().insertWidget(index, routeKey, widget, onClick)
|
||||||
|
self.ItemNumbChanged.emit()
|
||||||
|
|
||||||
|
def removeWidget(self, routeKey: str):
|
||||||
|
super().removeWidget(routeKey)
|
||||||
|
self.ItemNumbChanged.emit()
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
super().clear()
|
||||||
|
self.ItemNumbChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
class QuickExpandGroupCard(ExpandGroupSettingCard):
|
class QuickExpandGroupCard(ExpandGroupSettingCard):
|
||||||
"""全局配置"""
|
"""全局配置"""
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ from PySide6.QtWidgets import (
|
|||||||
QHBoxLayout,
|
QHBoxLayout,
|
||||||
)
|
)
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
|
BodyLabel,
|
||||||
CardWidget,
|
CardWidget,
|
||||||
Pivot,
|
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
FluentIcon,
|
FluentIcon,
|
||||||
HeaderCardWidget,
|
HeaderCardWidget,
|
||||||
@@ -44,13 +44,12 @@ from qfluentwidgets import (
|
|||||||
SubtitleLabel,
|
SubtitleLabel,
|
||||||
PushButton,
|
PushButton,
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt
|
|
||||||
from PySide6.QtGui import QTextCursor
|
from PySide6.QtGui import QTextCursor
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
|
||||||
|
|
||||||
from app.core import Config, TaskManager, Task, MainInfoBar
|
from app.core import Config, TaskManager, Task, MainInfoBar
|
||||||
from .Widget import StatefulItemCard, ComboBoxMessageBox
|
from .Widget import StatefulItemCard, ComboBoxMessageBox, PivotArea
|
||||||
|
|
||||||
|
|
||||||
class DispatchCenter(QWidget):
|
class DispatchCenter(QWidget):
|
||||||
@@ -60,13 +59,29 @@ class DispatchCenter(QWidget):
|
|||||||
|
|
||||||
self.setObjectName("调度中枢")
|
self.setObjectName("调度中枢")
|
||||||
|
|
||||||
self.pivot = Pivot(self)
|
self.multi_button = PushButton(FluentIcon.ADD, "添加任务", self)
|
||||||
|
self.multi_button.setToolTip("添加任务")
|
||||||
|
self.multi_button.clicked.connect(self.start_multi_task)
|
||||||
|
|
||||||
|
self.power_combox = ComboBox()
|
||||||
|
self.power_combox.addItem("无动作", userData="NoAction")
|
||||||
|
self.power_combox.addItem("退出软件", userData="KillSelf")
|
||||||
|
self.power_combox.addItem("睡眠", userData="Sleep")
|
||||||
|
self.power_combox.addItem("休眠", userData="Hibernate")
|
||||||
|
self.power_combox.addItem("关机", userData="Shutdown")
|
||||||
|
self.power_combox.setCurrentText("无动作")
|
||||||
|
self.power_combox.currentIndexChanged.connect(self.set_power_sign)
|
||||||
|
|
||||||
|
self.pivotArea = PivotArea(self)
|
||||||
|
self.pivot = self.pivotArea.pivot
|
||||||
|
|
||||||
self.stackedWidget = QStackedWidget(self)
|
self.stackedWidget = QStackedWidget(self)
|
||||||
self.Layout = QVBoxLayout(self)
|
self.stackedWidget.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.stackedWidget.setStyleSheet("background: transparent; border: none;")
|
||||||
|
|
||||||
self.script_list: Dict[str, DispatchBox] = {}
|
self.script_list: Dict[str, DispatchCenter.DispatchBox] = {}
|
||||||
|
|
||||||
dispatch_box = DispatchBox("主调度台", self)
|
dispatch_box = self.DispatchBox("主调度台", self)
|
||||||
self.script_list["主调度台"] = dispatch_box
|
self.script_list["主调度台"] = dispatch_box
|
||||||
self.stackedWidget.addWidget(self.script_list["主调度台"])
|
self.stackedWidget.addWidget(self.script_list["主调度台"])
|
||||||
self.pivot.addItem(
|
self.pivot.addItem(
|
||||||
@@ -76,7 +91,15 @@ class DispatchCenter(QWidget):
|
|||||||
icon=FluentIcon.CAFE,
|
icon=FluentIcon.CAFE,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.Layout.addWidget(self.pivot, 0, Qt.AlignHCenter)
|
h_layout = QHBoxLayout()
|
||||||
|
h_layout.addWidget(self.multi_button)
|
||||||
|
h_layout.addWidget(self.pivotArea)
|
||||||
|
h_layout.addWidget(BodyLabel("全部完成后", self))
|
||||||
|
h_layout.addWidget(self.power_combox)
|
||||||
|
h_layout.setContentsMargins(11, 5, 11, 0)
|
||||||
|
|
||||||
|
self.Layout = QVBoxLayout(self)
|
||||||
|
self.Layout.addLayout(h_layout)
|
||||||
self.Layout.addWidget(self.stackedWidget)
|
self.Layout.addWidget(self.stackedWidget)
|
||||||
self.Layout.setContentsMargins(0, 0, 0, 0)
|
self.Layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
@@ -87,7 +110,7 @@ class DispatchCenter(QWidget):
|
|||||||
def add_board(self, task: Task) -> None:
|
def add_board(self, task: Task) -> None:
|
||||||
"""添加一个调度台界面"""
|
"""添加一个调度台界面"""
|
||||||
|
|
||||||
dispatch_box = DispatchBox(task.name, self)
|
dispatch_box = self.DispatchBox(task.name, self)
|
||||||
|
|
||||||
dispatch_box.top_bar.main_button.clicked.connect(
|
dispatch_box.top_bar.main_button.clicked.connect(
|
||||||
lambda: TaskManager.stop_task(task.name)
|
lambda: TaskManager.stop_task(task.name)
|
||||||
@@ -123,7 +146,6 @@ class DispatchCenter(QWidget):
|
|||||||
self.script_list["主调度台"].top_bar.Lable.show()
|
self.script_list["主调度台"].top_bar.Lable.show()
|
||||||
self.script_list["主调度台"].top_bar.object.hide()
|
self.script_list["主调度台"].top_bar.object.hide()
|
||||||
self.script_list["主调度台"].top_bar.mode.hide()
|
self.script_list["主调度台"].top_bar.mode.hide()
|
||||||
self.script_list["主调度台"].top_bar.multi_button.show()
|
|
||||||
self.script_list["主调度台"].top_bar.main_button.clicked.disconnect()
|
self.script_list["主调度台"].top_bar.main_button.clicked.disconnect()
|
||||||
self.script_list["主调度台"].top_bar.main_button.setText("中止任务")
|
self.script_list["主调度台"].top_bar.main_button.setText("中止任务")
|
||||||
self.script_list["主调度台"].top_bar.main_button.clicked.connect(
|
self.script_list["主调度台"].top_bar.main_button.clicked.connect(
|
||||||
@@ -154,7 +176,6 @@ class DispatchCenter(QWidget):
|
|||||||
self.script_list["主调度台"].top_bar.Lable.hide()
|
self.script_list["主调度台"].top_bar.Lable.hide()
|
||||||
self.script_list["主调度台"].top_bar.object.show()
|
self.script_list["主调度台"].top_bar.object.show()
|
||||||
self.script_list["主调度台"].top_bar.mode.show()
|
self.script_list["主调度台"].top_bar.mode.show()
|
||||||
self.script_list["主调度台"].top_bar.multi_button.hide()
|
|
||||||
self.script_list["主调度台"].top_bar.main_button.clicked.disconnect()
|
self.script_list["主调度台"].top_bar.main_button.clicked.disconnect()
|
||||||
self.script_list["主调度台"].top_bar.main_button.setText("开始任务")
|
self.script_list["主调度台"].top_bar.main_button.setText("开始任务")
|
||||||
self.script_list["主调度台"].top_bar.main_button.clicked.connect(
|
self.script_list["主调度台"].top_bar.main_button.clicked.connect(
|
||||||
@@ -208,301 +229,323 @@ class DispatchCenter(QWidget):
|
|||||||
self.script_list["主调度台"].top_bar.mode.addItems(["自动代理", "人工排查"])
|
self.script_list["主调度台"].top_bar.mode.addItems(["自动代理", "人工排查"])
|
||||||
self.script_list["主调度台"].top_bar.mode.setCurrentIndex(0)
|
self.script_list["主调度台"].top_bar.mode.setCurrentIndex(0)
|
||||||
|
|
||||||
|
def update_power_sign(self) -> None:
|
||||||
|
"""更新电源设置"""
|
||||||
|
|
||||||
class DispatchBox(QWidget):
|
mode_book = {
|
||||||
|
"NoAction": "无动作",
|
||||||
|
"KillSelf": "退出软件",
|
||||||
|
"Sleep": "睡眠",
|
||||||
|
"Hibernate": "休眠",
|
||||||
|
"Shutdown": "关机",
|
||||||
|
}
|
||||||
|
self.power_combox.currentIndexChanged.disconnect()
|
||||||
|
self.power_combox.setCurrentText(mode_book[Config.power_sign])
|
||||||
|
self.power_combox.currentIndexChanged.connect(self.set_power_sign)
|
||||||
|
|
||||||
def __init__(self, name: str, parent=None):
|
def set_power_sign(self) -> None:
|
||||||
super().__init__(parent)
|
"""设置所有任务完成后动作"""
|
||||||
|
|
||||||
self.setObjectName(name)
|
if not Config.running_list:
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
self.power_combox.currentIndexChanged.disconnect()
|
||||||
|
self.power_combox.setCurrentText("无动作")
|
||||||
scrollArea = ScrollArea()
|
self.power_combox.currentIndexChanged.connect(self.set_power_sign)
|
||||||
scrollArea.setWidgetResizable(True)
|
logger.warning("没有正在运行的任务,无法设置任务完成后动作")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
content_widget = QWidget()
|
"warning",
|
||||||
content_layout = QVBoxLayout(content_widget)
|
"没有正在运行的任务",
|
||||||
|
"无法设置任务完成后动作",
|
||||||
self.top_bar = self.DispatchTopBar(self, name)
|
5000,
|
||||||
self.info = self.DispatchInfoCard(self)
|
|
||||||
|
|
||||||
content_layout.addWidget(self.top_bar)
|
|
||||||
content_layout.addWidget(self.info)
|
|
||||||
|
|
||||||
scrollArea.setWidget(content_widget)
|
|
||||||
|
|
||||||
layout.addWidget(scrollArea)
|
|
||||||
|
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
class DispatchTopBar(CardWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent=None, name: str = None):
|
|
||||||
super().__init__(parent)
|
|
||||||
|
|
||||||
Layout = QHBoxLayout(self)
|
|
||||||
|
|
||||||
if name == "主调度台":
|
|
||||||
|
|
||||||
self.Lable = SubtitleLabel("", self)
|
|
||||||
self.Lable.hide()
|
|
||||||
self.object = ComboBox()
|
|
||||||
self.object.setPlaceholderText("请选择调度对象")
|
|
||||||
self.mode = ComboBox()
|
|
||||||
self.mode.setPlaceholderText("请选择调度模式")
|
|
||||||
|
|
||||||
self.multi_button = PushButton("添加任务")
|
|
||||||
self.multi_button.clicked.connect(self.start_multi_task)
|
|
||||||
self.main_button = PushButton("开始任务")
|
|
||||||
self.main_button.clicked.connect(self.start_main_task)
|
|
||||||
self.multi_button.hide()
|
|
||||||
|
|
||||||
Layout.addWidget(self.Lable)
|
|
||||||
Layout.addWidget(self.object)
|
|
||||||
Layout.addWidget(self.mode)
|
|
||||||
Layout.addStretch(1)
|
|
||||||
Layout.addWidget(self.multi_button)
|
|
||||||
Layout.addWidget(self.main_button)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
self.Lable = SubtitleLabel(name, self)
|
|
||||||
self.main_button = PushButton("中止任务")
|
|
||||||
|
|
||||||
Layout.addWidget(self.Lable)
|
|
||||||
Layout.addStretch(1)
|
|
||||||
Layout.addWidget(self.main_button)
|
|
||||||
|
|
||||||
def start_main_task(self):
|
|
||||||
"""开始任务"""
|
|
||||||
|
|
||||||
if self.object.currentIndex() == -1:
|
|
||||||
logger.warning("未选择调度对象")
|
|
||||||
MainInfoBar.push_info_bar(
|
|
||||||
"warning", "未选择调度对象", "请选择后再开始任务", 5000
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if self.mode.currentIndex() == -1:
|
|
||||||
logger.warning("未选择调度模式")
|
|
||||||
MainInfoBar.push_info_bar(
|
|
||||||
"warning", "未选择调度模式", "请选择后再开始任务", 5000
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if self.object.currentData() in Config.running_list:
|
|
||||||
logger.warning(f"任务已存在:{self.object.currentData()}")
|
|
||||||
MainInfoBar.push_info_bar(
|
|
||||||
"warning", "任务已存在", self.object.currentData(), 5000
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if "调度队列" in self.object.currentData():
|
|
||||||
|
|
||||||
logger.info(f"用户添加任务:{self.object.currentData()}")
|
|
||||||
TaskManager.add_task(
|
|
||||||
f"{self.mode.currentText()}_主调度台",
|
|
||||||
self.object.currentData(),
|
|
||||||
Config.queue_dict[self.object.currentData()]["Config"].toDict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
elif "脚本" in self.object.currentData():
|
|
||||||
|
|
||||||
if Config.member_dict[self.object.currentData()]["Type"] == "Maa":
|
|
||||||
|
|
||||||
logger.info(f"用户添加任务:{self.object.currentData()}")
|
|
||||||
TaskManager.add_task(
|
|
||||||
f"{self.mode.currentText()}_主调度台",
|
|
||||||
"自定义队列",
|
|
||||||
{"Queue": {"Member_1": self.object.currentData()}},
|
|
||||||
)
|
|
||||||
|
|
||||||
def start_multi_task(self):
|
|
||||||
"""开始任务"""
|
|
||||||
|
|
||||||
# 获取所有可用的队列和实例
|
|
||||||
text_list = []
|
|
||||||
data_list = []
|
|
||||||
for name, info in Config.queue_dict.items():
|
|
||||||
if name in Config.running_list:
|
|
||||||
continue
|
|
||||||
text_list.append(
|
|
||||||
"队列"
|
|
||||||
if info["Config"].get(info["Config"].queueSet_Name) == ""
|
|
||||||
else f"队列 - {info["Config"].get(info["Config"].queueSet_Name)}"
|
|
||||||
)
|
|
||||||
data_list.append(name)
|
|
||||||
|
|
||||||
for name, info in Config.member_dict.items():
|
|
||||||
if name in Config.running_list:
|
|
||||||
continue
|
|
||||||
text_list.append(
|
|
||||||
f"实例 - {info['Type']}"
|
|
||||||
if info["Config"].get(info["Config"].MaaSet_Name) == ""
|
|
||||||
else f"实例 - {info['Type']} - {info["Config"].get(info["Config"].MaaSet_Name)}"
|
|
||||||
)
|
|
||||||
data_list.append(name)
|
|
||||||
|
|
||||||
choice = ComboBoxMessageBox(
|
|
||||||
self.window(),
|
|
||||||
"选择一个对象以添加相应多开任务",
|
|
||||||
["选择调度对象"],
|
|
||||||
[text_list],
|
|
||||||
[data_list],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if choice.exec() and choice.input[0].currentIndex() != -1:
|
else:
|
||||||
|
|
||||||
if choice.input[0].currentData() in Config.running_list:
|
Config.set_power_sign(self.power_combox.currentData())
|
||||||
logger.warning(f"任务已存在:{choice.input[0].currentData()}")
|
|
||||||
MainInfoBar.push_info_bar(
|
|
||||||
"warning", "任务已存在", choice.input[0].currentData(), 5000
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if "调度队列" in choice.input[0].currentData():
|
def start_multi_task(self) -> None:
|
||||||
|
"""开始任务"""
|
||||||
|
|
||||||
|
# 获取所有可用的队列和实例
|
||||||
|
text_list = []
|
||||||
|
data_list = []
|
||||||
|
for name, info in Config.queue_dict.items():
|
||||||
|
if name in Config.running_list:
|
||||||
|
continue
|
||||||
|
text_list.append(
|
||||||
|
"队列"
|
||||||
|
if info["Config"].get(info["Config"].queueSet_Name) == ""
|
||||||
|
else f"队列 - {info["Config"].get(info["Config"].queueSet_Name)}"
|
||||||
|
)
|
||||||
|
data_list.append(name)
|
||||||
|
|
||||||
|
for name, info in Config.member_dict.items():
|
||||||
|
if name in Config.running_list:
|
||||||
|
continue
|
||||||
|
text_list.append(
|
||||||
|
f"实例 - {info['Type']}"
|
||||||
|
if info["Config"].get(info["Config"].MaaSet_Name) == ""
|
||||||
|
else f"实例 - {info['Type']} - {info["Config"].get(info["Config"].MaaSet_Name)}"
|
||||||
|
)
|
||||||
|
data_list.append(name)
|
||||||
|
|
||||||
|
choice = ComboBoxMessageBox(
|
||||||
|
self.window(),
|
||||||
|
"选择一个对象以添加相应多开任务",
|
||||||
|
["选择调度对象"],
|
||||||
|
[text_list],
|
||||||
|
[data_list],
|
||||||
|
)
|
||||||
|
|
||||||
|
if choice.exec() and choice.input[0].currentIndex() != -1:
|
||||||
|
|
||||||
|
if choice.input[0].currentData() in Config.running_list:
|
||||||
|
logger.warning(f"任务已存在:{choice.input[0].currentData()}")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "任务已存在", choice.input[0].currentData(), 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if "调度队列" in choice.input[0].currentData():
|
||||||
|
|
||||||
|
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
||||||
|
TaskManager.add_task(
|
||||||
|
"自动代理_新调度台",
|
||||||
|
choice.input[0].currentData(),
|
||||||
|
Config.queue_dict[choice.input[0].currentData()]["Config"].toDict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
elif "脚本" in choice.input[0].currentData():
|
||||||
|
|
||||||
|
if Config.member_dict[choice.input[0].currentData()]["Type"] == "Maa":
|
||||||
|
|
||||||
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
||||||
TaskManager.add_task(
|
TaskManager.add_task(
|
||||||
"自动代理_新调度台",
|
"自动代理_新调度台",
|
||||||
choice.input[0].currentData(),
|
f"自定义队列 - {choice.input[0].currentData()}",
|
||||||
Config.queue_dict[choice.input[0].currentData()][
|
{"Queue": {"Member_1": choice.input[0].currentData()}},
|
||||||
"Config"
|
|
||||||
].toDict(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
elif "脚本" in choice.input[0].currentData():
|
class DispatchBox(QWidget):
|
||||||
|
|
||||||
if (
|
def __init__(self, name: str, parent=None):
|
||||||
Config.member_dict[choice.input[0].currentData()]["Type"]
|
|
||||||
== "Maa"
|
|
||||||
):
|
|
||||||
|
|
||||||
logger.info(f"用户添加任务:{choice.input[0].currentData()}")
|
|
||||||
TaskManager.add_task(
|
|
||||||
"自动代理_新调度台",
|
|
||||||
f"自定义队列 - {choice.input[0].currentData()}",
|
|
||||||
{"Queue": {"Member_1": choice.input[0].currentData()}},
|
|
||||||
)
|
|
||||||
|
|
||||||
class DispatchInfoCard(HeaderCardWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.setTitle("调度信息")
|
self.setObjectName(name)
|
||||||
|
|
||||||
self.task = self.TaskInfoCard(self)
|
self.top_bar = self.DispatchTopBar(self, name)
|
||||||
self.user = self.UserInfoCard(self)
|
self.info = self.DispatchInfoCard(self)
|
||||||
self.log_text = self.LogCard(self)
|
|
||||||
|
|
||||||
self.viewLayout.addWidget(self.task)
|
content_widget = QWidget()
|
||||||
self.viewLayout.addWidget(self.user)
|
content_layout = QVBoxLayout(content_widget)
|
||||||
self.viewLayout.addWidget(self.log_text)
|
content_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
content_layout.addWidget(self.top_bar)
|
||||||
|
content_layout.addWidget(self.info)
|
||||||
|
|
||||||
self.viewLayout.setStretch(0, 1)
|
scrollArea = ScrollArea()
|
||||||
self.viewLayout.setStretch(1, 1)
|
scrollArea.setWidgetResizable(True)
|
||||||
self.viewLayout.setStretch(2, 5)
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
|
scrollArea.setWidget(content_widget)
|
||||||
|
|
||||||
def update_board(self, task_list: list, user_list: list, log: str):
|
layout = QVBoxLayout(self)
|
||||||
"""更新调度信息"""
|
layout.addWidget(scrollArea)
|
||||||
|
|
||||||
self.task.update_task(task_list)
|
class DispatchTopBar(CardWidget):
|
||||||
self.user.update_user(user_list)
|
|
||||||
self.log_text.text.setText(log)
|
|
||||||
|
|
||||||
class TaskInfoCard(HeaderCardWidget):
|
def __init__(self, parent=None, name: str = None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
Layout = QHBoxLayout(self)
|
||||||
|
|
||||||
|
if name == "主调度台":
|
||||||
|
|
||||||
|
self.Lable = SubtitleLabel("", self)
|
||||||
|
self.Lable.hide()
|
||||||
|
self.object = ComboBox()
|
||||||
|
self.object.setPlaceholderText("请选择调度对象")
|
||||||
|
self.mode = ComboBox()
|
||||||
|
self.mode.setPlaceholderText("请选择调度模式")
|
||||||
|
|
||||||
|
self.main_button = PushButton("开始任务")
|
||||||
|
self.main_button.clicked.connect(self.start_main_task)
|
||||||
|
|
||||||
|
Layout.addWidget(self.Lable)
|
||||||
|
Layout.addWidget(self.object)
|
||||||
|
Layout.addWidget(self.mode)
|
||||||
|
Layout.addStretch(1)
|
||||||
|
Layout.addWidget(self.main_button)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
self.Lable = SubtitleLabel(name, self)
|
||||||
|
self.main_button = PushButton("中止任务")
|
||||||
|
|
||||||
|
Layout.addWidget(self.Lable)
|
||||||
|
Layout.addStretch(1)
|
||||||
|
Layout.addWidget(self.main_button)
|
||||||
|
|
||||||
|
def start_main_task(self):
|
||||||
|
"""开始任务"""
|
||||||
|
|
||||||
|
if self.object.currentIndex() == -1:
|
||||||
|
logger.warning("未选择调度对象")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "未选择调度对象", "请选择后再开始任务", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.mode.currentIndex() == -1:
|
||||||
|
logger.warning("未选择调度模式")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "未选择调度模式", "请选择后再开始任务", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.object.currentData() in Config.running_list:
|
||||||
|
logger.warning(f"任务已存在:{self.object.currentData()}")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "任务已存在", self.object.currentData(), 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if "调度队列" in self.object.currentData():
|
||||||
|
|
||||||
|
logger.info(f"用户添加任务:{self.object.currentData()}")
|
||||||
|
TaskManager.add_task(
|
||||||
|
f"{self.mode.currentText()}_主调度台",
|
||||||
|
self.object.currentData(),
|
||||||
|
Config.queue_dict[self.object.currentData()]["Config"].toDict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
elif "脚本" in self.object.currentData():
|
||||||
|
|
||||||
|
if Config.member_dict[self.object.currentData()]["Type"] == "Maa":
|
||||||
|
|
||||||
|
logger.info(f"用户添加任务:{self.object.currentData()}")
|
||||||
|
TaskManager.add_task(
|
||||||
|
f"{self.mode.currentText()}_主调度台",
|
||||||
|
"自定义队列",
|
||||||
|
{"Queue": {"Member_1": self.object.currentData()}},
|
||||||
|
)
|
||||||
|
|
||||||
|
class DispatchInfoCard(HeaderCardWidget):
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setTitle("任务队列")
|
|
||||||
|
|
||||||
self.Layout = QVBoxLayout()
|
self.setTitle("调度信息")
|
||||||
self.viewLayout.addLayout(self.Layout)
|
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
|
||||||
|
|
||||||
self.task_cards: List[StatefulItemCard] = []
|
self.task = self.TaskInfoCard(self)
|
||||||
|
self.user = self.UserInfoCard(self)
|
||||||
|
self.log_text = self.LogCard(self)
|
||||||
|
|
||||||
def create_task(self, task_list: list):
|
self.viewLayout.addWidget(self.task)
|
||||||
"""创建任务队列"""
|
self.viewLayout.addWidget(self.user)
|
||||||
|
self.viewLayout.addWidget(self.log_text)
|
||||||
|
|
||||||
while self.Layout.count() > 0:
|
self.viewLayout.setStretch(0, 1)
|
||||||
item = self.Layout.takeAt(0)
|
self.viewLayout.setStretch(1, 1)
|
||||||
if item.spacerItem():
|
self.viewLayout.setStretch(2, 5)
|
||||||
self.Layout.removeItem(item.spacerItem())
|
|
||||||
elif item.widget():
|
|
||||||
item.widget().deleteLater()
|
|
||||||
|
|
||||||
self.task_cards = []
|
def update_board(self, task_list: list, user_list: list, log: str):
|
||||||
|
"""更新调度信息"""
|
||||||
|
|
||||||
for task in task_list:
|
self.task.update_task(task_list)
|
||||||
|
self.user.update_user(user_list)
|
||||||
|
self.log_text.text.setText(log)
|
||||||
|
|
||||||
self.task_cards.append(StatefulItemCard(task))
|
class TaskInfoCard(HeaderCardWidget):
|
||||||
self.Layout.addWidget(self.task_cards[-1])
|
|
||||||
|
|
||||||
self.Layout.addStretch(1)
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("任务队列")
|
||||||
|
|
||||||
def update_task(self, task_list: list):
|
self.Layout = QVBoxLayout()
|
||||||
"""更新任务队列"""
|
self.viewLayout.addLayout(self.Layout)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
for i in range(len(task_list)):
|
self.task_cards: List[StatefulItemCard] = []
|
||||||
|
|
||||||
self.task_cards[i].update_status(task_list[i][1])
|
def create_task(self, task_list: list):
|
||||||
|
"""创建任务队列"""
|
||||||
|
|
||||||
class UserInfoCard(HeaderCardWidget):
|
while self.Layout.count() > 0:
|
||||||
|
item = self.Layout.takeAt(0)
|
||||||
|
if item.spacerItem():
|
||||||
|
self.Layout.removeItem(item.spacerItem())
|
||||||
|
elif item.widget():
|
||||||
|
item.widget().deleteLater()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
self.task_cards = []
|
||||||
super().__init__(parent)
|
|
||||||
self.setTitle("用户队列")
|
|
||||||
|
|
||||||
self.Layout = QVBoxLayout()
|
for task in task_list:
|
||||||
self.viewLayout.addLayout(self.Layout)
|
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
|
||||||
|
|
||||||
self.user_cards: List[StatefulItemCard] = []
|
self.task_cards.append(StatefulItemCard(task))
|
||||||
|
self.Layout.addWidget(self.task_cards[-1])
|
||||||
|
|
||||||
def create_user(self, user_list: list):
|
self.Layout.addStretch(1)
|
||||||
"""创建用户队列"""
|
|
||||||
|
|
||||||
while self.Layout.count() > 0:
|
def update_task(self, task_list: list):
|
||||||
item = self.Layout.takeAt(0)
|
"""更新任务队列"""
|
||||||
if item.spacerItem():
|
|
||||||
self.Layout.removeItem(item.spacerItem())
|
|
||||||
elif item.widget():
|
|
||||||
item.widget().deleteLater()
|
|
||||||
|
|
||||||
self.user_cards = []
|
for i in range(len(task_list)):
|
||||||
|
|
||||||
for user in user_list:
|
self.task_cards[i].update_status(task_list[i][1])
|
||||||
|
|
||||||
self.user_cards.append(StatefulItemCard(user))
|
class UserInfoCard(HeaderCardWidget):
|
||||||
self.Layout.addWidget(self.user_cards[-1])
|
|
||||||
|
|
||||||
self.Layout.addStretch(1)
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("用户队列")
|
||||||
|
|
||||||
def update_user(self, user_list: list):
|
self.Layout = QVBoxLayout()
|
||||||
"""更新用户队列"""
|
self.viewLayout.addLayout(self.Layout)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
for i in range(len(user_list)):
|
self.user_cards: List[StatefulItemCard] = []
|
||||||
|
|
||||||
self.user_cards[i].Label.setText(user_list[i][0])
|
def create_user(self, user_list: list):
|
||||||
self.user_cards[i].update_status(user_list[i][1])
|
"""创建用户队列"""
|
||||||
|
|
||||||
class LogCard(HeaderCardWidget):
|
while self.Layout.count() > 0:
|
||||||
|
item = self.Layout.takeAt(0)
|
||||||
|
if item.spacerItem():
|
||||||
|
self.Layout.removeItem(item.spacerItem())
|
||||||
|
elif item.widget():
|
||||||
|
item.widget().deleteLater()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
self.user_cards = []
|
||||||
super().__init__(parent)
|
|
||||||
self.setTitle("日志")
|
|
||||||
|
|
||||||
self.text = TextBrowser()
|
for user in user_list:
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
|
||||||
self.viewLayout.addWidget(self.text)
|
|
||||||
|
|
||||||
self.text.textChanged.connect(self.to_end)
|
self.user_cards.append(StatefulItemCard(user))
|
||||||
|
self.Layout.addWidget(self.user_cards[-1])
|
||||||
|
|
||||||
def to_end(self):
|
self.Layout.addStretch(1)
|
||||||
"""滚动到底部"""
|
|
||||||
|
|
||||||
self.text.moveCursor(QTextCursor.End)
|
def update_user(self, user_list: list):
|
||||||
self.text.ensureCursorVisible()
|
"""更新用户队列"""
|
||||||
|
|
||||||
|
for i in range(len(user_list)):
|
||||||
|
|
||||||
|
self.user_cards[i].Label.setText(user_list[i][0])
|
||||||
|
self.user_cards[i].update_status(user_list[i][1])
|
||||||
|
|
||||||
|
class LogCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("日志")
|
||||||
|
|
||||||
|
self.text = TextBrowser()
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
self.viewLayout.addWidget(self.text)
|
||||||
|
|
||||||
|
self.text.textChanged.connect(self.to_end)
|
||||||
|
|
||||||
|
def to_end(self):
|
||||||
|
"""滚动到底部"""
|
||||||
|
|
||||||
|
self.text.moveCursor(QTextCursor.End)
|
||||||
|
self.text.ensureCursorVisible()
|
||||||
|
|||||||
@@ -21,11 +21,10 @@
|
|||||||
"""
|
"""
|
||||||
AUTO_MAA
|
AUTO_MAA
|
||||||
AUTO_MAA更新器
|
AUTO_MAA更新器
|
||||||
v1.2
|
v4.3
|
||||||
作者:DLmaster_361
|
作者:DLmaster_361
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
|
||||||
import zipfile
|
import zipfile
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|||||||
@@ -61,19 +61,22 @@ class History(QWidget):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setObjectName("历史记录")
|
self.setObjectName("历史记录")
|
||||||
|
|
||||||
|
self.history_top_bar = self.HistoryTopBar(self)
|
||||||
|
self.history_top_bar.search_history.connect(self.reload_history)
|
||||||
|
|
||||||
content_widget = QWidget()
|
content_widget = QWidget()
|
||||||
self.content_layout = QVBoxLayout(content_widget)
|
self.content_layout = QVBoxLayout(content_widget)
|
||||||
self.history_top_bar = self.HistoryTopBar(self)
|
self.content_layout.setContentsMargins(0, 0, 11, 0)
|
||||||
|
|
||||||
self.history_top_bar.search_history.connect(self.reload_history)
|
|
||||||
|
|
||||||
scrollArea = ScrollArea()
|
scrollArea = ScrollArea()
|
||||||
scrollArea.setWidgetResizable(True)
|
scrollArea.setWidgetResizable(True)
|
||||||
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
scrollArea.setWidget(content_widget)
|
scrollArea.setWidget(content_widget)
|
||||||
layout = QVBoxLayout()
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(self.history_top_bar)
|
layout.addWidget(self.history_top_bar)
|
||||||
layout.addWidget(scrollArea)
|
layout.addWidget(scrollArea)
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
self.history_card_list = []
|
self.history_card_list = []
|
||||||
|
|
||||||
|
|||||||
@@ -62,14 +62,6 @@ class Home(QWidget):
|
|||||||
self.banner = Banner()
|
self.banner = Banner()
|
||||||
self.banner_text = TextBrowser()
|
self.banner_text = TextBrowser()
|
||||||
|
|
||||||
widget = QWidget()
|
|
||||||
Layout = QVBoxLayout(widget)
|
|
||||||
|
|
||||||
Layout.addWidget(self.banner)
|
|
||||||
Layout.addWidget(self.banner_text)
|
|
||||||
Layout.setStretch(0, 2)
|
|
||||||
Layout.setStretch(1, 3)
|
|
||||||
|
|
||||||
v_layout = QVBoxLayout(self.banner)
|
v_layout = QVBoxLayout(self.banner)
|
||||||
v_layout.setContentsMargins(0, 0, 0, 15)
|
v_layout.setContentsMargins(0, 0, 0, 15)
|
||||||
v_layout.setSpacing(5)
|
v_layout.setSpacing(5)
|
||||||
@@ -146,12 +138,22 @@ class Home(QWidget):
|
|||||||
# 将底部水平布局添加到垂直布局
|
# 将底部水平布局添加到垂直布局
|
||||||
v_layout.addLayout(h2_layout)
|
v_layout.addLayout(h2_layout)
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
content_widget = QWidget()
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
content_layout.addWidget(self.banner)
|
||||||
|
content_layout.addWidget(self.banner_text)
|
||||||
|
content_layout.setStretch(0, 2)
|
||||||
|
content_layout.setStretch(1, 3)
|
||||||
|
|
||||||
scrollArea = ScrollArea()
|
scrollArea = ScrollArea()
|
||||||
scrollArea.setWidgetResizable(True)
|
scrollArea.setWidgetResizable(True)
|
||||||
scrollArea.setWidget(widget)
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
|
scrollArea.setWidget(content_widget)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(scrollArea)
|
layout.addWidget(scrollArea)
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
self.set_banner()
|
self.set_banner()
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ from app.core import Config, TaskManager, MainTimer, MainInfoBar
|
|||||||
from app.services import Notify, Crypto, System
|
from app.services import Notify, Crypto, System
|
||||||
from .home import Home
|
from .home import Home
|
||||||
from .member_manager import MemberManager
|
from .member_manager import MemberManager
|
||||||
|
from .plan_manager import PlanManager
|
||||||
from .queue_manager import QueueManager
|
from .queue_manager import QueueManager
|
||||||
from .dispatch_center import DispatchCenter
|
from .dispatch_center import DispatchCenter
|
||||||
from .history import History
|
from .history import History
|
||||||
@@ -80,6 +81,7 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
|
|
||||||
# 创建主窗口
|
# 创建主窗口
|
||||||
self.home = Home(self)
|
self.home = Home(self)
|
||||||
|
self.plan_manager = PlanManager(self)
|
||||||
self.member_manager = MemberManager(self)
|
self.member_manager = MemberManager(self)
|
||||||
self.queue_manager = QueueManager(self)
|
self.queue_manager = QueueManager(self)
|
||||||
self.dispatch_center = DispatchCenter(self)
|
self.dispatch_center = DispatchCenter(self)
|
||||||
@@ -100,6 +102,13 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
FluentIcon.ROBOT,
|
FluentIcon.ROBOT,
|
||||||
NavigationItemPosition.TOP,
|
NavigationItemPosition.TOP,
|
||||||
)
|
)
|
||||||
|
self.addSubInterface(
|
||||||
|
self.plan_manager,
|
||||||
|
FluentIcon.CALENDAR,
|
||||||
|
"计划管理",
|
||||||
|
FluentIcon.CALENDAR,
|
||||||
|
NavigationItemPosition.TOP,
|
||||||
|
)
|
||||||
self.addSubInterface(
|
self.addSubInterface(
|
||||||
self.queue_manager,
|
self.queue_manager,
|
||||||
FluentIcon.BOOK_SHELF,
|
FluentIcon.BOOK_SHELF,
|
||||||
@@ -128,23 +137,7 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
FluentIcon.SETTING,
|
FluentIcon.SETTING,
|
||||||
NavigationItemPosition.BOTTOM,
|
NavigationItemPosition.BOTTOM,
|
||||||
)
|
)
|
||||||
self.stackedWidget.currentChanged.connect(
|
self.stackedWidget.currentChanged.connect(self.__currentChanged)
|
||||||
lambda index: (
|
|
||||||
self.queue_manager.reload_member_name() if index == 2 else None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.stackedWidget.currentChanged.connect(
|
|
||||||
lambda index: (
|
|
||||||
self.dispatch_center.pivot.setCurrentItem("主调度台")
|
|
||||||
if index == 3
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.stackedWidget.currentChanged.connect(
|
|
||||||
lambda index: (
|
|
||||||
self.dispatch_center.update_top_bar() if index == 3 else None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# 创建系统托盘及其菜单
|
# 创建系统托盘及其菜单
|
||||||
self.tray = QSystemTrayIcon(
|
self.tray = QSystemTrayIcon(
|
||||||
@@ -192,6 +185,7 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
self.set_min_method()
|
self.set_min_method()
|
||||||
|
|
||||||
Config.user_info_changed.connect(self.member_manager.refresh_dashboard)
|
Config.user_info_changed.connect(self.member_manager.refresh_dashboard)
|
||||||
|
Config.power_sign_changed.connect(self.dispatch_center.update_power_sign)
|
||||||
TaskManager.create_gui.connect(self.dispatch_center.add_board)
|
TaskManager.create_gui.connect(self.dispatch_center.add_board)
|
||||||
TaskManager.connect_gui.connect(self.dispatch_center.connect_main_board)
|
TaskManager.connect_gui.connect(self.dispatch_center.connect_main_board)
|
||||||
Notify.push_info_bar.connect(MainInfoBar.push_info_bar)
|
Notify.push_info_bar.connect(MainInfoBar.push_info_bar)
|
||||||
@@ -240,6 +234,113 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
else:
|
else:
|
||||||
self.setStyleSheet("background-color: #ffffff;")
|
self.setStyleSheet("background-color: #ffffff;")
|
||||||
|
|
||||||
|
def set_min_method(self) -> None:
|
||||||
|
"""设置最小化方法"""
|
||||||
|
|
||||||
|
if Config.get(Config.ui_IfToTray):
|
||||||
|
|
||||||
|
self.titleBar.minBtn.clicked.disconnect()
|
||||||
|
self.titleBar.minBtn.clicked.connect(lambda: self.show_ui("隐藏到托盘"))
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
self.titleBar.minBtn.clicked.disconnect()
|
||||||
|
self.titleBar.minBtn.clicked.connect(self.window().showMinimized)
|
||||||
|
|
||||||
|
def on_tray_activated(self, reason):
|
||||||
|
"""双击返回主界面"""
|
||||||
|
if reason == QSystemTrayIcon.DoubleClick:
|
||||||
|
self.show_ui("显示主窗口")
|
||||||
|
|
||||||
|
def show_ui(
|
||||||
|
self, mode: str, if_quick: bool = False, if_start: bool = False
|
||||||
|
) -> None:
|
||||||
|
"""配置窗口状态"""
|
||||||
|
|
||||||
|
self.switch_theme()
|
||||||
|
|
||||||
|
if mode == "显示主窗口":
|
||||||
|
|
||||||
|
# 配置主窗口
|
||||||
|
if not self.window().isVisible():
|
||||||
|
size = list(
|
||||||
|
map(
|
||||||
|
int,
|
||||||
|
Config.get(Config.ui_size).split("x"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
location = list(
|
||||||
|
map(
|
||||||
|
int,
|
||||||
|
Config.get(Config.ui_location).split("x"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if self.window().isMaximized():
|
||||||
|
self.window().showNormal()
|
||||||
|
self.window().setGeometry(location[0], location[1], size[0], size[1])
|
||||||
|
self.window().show()
|
||||||
|
if not if_quick:
|
||||||
|
if (
|
||||||
|
Config.get(Config.ui_maximized)
|
||||||
|
and not self.window().isMaximized()
|
||||||
|
):
|
||||||
|
self.titleBar.maxBtn.click()
|
||||||
|
self.show_ui("配置托盘")
|
||||||
|
elif if_start:
|
||||||
|
if Config.get(Config.ui_maximized) and not self.window().isMaximized():
|
||||||
|
self.titleBar.maxBtn.click()
|
||||||
|
self.show_ui("配置托盘")
|
||||||
|
|
||||||
|
# 如果窗口不在屏幕内,则重置窗口位置
|
||||||
|
if not any(
|
||||||
|
self.window().geometry().intersects(screen.availableGeometry())
|
||||||
|
for screen in QApplication.screens()
|
||||||
|
):
|
||||||
|
self.window().showNormal()
|
||||||
|
self.window().setGeometry(100, 100, 1200, 700)
|
||||||
|
|
||||||
|
self.window().raise_()
|
||||||
|
self.window().activateWindow()
|
||||||
|
|
||||||
|
while Config.info_bar_list:
|
||||||
|
info_bar_item = Config.info_bar_list.pop(0)
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
info_bar_item["mode"],
|
||||||
|
info_bar_item["title"],
|
||||||
|
info_bar_item["content"],
|
||||||
|
info_bar_item["time"],
|
||||||
|
)
|
||||||
|
|
||||||
|
elif mode == "配置托盘":
|
||||||
|
|
||||||
|
if Config.get(Config.ui_IfShowTray):
|
||||||
|
self.tray.show()
|
||||||
|
else:
|
||||||
|
self.tray.hide()
|
||||||
|
|
||||||
|
elif mode == "隐藏到托盘":
|
||||||
|
|
||||||
|
# 保存窗口相关属性
|
||||||
|
if not self.window().isMaximized():
|
||||||
|
|
||||||
|
Config.set(
|
||||||
|
Config.ui_size,
|
||||||
|
f"{self.geometry().width()}x{self.geometry().height()}",
|
||||||
|
)
|
||||||
|
Config.set(
|
||||||
|
Config.ui_location,
|
||||||
|
f"{self.geometry().x()}x{self.geometry().y()}",
|
||||||
|
)
|
||||||
|
|
||||||
|
Config.set(Config.ui_maximized, self.window().isMaximized())
|
||||||
|
Config.save()
|
||||||
|
|
||||||
|
# 隐藏主窗口
|
||||||
|
if not if_quick:
|
||||||
|
|
||||||
|
self.window().hide()
|
||||||
|
self.tray.show()
|
||||||
|
|
||||||
def start_up_task(self) -> None:
|
def start_up_task(self) -> None:
|
||||||
"""启动时任务"""
|
"""启动时任务"""
|
||||||
|
|
||||||
@@ -277,24 +378,6 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
|
|
||||||
self.titleBar.minBtn.click()
|
self.titleBar.minBtn.click()
|
||||||
|
|
||||||
def set_min_method(self) -> None:
|
|
||||||
"""设置最小化方法"""
|
|
||||||
|
|
||||||
if Config.get(Config.ui_IfToTray):
|
|
||||||
|
|
||||||
self.titleBar.minBtn.clicked.disconnect()
|
|
||||||
self.titleBar.minBtn.clicked.connect(lambda: self.show_ui("隐藏到托盘"))
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
self.titleBar.minBtn.clicked.disconnect()
|
|
||||||
self.titleBar.minBtn.clicked.connect(self.window().showMinimized)
|
|
||||||
|
|
||||||
def on_tray_activated(self, reason):
|
|
||||||
"""双击返回主界面"""
|
|
||||||
if reason == QSystemTrayIcon.DoubleClick:
|
|
||||||
self.show_ui("显示主窗口")
|
|
||||||
|
|
||||||
def clean_old_logs(self):
|
def clean_old_logs(self):
|
||||||
"""
|
"""
|
||||||
删除超过用户设定天数的日志文件(基于目录日期)
|
删除超过用户设定天数的日志文件(基于目录日期)
|
||||||
@@ -350,75 +433,16 @@ class AUTO_MAA(MSFluentWindow):
|
|||||||
"warning", "启动主任务失败", "“调度队列_1”与“脚本_1”均不存在", -1
|
"warning", "启动主任务失败", "“调度队列_1”与“脚本_1”均不存在", -1
|
||||||
)
|
)
|
||||||
|
|
||||||
def show_ui(self, mode: str, if_quick: bool = False) -> None:
|
def __currentChanged(self, index: int) -> None:
|
||||||
"""配置窗口状态"""
|
"""切换界面时任务"""
|
||||||
|
|
||||||
self.switch_theme()
|
if index == 1:
|
||||||
|
self.member_manager.reload_plan_name()
|
||||||
if mode == "显示主窗口":
|
elif index == 3:
|
||||||
|
self.queue_manager.reload_member_name()
|
||||||
# 配置主窗口
|
elif index == 4:
|
||||||
if not self.window().isVisible():
|
self.dispatch_center.pivot.setCurrentItem("主调度台")
|
||||||
size = list(
|
self.dispatch_center.update_top_bar()
|
||||||
map(
|
|
||||||
int,
|
|
||||||
Config.get(Config.ui_size).split("x"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
location = list(
|
|
||||||
map(
|
|
||||||
int,
|
|
||||||
Config.get(Config.ui_location).split("x"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if self.window().isMaximized():
|
|
||||||
self.window().showNormal()
|
|
||||||
self.window().setGeometry(location[0], location[1], size[0], size[1])
|
|
||||||
self.window().show()
|
|
||||||
if not if_quick:
|
|
||||||
if Config.get(Config.ui_maximized):
|
|
||||||
self.titleBar.maxBtn.click()
|
|
||||||
self.show_ui("配置托盘")
|
|
||||||
|
|
||||||
if not any(
|
|
||||||
self.window().geometry().intersects(screen.availableGeometry())
|
|
||||||
for screen in QApplication.screens()
|
|
||||||
):
|
|
||||||
self.window().showNormal()
|
|
||||||
self.window().setGeometry(100, 100, 1200, 700)
|
|
||||||
|
|
||||||
self.window().raise_()
|
|
||||||
self.window().activateWindow()
|
|
||||||
|
|
||||||
elif mode == "配置托盘":
|
|
||||||
|
|
||||||
if Config.get(Config.ui_IfShowTray):
|
|
||||||
self.tray.show()
|
|
||||||
else:
|
|
||||||
self.tray.hide()
|
|
||||||
|
|
||||||
elif mode == "隐藏到托盘":
|
|
||||||
|
|
||||||
# 保存窗口相关属性
|
|
||||||
if not self.window().isMaximized():
|
|
||||||
|
|
||||||
Config.set(
|
|
||||||
Config.ui_size,
|
|
||||||
f"{self.geometry().width()}x{self.geometry().height()}",
|
|
||||||
)
|
|
||||||
Config.set(
|
|
||||||
Config.ui_location,
|
|
||||||
f"{self.geometry().x()}x{self.geometry().y()}",
|
|
||||||
)
|
|
||||||
|
|
||||||
Config.set(Config.ui_maximized, self.window().isMaximized())
|
|
||||||
Config.save()
|
|
||||||
|
|
||||||
# 隐藏主窗口
|
|
||||||
if not if_quick:
|
|
||||||
|
|
||||||
self.window().hide()
|
|
||||||
self.tray.show()
|
|
||||||
|
|
||||||
def closeEvent(self, event: QCloseEvent):
|
def closeEvent(self, event: QCloseEvent):
|
||||||
"""清理残余进程"""
|
"""清理残余进程"""
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ from PySide6.QtWidgets import (
|
|||||||
from PySide6.QtGui import QIcon
|
from PySide6.QtGui import QIcon
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
Action,
|
Action,
|
||||||
Pivot,
|
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
FluentIcon,
|
FluentIcon,
|
||||||
MessageBox,
|
MessageBox,
|
||||||
@@ -48,13 +47,16 @@ from qfluentwidgets import (
|
|||||||
PushSettingCard,
|
PushSettingCard,
|
||||||
TableWidget,
|
TableWidget,
|
||||||
PrimaryToolButton,
|
PrimaryToolButton,
|
||||||
|
Flyout,
|
||||||
|
FlyoutAnimationType,
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt, Signal
|
from PySide6.QtCore import Signal
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
import shutil
|
import shutil
|
||||||
|
import json
|
||||||
|
|
||||||
from app.core import Config, MainInfoBar, TaskManager, MaaConfig, MaaUserConfig, Network
|
from app.core import Config, MainInfoBar, TaskManager, MaaConfig, MaaUserConfig, Network
|
||||||
from app.services import Crypto
|
from app.services import Crypto
|
||||||
@@ -64,13 +66,21 @@ from .Widget import (
|
|||||||
LineEditSettingCard,
|
LineEditSettingCard,
|
||||||
SpinBoxSettingCard,
|
SpinBoxSettingCard,
|
||||||
ComboBoxMessageBox,
|
ComboBoxMessageBox,
|
||||||
EditableComboBoxSettingCard,
|
SettingFlyoutView,
|
||||||
|
NoOptionComboBoxSettingCard,
|
||||||
|
ComboBoxWithPlanSettingCard,
|
||||||
|
EditableComboBoxWithPlanSettingCard,
|
||||||
|
SpinBoxWithPlanSettingCard,
|
||||||
PasswordLineEditSettingCard,
|
PasswordLineEditSettingCard,
|
||||||
UserLableSettingCard,
|
UserLableSettingCard,
|
||||||
|
UserTaskSettingCard,
|
||||||
ComboBoxSettingCard,
|
ComboBoxSettingCard,
|
||||||
SwitchSettingCard,
|
SwitchSettingCard,
|
||||||
PushAndSwitchButtonSettingCard,
|
PushAndSwitchButtonSettingCard,
|
||||||
PushAndComboBoxSettingCard,
|
PushAndComboBoxSettingCard,
|
||||||
|
StatusSwitchSetting,
|
||||||
|
UserNoticeSettingCard,
|
||||||
|
PivotArea,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -177,7 +187,7 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
name = self.member_manager.pivot.currentRouteKey()
|
name = self.member_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("删除脚本实例时未选择脚本实例")
|
logger.warning("删除脚本实例时未选择脚本实例")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
||||||
@@ -191,11 +201,7 @@ class MemberManager(QWidget):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
choice = MessageBox(
|
choice = MessageBox("确认", f"确定要删除 {name} 实例吗?", self.window())
|
||||||
"确认",
|
|
||||||
f"确定要删除 {name} 实例吗?",
|
|
||||||
self.window(),
|
|
||||||
)
|
|
||||||
if choice.exec():
|
if choice.exec():
|
||||||
|
|
||||||
self.member_manager.clear_SettingBox()
|
self.member_manager.clear_SettingBox()
|
||||||
@@ -221,7 +227,7 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
name = self.member_manager.pivot.currentRouteKey()
|
name = self.member_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("向左移动脚本实例时未选择脚本实例")
|
logger.warning("向左移动脚本实例时未选择脚本实例")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
||||||
@@ -269,7 +275,7 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
name = self.member_manager.pivot.currentRouteKey()
|
name = self.member_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("向右移动脚本实例时未选择脚本实例")
|
logger.warning("向右移动脚本实例时未选择脚本实例")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
"warning", "未选择脚本实例", "请选择一个脚本实例", 5000
|
||||||
@@ -470,11 +476,57 @@ class MemberManager(QWidget):
|
|||||||
self.key.setIcon(FluentIcon.HIDE)
|
self.key.setIcon(FluentIcon.HIDE)
|
||||||
self.key.setChecked(False)
|
self.key.setChecked(False)
|
||||||
|
|
||||||
|
def reload_plan_name(self):
|
||||||
|
"""刷新计划表名称"""
|
||||||
|
|
||||||
|
plan_list = [
|
||||||
|
["固定"] + [_ for _ in Config.plan_dict.keys()],
|
||||||
|
["固定"]
|
||||||
|
+ [
|
||||||
|
(
|
||||||
|
k
|
||||||
|
if v["Config"].get(v["Config"].Info_Name) == ""
|
||||||
|
else f"{k} - {v["Config"].get(v["Config"].Info_Name)}"
|
||||||
|
)
|
||||||
|
for k, v in Config.plan_dict.items()
|
||||||
|
],
|
||||||
|
]
|
||||||
|
for member in self.member_manager.script_list:
|
||||||
|
|
||||||
|
if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox):
|
||||||
|
|
||||||
|
for user_setting in member.user_setting.user_manager.script_list:
|
||||||
|
|
||||||
|
user_setting.card_GameIdMode.comboBox.currentIndexChanged.disconnect(
|
||||||
|
user_setting.switch_gameid_mode
|
||||||
|
)
|
||||||
|
user_setting.card_GameIdMode.reLoadOptions(
|
||||||
|
plan_list[0], plan_list[1]
|
||||||
|
)
|
||||||
|
user_setting.card_GameIdMode.comboBox.currentIndexChanged.connect(
|
||||||
|
user_setting.switch_gameid_mode
|
||||||
|
)
|
||||||
|
|
||||||
|
self.refresh_plan_info()
|
||||||
|
|
||||||
def refresh_dashboard(self):
|
def refresh_dashboard(self):
|
||||||
"""刷新所有脚本实例的用户仪表盘"""
|
"""刷新所有脚本实例的用户仪表盘"""
|
||||||
|
|
||||||
for script in self.member_manager.script_list:
|
for member in self.member_manager.script_list:
|
||||||
script.user_setting.user_manager.user_dashboard.load_info()
|
|
||||||
|
if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox):
|
||||||
|
member.user_setting.user_manager.user_dashboard.load_info()
|
||||||
|
|
||||||
|
def refresh_plan_info(self):
|
||||||
|
"""刷新所有计划信息"""
|
||||||
|
|
||||||
|
for member in self.member_manager.script_list:
|
||||||
|
|
||||||
|
if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox):
|
||||||
|
|
||||||
|
member.user_setting.user_manager.user_dashboard.load_info()
|
||||||
|
for user_setting in member.user_setting.user_manager.script_list:
|
||||||
|
user_setting.switch_gameid_mode()
|
||||||
|
|
||||||
class MemberSettingBox(QWidget):
|
class MemberSettingBox(QWidget):
|
||||||
"""脚本管理子页面组"""
|
"""脚本管理子页面组"""
|
||||||
@@ -484,13 +536,17 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
self.setObjectName("脚本管理页面组")
|
self.setObjectName("脚本管理页面组")
|
||||||
|
|
||||||
self.pivot = Pivot(self)
|
self.pivotArea = PivotArea(self)
|
||||||
|
self.pivot = self.pivotArea.pivot
|
||||||
|
|
||||||
self.stackedWidget = QStackedWidget(self)
|
self.stackedWidget = QStackedWidget(self)
|
||||||
self.Layout = QVBoxLayout(self)
|
self.stackedWidget.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.stackedWidget.setStyleSheet("background: transparent; border: none;")
|
||||||
|
|
||||||
self.script_list: List[MemberManager.MemberSettingBox.MaaSettingBox] = []
|
self.script_list: List[MemberManager.MemberSettingBox.MaaSettingBox] = []
|
||||||
|
|
||||||
self.Layout.addWidget(self.pivot, 0, Qt.AlignHCenter)
|
self.Layout = QVBoxLayout(self)
|
||||||
|
self.Layout.addWidget(self.pivotArea)
|
||||||
self.Layout.addWidget(self.stackedWidget)
|
self.Layout.addWidget(self.stackedWidget)
|
||||||
self.Layout.setContentsMargins(0, 0, 0, 0)
|
self.Layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
@@ -558,27 +614,25 @@ class MemberManager(QWidget):
|
|||||||
self.setObjectName(f"脚本_{uid}")
|
self.setObjectName(f"脚本_{uid}")
|
||||||
self.config = Config.member_dict[f"脚本_{uid}"]["Config"]
|
self.config = Config.member_dict[f"脚本_{uid}"]["Config"]
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
|
|
||||||
scrollArea = ScrollArea()
|
|
||||||
scrollArea.setWidgetResizable(True)
|
|
||||||
|
|
||||||
content_widget = QWidget()
|
|
||||||
content_layout = QVBoxLayout(content_widget)
|
|
||||||
|
|
||||||
self.app_setting = self.AppSettingCard(f"脚本_{uid}", self.config, self)
|
self.app_setting = self.AppSettingCard(f"脚本_{uid}", self.config, self)
|
||||||
self.user_setting = self.UserManager(f"脚本_{uid}", self)
|
self.user_setting = self.UserManager(f"脚本_{uid}", self)
|
||||||
|
|
||||||
|
content_widget = QWidget()
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(0, 0, 11, 0)
|
||||||
content_layout.addWidget(self.app_setting)
|
content_layout.addWidget(self.app_setting)
|
||||||
content_layout.addWidget(self.user_setting)
|
content_layout.addWidget(self.user_setting)
|
||||||
content_layout.addStretch(1)
|
content_layout.addStretch(1)
|
||||||
|
|
||||||
|
scrollArea = ScrollArea()
|
||||||
|
scrollArea.setWidgetResizable(True)
|
||||||
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
scrollArea.setWidget(content_widget)
|
scrollArea.setWidget(content_widget)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(scrollArea)
|
layout.addWidget(scrollArea)
|
||||||
|
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
class AppSettingCard(HeaderCardWidget):
|
class AppSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
def __init__(self, name: str, config: MaaConfig, parent=None):
|
def __init__(self, name: str, config: MaaConfig, parent=None):
|
||||||
@@ -691,6 +745,15 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.RunSet_ProxyTimesLimit,
|
configItem=self.config.RunSet_ProxyTimesLimit,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
self.card_ADBSearchRange = SpinBoxSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="ADB端口号搜索范围",
|
||||||
|
content="在【±端口号范围】内搜索实际ADB端口号",
|
||||||
|
range=(0, 3),
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.RunSet_ADBSearchRange,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
self.card_RunTimesLimit = SpinBoxSettingCard(
|
self.card_RunTimesLimit = SpinBoxSettingCard(
|
||||||
icon=FluentIcon.PAGE_RIGHT,
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
title="代理重试次数限制",
|
title="代理重试次数限制",
|
||||||
@@ -739,6 +802,7 @@ class MemberManager(QWidget):
|
|||||||
Layout = QVBoxLayout(widget)
|
Layout = QVBoxLayout(widget)
|
||||||
Layout.addWidget(self.card_TaskTransitionMethod)
|
Layout.addWidget(self.card_TaskTransitionMethod)
|
||||||
Layout.addWidget(self.card_ProxyTimesLimit)
|
Layout.addWidget(self.card_ProxyTimesLimit)
|
||||||
|
Layout.addWidget(self.card_ADBSearchRange)
|
||||||
Layout.addWidget(self.card_RunTimesLimit)
|
Layout.addWidget(self.card_RunTimesLimit)
|
||||||
Layout.addWidget(self.card_AnnihilationTimeLimit)
|
Layout.addWidget(self.card_AnnihilationTimeLimit)
|
||||||
Layout.addWidget(self.card_RoutineTimeLimit)
|
Layout.addWidget(self.card_RoutineTimeLimit)
|
||||||
@@ -827,7 +891,7 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
name = self.user_manager.pivot.currentRouteKey()
|
name = self.user_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("未选择用户")
|
logger.warning("未选择用户")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择用户", "请先选择一个用户", 5000
|
"warning", "未选择用户", "请先选择一个用户", 5000
|
||||||
@@ -848,9 +912,7 @@ class MemberManager(QWidget):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
choice = MessageBox(
|
choice = MessageBox(
|
||||||
"确认",
|
"确认", f"确定要删除 {name} 吗?", self.window()
|
||||||
f"确定要删除 {name} 吗?",
|
|
||||||
self.window(),
|
|
||||||
)
|
)
|
||||||
if choice.exec():
|
if choice.exec():
|
||||||
|
|
||||||
@@ -888,7 +950,7 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
name = self.user_manager.pivot.currentRouteKey()
|
name = self.user_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("未选择用户")
|
logger.warning("未选择用户")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择用户", "请先选择一个用户", 5000
|
"warning", "未选择用户", "请先选择一个用户", 5000
|
||||||
@@ -947,7 +1009,7 @@ class MemberManager(QWidget):
|
|||||||
|
|
||||||
name = self.user_manager.pivot.currentRouteKey()
|
name = self.user_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("未选择用户")
|
logger.warning("未选择用户")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择用户", "请先选择一个用户", 5000
|
"warning", "未选择用户", "请先选择一个用户", 5000
|
||||||
@@ -1010,9 +1072,14 @@ class MemberManager(QWidget):
|
|||||||
self.setObjectName("用户管理")
|
self.setObjectName("用户管理")
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
self.pivot = Pivot(self)
|
self.pivotArea = PivotArea(self)
|
||||||
|
self.pivot = self.pivotArea.pivot
|
||||||
|
|
||||||
self.stackedWidget = QStackedWidget(self)
|
self.stackedWidget = QStackedWidget(self)
|
||||||
self.Layout = QVBoxLayout(self)
|
self.stackedWidget.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.stackedWidget.setStyleSheet(
|
||||||
|
"background: transparent; border: none;"
|
||||||
|
)
|
||||||
|
|
||||||
self.script_list: List[
|
self.script_list: List[
|
||||||
MemberManager.MemberSettingBox.MaaSettingBox.UserManager.UserSettingBox.UserMemberSettingBox
|
MemberManager.MemberSettingBox.MaaSettingBox.UserManager.UserSettingBox.UserMemberSettingBox
|
||||||
@@ -1023,7 +1090,8 @@ class MemberManager(QWidget):
|
|||||||
self.stackedWidget.addWidget(self.user_dashboard)
|
self.stackedWidget.addWidget(self.user_dashboard)
|
||||||
self.pivot.addItem(routeKey="用户仪表盘", text="用户仪表盘")
|
self.pivot.addItem(routeKey="用户仪表盘", text="用户仪表盘")
|
||||||
|
|
||||||
self.Layout.addWidget(self.pivot, 0, Qt.AlignHCenter)
|
self.Layout = QVBoxLayout(self)
|
||||||
|
self.Layout.addWidget(self.pivotArea)
|
||||||
self.Layout.addWidget(self.stackedWidget)
|
self.Layout.addWidget(self.stackedWidget)
|
||||||
self.Layout.setContentsMargins(0, 0, 0, 0)
|
self.Layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
@@ -1177,6 +1245,8 @@ class MemberManager(QWidget):
|
|||||||
else "本周剿灭未完成"
|
else "本周剿灭未完成"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
gameid_info = config.get_plan_info()
|
||||||
|
|
||||||
button = PrimaryToolButton(
|
button = PrimaryToolButton(
|
||||||
FluentIcon.CHEVRON_RIGHT, self
|
FluentIcon.CHEVRON_RIGHT, self
|
||||||
)
|
)
|
||||||
@@ -1207,14 +1277,14 @@ class MemberManager(QWidget):
|
|||||||
else "******"
|
else "******"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.dashboard.setItem(
|
self.dashboard.setCellWidget(
|
||||||
int(name[3:]) - 1,
|
int(name[3:]) - 1,
|
||||||
3,
|
3,
|
||||||
QTableWidgetItem(
|
StatusSwitchSetting(
|
||||||
"启用"
|
qconfig=config,
|
||||||
if config.get(config.Info_Status)
|
configItem_check=config.Info_Status,
|
||||||
and config.get(config.Info_RemainedDay) != 0
|
configItem_enable=config.Info_RemainedDay,
|
||||||
else "禁用"
|
parent=self,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.dashboard.setItem(
|
self.dashboard.setItem(
|
||||||
@@ -1225,9 +1295,7 @@ class MemberManager(QWidget):
|
|||||||
self.dashboard.setItem(
|
self.dashboard.setItem(
|
||||||
int(name[3:]) - 1,
|
int(name[3:]) - 1,
|
||||||
5,
|
5,
|
||||||
QTableWidgetItem(
|
QTableWidgetItem(str(gameid_info["MedicineNumb"])),
|
||||||
str(config.get(config.Info_MedicineNumb))
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
self.dashboard.setItem(
|
self.dashboard.setItem(
|
||||||
int(name[3:]) - 1,
|
int(name[3:]) - 1,
|
||||||
@@ -1235,12 +1303,12 @@ class MemberManager(QWidget):
|
|||||||
QTableWidgetItem(
|
QTableWidgetItem(
|
||||||
Config.gameid_dict["ALL"]["text"][
|
Config.gameid_dict["ALL"]["text"][
|
||||||
Config.gameid_dict["ALL"]["value"].index(
|
Config.gameid_dict["ALL"]["value"].index(
|
||||||
config.get(config.Info_GameId)
|
gameid_info["GameId"]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if config.get(config.Info_GameId)
|
if gameid_info["GameId"]
|
||||||
in Config.gameid_dict["ALL"]["value"]
|
in Config.gameid_dict["ALL"]["value"]
|
||||||
else config.get(config.Info_GameId)
|
else gameid_info["GameId"]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.dashboard.setItem(
|
self.dashboard.setItem(
|
||||||
@@ -1249,12 +1317,12 @@ class MemberManager(QWidget):
|
|||||||
QTableWidgetItem(
|
QTableWidgetItem(
|
||||||
Config.gameid_dict["ALL"]["text"][
|
Config.gameid_dict["ALL"]["text"][
|
||||||
Config.gameid_dict["ALL"]["value"].index(
|
Config.gameid_dict["ALL"]["value"].index(
|
||||||
config.get(config.Info_GameId_1)
|
gameid_info["GameId_1"]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if config.get(config.Info_GameId_1)
|
if gameid_info["GameId_1"]
|
||||||
in Config.gameid_dict["ALL"]["value"]
|
in Config.gameid_dict["ALL"]["value"]
|
||||||
else config.get(config.Info_GameId_1)
|
else gameid_info["GameId_1"]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.dashboard.setItem(
|
self.dashboard.setItem(
|
||||||
@@ -1263,12 +1331,12 @@ class MemberManager(QWidget):
|
|||||||
QTableWidgetItem(
|
QTableWidgetItem(
|
||||||
Config.gameid_dict["ALL"]["text"][
|
Config.gameid_dict["ALL"]["text"][
|
||||||
Config.gameid_dict["ALL"]["value"].index(
|
Config.gameid_dict["ALL"]["value"].index(
|
||||||
config.get(config.Info_GameId_2)
|
gameid_info["GameId_2"]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if config.get(config.Info_GameId_2)
|
if gameid_info["GameId_2"]
|
||||||
in Config.gameid_dict["ALL"]["value"]
|
in Config.gameid_dict["ALL"]["value"]
|
||||||
else config.get(config.Info_GameId_2)
|
else gameid_info["GameId_2"]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.dashboard.setItem(
|
self.dashboard.setItem(
|
||||||
@@ -1276,22 +1344,20 @@ class MemberManager(QWidget):
|
|||||||
9,
|
9,
|
||||||
QTableWidgetItem(
|
QTableWidgetItem(
|
||||||
"不使用"
|
"不使用"
|
||||||
if config.get(config.Info_GameId_Remain) == "-"
|
if gameid_info["GameId_Remain"] == "-"
|
||||||
else (
|
else (
|
||||||
(
|
(
|
||||||
Config.gameid_dict["ALL"]["text"][
|
Config.gameid_dict["ALL"]["text"][
|
||||||
Config.gameid_dict["ALL"][
|
Config.gameid_dict["ALL"][
|
||||||
"value"
|
"value"
|
||||||
].index(
|
].index(
|
||||||
config.get(
|
gameid_info["GameId_Remain"]
|
||||||
config.Info_GameId_Remain
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
if config.get(config.Info_GameId_Remain)
|
if gameid_info["GameId_Remain"]
|
||||||
in Config.gameid_dict["ALL"]["value"]
|
in Config.gameid_dict["ALL"]["value"]
|
||||||
else config.get(config.Info_GameId_Remain)
|
else gameid_info["GameId_Remain"]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1315,6 +1381,19 @@ class MemberManager(QWidget):
|
|||||||
f"用户_{uid}"
|
f"用户_{uid}"
|
||||||
]["Path"]
|
]["Path"]
|
||||||
|
|
||||||
|
plan_list = [
|
||||||
|
["固定"] + [_ for _ in Config.plan_dict.keys()],
|
||||||
|
["固定"]
|
||||||
|
+ [
|
||||||
|
(
|
||||||
|
k
|
||||||
|
if v["Config"].get(v["Config"].Info_Name) == ""
|
||||||
|
else f"{k} - {v["Config"].get(v["Config"].Info_Name)}"
|
||||||
|
)
|
||||||
|
for k, v in Config.plan_dict.items()
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
self.card_Name = LineEditSettingCard(
|
self.card_Name = LineEditSettingCard(
|
||||||
icon=FluentIcon.PEOPLE,
|
icon=FluentIcon.PEOPLE,
|
||||||
title="用户名",
|
title="用户名",
|
||||||
@@ -1342,15 +1421,17 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_Mode,
|
configItem=self.config.Info_Mode,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_GameIdMode = ComboBoxSettingCard(
|
self.card_GameIdMode = NoOptionComboBoxSettingCard(
|
||||||
icon=FluentIcon.DICTIONARY,
|
icon=FluentIcon.DICTIONARY,
|
||||||
title="关卡配置模式",
|
title="关卡配置模式",
|
||||||
content="刷理智关卡号的配置模式",
|
content="刷理智关卡号的配置模式",
|
||||||
texts=["固定"],
|
value=plan_list[0],
|
||||||
|
texts=plan_list[1],
|
||||||
qconfig=self.config,
|
qconfig=self.config,
|
||||||
configItem=self.config.Info_GameIdMode,
|
configItem=self.config.Info_GameIdMode,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
self.card_GameIdMode.comboBox.setMinimumWidth(0)
|
||||||
self.card_Server = ComboBoxSettingCard(
|
self.card_Server = ComboBoxSettingCard(
|
||||||
icon=FluentIcon.PROJECTOR,
|
icon=FluentIcon.PROJECTOR,
|
||||||
title="服务器",
|
title="服务器",
|
||||||
@@ -1398,7 +1479,7 @@ class MemberManager(QWidget):
|
|||||||
self.card_InfrastMode = PushAndComboBoxSettingCard(
|
self.card_InfrastMode = PushAndComboBoxSettingCard(
|
||||||
icon=FluentIcon.CAFE,
|
icon=FluentIcon.CAFE,
|
||||||
title="基建模式",
|
title="基建模式",
|
||||||
content="配置文件仅在自定义基建中生效",
|
content="自定义基建配置文件未生效",
|
||||||
text="选择配置文件",
|
text="选择配置文件",
|
||||||
texts=[
|
texts=[
|
||||||
"常规模式",
|
"常规模式",
|
||||||
@@ -1428,7 +1509,7 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_Notes,
|
configItem=self.config.Info_Notes,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_MedicineNumb = SpinBoxSettingCard(
|
self.card_MedicineNumb = SpinBoxWithPlanSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="吃理智药",
|
title="吃理智药",
|
||||||
content="吃理智药次数,输入0以关闭",
|
content="吃理智药次数,输入0以关闭",
|
||||||
@@ -1437,7 +1518,7 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_MedicineNumb,
|
configItem=self.config.Info_MedicineNumb,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_SeriesNumb = ComboBoxSettingCard(
|
self.card_SeriesNumb = ComboBoxWithPlanSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="连战次数",
|
title="连战次数",
|
||||||
content="连战次数较大时建议搭配剩余理智关卡使用",
|
content="连战次数较大时建议搭配剩余理智关卡使用",
|
||||||
@@ -1447,7 +1528,7 @@ class MemberManager(QWidget):
|
|||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_SeriesNumb.comboBox.setMinimumWidth(150)
|
self.card_SeriesNumb.comboBox.setMinimumWidth(150)
|
||||||
self.card_GameId = EditableComboBoxSettingCard(
|
self.card_GameId = EditableComboBoxWithPlanSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="关卡选择",
|
title="关卡选择",
|
||||||
content="按下回车以添加自定义关卡号",
|
content="按下回车以添加自定义关卡号",
|
||||||
@@ -1457,7 +1538,7 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_GameId,
|
configItem=self.config.Info_GameId,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_GameId_1 = EditableComboBoxSettingCard(
|
self.card_GameId_1 = EditableComboBoxWithPlanSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="备选关卡 - 1",
|
title="备选关卡 - 1",
|
||||||
content="按下回车以添加自定义关卡号",
|
content="按下回车以添加自定义关卡号",
|
||||||
@@ -1467,7 +1548,7 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_GameId_1,
|
configItem=self.config.Info_GameId_1,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_GameId_2 = EditableComboBoxSettingCard(
|
self.card_GameId_2 = EditableComboBoxWithPlanSettingCard(
|
||||||
icon=FluentIcon.GAME,
|
icon=FluentIcon.GAME,
|
||||||
title="备选关卡 - 2",
|
title="备选关卡 - 2",
|
||||||
content="按下回车以添加自定义关卡号",
|
content="按下回车以添加自定义关卡号",
|
||||||
@@ -1477,18 +1558,20 @@ class MemberManager(QWidget):
|
|||||||
configItem=self.config.Info_GameId_2,
|
configItem=self.config.Info_GameId_2,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
self.card_GameId_Remain = EditableComboBoxSettingCard(
|
self.card_GameId_Remain = (
|
||||||
icon=FluentIcon.GAME,
|
EditableComboBoxWithPlanSettingCard(
|
||||||
title="剩余理智关卡",
|
icon=FluentIcon.GAME,
|
||||||
content="按下回车以添加自定义关卡号",
|
title="剩余理智关卡",
|
||||||
value=Config.gameid_dict["ALL"]["value"],
|
content="按下回车以添加自定义关卡号",
|
||||||
texts=[
|
value=Config.gameid_dict["ALL"]["value"],
|
||||||
"不使用" if _ == "当前/上次" else _
|
texts=[
|
||||||
for _ in Config.gameid_dict["ALL"]["text"]
|
"不使用" if _ == "当前/上次" else _
|
||||||
],
|
for _ in Config.gameid_dict["ALL"]["text"]
|
||||||
qconfig=self.config,
|
],
|
||||||
configItem=self.config.Info_GameId_Remain,
|
qconfig=self.config,
|
||||||
parent=self,
|
configItem=self.config.Info_GameId_Remain,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.card_UserLable = UserLableSettingCard(
|
self.card_UserLable = UserLableSettingCard(
|
||||||
@@ -1505,6 +1588,147 @@ class MemberManager(QWidget):
|
|||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 单独任务卡片
|
||||||
|
self.card_TaskSet = UserTaskSettingCard(
|
||||||
|
icon=FluentIcon.LIBRARY,
|
||||||
|
title="自动日常代理任务序列",
|
||||||
|
content="未启用任何任务项",
|
||||||
|
text="设置",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItems={
|
||||||
|
"IfWakeUp": self.config.Task_IfWakeUp,
|
||||||
|
"IfRecruiting": self.config.Task_IfRecruiting,
|
||||||
|
"IfBase": self.config.Task_IfBase,
|
||||||
|
"IfCombat": self.config.Task_IfCombat,
|
||||||
|
"IfMall": self.config.Task_IfMall,
|
||||||
|
"IfMission": self.config.Task_IfMission,
|
||||||
|
"IfAutoRoguelike": self.config.Task_IfAutoRoguelike,
|
||||||
|
"IfReclamation": self.config.Task_IfReclamation,
|
||||||
|
},
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfWakeUp = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="开始唤醒",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfWakeUp,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfRecruiting = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="自动公招",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfRecruiting,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfBase = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="基建换班",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfBase,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfCombat = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="刷理智",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfCombat,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfMall = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="获取信用及购物",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfMall,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfMission = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="领取奖励",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfMission,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfAutoRoguelike = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="自动肉鸽",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfAutoRoguelike,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfReclamation = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.TILES,
|
||||||
|
title="生息演算",
|
||||||
|
content="",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Task_IfReclamation,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.TaskSetCard = SettingFlyoutView(
|
||||||
|
self,
|
||||||
|
"自动日常代理任务序列设置",
|
||||||
|
[
|
||||||
|
self.card_IfWakeUp,
|
||||||
|
self.card_IfRecruiting,
|
||||||
|
self.card_IfBase,
|
||||||
|
self.card_IfCombat,
|
||||||
|
self.card_IfMall,
|
||||||
|
self.card_IfMission,
|
||||||
|
self.card_IfAutoRoguelike,
|
||||||
|
self.card_IfReclamation,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# 单独通知卡片
|
||||||
|
self.card_NotifySet = UserNoticeSettingCard(
|
||||||
|
icon=FluentIcon.MAIL,
|
||||||
|
title="用户单独通知设置",
|
||||||
|
content="未启用任何通知项",
|
||||||
|
text="设置",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_Enabled,
|
||||||
|
configItems={
|
||||||
|
"IfSendStatistic": self.config.Notify_IfSendStatistic,
|
||||||
|
"IfSendSixStar": self.config.Notify_IfSendSixStar,
|
||||||
|
"IfSendMail": self.config.Notify_IfSendMail,
|
||||||
|
"ToAddress": self.config.Notify_ToAddress,
|
||||||
|
"IfServerChan": self.config.Notify_IfServerChan,
|
||||||
|
"ServerChanKey": self.config.Notify_ServerChanKey,
|
||||||
|
"IfCompanyWebHookBot": self.config.Notify_IfCompanyWebHookBot,
|
||||||
|
"CompanyWebHookBotUrl": self.config.Notify_CompanyWebHookBotUrl,
|
||||||
|
},
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_NotifyContent = self.NotifyContentSettingCard(
|
||||||
|
self.config, self
|
||||||
|
)
|
||||||
|
self.card_EMail = self.EMailSettingCard(self.config, self)
|
||||||
|
self.card_ServerChan = self.ServerChanSettingCard(
|
||||||
|
self.config, self
|
||||||
|
)
|
||||||
|
self.card_CompanyWebhookBot = (
|
||||||
|
self.CompanyWechatPushSettingCard(self.config, self)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.NotifySetCard = SettingFlyoutView(
|
||||||
|
self,
|
||||||
|
"用户通知设置",
|
||||||
|
[
|
||||||
|
self.card_NotifyContent,
|
||||||
|
self.card_EMail,
|
||||||
|
self.card_ServerChan,
|
||||||
|
self.card_CompanyWebhookBot,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
h1_layout = QHBoxLayout()
|
h1_layout = QHBoxLayout()
|
||||||
h1_layout.addWidget(self.card_Name)
|
h1_layout.addWidget(self.card_Name)
|
||||||
h1_layout.addWidget(self.card_Id)
|
h1_layout.addWidget(self.card_Id)
|
||||||
@@ -1542,6 +1766,8 @@ class MemberManager(QWidget):
|
|||||||
Layout.addLayout(h6_layout)
|
Layout.addLayout(h6_layout)
|
||||||
Layout.addLayout(h7_layout)
|
Layout.addLayout(h7_layout)
|
||||||
Layout.addLayout(h8_layout)
|
Layout.addLayout(h8_layout)
|
||||||
|
Layout.addWidget(self.card_TaskSet)
|
||||||
|
Layout.addWidget(self.card_NotifySet)
|
||||||
|
|
||||||
self.viewLayout.addLayout(Layout)
|
self.viewLayout.addLayout(Layout)
|
||||||
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
@@ -1549,6 +1775,9 @@ class MemberManager(QWidget):
|
|||||||
self.card_Mode.comboBox.currentIndexChanged.connect(
|
self.card_Mode.comboBox.currentIndexChanged.connect(
|
||||||
self.switch_mode
|
self.switch_mode
|
||||||
)
|
)
|
||||||
|
self.card_InfrastMode.comboBox.currentIndexChanged.connect(
|
||||||
|
self.switch_infrastructure
|
||||||
|
)
|
||||||
self.card_Annihilation.clicked.connect(
|
self.card_Annihilation.clicked.connect(
|
||||||
lambda: self.set_maa("Annihilation")
|
lambda: self.set_maa("Annihilation")
|
||||||
)
|
)
|
||||||
@@ -1558,10 +1787,17 @@ class MemberManager(QWidget):
|
|||||||
self.card_InfrastMode.clicked.connect(
|
self.card_InfrastMode.clicked.connect(
|
||||||
self.set_infrastructure
|
self.set_infrastructure
|
||||||
)
|
)
|
||||||
|
self.card_TaskSet.clicked.connect(self.set_task)
|
||||||
|
self.card_NotifySet.clicked.connect(self.set_notify)
|
||||||
|
self.card_GameIdMode.comboBox.currentIndexChanged.connect(
|
||||||
|
self.switch_gameid_mode
|
||||||
|
)
|
||||||
Config.gameid_refreshed.connect(self.refresh_gameid)
|
Config.gameid_refreshed.connect(self.refresh_gameid)
|
||||||
Config.PASSWORD_refreshed.connect(self.refresh_password)
|
Config.PASSWORD_refreshed.connect(self.refresh_password)
|
||||||
|
|
||||||
self.switch_mode()
|
self.switch_mode()
|
||||||
|
self.switch_gameid_mode()
|
||||||
|
self.switch_infrastructure()
|
||||||
|
|
||||||
def switch_mode(self) -> None:
|
def switch_mode(self) -> None:
|
||||||
|
|
||||||
@@ -1579,6 +1815,61 @@ class MemberManager(QWidget):
|
|||||||
self.card_Annihilation.button.setVisible(True)
|
self.card_Annihilation.button.setVisible(True)
|
||||||
self.card_Routine.setVisible(True)
|
self.card_Routine.setVisible(True)
|
||||||
|
|
||||||
|
def switch_gameid_mode(self) -> None:
|
||||||
|
|
||||||
|
for card, name in zip(
|
||||||
|
[
|
||||||
|
self.card_MedicineNumb,
|
||||||
|
self.card_SeriesNumb,
|
||||||
|
self.card_GameId,
|
||||||
|
self.card_GameId_1,
|
||||||
|
self.card_GameId_2,
|
||||||
|
self.card_GameId_Remain,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"MedicineNumb",
|
||||||
|
"SeriesNumb",
|
||||||
|
"GameId",
|
||||||
|
"GameId_1",
|
||||||
|
"GameId_2",
|
||||||
|
"GameId_Remain",
|
||||||
|
],
|
||||||
|
):
|
||||||
|
|
||||||
|
card.switch_mode(
|
||||||
|
self.config.get(self.config.Info_GameIdMode)[:2]
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
self.config.get(self.config.Info_GameIdMode)
|
||||||
|
!= "固定"
|
||||||
|
):
|
||||||
|
card.change_plan(
|
||||||
|
Config.plan_dict[
|
||||||
|
self.config.get(self.config.Info_GameIdMode)
|
||||||
|
]["Config"].get_current_info(name)
|
||||||
|
)
|
||||||
|
|
||||||
|
def switch_infrastructure(self) -> None:
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.config.get(self.config.Info_InfrastMode)
|
||||||
|
== "Custom"
|
||||||
|
):
|
||||||
|
self.card_InfrastMode.button.setVisible(True)
|
||||||
|
with (
|
||||||
|
self.user_path
|
||||||
|
/ "Infrastructure/infrastructure.json"
|
||||||
|
).open(mode="r", encoding="utf-8") as f:
|
||||||
|
infrastructure = json.load(f)
|
||||||
|
self.card_InfrastMode.setContent(
|
||||||
|
f"当前基建配置:{infrastructure.get("title","未命名")}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.card_InfrastMode.button.setVisible(False)
|
||||||
|
self.card_InfrastMode.setContent(
|
||||||
|
"自定义基建配置文件未生效"
|
||||||
|
)
|
||||||
|
|
||||||
def refresh_gameid(self):
|
def refresh_gameid(self):
|
||||||
|
|
||||||
self.card_GameId.reLoadOptions(
|
self.card_GameId.reLoadOptions(
|
||||||
@@ -1634,6 +1925,7 @@ class MemberManager(QWidget):
|
|||||||
self.user_path
|
self.user_path
|
||||||
/ "Infrastructure/infrastructure.json",
|
/ "Infrastructure/infrastructure.json",
|
||||||
)
|
)
|
||||||
|
self.switch_infrastructure()
|
||||||
else:
|
else:
|
||||||
logger.warning("未选择自定义基建文件")
|
logger.warning("未选择自定义基建文件")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
@@ -1659,3 +1951,178 @@ class MemberManager(QWidget):
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def set_task(self) -> None:
|
||||||
|
"""设置用户任务序列相关配置"""
|
||||||
|
|
||||||
|
self.TaskSetCard.setVisible(True)
|
||||||
|
Flyout.make(
|
||||||
|
self.TaskSetCard,
|
||||||
|
self.card_TaskSet,
|
||||||
|
self,
|
||||||
|
aniType=FlyoutAnimationType.PULL_UP,
|
||||||
|
isDeleteOnClose=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_notify(self) -> None:
|
||||||
|
"""设置用户通知相关配置"""
|
||||||
|
|
||||||
|
self.NotifySetCard.setVisible(True)
|
||||||
|
Flyout.make(
|
||||||
|
self.NotifySetCard,
|
||||||
|
self.card_NotifySet,
|
||||||
|
self,
|
||||||
|
aniType=FlyoutAnimationType.PULL_UP,
|
||||||
|
isDeleteOnClose=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
class NotifyContentSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, config: MaaUserConfig, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("用户通知内容选项")
|
||||||
|
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
self.card_IfSendStatistic = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="推送统计信息",
|
||||||
|
content="推送自动代理统计信息的通知",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_IfSendStatistic,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_IfSendSixStar = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="推送公招高资喜报",
|
||||||
|
content="公招出现六星词条时推送喜报",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_IfSendSixStar,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
Layout = QVBoxLayout()
|
||||||
|
Layout.addWidget(self.card_IfSendStatistic)
|
||||||
|
Layout.addWidget(self.card_IfSendSixStar)
|
||||||
|
self.viewLayout.addLayout(Layout)
|
||||||
|
self.viewLayout.setSpacing(3)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
|
class EMailSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, config: MaaUserConfig, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("用户邮箱通知")
|
||||||
|
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
self.card_IfSendMail = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="推送用户邮件通知",
|
||||||
|
content="是否启用用户邮件通知功能",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_IfSendMail,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_ToAddress = LineEditSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="用户收信邮箱地址",
|
||||||
|
content="接收用户通知的邮箱地址",
|
||||||
|
text="请输入用户收信邮箱地址",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_ToAddress,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
Layout = QVBoxLayout()
|
||||||
|
Layout.addWidget(self.card_IfSendMail)
|
||||||
|
Layout.addWidget(self.card_ToAddress)
|
||||||
|
self.viewLayout.addLayout(Layout)
|
||||||
|
self.viewLayout.setSpacing(3)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
|
class ServerChanSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, config: MaaUserConfig, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("用户ServerChan通知")
|
||||||
|
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
self.card_IfServerChan = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="推送用户Server酱通知",
|
||||||
|
content="是否启用用户Server酱通知功能",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_IfServerChan,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_ServerChanKey = LineEditSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="用户SendKey",
|
||||||
|
content="SC3与SCT均须填写",
|
||||||
|
text="请输入用户SendKey",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_ServerChanKey,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_ServerChanChannel = LineEditSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="用户ServerChanChannel代码",
|
||||||
|
content="留空则默认,多个请使用“|”隔开",
|
||||||
|
text="请输入Channel代码,仅SCT生效",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_ServerChanChannel,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_ServerChanTag = LineEditSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="用户Tag内容",
|
||||||
|
content="留空则默认,多个请使用“|”隔开",
|
||||||
|
text="请输入加入推送的Tag,仅SC3生效",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_ServerChanTag,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
Layout = QVBoxLayout()
|
||||||
|
Layout.addWidget(self.card_IfServerChan)
|
||||||
|
Layout.addWidget(self.card_ServerChanKey)
|
||||||
|
Layout.addWidget(self.card_ServerChanChannel)
|
||||||
|
Layout.addWidget(self.card_ServerChanTag)
|
||||||
|
self.viewLayout.addLayout(Layout)
|
||||||
|
self.viewLayout.setSpacing(3)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
|
class CompanyWechatPushSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
|
def __init__(self, config: MaaUserConfig, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setTitle("用户企业微信推送")
|
||||||
|
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
self.card_IfCompanyWebHookBot = SwitchSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="推送用户企业微信机器人通知",
|
||||||
|
content="是否启用用户企微机器人通知功能",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_IfCompanyWebHookBot,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_CompanyWebHookBotUrl = LineEditSettingCard(
|
||||||
|
icon=FluentIcon.PAGE_RIGHT,
|
||||||
|
title="WebhookUrl",
|
||||||
|
content="用户企微群机器人Webhook地址",
|
||||||
|
text="请输入用户Webhook的Url",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Notify_CompanyWebHookBotUrl,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
Layout = QVBoxLayout()
|
||||||
|
Layout.addWidget(self.card_IfCompanyWebHookBot)
|
||||||
|
Layout.addWidget(self.card_CompanyWebHookBotUrl)
|
||||||
|
self.viewLayout.addLayout(Layout)
|
||||||
|
self.viewLayout.setSpacing(3)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|||||||
495
app/ui/plan_manager.py
Normal file
495
app/ui/plan_manager.py
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
# 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.QtWidgets import (
|
||||||
|
QWidget,
|
||||||
|
QVBoxLayout,
|
||||||
|
QStackedWidget,
|
||||||
|
QHeaderView,
|
||||||
|
)
|
||||||
|
from qfluentwidgets import (
|
||||||
|
Action,
|
||||||
|
FluentIcon,
|
||||||
|
MessageBox,
|
||||||
|
HeaderCardWidget,
|
||||||
|
CommandBar,
|
||||||
|
TableWidget,
|
||||||
|
)
|
||||||
|
from typing import List, Dict, Union
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from app.core import Config, MainInfoBar, MaaPlanConfig
|
||||||
|
from .Widget import (
|
||||||
|
ComboBoxMessageBox,
|
||||||
|
LineEditSettingCard,
|
||||||
|
ComboBoxSettingCard,
|
||||||
|
SpinBoxSetting,
|
||||||
|
EditableComboBoxSetting,
|
||||||
|
ComboBoxSetting,
|
||||||
|
PivotArea,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PlanManager(QWidget):
|
||||||
|
"""计划管理父界面"""
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.setObjectName("计划管理")
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
self.tools = CommandBar()
|
||||||
|
|
||||||
|
self.plan_manager = self.PlanSettingBox(self)
|
||||||
|
|
||||||
|
# 逐个添加动作
|
||||||
|
self.tools.addActions(
|
||||||
|
[
|
||||||
|
Action(FluentIcon.ADD_TO, "新建计划表", triggered=self.add_setting_box),
|
||||||
|
Action(
|
||||||
|
FluentIcon.REMOVE_FROM, "删除计划表", triggered=self.del_setting_box
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.tools.addSeparator()
|
||||||
|
self.tools.addActions(
|
||||||
|
[
|
||||||
|
Action(
|
||||||
|
FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_setting_box
|
||||||
|
),
|
||||||
|
Action(
|
||||||
|
FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_setting_box
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.tools.addSeparator()
|
||||||
|
|
||||||
|
layout.addWidget(self.tools)
|
||||||
|
layout.addWidget(self.plan_manager)
|
||||||
|
|
||||||
|
def add_setting_box(self):
|
||||||
|
"""添加一个计划表"""
|
||||||
|
|
||||||
|
choice = ComboBoxMessageBox(
|
||||||
|
self.window(),
|
||||||
|
"选择一个计划类型以添加相应计划表",
|
||||||
|
["选择计划类型"],
|
||||||
|
[["MAA"]],
|
||||||
|
)
|
||||||
|
if choice.exec() and choice.input[0].currentIndex() != -1:
|
||||||
|
|
||||||
|
if choice.input[0].currentText() == "MAA":
|
||||||
|
|
||||||
|
index = len(Config.plan_dict) + 1
|
||||||
|
|
||||||
|
maa_plan_config = MaaPlanConfig()
|
||||||
|
maa_plan_config.load(
|
||||||
|
Config.app_path / f"config/MaaPlanConfig/计划_{index}/config.json",
|
||||||
|
maa_plan_config,
|
||||||
|
)
|
||||||
|
maa_plan_config.save()
|
||||||
|
|
||||||
|
Config.plan_dict[f"计划_{index}"] = {
|
||||||
|
"Type": "Maa",
|
||||||
|
"Path": Config.app_path / f"config/MaaPlanConfig/计划_{index}",
|
||||||
|
"Config": maa_plan_config,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.plan_manager.add_MaaPlanSettingBox(index)
|
||||||
|
self.plan_manager.switch_SettingBox(index)
|
||||||
|
|
||||||
|
logger.success(f"计划管理 计划_{index} 添加成功")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"success", "操作成功", f"添加计划表 计划_{index}", 3000
|
||||||
|
)
|
||||||
|
|
||||||
|
def del_setting_box(self):
|
||||||
|
"""删除一个计划表"""
|
||||||
|
|
||||||
|
name = self.plan_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
logger.warning("删除计划表时未选择计划表")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "未选择计划表", "请选择一个计划表", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(Config.running_list) > 0:
|
||||||
|
logger.warning("删除计划表时调度队列未停止运行")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
choice = MessageBox("确认", f"确定要删除 {name} 吗?", self.window())
|
||||||
|
if choice.exec():
|
||||||
|
|
||||||
|
self.plan_manager.clear_SettingBox()
|
||||||
|
|
||||||
|
shutil.rmtree(Config.plan_dict[name]["Path"])
|
||||||
|
Config.change_plan(name, "禁用")
|
||||||
|
for i in range(int(name[3:]) + 1, len(Config.plan_dict) + 1):
|
||||||
|
if Config.plan_dict[f"计划_{i}"]["Path"].exists():
|
||||||
|
Config.plan_dict[f"计划_{i}"]["Path"].rename(
|
||||||
|
Config.plan_dict[f"计划_{i}"]["Path"].with_name(f"计划_{i-1}")
|
||||||
|
)
|
||||||
|
Config.change_plan(f"计划_{i}", f"计划_{i-1}")
|
||||||
|
|
||||||
|
self.plan_manager.show_SettingBox(max(int(name[3:]) - 1, 1))
|
||||||
|
|
||||||
|
logger.success(f"计划表 {name} 删除成功")
|
||||||
|
MainInfoBar.push_info_bar("success", "操作成功", f"删除计划表 {name}", 3000)
|
||||||
|
|
||||||
|
def left_setting_box(self):
|
||||||
|
"""向左移动计划表"""
|
||||||
|
|
||||||
|
name = self.plan_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
logger.warning("向左移动计划表时未选择计划表")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "未选择计划表", "请选择一个计划表", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
index = int(name[3:])
|
||||||
|
|
||||||
|
if index == 1:
|
||||||
|
logger.warning("向左移动计划表时已到达最左端")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "已经是第一个计划表", "无法向左移动", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(Config.running_list) > 0:
|
||||||
|
logger.warning("向左移动计划表时调度队列未停止运行")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.plan_manager.clear_SettingBox()
|
||||||
|
|
||||||
|
Config.plan_dict[name]["Path"].rename(
|
||||||
|
Config.plan_dict[name]["Path"].with_name("计划_0")
|
||||||
|
)
|
||||||
|
Config.change_plan(name, "计划_0")
|
||||||
|
Config.plan_dict[f"计划_{index-1}"]["Path"].rename(
|
||||||
|
Config.plan_dict[name]["Path"]
|
||||||
|
)
|
||||||
|
Config.change_plan(f"计划_{index-1}", name)
|
||||||
|
Config.plan_dict[name]["Path"].with_name("计划_0").rename(
|
||||||
|
Config.plan_dict[f"计划_{index-1}"]["Path"]
|
||||||
|
)
|
||||||
|
Config.change_plan("计划_0", f"计划_{index-1}")
|
||||||
|
|
||||||
|
self.plan_manager.show_SettingBox(index - 1)
|
||||||
|
|
||||||
|
logger.success(f"计划表 {name} 左移成功")
|
||||||
|
MainInfoBar.push_info_bar("success", "操作成功", f"左移计划表 {name}", 3000)
|
||||||
|
|
||||||
|
def right_setting_box(self):
|
||||||
|
"""向右移动计划表"""
|
||||||
|
|
||||||
|
name = self.plan_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
logger.warning("向右移动计划表时未选择计划表")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "未选择计划表", "请选择一个计划表", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
index = int(name[3:])
|
||||||
|
|
||||||
|
if index == len(Config.plan_dict):
|
||||||
|
logger.warning("向右移动计划表时已到达最右端")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "已经是最后一个计划表", "无法向右移动", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(Config.running_list) > 0:
|
||||||
|
logger.warning("向右移动计划表时调度队列未停止运行")
|
||||||
|
MainInfoBar.push_info_bar(
|
||||||
|
"warning", "调度中心正在执行任务", "请等待或手动中止任务", 5000
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.plan_manager.clear_SettingBox()
|
||||||
|
|
||||||
|
Config.plan_dict[name]["Path"].rename(
|
||||||
|
Config.plan_dict[name]["Path"].with_name("计划_0")
|
||||||
|
)
|
||||||
|
Config.change_plan(name, "计划_0")
|
||||||
|
Config.plan_dict[f"计划_{index+1}"]["Path"].rename(
|
||||||
|
Config.plan_dict[name]["Path"]
|
||||||
|
)
|
||||||
|
Config.change_plan(f"计划_{index+1}", name)
|
||||||
|
Config.plan_dict[name]["Path"].with_name("计划_0").rename(
|
||||||
|
Config.plan_dict[f"计划_{index+1}"]["Path"]
|
||||||
|
)
|
||||||
|
Config.change_plan("计划_0", f"计划_{index+1}")
|
||||||
|
|
||||||
|
self.plan_manager.show_SettingBox(index + 1)
|
||||||
|
|
||||||
|
logger.success(f"计划表 {name} 右移成功")
|
||||||
|
MainInfoBar.push_info_bar("success", "操作成功", f"右移计划表 {name}", 3000)
|
||||||
|
|
||||||
|
class PlanSettingBox(QWidget):
|
||||||
|
"""计划管理子页面组"""
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.setObjectName("计划管理页面组")
|
||||||
|
|
||||||
|
self.pivotArea = PivotArea(self)
|
||||||
|
self.pivot = self.pivotArea.pivot
|
||||||
|
|
||||||
|
self.stackedWidget = QStackedWidget(self)
|
||||||
|
self.stackedWidget.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.stackedWidget.setStyleSheet("background: transparent; border: none;")
|
||||||
|
|
||||||
|
self.script_list: List[PlanManager.PlanSettingBox.MaaPlanSettingBox] = []
|
||||||
|
|
||||||
|
self.Layout = QVBoxLayout(self)
|
||||||
|
self.Layout.addWidget(self.pivotArea)
|
||||||
|
self.Layout.addWidget(self.stackedWidget)
|
||||||
|
self.Layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
|
self.pivot.currentItemChanged.connect(
|
||||||
|
lambda index: self.switch_SettingBox(
|
||||||
|
int(index[3:]), if_chang_pivot=False
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.show_SettingBox(1)
|
||||||
|
|
||||||
|
def show_SettingBox(self, index) -> None:
|
||||||
|
"""加载所有子界面"""
|
||||||
|
|
||||||
|
Config.search_plan()
|
||||||
|
|
||||||
|
for name, info in Config.plan_dict.items():
|
||||||
|
if info["Type"] == "Maa":
|
||||||
|
self.add_MaaPlanSettingBox(int(name[3:]))
|
||||||
|
|
||||||
|
self.switch_SettingBox(index)
|
||||||
|
|
||||||
|
def switch_SettingBox(self, index: int, if_chang_pivot: bool = True) -> None:
|
||||||
|
"""切换到指定的子界面"""
|
||||||
|
|
||||||
|
if len(Config.plan_dict) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if index > len(Config.plan_dict):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if if_chang_pivot:
|
||||||
|
self.pivot.setCurrentItem(self.script_list[index - 1].objectName())
|
||||||
|
self.stackedWidget.setCurrentWidget(self.script_list[index - 1])
|
||||||
|
|
||||||
|
def clear_SettingBox(self) -> None:
|
||||||
|
"""清空所有子界面"""
|
||||||
|
|
||||||
|
for sub_interface in self.script_list:
|
||||||
|
Config.gameid_refreshed.disconnect(sub_interface.refresh_gameid)
|
||||||
|
self.stackedWidget.removeWidget(sub_interface)
|
||||||
|
sub_interface.deleteLater()
|
||||||
|
self.script_list.clear()
|
||||||
|
self.pivot.clear()
|
||||||
|
|
||||||
|
def add_MaaPlanSettingBox(self, uid: int) -> None:
|
||||||
|
"""添加一个MAA设置界面"""
|
||||||
|
|
||||||
|
maa_plan_setting_box = self.MaaPlanSettingBox(uid, self)
|
||||||
|
|
||||||
|
self.script_list.append(maa_plan_setting_box)
|
||||||
|
|
||||||
|
self.stackedWidget.addWidget(self.script_list[-1])
|
||||||
|
|
||||||
|
self.pivot.addItem(routeKey=f"计划_{uid}", text=f"计划 {uid}")
|
||||||
|
|
||||||
|
class MaaPlanSettingBox(HeaderCardWidget):
|
||||||
|
"""MAA类计划设置界面"""
|
||||||
|
|
||||||
|
def __init__(self, uid: int, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.setObjectName(f"计划_{uid}")
|
||||||
|
self.setTitle("MAA计划表")
|
||||||
|
self.config = Config.plan_dict[f"计划_{uid}"]["Config"]
|
||||||
|
|
||||||
|
self.card_Name = LineEditSettingCard(
|
||||||
|
icon=FluentIcon.EDIT,
|
||||||
|
title="计划表名称",
|
||||||
|
content="用于标识计划表的名称",
|
||||||
|
text="请输入计划表名称",
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Info_Name,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
self.card_Mode = ComboBoxSettingCard(
|
||||||
|
icon=FluentIcon.DICTIONARY,
|
||||||
|
title="计划模式",
|
||||||
|
content="全局模式下计划内容固定,周计划模式下计划按周一到周日切换",
|
||||||
|
texts=["全局", "周计划"],
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=self.config.Info_Mode,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.table = TableWidget(self)
|
||||||
|
self.table.setColumnCount(8)
|
||||||
|
self.table.setRowCount(6)
|
||||||
|
self.table.setHorizontalHeaderLabels(
|
||||||
|
["全局", "周一", "周二", "周三", "周四", "周五", "周六", "周日"]
|
||||||
|
)
|
||||||
|
self.table.setVerticalHeaderLabels(
|
||||||
|
[
|
||||||
|
"吃理智药",
|
||||||
|
"连战次数",
|
||||||
|
"关卡选择",
|
||||||
|
"备选 - 1",
|
||||||
|
"备选 - 2",
|
||||||
|
"剩余理智",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.table.setAlternatingRowColors(False)
|
||||||
|
self.table.setEditTriggers(TableWidget.NoEditTriggers)
|
||||||
|
for col in range(8):
|
||||||
|
self.table.horizontalHeader().setSectionResizeMode(
|
||||||
|
col, QHeaderView.ResizeMode.Stretch
|
||||||
|
)
|
||||||
|
for row in range(6):
|
||||||
|
self.table.verticalHeader().setSectionResizeMode(
|
||||||
|
row, QHeaderView.ResizeMode.ResizeToContents
|
||||||
|
)
|
||||||
|
|
||||||
|
self.item_dict: Dict[
|
||||||
|
str,
|
||||||
|
Dict[
|
||||||
|
str,
|
||||||
|
Union[SpinBoxSetting, ComboBoxSetting, EditableComboBoxSetting],
|
||||||
|
],
|
||||||
|
] = {}
|
||||||
|
|
||||||
|
for col, (group, name_dict) in enumerate(
|
||||||
|
self.config.config_item_dict.items()
|
||||||
|
):
|
||||||
|
|
||||||
|
self.item_dict[group] = {}
|
||||||
|
|
||||||
|
for row, (name, configItem) in enumerate(name_dict.items()):
|
||||||
|
|
||||||
|
if name == "MedicineNumb":
|
||||||
|
self.item_dict[group][name] = SpinBoxSetting(
|
||||||
|
range=(0, 1024),
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=configItem,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
elif name == "SeriesNumb":
|
||||||
|
self.item_dict[group][name] = ComboBoxSetting(
|
||||||
|
texts=["AUTO", "6", "5", "4", "3", "2", "1", "不选择"],
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=configItem,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
elif name == "GameId_Remain":
|
||||||
|
self.item_dict[group][name] = EditableComboBoxSetting(
|
||||||
|
value=Config.gameid_dict[group]["value"],
|
||||||
|
texts=[
|
||||||
|
"不使用" if _ == "当前/上次" else _
|
||||||
|
for _ in Config.gameid_dict[group]["text"]
|
||||||
|
],
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=configItem,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
elif "GameId" in name:
|
||||||
|
self.item_dict[group][name] = EditableComboBoxSetting(
|
||||||
|
value=Config.gameid_dict[group]["value"],
|
||||||
|
texts=Config.gameid_dict[group]["text"],
|
||||||
|
qconfig=self.config,
|
||||||
|
configItem=configItem,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.table.setCellWidget(row, col, self.item_dict[group][name])
|
||||||
|
|
||||||
|
Layout = QVBoxLayout()
|
||||||
|
Layout.addWidget(self.card_Name)
|
||||||
|
Layout.addWidget(self.card_Mode)
|
||||||
|
Layout.addWidget(self.table)
|
||||||
|
|
||||||
|
self.viewLayout.addLayout(Layout)
|
||||||
|
self.viewLayout.setSpacing(3)
|
||||||
|
self.viewLayout.setContentsMargins(3, 0, 3, 3)
|
||||||
|
|
||||||
|
self.card_Mode.comboBox.currentIndexChanged.connect(self.switch_mode)
|
||||||
|
Config.gameid_refreshed.connect(self.refresh_gameid)
|
||||||
|
|
||||||
|
self.switch_mode()
|
||||||
|
|
||||||
|
def switch_mode(self) -> None:
|
||||||
|
"""切换计划模式"""
|
||||||
|
|
||||||
|
for group, name_dict in self.item_dict.items():
|
||||||
|
for name, setting_item in name_dict.items():
|
||||||
|
setting_item.setEnabled(
|
||||||
|
(group == "ALL")
|
||||||
|
== (self.config.get(self.config.Info_Mode) == "ALL")
|
||||||
|
)
|
||||||
|
|
||||||
|
def refresh_gameid(self):
|
||||||
|
|
||||||
|
for group, name_dict in self.item_dict.items():
|
||||||
|
|
||||||
|
for name, setting_item in name_dict.items():
|
||||||
|
|
||||||
|
if name == "GameId_Remain":
|
||||||
|
|
||||||
|
setting_item.reLoadOptions(
|
||||||
|
Config.gameid_dict[group]["value"],
|
||||||
|
[
|
||||||
|
"不使用" if _ == "当前/上次" else _
|
||||||
|
for _ in Config.gameid_dict[group]["text"]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
elif "GameId" in name:
|
||||||
|
|
||||||
|
setting_item.reLoadOptions(
|
||||||
|
Config.gameid_dict[group]["value"],
|
||||||
|
Config.gameid_dict[group]["text"],
|
||||||
|
)
|
||||||
@@ -34,14 +34,12 @@ from PySide6.QtWidgets import (
|
|||||||
)
|
)
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
Action,
|
Action,
|
||||||
Pivot,
|
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
FluentIcon,
|
FluentIcon,
|
||||||
MessageBox,
|
MessageBox,
|
||||||
HeaderCardWidget,
|
HeaderCardWidget,
|
||||||
CommandBar,
|
CommandBar,
|
||||||
)
|
)
|
||||||
from PySide6.QtCore import Qt
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from app.core import QueueConfig, Config, MainInfoBar
|
from app.core import QueueConfig, Config, MainInfoBar
|
||||||
@@ -52,6 +50,7 @@ from .Widget import (
|
|||||||
TimeEditSettingCard,
|
TimeEditSettingCard,
|
||||||
NoOptionComboBoxSettingCard,
|
NoOptionComboBoxSettingCard,
|
||||||
HistoryCard,
|
HistoryCard,
|
||||||
|
PivotArea,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -123,7 +122,7 @@ class QueueManager(QWidget):
|
|||||||
|
|
||||||
name = self.queue_manager.pivot.currentRouteKey()
|
name = self.queue_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("未选择调度队列")
|
logger.warning("未选择调度队列")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
||||||
@@ -137,11 +136,7 @@ class QueueManager(QWidget):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
choice = MessageBox(
|
choice = MessageBox("确认", f"确定要删除 {name} 吗?", self.window())
|
||||||
"确认",
|
|
||||||
f"确定要删除 {name} 吗?",
|
|
||||||
self.window(),
|
|
||||||
)
|
|
||||||
if choice.exec():
|
if choice.exec():
|
||||||
|
|
||||||
self.queue_manager.clear_SettingBox()
|
self.queue_manager.clear_SettingBox()
|
||||||
@@ -165,7 +160,7 @@ class QueueManager(QWidget):
|
|||||||
|
|
||||||
name = self.queue_manager.pivot.currentRouteKey()
|
name = self.queue_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("未选择调度队列")
|
logger.warning("未选择调度队列")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
||||||
@@ -210,7 +205,7 @@ class QueueManager(QWidget):
|
|||||||
|
|
||||||
name = self.queue_manager.pivot.currentRouteKey()
|
name = self.queue_manager.pivot.currentRouteKey()
|
||||||
|
|
||||||
if name == None:
|
if name is None:
|
||||||
logger.warning("未选择调度队列")
|
logger.warning("未选择调度队列")
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
"warning", "未选择调度队列", "请先选择一个调度队列", 5000
|
||||||
@@ -305,15 +300,19 @@ class QueueManager(QWidget):
|
|||||||
|
|
||||||
self.setObjectName("调度队列管理")
|
self.setObjectName("调度队列管理")
|
||||||
|
|
||||||
self.pivot = Pivot(self)
|
self.pivotArea = PivotArea()
|
||||||
|
self.pivot = self.pivotArea.pivot
|
||||||
|
|
||||||
self.stackedWidget = QStackedWidget(self)
|
self.stackedWidget = QStackedWidget(self)
|
||||||
self.Layout = QVBoxLayout(self)
|
self.stackedWidget.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.stackedWidget.setStyleSheet("background: transparent; border: none;")
|
||||||
|
|
||||||
self.script_list: List[
|
self.script_list: List[
|
||||||
QueueManager.QueueSettingBox.QueueMemberSettingBox
|
QueueManager.QueueSettingBox.QueueMemberSettingBox
|
||||||
] = []
|
] = []
|
||||||
|
|
||||||
self.Layout.addWidget(self.pivot, 0, Qt.AlignHCenter)
|
self.Layout = QVBoxLayout(self)
|
||||||
|
self.Layout.addWidget(self.pivotArea)
|
||||||
self.Layout.addWidget(self.stackedWidget)
|
self.Layout.addWidget(self.stackedWidget)
|
||||||
self.Layout.setContentsMargins(0, 0, 0, 0)
|
self.Layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
@@ -376,14 +375,6 @@ class QueueManager(QWidget):
|
|||||||
self.setObjectName(f"调度队列_{uid}")
|
self.setObjectName(f"调度队列_{uid}")
|
||||||
self.config = Config.queue_dict[f"调度队列_{uid}"]["Config"]
|
self.config = Config.queue_dict[f"调度队列_{uid}"]["Config"]
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
|
|
||||||
scrollArea = ScrollArea()
|
|
||||||
scrollArea.setWidgetResizable(True)
|
|
||||||
|
|
||||||
content_widget = QWidget()
|
|
||||||
content_layout = QVBoxLayout(content_widget)
|
|
||||||
|
|
||||||
self.queue_set = self.QueueSetSettingCard(self.config, self)
|
self.queue_set = self.QueueSetSettingCard(self.config, self)
|
||||||
self.time = self.TimeSettingCard(self.config, self)
|
self.time = self.TimeSettingCard(self.config, self)
|
||||||
self.task = self.TaskSettingCard(self.config, self)
|
self.task = self.TaskSettingCard(self.config, self)
|
||||||
@@ -393,18 +384,24 @@ class QueueManager(QWidget):
|
|||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
content_widget = QWidget()
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(0, 0, 11, 0)
|
||||||
content_layout.addWidget(self.queue_set)
|
content_layout.addWidget(self.queue_set)
|
||||||
content_layout.addWidget(self.time)
|
content_layout.addWidget(self.time)
|
||||||
content_layout.addWidget(self.task)
|
content_layout.addWidget(self.task)
|
||||||
content_layout.addWidget(self.history)
|
content_layout.addWidget(self.history)
|
||||||
content_layout.addStretch(1)
|
content_layout.addStretch(1)
|
||||||
|
|
||||||
|
scrollArea = ScrollArea()
|
||||||
|
scrollArea.setWidgetResizable(True)
|
||||||
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
scrollArea.setWidget(content_widget)
|
scrollArea.setWidget(content_widget)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(scrollArea)
|
layout.addWidget(scrollArea)
|
||||||
|
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
class QueueSetSettingCard(HeaderCardWidget):
|
class QueueSetSettingCard(HeaderCardWidget):
|
||||||
|
|
||||||
def __init__(self, config: QueueConfig, parent=None):
|
def __init__(self, config: QueueConfig, parent=None):
|
||||||
|
|||||||
@@ -70,9 +70,6 @@ class Setting(QWidget):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setObjectName("设置")
|
self.setObjectName("设置")
|
||||||
|
|
||||||
content_widget = QWidget()
|
|
||||||
content_layout = QVBoxLayout(content_widget)
|
|
||||||
|
|
||||||
self.function = FunctionSettingCard(self)
|
self.function = FunctionSettingCard(self)
|
||||||
self.start = StartSettingCard(self)
|
self.start = StartSettingCard(self)
|
||||||
self.ui = UiSettingCard(self)
|
self.ui = UiSettingCard(self)
|
||||||
@@ -93,6 +90,9 @@ class Setting(QWidget):
|
|||||||
)
|
)
|
||||||
self.other.card_Notice.clicked.connect(lambda: self.show_notice(if_show=True))
|
self.other.card_Notice.clicked.connect(lambda: self.show_notice(if_show=True))
|
||||||
|
|
||||||
|
content_widget = QWidget()
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(0, 0, 11, 0)
|
||||||
content_layout.addWidget(self.function)
|
content_layout.addWidget(self.function)
|
||||||
content_layout.addWidget(self.start)
|
content_layout.addWidget(self.start)
|
||||||
content_layout.addWidget(self.ui)
|
content_layout.addWidget(self.ui)
|
||||||
@@ -103,10 +103,12 @@ class Setting(QWidget):
|
|||||||
|
|
||||||
scrollArea = ScrollArea()
|
scrollArea = ScrollArea()
|
||||||
scrollArea.setWidgetResizable(True)
|
scrollArea.setWidgetResizable(True)
|
||||||
|
scrollArea.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scrollArea.setStyleSheet("background: transparent; border: none;")
|
||||||
scrollArea.setWidget(content_widget)
|
scrollArea.setWidget(content_widget)
|
||||||
layout = QVBoxLayout()
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(scrollArea)
|
layout.addWidget(scrollArea)
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
def agree_bilibili(self) -> None:
|
def agree_bilibili(self) -> None:
|
||||||
"""授权bilibili游戏隐私政策"""
|
"""授权bilibili游戏隐私政策"""
|
||||||
@@ -250,9 +252,7 @@ class Setting(QWidget):
|
|||||||
choice.exec()
|
choice.exec()
|
||||||
else:
|
else:
|
||||||
choice = MessageBox(
|
choice = MessageBox(
|
||||||
"确认",
|
"确认", "您没有输入管理密钥,是否取消修改管理密钥?", self.window()
|
||||||
"您没有输入管理密钥,是否取消修改管理密钥?",
|
|
||||||
self.window(),
|
|
||||||
)
|
)
|
||||||
if choice.exec():
|
if choice.exec():
|
||||||
break
|
break
|
||||||
@@ -462,6 +462,7 @@ class Setting(QWidget):
|
|||||||
"发现新版本",
|
"发现新版本",
|
||||||
f"{version_text(current_version)} --> {version_text(remote_version)}",
|
f"{version_text(current_version)} --> {version_text(remote_version)}",
|
||||||
3600000,
|
3600000,
|
||||||
|
if_force=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
MainInfoBar.push_info_bar("success", "更新检查", "已是最新版本~", 3000)
|
MainInfoBar.push_info_bar("success", "更新检查", "已是最新版本~", 3000)
|
||||||
@@ -545,7 +546,7 @@ class Setting(QWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
MainInfoBar.push_info_bar(
|
MainInfoBar.push_info_bar(
|
||||||
"info", "有新公告", "请前往设置界面查看公告", 3600000
|
"info", "有新公告", "请前往设置界面查看公告", 3600000, if_force=True
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ if __name__ == "__main__":
|
|||||||
version = json.load(f)
|
version = json.load(f)
|
||||||
|
|
||||||
main_version_numb = list(map(int, version["main_version"].split(".")))
|
main_version_numb = list(map(int, version["main_version"].split(".")))
|
||||||
updater_version_numb = list(map(int, version["updater_version"].split(".")))
|
|
||||||
|
|
||||||
print("Packaging AUTO_MAA main program ...")
|
print("Packaging AUTO_MAA main program ...")
|
||||||
|
|
||||||
@@ -120,7 +119,7 @@ if __name__ == "__main__":
|
|||||||
shutil.make_archive(
|
shutil.make_archive(
|
||||||
base_name=root_path / f"AUTO_MAA_{version_text(main_version_numb)}",
|
base_name=root_path / f"AUTO_MAA_{version_text(main_version_numb)}",
|
||||||
format="zip",
|
format="zip",
|
||||||
root_dir=root_path / "AUTO_MAA",
|
root_dir=root_path / "AUTO_MAA_Setup",
|
||||||
base_dir=".",
|
base_dir=".",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -139,6 +138,6 @@ if __name__ == "__main__":
|
|||||||
all_version_info[key] = value.copy()
|
all_version_info[key] = value.copy()
|
||||||
|
|
||||||
(root_path / "version_info.txt").write_text(
|
(root_path / "version_info.txt").write_text(
|
||||||
f"{version_text(main_version_numb)}\n{version_text(updater_version_numb)}\n<!--{json.dumps(version["version_info"], ensure_ascii=False)}-->\n{version_info_markdown(all_version_info)}",
|
f"{version_text(main_version_numb)}\n\n<!--{json.dumps(version["version_info"], ensure_ascii=False)}-->\n{version_info_markdown(all_version_info)}",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|||||||
2
main.py
2
main.py
@@ -42,7 +42,7 @@ def main():
|
|||||||
from app.ui.main_window import AUTO_MAA
|
from app.ui.main_window import AUTO_MAA
|
||||||
|
|
||||||
window = AUTO_MAA()
|
window = AUTO_MAA()
|
||||||
window.show_ui("显示主窗口")
|
window.show_ui("显示主窗口", if_start=True)
|
||||||
window.start_up_task()
|
window.start_up_task()
|
||||||
sys.exit(application.exec())
|
sys.exit(application.exec())
|
||||||
|
|
||||||
|
|||||||
@@ -58,4 +58,5 @@ G"GUI.UseTray": "True" #显示托盘图标
|
|||||||
G"GUI.MinimizeToTray": "False" #最小化时隐藏至托盘
|
G"GUI.MinimizeToTray": "False" #最小化时隐藏至托盘
|
||||||
"Start.EmulatorPath" #模拟器路径
|
"Start.EmulatorPath" #模拟器路径
|
||||||
"Start.EmulatorAddCommand": "-v 2" #附加命令
|
"Start.EmulatorAddCommand": "-v 2" #附加命令
|
||||||
|
"Start.EmulatorWaitSeconds": "10" #等待模拟器启动时间
|
||||||
G"VersionUpdate.package": "MirrorChyanAppv5.15.6.zip" #更新包标识
|
G"VersionUpdate.package": "MirrorChyanAppv5.15.6.zip" #更新包标识
|
||||||
@@ -1,13 +1,53 @@
|
|||||||
{
|
{
|
||||||
"main_version": "4.3.7.0",
|
"main_version": "4.3.8.0",
|
||||||
"updater_version": "1.0.0.0",
|
|
||||||
"version_info": {
|
"version_info": {
|
||||||
"4.3.7.0": {
|
"4.3.8.0": {
|
||||||
"新增功能": [
|
"新增功能": [
|
||||||
"下载器支持完整mirrorc列表"
|
"吐司通知在主窗口隐藏时不再弹出"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.8.4": {
|
||||||
|
"新增功能": [
|
||||||
|
"支持为每一个用户执行独立通知",
|
||||||
|
"输入文本框适配文本插入操作",
|
||||||
|
"计划表功能上线",
|
||||||
|
"静默控制时长从全任务内缩短至搜索ADB时段内",
|
||||||
|
"UI界面添加自动日常代理任务序列设置项"
|
||||||
|
],
|
||||||
|
"修复bug": [
|
||||||
|
"修复雷电模拟器静默模式无法正常识别模拟器是否隐藏相关问题"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.8.3": {
|
||||||
|
"新增功能": [
|
||||||
|
"用户仪表盘支持直接控制用户状态"
|
||||||
|
],
|
||||||
|
"修复bug": [
|
||||||
|
"修复雷电ADB端口号相关问题"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.8.2": {
|
||||||
|
"新增功能": [
|
||||||
|
"添加ADB端口号宽幅适配能力"
|
||||||
|
],
|
||||||
|
"修复bug": [
|
||||||
|
"日志分析忽略MAA超时提示"
|
||||||
],
|
],
|
||||||
"程序优化": [
|
"程序优化": [
|
||||||
"重构更新逻辑,去除独立更新器"
|
"配置类定义方法优化"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4.3.8.1": {
|
||||||
|
"新增功能": [
|
||||||
|
"自定义基建显示配置名称 #46",
|
||||||
|
"主调度台添加仅一次电源任务"
|
||||||
|
],
|
||||||
|
"修复bug": [
|
||||||
|
"电源相关选项改为所有任务完成后生效",
|
||||||
|
"适配MAAv5.16.3的ADB报错信息更改"
|
||||||
|
],
|
||||||
|
"程序优化": [
|
||||||
|
"UI样式优化,进一步适配win10主题"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user