steam_backlog_enforcer: retry install after library hide restart

This commit is contained in:
Krzysztof kuhy Rudnicki 2026-05-08 14:54:13 +02:00
parent a1fbd034c9
commit e020e84a3a
2 changed files with 78 additions and 0 deletions

View File

@ -2,6 +2,8 @@
from __future__ import annotations from __future__ import annotations
import logging
from python_pkg.steam_backlog_enforcer._enforce_loop import get_all_owned_app_ids from python_pkg.steam_backlog_enforcer._enforce_loop import get_all_owned_app_ids
from python_pkg.steam_backlog_enforcer.config import Config, State, load_snapshot from python_pkg.steam_backlog_enforcer.config import Config, State, load_snapshot
from python_pkg.steam_backlog_enforcer.enforcer import ( from python_pkg.steam_backlog_enforcer.enforcer import (
@ -32,6 +34,7 @@ from python_pkg.steam_backlog_enforcer.scanning import (
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient from python_pkg.steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
_REASSIGN_REFRESH_LIMIT = 50 _REASSIGN_REFRESH_LIMIT = 50
logger = logging.getLogger(__name__)
def _backfill_polls_for_finished( def _backfill_polls_for_finished(
@ -308,6 +311,23 @@ def _finalize_completion(
if hidden > 0: if hidden > 0:
_echo(f"\n Library: hid {hidden} games") _echo(f"\n Library: hid {hidden} games")
if not is_game_installed(state.current_app_id):
logger.info(
"Assigned game still missing after library reconciliation; "
"re-triggering install"
)
_echo(
"\n Assigned game still missing after library reconciliation; "
"re-triggering install..."
)
_echo(f"\n Auto-installing {state.current_game_name}...")
install_game(
state.current_app_id,
state.current_game_name,
config.steam_id,
use_steam_protocol=True,
)
send_notification( send_notification(
"Game Complete!", "Game Complete!",
f"Finished {game_name}! Now playing: {state.current_game_name}", f"Finished {game_name}! Now playing: {state.current_game_name}",

View File

@ -185,6 +185,64 @@ class TestFinalizeCompletion:
assert seen[3] == 18.81 assert seen[3] == 18.81
mock_fetch_hltb.assert_called_once_with([(3, "Lacuna")]) mock_fetch_hltb.assert_called_once_with([(3, "Lacuna")])
def test_retriggers_install_after_library_hide_if_still_missing(self) -> None:
"""Re-trigger install after hide step in case Steam restart drops it."""
config = Config(steam_id="sid")
state = State(current_app_id=1, current_game_name="DoneGame")
snap = [_snap(2, "Next", 10, 0, 5.0)]
def set_next(
_games: object,
s: State,
_c: object,
) -> None:
s.current_app_id = 2
s.current_game_name = "Next"
with (
patch(f"{CMD_DONE_PKG}._echo"),
patch(f"{CMD_DONE_PKG}.load_snapshot", return_value=snap),
patch(f"{CMD_DONE_PKG}.pick_next_game", side_effect=set_next),
patch(f"{CMD_DONE_PKG}.get_all_owned_app_ids", return_value=[1, 2]),
patch(f"{CMD_DONE_PKG}.hide_other_games", return_value=1),
patch(f"{CMD_DONE_PKG}.is_game_installed", return_value=False),
patch(f"{CMD_DONE_PKG}.install_game") as mock_install,
patch(f"{CMD_DONE_PKG}.send_notification"),
patch.object(State, "save"),
):
_finalize_completion(config, state, "DoneGame", 1)
mock_install.assert_called_once_with(2, "Next", "sid", use_steam_protocol=True)
def test_skips_install_retry_when_assigned_game_already_installed(self) -> None:
"""Do not re-trigger install when assigned game is already present."""
config = Config(steam_id="sid")
state = State(current_app_id=1, current_game_name="DoneGame")
snap = [_snap(2, "Next", 10, 0, 5.0)]
def set_next(
_games: object,
s: State,
_c: object,
) -> None:
s.current_app_id = 2
s.current_game_name = "Next"
with (
patch(f"{CMD_DONE_PKG}._echo"),
patch(f"{CMD_DONE_PKG}.load_snapshot", return_value=snap),
patch(f"{CMD_DONE_PKG}.pick_next_game", side_effect=set_next),
patch(f"{CMD_DONE_PKG}.get_all_owned_app_ids", return_value=[1, 2]),
patch(f"{CMD_DONE_PKG}.hide_other_games", return_value=1),
patch(f"{CMD_DONE_PKG}.is_game_installed", return_value=True),
patch(f"{CMD_DONE_PKG}.install_game") as mock_install,
patch(f"{CMD_DONE_PKG}.send_notification"),
patch.object(State, "save"),
):
_finalize_completion(config, state, "DoneGame", 1)
mock_install.assert_not_called()
class TestEnforceOnDone: class TestEnforceOnDone:
"""Tests for _enforce_on_done.""" """Tests for _enforce_on_done."""