Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 任务完成后运行指定程序或脚本 支持波提欧 阿格莱雅 #453

Merged
merged 2 commits into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions app/setting_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,13 @@ def __initCard(self):
self.tr('任务完成后'),
self.tr('其中“退出”指退出游戏,“循环”指7×24小时无人值守循环运行程序(仅限完整运行生效)'),
texts={'无': 'None', '退出': 'Exit', '循环': 'Loop',
'关机': 'Shutdown', '睡眠': 'Sleep', '休眠': 'Hibernate', '重启': 'Restart', '注销': 'Logoff'}
'关机': 'Shutdown', '睡眠': 'Sleep', '休眠': 'Hibernate', '重启': 'Restart', '注销': 'Logoff', '运行脚本': 'RunScript'}
)
self.ScriptPathCard = PushSettingCard(
self.tr('修改'),
FIF.CODE,
self.tr("脚本或程序路径(选择运行脚本时生效)"),
cfg.script_path
)
self.loopModeCard = ComboBoxSettingCard2(
"loop_mode",
Expand Down Expand Up @@ -797,6 +803,7 @@ def __initLayout(self):
# self.ProgramGroup.addSettingCard(self.importConfigCard)
self.ProgramGroup.addSettingCard(self.checkUpdateCard)
self.ProgramGroup.addSettingCard(self.afterFinishCard)
self.ProgramGroup.addSettingCard(self.ScriptPathCard)
self.ProgramGroup.addSettingCard(self.loopModeCard)
self.ProgramGroup.addSettingCard(self.scheduledCard)
self.ProgramGroup.addSettingCard(self.playAudioCard)
Expand Down Expand Up @@ -855,7 +862,7 @@ def __initLayout(self):
def __connectSignalToSlot(self):
# self.importConfigCard.clicked.connect(self.__onImportConfigCardClicked)
self.gamePathCard.clicked.connect(self.__onGamePathCardClicked)

self.ScriptPathCard.clicked.connect(self.__onScriptPathCardClicked)
# self.borrowCharacterInfoCard.clicked.connect(self.__openCharacterFolder())

self.testNotifyCard.clicked.connect(lambda: start_task("notify"))
Expand Down Expand Up @@ -919,3 +926,9 @@ def __openUrl(self, url):
# duration=1500,
# parent=self
# )
def __onScriptPathCardClicked(self):
script_path, _ = QFileDialog.getOpenFileName(self, "脚本或程序路径", "", "脚本或可执行文件 (*.ps1 *.bat *.exe)")
if not script_path or cfg.script_path == script_path:
return
cfg.set_value("script_path", script_path)
self.ScriptPathCard.setContent(script_path)
4 changes: 3 additions & 1 deletion assets/config/character_names.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"Asta": "艾丝妲",
"Bailu": "白露",
"Bronya": "布洛妮娅",
"Boothill": "波提欧",
"DanHeng": "丹恒",
"DanHengImbibitorLunae": "丹恒·饮月",
"Jade": "翡翠",
Expand Down Expand Up @@ -65,5 +66,6 @@
"Robin": "知更鸟",
"DrRatio": "真理医生",
"Fugue": "忘归人",
"TheHerta": "大黑塔"
"TheHerta": "大黑塔",
"Aglaea": "阿格莱雅"
}
2 changes: 1 addition & 1 deletion assets/config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pypi_mirror_urls:
game_title_name: 崩坏:星穹铁道 # 游戏窗口标题。
game_process_name: StarRail # 游戏进程名。
game_path: C:\Program Files\Star Rail\Game\StarRail.exe # 游戏安装路径。

script_path: C:\Path\to\your\Script.bat
# 副本设置
instance_type: 拟造花萼(金) # 设置副本类型,可选值:拟造花萼(金)、拟造花萼(赤)、凝滞虚影、侵蚀隧洞、饰品提取。
calyx_golden_preference: Jarilo-VI # 设置拟造花萼(金)偏好地区,可选值:"雅利洛-VI"(Jarilo-VI)、仙舟「罗浮」(XianzhouLuofu)、匹诺康尼(Penacony)。
Expand Down
Binary file added assets/images/share/character/Aglaea.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/share/character/Boothill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions tasks/game/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from module.ocr import ocr


starrail = StarRailController(cfg.game_path, cfg.game_process_name, cfg.game_title_name, 'UnityWndClass', log)
starrail = StarRailController(cfg.game_path, cfg.game_process_name, cfg.game_title_name, 'UnityWndClass', logger=log, script_path=cfg.script_path)


def start():
Expand Down Expand Up @@ -127,7 +127,7 @@ def play_audio():
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide"
import pygame.mixer

# 有用户反馈会报错 “mixer not initialized”
# 有用户反馈会报错 “mixer not initialized”
# 不清楚为什么,可能是远程桌面的情况下缺少音频设备吗
pygame.init()
pygame.mixer.music.load("./assets/audio/pa.mp3")
Expand All @@ -147,10 +147,10 @@ def play_audio():
else:
if detect_loop:
notify_after_finish_not_loop()
if cfg.after_finish in ["Exit", "Loop", "Shutdown", "Sleep", "Hibernate", "Restart", "Logoff"]:
if cfg.after_finish in ["Exit", "Loop", "Shutdown", "Sleep", "Hibernate", "Restart", "Logoff", "RunScript"]:
starrail.shutdown(cfg.after_finish)
log.hr("完成", 2)
if cfg.after_finish not in ["Shutdown", "Sleep", "Hibernate", "Restart", "Logoff"]:
if cfg.after_finish not in ["Shutdown", "Sleep", "Hibernate", "Restart", "Logoff", "RunScript"]:
input("按回车键关闭窗口. . .")
sys.exit(0)

