feat(core): 初步完成通用调度模块

This commit is contained in:
DLmaster361
2025-07-10 02:29:08 +08:00
parent 7c315624b1
commit 1c0a65957d
22 changed files with 3280 additions and 408 deletions

View File

@@ -29,7 +29,15 @@ __version__ = "4.2.0"
__author__ = "DLmaster361 <DLmaster_361@163.com>"
__license__ = "GPL-3.0 license"
from .config import QueueConfig, MaaConfig, MaaUserConfig, MaaPlanConfig, Config
from .config import (
QueueConfig,
MaaConfig,
MaaUserConfig,
MaaPlanConfig,
GeneralConfig,
GeneralSubConfig,
Config,
)
from .main_info_bar import MainInfoBar
from .network import Network
from .sound_player import SoundPlayer
@@ -42,6 +50,8 @@ __all__ = [
"MaaConfig",
"MaaUserConfig",
"MaaPlanConfig",
"GeneralConfig",
"GeneralSubConfig",
"MainInfoBar",
"Network",
"SoundPlayer",

View File

@@ -56,6 +56,17 @@ from typing import Union, Dict, List
from .network import Network
class FileValidator(ConfigValidator):
"""File validator"""
def validate(self, value):
return Path(value).exists()
def correct(self, value):
path = Path(value)
return str(path.absolute()).replace("\\", "/")
class UrlListValidator(ConfigValidator):
"""Url list validator"""
@@ -382,6 +393,9 @@ class MaaConfig(LQConfig):
"RunSet", "AutoUpdateMaa", False, BoolValidator()
)
def get_name(self) -> str:
return self.get(self.MaaSet_Name)
class MaaUserConfig(LQConfig):
"""MAA用户配置"""
@@ -574,13 +588,118 @@ class MaaPlanConfig(LQConfig):
return self.config_item_dict["ALL"][name]
class GeneralConfig(LQConfig):
"""通用配置"""
def __init__(self) -> None:
super().__init__()
self.Script_Name = ConfigItem("Script", "Name", "")
self.Script_RootPath = ConfigItem("Script", "RootPath", ".", FolderValidator())
self.Script_ScriptPath = ConfigItem(
"Script", "ScriptPath", ".", FileValidator()
)
self.Script_Arguments = ConfigItem("Script", "Arguments", "")
self.Script_ConfigPath = ConfigItem(
"Script", "ConfigPath", ".", FolderValidator()
)
self.Script_LogPath = ConfigItem("Script", "LogPath", ".", FileValidator())
self.Script_LogTimeStart = ConfigItem(
"Script", "LogTimeStart", 0, RangeValidator(0, 1024)
)
self.Script_LogTimeEnd = ConfigItem(
"Script", "LogTimeEnd", 0, RangeValidator(0, 1024)
)
self.Script_LogTimeFormat = ConfigItem(
"Script", "LogTimeFormat", "%Y-%m-%d %H:%M:%S"
)
self.Script_SuccessLog = ConfigItem("Script", "SuccessLog", "")
self.Script_ErrorLog = ConfigItem("Script", "ErrorLog", "")
self.Game_Enabled = ConfigItem("Game", "Enabled", True, BoolValidator())
self.Game_Style = OptionsConfigItem(
"Game", "Style", "Emulator", OptionsValidator(["Emulator", "Client"])
)
self.Game_Path = ConfigItem("Game", "Path", ".", FileValidator())
self.Game_Arguments = ConfigItem("Game", "Arguments", "")
self.Game_WaitTime = ConfigItem("Game", "WaitTime", 0, RangeValidator(0, 1024))
self.Game_IfForceClose = ConfigItem(
"Game", "IfForceClose", False, BoolValidator()
)
self.Run_ProxyTimesLimit = RangeConfigItem(
"Run", "ProxyTimesLimit", 0, RangeValidator(0, 1024)
)
self.Run_RunTimesLimit = RangeConfigItem(
"Run", "RunTimesLimit", 3, RangeValidator(1, 1024)
)
self.Run_RunTimeLimit = RangeConfigItem(
"Run", "RunTimeLimit", 10, RangeValidator(1, 1024)
)
def get_name(self) -> str:
return self.get(self.Script_Name)
class GeneralSubConfig(LQConfig):
"""通用子配置"""
def __init__(self) -> None:
super().__init__()
self.Info_Name = ConfigItem("Info", "Name", "新配置")
self.Info_Status = ConfigItem("Info", "Status", True, BoolValidator())
self.Info_RemainedDay = ConfigItem(
"Info", "RemainedDay", -1, RangeValidator(-1, 1024)
)
self.Info_IfScriptBeforeTask = ConfigItem(
"Info", "IfScriptBeforeTask", False, BoolValidator()
)
self.Info_ScriptBeforeTask = ConfigItem(
"Info", "ScriptBeforeTask", "", FileValidator()
)
self.Info_IfScriptAfterTask = ConfigItem(
"Info", "IfScriptAfterTask", False, BoolValidator()
)
self.Info_ScriptAfterTask = ConfigItem(
"Info", "ScriptAfterTask", "", FileValidator()
)
self.Info_Notes = ConfigItem("Info", "Notes", "")
self.Data_LastProxyDate = ConfigItem("Data", "LastProxyDate", "2000-01-01")
self.Data_ProxyTimes = ConfigItem(
"Data", "ProxyTimes", 0, RangeValidator(0, 1024)
)
self.Notify_Enabled = ConfigItem("Notify", "Enabled", False, BoolValidator())
self.Notify_IfSendStatistic = ConfigItem(
"Notify", "IfSendStatistic", 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", ""
)
class AppConfig(GlobalConfig):
VERSION = "4.3.12.0"
VERSION = "4.4.0.1"
gameid_refreshed = Signal()
PASSWORD_refreshed = Signal()
user_info_changed = Signal()
sub_info_changed = Signal()
power_sign_changed = Signal()
def __init__(self) -> None:
@@ -777,7 +896,7 @@ class AppConfig(GlobalConfig):
db = sqlite3.connect(self.database_path)
cur = db.cursor()
cur.execute("CREATE TABLE version(v text)")
cur.execute("INSERT INTO version VALUES(?)", ("v1.5",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.6",))
db.commit()
cur.close()
db.close()
@@ -788,221 +907,9 @@ class AppConfig(GlobalConfig):
cur.execute("SELECT * FROM version WHERE True")
version = cur.fetchall()
if version[0][0] != "v1.5":
if version[0][0] != "v1.6":
logger.info("数据文件版本更新开始")
if_streaming = False
# v1.0-->v1.1
if version[0][0] == "v1.0" or if_streaming:
logger.info("数据文件版本更新v1.0-->v1.1")
if_streaming = True
cur.execute("SELECT * FROM adminx WHERE True")
data = cur.fetchall()
cur.execute("DROP TABLE IF EXISTS adminx")
cur.execute(
"CREATE TABLE adminx(admin text,id text,server text,day int,status text,last date,game text,game_1 text,game_2 text,routines text,annihilation text,infrastructure text,password byte,notes text,numb int,mode text,uid int)"
)
for i in range(len(data)):
cur.execute(
"INSERT INTO adminx VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
data[i][0], # 0 0 0
data[i][1], # 1 1 -
"Official", # 2 2 -
data[i][2], # 3 3 1
data[i][3], # 4 4 2
data[i][4], # 5 5 3
data[i][5], # 6 6 -
data[i][6], # 7 7 -
data[i][7], # 8 8 -
"y", # 9 - 4
data[i][8], # 10 9 5
data[i][9], # 11 10 -
data[i][10], # 12 11 6
data[i][11], # 13 12 7
data[i][12], # 14 - -
"simple", # 15 - -
data[i][13], # 16 - -
),
)
cur.execute("DELETE FROM version WHERE v = ?", ("v1.0",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.1",))
db.commit()
# v1.1-->v1.2
if version[0][0] == "v1.1" or if_streaming:
logger.info("数据文件版本更新v1.1-->v1.2")
if_streaming = True
cur.execute("SELECT * FROM adminx WHERE True")
data = cur.fetchall()
for i in range(len(data)):
cur.execute(
"UPDATE adminx SET infrastructure = 'n' WHERE mode = ? AND uid = ?",
(
data[i][15],
data[i][16],
),
)
cur.execute("DELETE FROM version WHERE v = ?", ("v1.1",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.2",))
db.commit()
# v1.2-->v1.3
if version[0][0] == "v1.2" or if_streaming:
logger.info("数据文件版本更新v1.2-->v1.3")
if_streaming = True
cur.execute("ALTER TABLE adminx RENAME COLUMN routines TO routine")
cur.execute("DELETE FROM version WHERE v = ?", ("v1.2",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.3",))
db.commit()
# v1.3-->v1.4
if version[0][0] == "v1.3" or if_streaming:
logger.info("数据文件版本更新v1.3-->v1.4")
if_streaming = True
(self.app_path / "config/MaaConfig").mkdir(parents=True, exist_ok=True)
shutil.move(
self.app_path / "data/MaaConfig",
self.app_path / "config/MaaConfig",
)
(self.app_path / "config/MaaConfig/MaaConfig").rename(
self.app_path / "config/MaaConfig/脚本_1"
)
shutil.copy(
self.database_path,
self.app_path / "config/MaaConfig/脚本_1/user_data.db",
)
cur.execute("DROP TABLE IF EXISTS adminx")
cur.execute("DELETE FROM version WHERE v = ?", ("v1.3",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.4",))
db.commit()
with (self.app_path / "config/gui.json").open(
"r", encoding="utf-8"
) as f:
info = json.load(f)
maa_config = {
"MaaSet": {
"Name": "",
"Path": info["Default"]["MaaSet.path"],
},
"RunSet": {
"AnnihilationTimeLimit": info["Default"][
"TimeLimit.annihilation"
],
"RoutineTimeLimit": info["Default"]["TimeLimit.routine"],
"RunTimesLimit": info["Default"]["TimesLimit.run"],
},
}
with (self.app_path / "config/MaaConfig/脚本_1/config.json").open(
"w", encoding="utf-8"
) as f:
json.dump(maa_config, f, ensure_ascii=False, indent=4)
config = {
"Function": {
"BossKey": info["Default"]["SelfSet.BossKey"],
"IfAllowSleep": bool(
info["Default"]["SelfSet.IfSleep"] == "True"
),
"IfSilence": bool(
info["Default"]["SelfSet.IfSilence"] == "True"
),
},
"Notify": {
"IfPushPlyer": True,
"IfSendErrorOnly": bool(
info["Default"]["SelfSet.IfSendMail.OnlyError"] == "True"
),
"IfSendMail": bool(
info["Default"]["SelfSet.IfSendMail"] == "True"
),
"MailAddress": info["Default"]["SelfSet.MailAddress"],
},
"Start": {
"IfRunDirectly": bool(
info["Default"]["SelfSet.IfProxyDirectly"] == "True"
),
"IfSelfStart": bool(
info["Default"]["SelfSet.IfSelfStart"] == "True"
),
},
"UI": {
"IfShowTray": bool(
info["Default"]["SelfSet.IfToTray"] == "True"
),
"IfToTray": bool(info["Default"]["SelfSet.IfToTray"] == "True"),
"location": info["Default"]["SelfSet.UIlocation"],
"maximized": bool(
info["Default"]["SelfSet.UImaximized"] == "True"
),
"size": info["Default"]["SelfSet.UIsize"],
},
"Update": {"IfAutoUpdate": False},
}
with (self.app_path / "config/config.json").open(
"w", encoding="utf-8"
) as f:
json.dump(config, f, ensure_ascii=False, indent=4)
queue_config = {
"QueueSet": {"Enabled": True, "Name": ""},
"Queue": {
"Member_1": "脚本_1",
"Member_10": "禁用",
"Member_2": "禁用",
"Member_3": "禁用",
"Member_4": "禁用",
"Member_5": "禁用",
"Member_6": "禁用",
"Member_7": "禁用",
"Member_8": "禁用",
"Member_9": "禁用",
},
"Time": {
"TimeEnabled_0": bool(
info["Default"]["TimeSet.set1"] == "True"
),
"TimeEnabled_1": bool(
info["Default"]["TimeSet.set2"] == "True"
),
"TimeEnabled_2": bool(
info["Default"]["TimeSet.set3"] == "True"
),
"TimeEnabled_3": bool(
info["Default"]["TimeSet.set4"] == "True"
),
"TimeEnabled_4": bool(
info["Default"]["TimeSet.set5"] == "True"
),
"TimeEnabled_5": bool(
info["Default"]["TimeSet.set6"] == "True"
),
"TimeEnabled_6": bool(
info["Default"]["TimeSet.set7"] == "True"
),
"TimeEnabled_7": bool(
info["Default"]["TimeSet.set8"] == "True"
),
"TimeEnabled_8": bool(
info["Default"]["TimeSet.set9"] == "True"
),
"TimeEnabled_9": bool(
info["Default"]["TimeSet.set10"] == "True"
),
"TimeSet_0": info["Default"]["TimeSet.run1"],
"TimeSet_1": info["Default"]["TimeSet.run2"],
"TimeSet_2": info["Default"]["TimeSet.run3"],
"TimeSet_3": info["Default"]["TimeSet.run4"],
"TimeSet_4": info["Default"]["TimeSet.run5"],
"TimeSet_5": info["Default"]["TimeSet.run6"],
"TimeSet_6": info["Default"]["TimeSet.run7"],
"TimeSet_7": info["Default"]["TimeSet.run8"],
"TimeSet_8": info["Default"]["TimeSet.run9"],
"TimeSet_9": info["Default"]["TimeSet.run10"],
},
}
(self.app_path / "config/QueueConfig").mkdir(
parents=True, exist_ok=True
)
with (self.app_path / "config/QueueConfig/调度队列_1.json").open(
"w", encoding="utf-8"
) as f:
json.dump(queue_config, f, ensure_ascii=False, indent=4)
(self.app_path / "config/gui.json").unlink()
# v1.4-->v1.5
if version[0][0] == "v1.4" or if_streaming:
logger.info("数据文件版本更新v1.4-->v1.5")
@@ -1130,7 +1037,38 @@ class AppConfig(GlobalConfig):
shutil.rmtree(config["Path"] / f"simple")
if (config["Path"] / f"beta").exists():
shutil.rmtree(config["Path"] / f"beta")
# v1.5-->v1.6
if version[0][0] == "v1.5" or if_streaming:
logger.info("数据文件版本更新v1.5-->v1.6")
if_streaming = True
cur.execute("DELETE FROM version WHERE v = ?", ("v1.5",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.6",))
db.commit()
# 删除旧的注册表项
import winreg
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
0,
winreg.KEY_READ,
)
try:
value, _ = winreg.QueryValueEx(key, "AUTO_MAA")
winreg.CloseKey(key)
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
winreg.KEY_SET_VALUE,
winreg.KEY_ALL_ACCESS
| winreg.KEY_WRITE
| winreg.KEY_CREATE_SUB_KEY,
)
winreg.DeleteValue(key, "AUTO_MAA")
winreg.CloseKey(key)
except FileNotFoundError:
pass
cur.close()
db.close()
logger.info("数据文件版本更新完成")
@@ -1145,8 +1083,8 @@ class AppConfig(GlobalConfig):
Union[
str,
Path,
MaaConfig,
Dict[str, Dict[str, Union[Path, MaaUserConfig]]],
Union[MaaConfig, GeneralConfig],
Dict[str, Dict[str, Union[Path, MaaUserConfig, GeneralSubConfig]]],
],
],
] = {}
@@ -1164,12 +1102,26 @@ class AppConfig(GlobalConfig):
"Config": maa_config,
"UserData": None,
}
if (self.app_path / "config/GeneralConfig").exists():
for general_dir in (self.app_path / "config/GeneralConfig").iterdir():
if general_dir.is_dir():
general_config = GeneralConfig()
general_config.load(general_dir / "config.json", general_config)
general_config.save()
self.member_dict[general_dir.name] = {
"Type": "General",
"Path": general_dir,
"Config": general_config,
"SubData": None,
}
self.member_dict = dict(
sorted(self.member_dict.items(), key=lambda x: int(x[0][3:]))
)
def search_maa_user(self, name) -> None:
def search_maa_user(self, name: str) -> None:
user_dict: Dict[str, Dict[str, Union[Path, MaaUserConfig]]] = {}
for user_dir in (Config.member_dict[name]["Path"] / "UserData").iterdir():
@@ -1179,15 +1131,28 @@ class AppConfig(GlobalConfig):
user_config.load(user_dir / "config.json", user_config)
user_config.save()
user_dict[user_dir.stem] = {
"Path": user_dir,
"Config": user_config,
}
user_dict[user_dir.stem] = {"Path": user_dir, "Config": user_config}
self.member_dict[name]["UserData"] = dict(
sorted(user_dict.items(), key=lambda x: int(x[0][3:]))
)
def search_general_sub(self, name: str) -> None:
user_dict: Dict[str, Dict[str, Union[Path, GeneralSubConfig]]] = {}
for sub_dir in (Config.member_dict[name]["Path"] / "SubData").iterdir():
if sub_dir.is_dir():
sub_config = GeneralSubConfig()
sub_config.load(sub_dir / "config.json", sub_config)
sub_config.save()
user_dict[sub_dir.stem] = {"Path": sub_dir, "Config": sub_config}
self.member_dict[name]["SubData"] = dict(
sorted(user_dict.items(), key=lambda x: int(x[0][3:]))
)
def search_plan(self) -> None:
"""搜索所有计划表"""
@@ -1267,7 +1232,7 @@ class AppConfig(GlobalConfig):
if user["Config"].get(user["Config"].Info_GameIdMode) == old:
user["Config"].set(user["Config"].Info_GameIdMode, new)
def change_user_info(
def change_maa_user_info(
self, name: str, user_data: Dict[str, Dict[str, Union[str, Path, dict]]]
) -> None:
"""代理完成后保存改动的用户信息"""
@@ -1301,7 +1266,28 @@ class AppConfig(GlobalConfig):
info["Config"]["Data"]["CustomInfrastPlanIndex"],
)
self.user_info_changed.emit()
self.sub_info_changed.emit()
def change_general_sub_info(
self, name: str, sub_data: Dict[str, Dict[str, Union[str, Path, dict]]]
) -> None:
"""代理完成后保存改动的配置信息"""
for sub, info in sub_data.items():
sub_config = self.member_dict[name]["SubData"][sub]["Config"]
sub_config.set(
sub_config.Info_RemainedDay, info["Config"]["Info"]["RemainedDay"]
)
sub_config.set(
sub_config.Data_LastProxyDate, info["Config"]["Data"]["LastProxyDate"]
)
sub_config.set(
sub_config.Data_ProxyTimes, info["Config"]["Data"]["ProxyTimes"]
)
self.sub_info_changed.emit()
def set_power_sign(self, sign: str) -> None:
"""设置当前电源状态"""

View File

@@ -36,7 +36,7 @@ from .config import Config
from .main_info_bar import MainInfoBar
from .network import Network
from .sound_player import SoundPlayer
from app.models import MaaManager
from app.models import MaaManager, GeneralManager
from app.services import System
@@ -48,7 +48,8 @@ class Task(QThread):
play_sound = Signal(str)
question = Signal(str, str)
question_response = Signal(bool)
update_user_info = Signal(str, dict)
update_maa_user_info = Signal(str, dict)
update_general_sub_info = Signal(str, dict)
create_task_list = Signal(list)
create_user_list = Signal(list)
update_task_list = Signal(list)
@@ -89,7 +90,31 @@ class Task(QThread):
self.task.play_sound.connect(self.play_sound.emit)
self.task.accomplish.connect(lambda: self.accomplish.emit([]))
self.task.run()
try:
self.task.run()
except Exception as e:
logger.exception(f"任务异常:{self.name},错误信息:{e}")
self.push_info_bar.emit("error", "任务异常", self.name, -1)
elif self.mode == "设置通用脚本":
logger.info(f"任务开始:设置{self.name}")
self.push_info_bar.emit("info", "设置通用脚本", self.name, 3000)
self.task = GeneralManager(
self.mode,
Config.member_dict[self.name],
self.info["SetSubInfo"]["Path"],
)
self.task.push_info_bar.connect(self.push_info_bar.emit)
self.task.play_sound.connect(self.play_sound.emit)
self.task.accomplish.connect(lambda: self.accomplish.emit([]))
try:
self.task.run()
except Exception as e:
logger.exception(f"任务异常:{self.name},错误信息:{e}")
self.push_info_bar.emit("error", "任务异常", self.name, -1)
else:
@@ -97,11 +122,8 @@ class Task(QThread):
[
(
value
if Config.member_dict[value]["Config"].get(
Config.member_dict[value]["Config"].MaaSet_Name
)
== ""
else f"{value} - {Config.member_dict[value]["Config"].get(Config.member_dict[value]["Config"].MaaSet_Name)}"
if Config.member_dict[value]["Config"].get_name() == ""
else f"{value} - {Config.member_dict[value]["Config"].get_name()}"
),
"等待",
value,
@@ -150,24 +172,60 @@ class Task(QThread):
self.task.create_user_list.connect(self.create_user_list.emit)
self.task.update_user_list.connect(self.update_user_list.emit)
self.task.update_log_text.connect(self.update_log_text.emit)
self.task.update_user_info.connect(self.update_user_info.emit)
self.task.update_user_info.connect(self.update_maa_user_info.emit)
self.task.accomplish.connect(
lambda log: self.task_accomplish(task[2], log)
)
elif Config.member_dict[task[2]]["Type"] == "General":
self.task = GeneralManager(
self.mode[0:4],
Config.member_dict[task[2]],
)
self.task.question.connect(self.question.emit)
self.question_response.disconnect()
self.question_response.connect(self.task.question_response.emit)
self.task.push_info_bar.connect(self.push_info_bar.emit)
self.task.play_sound.connect(self.play_sound.emit)
self.task.create_user_list.connect(self.create_user_list.emit)
self.task.update_user_list.connect(self.update_user_list.emit)
self.task.update_log_text.connect(self.update_log_text.emit)
self.task.update_sub_info.connect(self.update_general_sub_info.emit)
self.task.accomplish.connect(
lambda log: self.task_accomplish(task[2], log)
)
try:
self.task.run()
Config.running_list.remove(task[2])
task[1] = "完成"
self.update_task_list.emit(self.task_list)
logger.info(f"任务完成:{task[0]}")
self.push_info_bar.emit("info", "任务完成", task[0], 3000)
task[1] = "完成"
self.update_task_list.emit(self.task_list)
logger.info(f"任务完成:{task[0]}")
self.push_info_bar.emit("info", "任务完成", task[0], 3000)
except Exception as e:
self.task_accomplish(
task[2],
{
"Time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"History": f"任务异常,异常简报:{e}",
},
)
task[1] = "异常"
self.update_task_list.emit(self.task_list)
logger.exception(f"任务异常:{task[0]},错误信息:{e}")
self.push_info_bar.emit("error", "任务异常", task[0], -1)
Config.running_list.remove(task[2])
self.accomplish.emit(self.logs)
def task_accomplish(self, name: str, log: dict):
"""保存保存任务结果"""
"""保存任务结果"""
self.logs.append([name, log])
self.task.deleteLater()
@@ -207,7 +265,10 @@ class _TaskManager(QObject):
)
self.task_dict[name].push_info_bar.connect(MainInfoBar.push_info_bar)
self.task_dict[name].play_sound.connect(SoundPlayer.play)
self.task_dict[name].update_user_info.connect(Config.change_user_info)
self.task_dict[name].update_maa_user_info.connect(Config.change_maa_user_info)
self.task_dict[name].update_general_sub_info.connect(
Config.change_general_sub_info
)
self.task_dict[name].accomplish.connect(
lambda logs: self.remove_task(mode, name, logs)
)