Complete resilient Steam login flow

This commit is contained in:
hz
2026-07-20 00:30:06 -05:00
parent d176640cff
commit f93b7ac380
3 changed files with 107 additions and 15 deletions
+52 -15
View File
@@ -42,7 +42,9 @@ var poll_timer: Timer
var mode := "login"
var reset_requested := false
var steam_transaction_id := ""
var steam_poll_attempts := 0
var steam_poll_deadline_msec := 0
var steam_poll_failures := 0
var steam_popup_opened := false
var automatic_login_pending := false
var login_attempt_username := ""
var compact_layout := false
@@ -73,6 +75,7 @@ func _ready() -> void:
func on_show(payload: Variant = null) -> void:
_reset_steam_flow()
_set_busy(false)
_set_mode("login")
_clear_message()
@@ -84,7 +87,7 @@ func on_show(payload: Variant = null) -> void:
func on_hide() -> void:
poll_timer.stop()
_reset_steam_flow()
func _build_ui() -> void:
@@ -407,6 +410,8 @@ func _add_dot_grid(origin: Vector2) -> void:
func _set_mode(next_mode: String) -> void:
if mode == "steam" and next_mode != "steam":
_reset_steam_flow()
mode = next_mode
if login_view == null: return
login_view.visible = mode == "login"
@@ -601,23 +606,30 @@ func _on_reset_confirmed(result: int, code: int, _headers: PackedStringArray, bo
func _start_steam() -> void:
if OS.has_feature("web"):
JavaScriptBridge.eval("window.medmindSteamWindow = window.open('about:blank', 'medmind_steam');", true)
var popup_result: Variant = JavaScriptBridge.eval("window.ranazeSteamWindow = window.open('about:blank', 'ranaze_steam'); window.ranazeSteamWindow !== null;", true)
steam_popup_opened = bool(popup_result)
if not steam_popup_opened:
return _show_error("Steam sign in needs a popup. Allow popups for this site, then try again.")
_send_json("steam_start", "/steam/start", {}, "Opening Steam...")
func _on_steam_started(result: int, code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
_set_busy(false)
if result != HTTPRequest.RESULT_SUCCESS or code < 200 or code >= 300:
_close_steam_popup()
return _show_error("Unable to start Steam sign in.")
var data := _parse_dictionary(body)
steam_transaction_id = str(data.get("transactionId", ""))
var auth_url := str(data.get("authUrl", ""))
if steam_transaction_id.is_empty() or auth_url.is_empty(): return _show_error("Steam returned an invalid sign-in response.")
if steam_transaction_id.is_empty() or auth_url.is_empty():
_close_steam_popup()
return _show_error("Steam returned an invalid sign-in response.")
if OS.has_feature("web"):
JavaScriptBridge.eval("if (window.medmindSteamWindow) { window.medmindSteamWindow.location.href = %s; } else { window.location.href = %s; }" % [JSON.stringify(auth_url), JSON.stringify(auth_url)], true)
JavaScriptBridge.eval("if (window.ranazeSteamWindow && !window.ranazeSteamWindow.closed) { window.ranazeSteamWindow.location.href = %s; }" % JSON.stringify(auth_url), true)
else:
OS.shell_open(auth_url)
steam_poll_attempts = 0
steam_poll_deadline_msec = Time.get_ticks_msec() + 300000
steam_poll_failures = 0
_show_success("Complete sign in in the Steam window. Waiting for verification...")
poll_timer.start()
@@ -625,21 +637,32 @@ func _on_steam_started(result: int, code: int, _headers: PackedStringArray, body
func _poll_steam() -> void:
var status_request: HTTPRequest = requests["steam_status"]
if steam_transaction_id.is_empty() or status_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED: return
steam_poll_attempts += 1
if steam_poll_attempts > 150:
poll_timer.stop(); return _show_error("Steam sign in timed out. Try again when ready.")
if steam_poll_deadline_msec > 0 and Time.get_ticks_msec() >= steam_poll_deadline_msec:
_reset_steam_flow()
return _show_error("Steam sign in timed out. Try again when ready.")
var error: Error = status_request.request("%s/steam/status/%s" % [auth_base_url, steam_transaction_id])
if error != OK: _show_error("Waiting for a stable connection to Steam...")
if error != OK:
steam_poll_failures += 1
if steam_poll_failures >= 3: _show_error("Connection interrupted. Still waiting for Steam...")
func _on_steam_status(result: int, code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS or code >= 500: return
if result != HTTPRequest.RESULT_SUCCESS or code >= 500 or code == 429:
steam_poll_failures += 1
if steam_poll_failures >= 3: _show_error("Connection interrupted. Still waiting for Steam...")
return
if code == 404:
poll_timer.stop(); return _show_error("Steam sign in expired. Please try again.")
_reset_steam_flow()
return _show_error("Steam sign in expired. Please try again.")
if code < 200 or code >= 300:
_reset_steam_flow()
return _show_error(_response_message(body, "Steam sign in could not be completed."))
steam_poll_failures = 0
var data := _parse_dictionary(body)
match str(data.get("status", "pending")):
"requires_account": poll_timer.stop(); _set_mode("steam")
"complete": poll_timer.stop(); _accept_session(body, str(data.get("username", "")))
"pending": _show_success("Complete sign in in the Steam window. Waiting for verification...")
"requires_account": poll_timer.stop(); _close_steam_popup(); _set_mode("steam")
"complete": poll_timer.stop(); _close_steam_popup(); _accept_session(body, str(data.get("username", "")))
func _on_steam_action_changed(index: int) -> void:
@@ -665,11 +688,25 @@ func _on_steam_completed(result: int, code: int, _headers: PackedStringArray, bo
_set_busy(false)
if result != HTTPRequest.RESULT_SUCCESS or code < 200 or code >= 300:
return _show_error(_response_message(body, "Unable to connect this Steam account."))
steam_poll_attempts = 0
steam_poll_failures = 0
poll_timer.start()
_poll_steam()
func _reset_steam_flow() -> void:
if poll_timer != null: poll_timer.stop()
steam_transaction_id = ""
steam_poll_deadline_msec = 0
steam_poll_failures = 0
_close_steam_popup()
func _close_steam_popup() -> void:
if OS.has_feature("web") and steam_popup_opened:
JavaScriptBridge.eval("if (window.ranazeSteamWindow && !window.ranazeSteamWindow.closed) { window.ranazeSteamWindow.close(); } window.ranazeSteamWindow = null;", true)
steam_popup_opened = false
func _accept_session(body: PackedByteArray, fallback_username: String) -> void:
var response := _parse_dictionary(body)
var token := str(response.get("accessToken", ""))