Skip to content
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
8 changes: 8 additions & 0 deletions app/setting_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,13 @@ def __initCard(self):
tr("最大排队等待时间(分钟)"),
''
)
self.cloudGameLoginTimeoutCard = RangeSettingCard1(
"cloud_game_login_timeout",
[1, 120],
FIF.DATE_TIME,
tr("登录超时时间(分钟)"),
tr("等待用户完成登录的最长时间,超时后将终止运行")
)
# self.cloudGameVideoQualityCard = ComboBoxSettingCard2(
# "cloud_game_video_quality",
# FIF.VIDEO,
Expand Down Expand Up @@ -2616,6 +2623,7 @@ def __initLayout(self):
self.CloudGameGroup.addSettingCard(self.browserHeadlessCard)
self.browserHeadlessCard.addSettingCards([self.browserHeadlessRestartCard])
self.CloudGameGroup.addSettingCard(self.cloudGameMaxQueueTimeCard)
self.CloudGameGroup.addSettingCard(self.cloudGameLoginTimeoutCard)
# self.CloudGameGroup.addSettingCard(self.cloudGameVideoQualityCard)
# self.CloudGameGroup.addSettingCard(self.cloudGameSmoothFirstCard)
# self.CloudGameGroup.addSettingCard(self.cloudGameShowStatusCard)
Expand Down
1 change: 1 addition & 0 deletions assets/config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ cloud_game_enable: False # 是否启动云游戏
cloud_game_fullscreen_enable: True # 云崩铁是否全屏运行
cloud_game_use_paid_time: False # 是否使用付费时长
cloud_game_max_queue_time: 60 # 最大排队等待时间(分钟)
cloud_game_login_timeout: 20 # 等待登录的超时时间(分钟),超时后终止运行
# cloud_game_video_quality: '0' # 云崩铁画质 '0'(超高清),'1'(高清), '2'(标清), '3'(低清)
# cloud_game_smooth_first_enable: False # 是否流畅优先
# cloud_game_status_bar_enable: False # 是否显示网速
Expand Down
4 changes: 3 additions & 1 deletion assets/locales/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
"打开后可在使用云游戏时使用付费时长免除排队": "Enable to use paid time for cloud gaming to skip queue",
"当前账号付费时间不足,已切换为免费时间。": "Insufficient paid time on current account, switched to free time.",
"最大排队等待时间(分钟)": "Max Queue Wait Time (Minutes)",
"登录超时时间(分钟)": "Login Timeout (Minutes)",
"等待用户完成登录的最长时间,超时后将终止运行": "Maximum time to wait for login. The run will stop after timeout.",
"浏览器类型": "Browser Type",
"建议保持默认的“集成(Chrome For Testing)”效果最好": "Recommended to keep default 'Integrated (Chrome For Testing)'",
"集成(Chrome For Testing)": "Integrated (Chrome For Testing)",
Expand Down Expand Up @@ -1483,4 +1485,4 @@
"界面可切换性测试": "Screen Switchability Test",
"测试": "Test",
"以最短路径遍历所有可达界面,验证界面切换是否正常": "Traverse all reachable screens via the shortest path to verify screen switching works correctly"
}
}
4 changes: 3 additions & 1 deletion assets/locales/ja_JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
"打开后可在使用云游戏时使用付费时长免除排队": "有効にすると、クラウドゲーム使用時に有料時間を使って待機時間を免除できます。",
"当前账号付费时间不足,已切换为免费时间。": "現在のアカウントの有料時間が不足しているため、無料時間に切り替えました。",
"最大排队等待时间(分钟)": "最大待機時間(分)",
"登录超时时间(分钟)": "ログインタイムアウト(分)",
"等待用户完成登录的最长时间,超时后将终止运行": "ユーザーのログイン完了を待つ最大時間です。タイムアウト後は実行を終了します。",
"浏览器类型": "ブラウザー種類",
"建议保持默认的“集成(Chrome For Testing)”效果最好": "通常はデフォルトの「統合(Chrome For Testing)」推奨です。",
"集成(Chrome For Testing)": "統合(Chrome For Testing)",
Expand Down Expand Up @@ -1483,4 +1485,4 @@
"界面可切换性测试": "画面切替テスト",
"测试": "テスト",
"以最短路径遍历所有可达界面,验证界面切换是否正常": "最短経路で到達可能なすべての画面を巡回し、画面切替が正常に動作するか検証します"
}
}
2 changes: 2 additions & 0 deletions assets/locales/ko_KR.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
"打开后可在使用云游戏时使用付费时长免除排队": "켜면 클라우드 게임 사용 시 유료 시간을 사용하여 대기열을 건너뛸 수 있습니다",
"当前账号付费时间不足,已切换为免费时间。": "현재 계정의 유료 시간이 부족하여 무료 시간으로 전환되었습니다。",
"最大排队等待时间(分钟)": "최대 대기열 대기 시간 (분)",
"登录超时时间(分钟)": "로그인 타임아웃 (분)",
"等待用户完成登录的最长时间,超时后将终止运行": "사용자가 로그인을 완료할 때까지 기다리는 최대 시간입니다. 타임아웃 후 실행을 종료합니다.",
"浏览器类型": "브라우저 유형",
"建议保持默认的“集成(Chrome For Testing)”效果最好": "기본값 '통합 (Chrome For Testing)' 사용 권장",
"集成(Chrome For Testing)": "통합 (Chrome For Testing)",
Expand Down
4 changes: 3 additions & 1 deletion assets/locales/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
"打开后可在使用云游戏时使用付费时长免除排队": "打开后可在使用云游戏时使用付费时长免除排队",
"当前账号付费时间不足,已切换为免费时间。": "当前账号付费时间不足,已切换为免费时间。",
"最大排队等待时间(分钟)": "最大排队等待时间(分钟)",
"登录超时时间(分钟)": "登录超时时间(分钟)",
"等待用户完成登录的最长时间,超时后将终止运行": "等待用户完成登录的最长时间,超时后将终止运行",
"浏览器类型": "浏览器类型",
"建议保持默认的“集成(Chrome For Testing)”效果最好": "建议保持默认的“集成(Chrome For Testing)”效果最好",
"集成(Chrome For Testing)": "集成(Chrome For Testing)",
Expand Down Expand Up @@ -1483,4 +1485,4 @@
"界面可切换性测试": "界面可切换性测试",
"测试": "测试",
"以最短路径遍历所有可达界面,验证界面切换是否正常": "以最短路径遍历所有可达界面,验证界面切换是否正常"
}
}
4 changes: 3 additions & 1 deletion assets/locales/zh_TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
"打开后可在使用云游戏时使用付费时长免除排队": "打開後可在使用雲遊戲時使用付費時長免除排隊",
"当前账号付费时间不足,已切换为免费时间。": "當前帳號付費時間不足,已切換為免費時間。",
"最大排队等待时间(分钟)": "最大排隊等待時間(分鐘)",
"登录超时时间(分钟)": "登入逾時時間(分鐘)",
"等待用户完成登录的最长时间,超时后将终止运行": "等待使用者完成登入的最長時間,逾時後將終止執行",
"浏览器类型": "瀏覽器類型",
"建议保持默认的“集成(Chrome For Testing)”效果最好": "建議保持預設的「整合(Chrome For Testing)」效果最好",
"集成(Chrome For Testing)": "整合(Chrome For Testing)",
Expand Down Expand Up @@ -1483,4 +1485,4 @@
"界面可切换性测试": "界面可切換性測試",
"测试": "測試",
"以最短路径遍历所有可达界面,验证界面切换是否正常": "以最短路徑遍歷所有可達界面,驗證界面切換是否正常"
}
}
44 changes: 38 additions & 6 deletions module/game/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
from utils.console import is_docker_started


