mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-08-14 00:23:42 +02:00
123 lines
4.2 KiB
Python
123 lines
4.2 KiB
Python
"""Update-vs-new installation detection service.
|
|
|
|
Free functions used by both GUI (install_modlist_workflow.py) and CLI
|
|
(modlist_operations.py) to avoid duplicated logic.
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
from typing import Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def normalize_version_token(value: Optional[str]) -> Optional[str]:
|
|
"""Return a normalised version token for equality checks."""
|
|
if value is None:
|
|
return None
|
|
token = str(value).strip()
|
|
if not token:
|
|
return None
|
|
return token.lstrip("vV").lower()
|
|
|
|
|
|
def normalize_modlist_name(value: Optional[str]) -> str:
|
|
"""Return a case/whitespace-normalised modlist name for comparison."""
|
|
return " ".join((value or "").strip().lower().split())
|
|
|
|
|
|
def evaluate_update_candidate(
|
|
modlist_name: str,
|
|
install_dir: str,
|
|
existing_appid: Optional[str],
|
|
requested_version: Optional[str] = None,
|
|
) -> tuple[bool, dict]:
|
|
"""Decide whether update-mode should be offered.
|
|
|
|
Args:
|
|
modlist_name: Name of the modlist being installed.
|
|
install_dir: Resolved installation directory path.
|
|
existing_appid: Steam AppID from an existing shortcut (None if not found).
|
|
requested_version: Pre-computed normalised version from the selected modlist
|
|
(pass None when unavailable, e.g. offline/file-based installs).
|
|
|
|
Returns:
|
|
(eligible, result_dict) where eligible is True when update mode is safe to offer.
|
|
"""
|
|
from jackify.backend.utils.modlist_meta import read_modlist_meta
|
|
|
|
result: dict = {
|
|
"eligible": False,
|
|
"reason": "unknown",
|
|
"requested_version": None,
|
|
"installed_version": None,
|
|
"version_relation": "unknown",
|
|
"installed_name": None,
|
|
}
|
|
|
|
if not existing_appid:
|
|
result["reason"] = "missing_shortcut_appid"
|
|
return False, result
|
|
|
|
meta = read_modlist_meta(install_dir)
|
|
if not meta:
|
|
result["reason"] = "missing_meta"
|
|
return False, result
|
|
|
|
installed_name = (meta.get("modlist_name") or "").strip()
|
|
result["installed_name"] = installed_name
|
|
|
|
if normalize_modlist_name(installed_name) != normalize_modlist_name(modlist_name):
|
|
result["reason"] = "modlist_name_mismatch"
|
|
return False, result
|
|
|
|
installed_version = normalize_version_token(meta.get("modlist_version"))
|
|
result["requested_version"] = requested_version
|
|
result["installed_version"] = installed_version
|
|
|
|
if requested_version and installed_version:
|
|
result["version_relation"] = (
|
|
"same" if requested_version == installed_version else "different"
|
|
)
|
|
|
|
result["eligible"] = True
|
|
result["reason"] = "eligible"
|
|
return True, result
|
|
|
|
|
|
def find_existing_shortcut_appid(modlist_name: str, install_dir: str) -> Optional[str]:
|
|
"""Return the Steam AppID of an existing shortcut for this install, or None."""
|
|
try:
|
|
from jackify.backend.handlers.shortcut_handler import ShortcutHandler
|
|
from jackify.backend.services.platform_detection_service import PlatformDetectionService
|
|
|
|
platform_service = PlatformDetectionService.get_instance()
|
|
shortcut_handler = ShortcutHandler(
|
|
steamdeck=platform_service.is_steamdeck, verbose=False
|
|
)
|
|
|
|
install_real = os.path.realpath(install_dir)
|
|
candidate_exes = [
|
|
os.path.join(install_real, "ModOrganizer.exe"),
|
|
os.path.join(install_real, "files", "ModOrganizer.exe"),
|
|
]
|
|
|
|
for exe_path in candidate_exes:
|
|
if not os.path.exists(exe_path):
|
|
continue
|
|
appid = shortcut_handler.get_appid_from_vdf(modlist_name, exe_path)
|
|
if appid:
|
|
return appid
|
|
|
|
for shortcut in shortcut_handler.find_shortcuts_by_exe("ModOrganizer.exe"):
|
|
if (
|
|
(shortcut.get("AppName", "").strip() == modlist_name.strip())
|
|
and os.path.realpath(shortcut.get("StartDir", "")) == install_real
|
|
):
|
|
raw_appid = shortcut.get("appid")
|
|
if raw_appid is not None:
|
|
return str(int(raw_appid) & 0xFFFFFFFF)
|
|
except Exception as e:
|
|
logger.warning("Update detection: failed shortcut lookup: %s", e)
|
|
return None
|