Expand Down
4 changes: 2 additions & 2 deletions tasks/game/starrailcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@


class StarRailController(GameController):
def __init__(self, game_path: str, process_name: str, window_name: str, window_class: Optional[str], logger: Optional[Logger] = None) -> None:
super().__init__(game_path, process_name, window_name, window_class, logger)
def __init__(self, game_path: str, process_name: str, window_name: str, window_class: Optional[str], script_path: Optional[str] = None, logger: Optional[Logger] = None) -> None:
super().__init__(game_path, process_name, window_name, window_class, script_path=script_path, logger=logger)
self.game_resolution = None
self.game_auto_hdr = None
self.screen_resolution = pyautogui.size()
Expand Down
53 changes: 50 additions & 3 deletions utils/gamecontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@


class GameController:
def __init__(self, game_path: str, process_name: str, window_name: str, window_class: Optional[str], logger: Optional[Logger] = None) -> None:
def __init__(self, game_path: str, process_name: str, window_name: str, window_class: Optional[str], script_path: Optional[str] = None, logger: Optional[Logger] = None) -> None:
self.game_path = os.path.normpath(game_path)
self.process_name = process_name
self.window_name = window_name
self.window_class = window_class
self.script_path = os.path.normpath(script_path) if script_path and isinstance(script_path, (str, bytes, os.PathLike)) else None
self.logger = logger

def log_debug(self, message: str) -> None:
Expand Down Expand Up @@ -136,7 +137,7 @@ def get_resolution(self) -> Optional[Tuple[int, int]]:
self.log_debug("游戏窗口未找到")
return None

def shutdown(self, action: Literal['Exit', 'Loop', 'Shutdown', 'Sleep', 'Hibernate', 'Restart', 'Logoff'], delay: int = 60) -> bool:
def shutdown(self, action: Literal['Exit', 'Loop', 'Shutdown', 'Sleep', 'Hibernate', 'Restart', 'Logoff', 'RunScript'], delay: int = 60) -> bool:
"""
终止游戏并在指定的延迟后执行系统操作:关机、睡眠、休眠、重启、注销。

Expand All @@ -148,7 +149,7 @@ def shutdown(self, action: Literal['Exit', 'Loop', 'Shutdown', 'Sleep', 'Hiberna
操作成功执行返回True,否则返回False。
"""
self.stop_game()
if action not in ["Shutdown", "Sleep", "Hibernate", "Restart", "Logoff"]:
if action not in ["Shutdown", "Sleep", "Hibernate", "Restart", "Logoff", "RunScript"]:
return True

self.log_warning(f"将在{delay}秒后开始执行系统操作:{action}")
Expand All @@ -168,8 +169,54 @@ def shutdown(self, action: Literal['Exit', 'Loop', 'Shutdown', 'Sleep', 'Hiberna
os.system("shutdown /r")
elif action == 'Logoff':
os.system("shutdown /l")
elif action == 'RunScript':
self.run_script()
self.log_info(f"执行系统操作:{action}")
return True
except Exception as e:
self.log_error(f"执行系统操作时发生错误:{action}, 错误:{e}")
return False

def run_script(self):
"""运行指定的程序或脚本(支持.exe、.ps1和.bat)"""
if not self.script_path or not isinstance(self.script_path, str) or not os.path.exists(
self.script_path):
self.log_warning(f"指定的路径无效或不存在:{self.script_path}")
return False

try:
# 获取脚本所在目录
script_dir = os.path.dirname(os.path.abspath(self.script_path))
# 保存当前工作目录
original_cwd = os.getcwd()

try:
# 切换到脚本所在目录
os.chdir(script_dir)

file_ext = os.path.splitext(self.script_path)[1].lower()
if file_ext == '.ps1':
# PowerShell脚本
subprocess.Popen(["powershell", "-ExecutionPolicy", "Bypass", "-File", self.script_path],
creationflags=subprocess.CREATE_NEW_CONSOLE)
self.log_info(f"已启动PowerShell脚本:{self.script_path}")
elif file_ext == '.bat':
# Batch脚本
subprocess.Popen([self.script_path], shell=True,
creationflags=subprocess.CREATE_NEW_CONSOLE)
self.log_info(f"已启动Batch脚本:{self.script_path}")
elif file_ext == '.exe':
# 可执行文件
subprocess.Popen([self.script_path],
creationflags=subprocess.CREATE_NEW_CONSOLE)
self.log_info(f"已启动可执行文件:{self.script_path}")
else:
self.log_warning(f"不支持的文件类型:{file_ext}")
return False
return True
finally:
# 恢复原始工作目录
os.chdir(original_cwd)
except Exception as e:
self.log_error(f"启动脚本时发生错误:{str(e)}")
return False