steam-backlog-enforcer/steam_backlog_enforcer/tests/_zero_ach.py
Krzysztof kuhy Rudnicki 401031602e Always allow games with zero achievements
Owned games Steam confirms have no achievements can never be assigned or
completed, so the enforcer no longer uninstalls, hides or kills them as
unauthorized. The gaming-time budget kill still applies to them.

Fail-closed: unknown status (no cache, other account, unreadable config
or snapshot, request error) keeps a game enforced. The set comes from
no_achievements_cache.json minus snapshot.json, so a game that gains
achievements is enforced again after the next scan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzxdWWAkVShjD2Bo6hM88B
2026-11-01 22:00:35 +01:00

56 lines
1.4 KiB
Python

"""Shared fixtures for the zero-achievement "always allowed" tests."""
from __future__ import annotations
import json
import re
from typing import TYPE_CHECKING
from steam_backlog_enforcer import _achievement_skip as skip
from steam_backlog_enforcer import config
if TYPE_CHECKING:
from collections.abc import Callable
from pathlib import Path
SIMS3 = 47890
ASSIGNED = 1091500
WITH_ACH = 570
STEAM_ID = "76561198009649542"
NOW = 1_000_000_000.0
def write(path: Path, payload: object) -> None:
path.write_text(json.dumps(payload), encoding="utf-8")
def confirm_zero(*app_ids: int, steam_id: str = STEAM_ID) -> None:
"""Make the real cache say Steam answered "no achievements" for these."""
write(config.CONFIG_FILE, {"steam_id": STEAM_ID})
write(
skip._cache_file(),
{"steam_id": steam_id, "checked": {str(a): NOW for a in app_ids}},
)
def write_snapshot(*app_ids: int) -> None:
write(
config.SNAPSHOT_FILE, [{"app_id": a, "total_achievements": 5} for a in app_ids]
)
def recorder(removed: list[int]) -> Callable[..., bool]:
"""An ``uninstall_game`` stand-in that notes which app was removed."""
def record(app_id: int, _name: str = "") -> bool:
removed.append(app_id)
return True
return record
def js_list(pattern: str, js: str) -> list[int]:
match = re.search(pattern, js)
assert match is not None
return list(json.loads(match.group(1)))