aboutsummaryrefslogtreecommitdiff
path: root/libs/basic_games/gog_utils.py
blob: 750f7395a18de4e644dea38be05378b9db427c70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# Code adapted from EzioTheDeadPoet / erri120:
#     https://github.com/ModOrganizer2/modorganizer-basic_games/pull/5

from __future__ import annotations

import json
import sys
from pathlib import Path

try:
    import winreg
except ImportError:
    winreg = None  # type: ignore[assignment]


def _find_heroic_gog_games() -> dict[str, Path]:
    """Detect GOG games installed via Heroic Launcher on Linux."""
    games: dict[str, Path] = {}

    for candidate in (
        Path.home() / ".config" / "heroic" / "gog_store" / "installed.json",
        Path.home()
        / ".var"
        / "app"
        / "com.heroicgameslauncher.hgl"
        / "config"
        / "heroic"
        / "gog_store"
        / "installed.json",
    ):
        if not candidate.is_file():
            continue
        try:
            with open(candidate, encoding="utf-8") as f:
                data = json.load(f)
            for game in data.get("installed", []):
                app_name = game.get("appName", "")
                install_path = game.get("install_path") or game.get("installPath", "")
                if app_name and install_path:
                    games[str(app_name)] = Path(install_path)
        except (json.JSONDecodeError, OSError) as e:
            print(
                f'Unable to parse Heroic GOG installed games from "{candidate}": {e}',
                file=sys.stderr,
            )

    return games


def find_games() -> dict[str, Path]:
    if winreg is None:
        # winreg not available (Linux without shim); use Heroic GOG.
        return _find_heroic_gog_games()

    # List the game IDs from the registry (Windows):
    game_ids: list[str] = []
    try:
        with winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE, r"Software\Wow6432Node\GOG.com\Games"
        ) as key:
            nkeys = winreg.QueryInfoKey(key)[0]
            for ik in range(nkeys):
                game_key = winreg.EnumKey(key, ik)
                if game_key.isdigit():
                    game_ids.append(game_key)
    except FileNotFoundError:
        # Windows registry not available; try Heroic GOG on Linux.
        return _find_heroic_gog_games()

    # For each game, query the path:
    games: dict[str, Path] = {}
    for game_id in game_ids:
        try:
            with winreg.OpenKey(
                winreg.HKEY_LOCAL_MACHINE,
                f"Software\\Wow6432Node\\GOG.com\\Games\\{game_id}",
            ) as key:
                games[game_id] = Path(winreg.QueryValueEx(key, "path")[0])
        except FileNotFoundError:
            pass

    return games