mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 11:37:01 +01:00
233 lines
9.6 KiB
Python
233 lines
9.6 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Protontricks Detection Service Module
|
|
Centralized service for detecting and managing protontricks installation across CLI and GUI frontends
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import importlib.util
|
|
from typing import Optional, Tuple
|
|
from ..handlers.protontricks_handler import ProtontricksHandler
|
|
from ..handlers.config_handler import ConfigHandler
|
|
|
|
# Initialize logger
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ProtontricksDetectionService:
|
|
"""
|
|
Centralized service for detecting and managing protontricks installation
|
|
Handles detection, validation, and installation guidance for both CLI and GUI
|
|
"""
|
|
|
|
def __init__(self, steamdeck: bool = False):
|
|
"""
|
|
Initialize the protontricks detection service
|
|
|
|
Args:
|
|
steamdeck (bool): Whether running on Steam Deck
|
|
"""
|
|
self.steamdeck = steamdeck
|
|
self.config_handler = ConfigHandler()
|
|
self._protontricks_handler = None
|
|
self._last_detection_result = None
|
|
self._cached_detection_valid = False
|
|
logger.debug(f"ProtontricksDetectionService initialized (steamdeck={steamdeck})")
|
|
|
|
def _get_protontricks_handler(self) -> ProtontricksHandler:
|
|
"""Get or create ProtontricksHandler instance"""
|
|
if self._protontricks_handler is None:
|
|
self._protontricks_handler = ProtontricksHandler(self.steamdeck)
|
|
return self._protontricks_handler
|
|
|
|
def detect_protontricks(self, use_cache: bool = True) -> Tuple[bool, str, str]:
|
|
"""
|
|
Detect if system protontricks is installed and get installation details
|
|
|
|
Args:
|
|
use_cache (bool): Whether to use cached detection result
|
|
|
|
Returns:
|
|
Tuple[bool, str, str]: (is_installed, installation_type, details_message)
|
|
- is_installed: True if protontricks is available
|
|
- installation_type: 'native', 'flatpak', or 'none'
|
|
- details_message: Human-readable status message
|
|
"""
|
|
if use_cache and self._cached_detection_valid and self._last_detection_result:
|
|
logger.debug("Using cached protontricks detection result")
|
|
return self._last_detection_result
|
|
|
|
logger.info("Detecting protontricks installation...")
|
|
|
|
handler = self._get_protontricks_handler()
|
|
|
|
# Reset handler state for fresh detection
|
|
handler.which_protontricks = None
|
|
handler.protontricks_path = None
|
|
handler.protontricks_version = None
|
|
|
|
# Perform detection without user prompts
|
|
is_installed = self._detect_without_prompts(handler)
|
|
|
|
# Determine installation type and create message
|
|
if is_installed:
|
|
installation_type = handler.which_protontricks or 'unknown'
|
|
if installation_type == 'native':
|
|
details_message = f"Native protontricks found at {handler.protontricks_path}"
|
|
elif installation_type == 'flatpak':
|
|
details_message = "Flatpak protontricks is installed"
|
|
else:
|
|
details_message = "Protontricks is installed (unknown type)"
|
|
else:
|
|
installation_type = 'none'
|
|
details_message = "Protontricks not found - install via flatpak or package manager"
|
|
|
|
# Cache the result
|
|
self._last_detection_result = (is_installed, installation_type, details_message)
|
|
self._cached_detection_valid = True
|
|
|
|
logger.info(f"Protontricks detection complete: {details_message}")
|
|
return self._last_detection_result
|
|
|
|
def _detect_without_prompts(self, handler: ProtontricksHandler) -> bool:
|
|
"""
|
|
Detect system protontricks (flatpak or native) without user prompts.
|
|
|
|
Args:
|
|
handler (ProtontricksHandler): Handler instance to use
|
|
|
|
Returns:
|
|
bool: True if system protontricks is found
|
|
"""
|
|
# Use the handler's silent detection method
|
|
return handler.detect_protontricks()
|
|
|
|
def is_bundled_mode(self) -> bool:
|
|
"""
|
|
DEPRECATED: Bundled protontricks no longer supported.
|
|
Always returns False for backwards compatibility.
|
|
"""
|
|
return False
|
|
|
|
def install_flatpak_protontricks(self) -> Tuple[bool, str]:
|
|
"""
|
|
Install protontricks via Flatpak
|
|
|
|
Returns:
|
|
Tuple[bool, str]: (success, message)
|
|
"""
|
|
logger.info("Attempting to install Flatpak Protontricks...")
|
|
|
|
try:
|
|
handler = self._get_protontricks_handler()
|
|
|
|
# Check if flatpak is available
|
|
if not shutil.which("flatpak"):
|
|
error_msg = "Flatpak not found. Please install Flatpak first."
|
|
logger.error(error_msg)
|
|
return False, error_msg
|
|
|
|
# Install command - use --user flag for user-level installation (works on Steam Deck)
|
|
# This avoids requiring system-wide installation permissions
|
|
install_cmd = ["flatpak", "install", "--user", "-y", "--noninteractive", "flathub", "com.github.Matoking.protontricks"]
|
|
|
|
# Use clean environment
|
|
env = handler._get_clean_subprocess_env()
|
|
|
|
# Log the command for debugging
|
|
logger.debug(f"Running flatpak install command: {' '.join(install_cmd)}")
|
|
|
|
# Run installation with timeout (5 minutes should be plenty)
|
|
process = subprocess.run(
|
|
install_cmd,
|
|
check=True,
|
|
text=True,
|
|
env=env,
|
|
capture_output=True,
|
|
timeout=300 # 5 minute timeout
|
|
)
|
|
|
|
# Log stdout/stderr for debugging (even on success, might contain useful info)
|
|
if process.stdout:
|
|
logger.debug(f"Flatpak install stdout: {process.stdout}")
|
|
if process.stderr:
|
|
logger.debug(f"Flatpak install stderr: {process.stderr}")
|
|
|
|
# Clear cache to force re-detection
|
|
self._cached_detection_valid = False
|
|
|
|
success_msg = "Flatpak Protontricks installed successfully."
|
|
logger.info(success_msg)
|
|
return True, success_msg
|
|
|
|
except FileNotFoundError:
|
|
error_msg = "Flatpak command not found. Please install Flatpak first."
|
|
logger.error(error_msg)
|
|
return False, error_msg
|
|
except subprocess.TimeoutExpired:
|
|
error_msg = "Flatpak installation timed out after 5 minutes. Please check your network connection and try again."
|
|
logger.error(error_msg)
|
|
return False, error_msg
|
|
except subprocess.CalledProcessError as e:
|
|
# Include stderr in error message for better debugging
|
|
stderr_msg = e.stderr.strip() if e.stderr else "No error details available"
|
|
stdout_msg = e.stdout.strip() if e.stdout else ""
|
|
|
|
# Try to extract meaningful error from stderr
|
|
if stderr_msg:
|
|
# Common errors: permission denied, network issues, etc.
|
|
if "permission" in stderr_msg.lower() or "denied" in stderr_msg.lower():
|
|
error_msg = f"Permission denied. Try running: flatpak install --user flathub com.github.Matoking.protontricks\n\nDetails: {stderr_msg}"
|
|
elif "network" in stderr_msg.lower() or "connection" in stderr_msg.lower():
|
|
error_msg = f"Network error during installation. Check your internet connection.\n\nDetails: {stderr_msg}"
|
|
elif "already installed" in stderr_msg.lower():
|
|
# This might actually be success - clear cache and re-detect
|
|
logger.info("Protontricks appears to already be installed (according to flatpak output)")
|
|
self._cached_detection_valid = False
|
|
return True, "Protontricks is already installed."
|
|
else:
|
|
error_msg = f"Flatpak installation failed:\n\n{stderr_msg}"
|
|
if stdout_msg:
|
|
error_msg += f"\n\nOutput: {stdout_msg}"
|
|
else:
|
|
error_msg = f"Flatpak installation failed with return code {e.returncode}."
|
|
if stdout_msg:
|
|
error_msg += f"\n\nOutput: {stdout_msg}"
|
|
|
|
logger.error(f"Flatpak installation error: {error_msg}")
|
|
return False, error_msg
|
|
except Exception as e:
|
|
error_msg = f"Unexpected error during Flatpak installation: {e}"
|
|
logger.error(error_msg, exc_info=True)
|
|
return False, error_msg
|
|
|
|
def get_installation_guidance(self) -> str:
|
|
"""
|
|
Get guidance message for installing protontricks natively
|
|
|
|
Returns:
|
|
str: Installation guidance message
|
|
"""
|
|
return """To install protontricks natively, use your distribution's package manager:
|
|
|
|
• Arch Linux: sudo pacman -S protontricks
|
|
• Ubuntu/Debian: sudo apt install protontricks
|
|
• Fedora: sudo dnf install protontricks
|
|
• OpenSUSE: sudo zypper install protontricks
|
|
• Gentoo: sudo emerge protontricks
|
|
|
|
Alternatively, you can install via Flatpak:
|
|
flatpak install flathub com.github.Matoking.protontricks
|
|
|
|
After installation, click "Re-detect" to continue."""
|
|
|
|
def clear_cache(self):
|
|
"""Clear cached detection results to force re-detection"""
|
|
self._cached_detection_valid = False
|
|
self._last_detection_result = None
|
|
logger.debug("Protontricks detection cache cleared") |