class CloudGameLoginTimeoutError(RuntimeError):
"""云游戏登录等待超时,不应按启动失败重试。"""


class CloudGameController(GameControllerBase):
COOKIE_PATH = "settings/cookies.enc" # Cookies 保存地址(仅用于调试)
GAME_URL = "https://sr.mihoyo.com/cloud" # 游戏地址
Expand Down Expand Up @@ -489,6 +493,24 @@ def _check_login(self, timeout=5) -> bool:
self.log_warning("检测登录状态超时:未出现登录或未登录标志元素")
return None

def _get_login_timeout_seconds(self) -> int:
try:
timeout_minutes = int(self.cfg.get_value("cloud_game_login_timeout", 10))
except (TypeError, ValueError):
timeout_minutes = 10
return max(1, timeout_minutes) * 60

def _abort_login_timeout(self, timeout_seconds: int) -> None:
timeout_minutes = timeout_seconds // 60
message = f"等待云游戏登录超时({timeout_minutes} 分钟),停止运行"
self.log_error(message)
self.stop_game()
raise CloudGameLoginTimeoutError(message)

def _check_login_timeout(self, deadline: float, timeout_seconds: int) -> None:
if time.monotonic() >= deadline:
self._abort_login_timeout(timeout_seconds)

def _click_enter_game(self, timeout=5) -> None:
"""
点击‘进入游戏’按钮。
Expand Down Expand Up @@ -979,10 +1001,13 @@ def _decode_qr_from_element(self, qr_img, qr_filename: str) -> None:
except Exception as e:
self.log_warning(f"解析二维码内容失败: {e}")

def _wait_scan_success_with_refresh(self, qr_filename: str) -> None:
def _wait_scan_success_with_refresh(self, qr_filename: str, login_deadline: float = None, timeout_seconds: int = None) -> None:
import os
check_interval = 2
while True:
if login_deadline is not None and timeout_seconds is not None:
self._check_login_timeout(login_deadline, timeout_seconds)

# 成功
if self.driver.find_elements(By.XPATH, "//*[contains(text(), '扫码成功')]"):
try:
Expand Down Expand Up @@ -1025,7 +1050,7 @@ def _wait_scan_success_with_refresh(self, qr_filename: str) -> None:

time.sleep(check_interval)

def _run_qr_login_flow(self) -> None:
def _run_qr_login_flow(self, login_deadline: float = None, timeout_seconds: int = None) -> None:
self.log_info("正在切换到二维码登录...")

# 每次进入二维码登录流程时重置通知限流状态
Expand All @@ -1047,7 +1072,7 @@ def _run_qr_login_flow(self) -> None:
self._decode_qr_from_element(qr_img, qr_filename)
self.log_info("=" * 60)
self.log_info("等待扫码(二维码过期将自动刷新)...")
self._wait_scan_success_with_refresh(qr_filename)
self._wait_scan_success_with_refresh(qr_filename, login_deadline, timeout_seconds)
except TimeoutException:
self.log_warning("等待二维码加载超时")
except Exception as e:
Expand Down Expand Up @@ -1086,6 +1111,8 @@ def enter_cloud_game(self) -> bool:
try:
# 检测登录状态
while not self._check_login():
login_timeout_seconds = self._get_login_timeout_seconds()
login_deadline = time.monotonic() + login_timeout_seconds
self.log_info("未登录")

# 如果是 headless 且配置了自动重启,则以非 headless 模式重启启动让用户登录
Expand All @@ -1095,12 +1122,15 @@ def enter_cloud_game(self) -> bool:

# 如果是 headless 且配置了不重启,则尝试二维码登录
if self.cfg.browser_headless_enable and (not self.cfg.browser_headless_restart_on_not_logged_in):
self._run_qr_login_flow()
self._run_qr_login_flow(login_deadline, login_timeout_seconds)

self.log_info("请在浏览器中完成登录操作")
self.log_info(f"请在浏览器中完成登录操作,超时时间:{login_timeout_seconds // 60} 分钟")

# 循环检测用户是否登录
while not self._check_login():
while True:
self._check_login_timeout(login_deadline, login_timeout_seconds)
if self._check_login():
break
time.sleep(2)

self.log_info("检测到登录成功")
Expand Down Expand Up @@ -1146,6 +1176,8 @@ def enter_cloud_game(self) -> bool:
self._confirm_viewport_resolution() # 将浏览器内部分辨率设置为 1920x1080
self.log_info("进入云游戏成功")
return True
except CloudGameLoginTimeoutError:
raise
except Exception as e:
self.try_dump_page()
self.log_error(f"进入云游戏失败: {e}")
Expand Down
3 changes: 3 additions & 0 deletions tasks/game/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from utils.console import pause_on_success
from tasks.power.power import Power
from module.game import cloud_game, get_game_controller
from module.game.cloud import CloudGameLoginTimeoutError
from module.logger import log
from module.screen import screen
from module.automation import auto
Expand Down Expand Up @@ -207,6 +208,8 @@ def start_cloud_game():
starrail.stop_game()
continue
break
except CloudGameLoginTimeoutError:
raise
except Exception as e:
log.error(f"尝试启动游戏时发生错误:{e}")
# 确保在重试前停止游戏
Expand Down
Loading