mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-06-08 03:07:44 +02:00
Sync from development - prepare for v0.3.0
This commit is contained in:
106
jackify/frontends/cli/commands/install_wabbajack.py
Normal file
106
jackify/frontends/cli/commands/install_wabbajack.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""
|
||||
Install Wabbajack Application Command
|
||||
Provides CLI interface for automated Wabbajack installation
|
||||
Uses backend service for complete workflow orchestration
|
||||
"""
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from jackify.backend.services.wabbajack_installer_service import WabbajackInstallerService
|
||||
from jackify.shared.colors import COLOR_PROMPT, COLOR_RESET, COLOR_INFO, COLOR_SUCCESS, COLOR_ERROR
|
||||
|
||||
|
||||
class InstallWabbajackCommand:
|
||||
"""CLI command for installing Wabbajack application"""
|
||||
|
||||
def __init__(self):
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def run(self):
|
||||
"""Execute Wabbajack installation workflow using backend service"""
|
||||
print(f"\n{COLOR_INFO}=== Install Wabbajack Application ==={COLOR_RESET}\n")
|
||||
print("This will download and configure Wabbajack.exe via Proton.")
|
||||
print("Wabbajack will be added to your Steam library as a non-Steam game.\n")
|
||||
|
||||
# Prompt for installation directory
|
||||
default_dir = str(Path.home() / "Games" / "Wabbajack")
|
||||
install_dir_input = input(
|
||||
f"{COLOR_PROMPT}Installation directory [{default_dir}]: {COLOR_RESET}"
|
||||
).strip()
|
||||
|
||||
install_dir = Path(install_dir_input) if install_dir_input else Path(default_dir)
|
||||
|
||||
# Prompt for shortcut name
|
||||
shortcut_name = "Wabbajack"
|
||||
shortcut_input = input(
|
||||
f"{COLOR_PROMPT}Shortcut name [{shortcut_name}]: {COLOR_RESET}"
|
||||
).strip()
|
||||
if shortcut_input:
|
||||
shortcut_name = shortcut_input
|
||||
|
||||
# Confirm installation with Steam restart warning
|
||||
print(f"\n{COLOR_INFO}Installation directory: {install_dir}{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Shortcut name: {shortcut_name}{COLOR_RESET}")
|
||||
print(f"\n{COLOR_PROMPT}{'='*60}{COLOR_RESET}")
|
||||
print(f"{COLOR_PROMPT}Important: Steam will be restarted during installation.{COLOR_RESET}")
|
||||
print(f"{COLOR_PROMPT}Please do not manually start or close Steam until installation is complete.{COLOR_RESET}")
|
||||
print(f"{COLOR_PROMPT}{'='*60}{COLOR_RESET}")
|
||||
confirm = input(f"\n{COLOR_PROMPT}Proceed with installation? (Y/n): {COLOR_RESET}").strip().lower()
|
||||
|
||||
if confirm == 'n':
|
||||
print("Installation cancelled.")
|
||||
return
|
||||
|
||||
# Execute installation using backend service
|
||||
print(f"\n{COLOR_INFO}Starting Wabbajack installation...{COLOR_RESET}\n")
|
||||
|
||||
service = WabbajackInstallerService()
|
||||
|
||||
def progress_callback(message: str, percentage: int):
|
||||
step_num = int((percentage / 100) * 12) if percentage < 100 else 12
|
||||
print(f"{COLOR_INFO}[{step_num}/12] {message}{COLOR_RESET}")
|
||||
|
||||
def log_callback(message: str):
|
||||
if "ERROR" in message or "WARNING" in message or "Failed" in message:
|
||||
print(f"{COLOR_ERROR}{message}{COLOR_RESET}")
|
||||
elif "successfully" in message.lower() or "created" in message.lower() or "installed" in message.lower():
|
||||
print(f"{COLOR_SUCCESS}{message}{COLOR_RESET}")
|
||||
else:
|
||||
print(f"{COLOR_INFO}{message}{COLOR_RESET}")
|
||||
|
||||
success, app_id, launch_options, gog_count, time_taken, error_msg = service.install_wabbajack(
|
||||
install_folder=install_dir,
|
||||
shortcut_name=shortcut_name,
|
||||
enable_gog=True,
|
||||
progress_callback=progress_callback,
|
||||
log_callback=log_callback
|
||||
)
|
||||
|
||||
if success:
|
||||
print(f"\n{COLOR_SUCCESS}{'='*60}{COLOR_RESET}")
|
||||
print(f"{COLOR_SUCCESS}Wabbajack installation complete!{COLOR_RESET}")
|
||||
print(f"{COLOR_SUCCESS}{'='*60}{COLOR_RESET}\n")
|
||||
|
||||
print(f"{COLOR_INFO}Installation directory: {install_dir}{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Steam AppID: {app_id}{COLOR_RESET}")
|
||||
if time_taken:
|
||||
print(f"{COLOR_INFO}Time taken: {time_taken}{COLOR_RESET}")
|
||||
|
||||
# Show launch options note (matches GUI)
|
||||
if launch_options and "STEAM_COMPAT_MOUNTS" in launch_options:
|
||||
print(f"\n{COLOR_INFO}Note: To access other drives, add paths to launch options (Steam → Properties).{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Append with colons: STEAM_COMPAT_MOUNTS=\"/existing:/new/path\" %command%{COLOR_RESET}")
|
||||
elif not launch_options:
|
||||
print(f"\n{COLOR_INFO}Note: To access other drives, add to launch options (Steam → Properties):{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}STEAM_COMPAT_MOUNTS=\"/path/to/directory\" %command%{COLOR_RESET}")
|
||||
|
||||
print(f"\n{COLOR_INFO}Next steps:{COLOR_RESET}")
|
||||
print(f" 1. Find '{shortcut_name}' in your Steam library")
|
||||
print(f" 2. Launch Wabbajack from Steam")
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}Installation failed: {error_msg}{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Check logs for details{COLOR_RESET}")
|
||||
|
||||
input(f"\n{COLOR_PROMPT}Press Enter to continue...{COLOR_RESET}")
|
||||
|
||||
@@ -423,8 +423,10 @@ class JackifyCLI:
|
||||
elif command == "configure-modlist":
|
||||
return self.commands['configure_modlist'].execute(args)
|
||||
elif command == "install-wabbajack":
|
||||
# Legacy functionality - TODO: extract to command handler
|
||||
return self._handle_legacy_install_wabbajack()
|
||||
print("Wabbajack installation is available through the interactive menu:")
|
||||
print(" Run: jackify --cli")
|
||||
print(" Then select: Additional Tasks > Install Wabbajack")
|
||||
return 0
|
||||
elif command == "install-mo2":
|
||||
print("MO2 installation not yet implemented")
|
||||
print("This functionality is coming soon!")
|
||||
@@ -493,12 +495,6 @@ class JackifyCLI:
|
||||
logger.error(f"Steam restart failed with exception: {e}")
|
||||
return 1
|
||||
|
||||
def _handle_legacy_install_wabbajack(self):
|
||||
"""Handle install-wabbajack command (legacy functionality)"""
|
||||
print("Install Wabbajack functionality not yet migrated to new structure")
|
||||
return 1
|
||||
|
||||
return 1
|
||||
|
||||
def _handle_legacy_recovery(self, args):
|
||||
"""Handle recovery command (legacy functionality)"""
|
||||
@@ -513,7 +509,10 @@ class JackifyCLI:
|
||||
# LEGACY BRIDGE: Methods that menu handlers expect to find on cli_instance
|
||||
def _cmd_install_wabbajack(self, args):
|
||||
"""LEGACY BRIDGE: Install Wabbajack application"""
|
||||
return self._handle_legacy_install_wabbajack()
|
||||
from jackify.frontends.cli.commands.install_wabbajack import InstallWabbajackCommand
|
||||
command_instance = InstallWabbajackCommand()
|
||||
command_instance.run()
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
@@ -522,6 +521,6 @@ def main():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# This should not be called directly - use __main__.py instead
|
||||
# Do not call directly -- use __main__.py
|
||||
print("Please use: python -m jackify.frontends.cli")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -35,7 +35,8 @@ class AdditionalMenuHandler:
|
||||
print(f" {COLOR_ACTION}→ Authorize with Nexus using OAuth or manage API key{COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}2.{COLOR_RESET} Tale of Two Wastelands (TTW) Installation")
|
||||
print(f" {COLOR_ACTION}→ Install TTW using TTW_Linux_Installer{COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}3.{COLOR_RESET} Coming Soon...")
|
||||
print(f"{COLOR_SELECTION}3.{COLOR_RESET} Install Wabbajack Application")
|
||||
print(f" {COLOR_ACTION}→ Downloads and configures the Wabbajack app itself (via Proton){COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}0.{COLOR_RESET} Return to Main Menu")
|
||||
selection = input(f"\n{COLOR_PROMPT}Enter your selection (0-3): {COLOR_RESET}").strip()
|
||||
|
||||
@@ -46,8 +47,7 @@ class AdditionalMenuHandler:
|
||||
elif selection == "2":
|
||||
self._execute_ttw_install(cli_instance)
|
||||
elif selection == "3":
|
||||
print(f"\n{COLOR_INFO}More features coming soon!{COLOR_RESET}")
|
||||
input("\nPress Enter to return to menu...")
|
||||
self._execute_install_wabbajack(cli_instance)
|
||||
elif selection == "0":
|
||||
break
|
||||
else:
|
||||
@@ -65,7 +65,7 @@ class AdditionalMenuHandler:
|
||||
|
||||
def _execute_legacy_recovery_menu(self, cli_instance):
|
||||
"""LEGACY BRIDGE: Execute recovery menu"""
|
||||
# This will be handled by the RecoveryMenuHandler
|
||||
# Handled by RecoveryMenuHandler
|
||||
from .recovery_menu import RecoveryMenuHandler
|
||||
|
||||
recovery_handler = RecoveryMenuHandler()
|
||||
@@ -107,9 +107,25 @@ class AdditionalMenuHandler:
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
|
||||
# Prompt for TTW .mpi file
|
||||
# Prompt for TTW .mpi file with tab completion
|
||||
try:
|
||||
import readline
|
||||
from ....backend.handlers.completers import path_completer
|
||||
READLINE_AVAILABLE = True
|
||||
except ImportError:
|
||||
READLINE_AVAILABLE = False
|
||||
|
||||
print(f"\n{COLOR_PROMPT}TTW Installer File (.mpi){COLOR_RESET}")
|
||||
mpi_path = input(f"{COLOR_PROMPT}Path to TTW .mpi file: {COLOR_RESET}").strip()
|
||||
if READLINE_AVAILABLE:
|
||||
readline.set_completer_delims(' \t\n;')
|
||||
readline.set_completer(path_completer)
|
||||
readline.parse_and_bind("tab: complete")
|
||||
try:
|
||||
mpi_path = input(f"{COLOR_PROMPT}Path to TTW .mpi file: {COLOR_RESET}").strip()
|
||||
finally:
|
||||
if READLINE_AVAILABLE:
|
||||
readline.set_completer(None)
|
||||
|
||||
if not mpi_path:
|
||||
print(f"{COLOR_WARNING}No .mpi file specified. Cancelling.{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
@@ -121,10 +137,19 @@ class AdditionalMenuHandler:
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
|
||||
# Prompt for output directory
|
||||
# Prompt for output directory with tab completion
|
||||
print(f"\n{COLOR_PROMPT}TTW Installation Directory{COLOR_RESET}")
|
||||
default_output = Path.home() / "ModdedGames" / "TTW"
|
||||
output_path = input(f"{COLOR_PROMPT}TTW install directory (Enter for default: {default_output}): {COLOR_RESET}").strip()
|
||||
if READLINE_AVAILABLE:
|
||||
readline.set_completer_delims(' \t\n;')
|
||||
readline.set_completer(path_completer)
|
||||
readline.parse_and_bind("tab: complete")
|
||||
try:
|
||||
output_path = input(f"{COLOR_PROMPT}TTW install directory (Enter for default: {default_output}): {COLOR_RESET}").strip()
|
||||
finally:
|
||||
if READLINE_AVAILABLE:
|
||||
readline.set_completer(None)
|
||||
|
||||
if not output_path:
|
||||
output_path = default_output
|
||||
else:
|
||||
@@ -280,3 +305,12 @@ class AdditionalMenuHandler:
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}Invalid selection.{COLOR_RESET}")
|
||||
time.sleep(1)
|
||||
|
||||
def _execute_install_wabbajack(self, cli_instance):
|
||||
"""Execute Wabbajack application installation"""
|
||||
from jackify.frontends.cli.commands.install_wabbajack import InstallWabbajackCommand
|
||||
|
||||
command = InstallWabbajackCommand()
|
||||
if self.logger:
|
||||
self.logger.debug("AdditionalMenuHandler: Executing Install Wabbajack command")
|
||||
command.run()
|
||||
|
||||
@@ -43,7 +43,7 @@ class MainMenuHandler:
|
||||
print(f"{COLOR_SELECTION}1.{COLOR_RESET} Modlist Tasks")
|
||||
print(f" {COLOR_ACTION}→ Install & Configure Modlists{COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}2.{COLOR_RESET} Additional Tasks & Tools")
|
||||
print(f" {COLOR_ACTION}→ TTW automation, Wabbajack via Wine, MO2, NXM Handling, Recovery{COLOR_RESET}")
|
||||
print(f" {COLOR_ACTION}→ Nexus OAuth, TTW Installation, Install Wabbajack{COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}0.{COLOR_RESET} Exit Jackify")
|
||||
choice = input(f"\n{COLOR_PROMPT}Enter your selection (0-2): {COLOR_RESET}").strip()
|
||||
|
||||
|
||||
@@ -37,9 +37,6 @@ class WabbajackMenuHandler:
|
||||
print(f" {COLOR_ACTION}→ Modlist already downloaded? Configure and add to Steam{COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}3.{COLOR_RESET} Configure Existing Modlist (In Steam)")
|
||||
print(f" {COLOR_ACTION}→ Modlist already in Steam? Re-configure it here{COLOR_RESET}")
|
||||
# HIDDEN FOR FIRST RELEASE - UNCOMMENT WHEN READY
|
||||
# print(f"{COLOR_SELECTION}4.{COLOR_RESET} Install Wabbajack Application")
|
||||
# print(f" {COLOR_ACTION}→ Downloads and configures the Wabbajack app itself (via WINE){COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}0.{COLOR_RESET} Return to Main Menu")
|
||||
selection = input(f"\n{COLOR_PROMPT}Enter your selection (0-3): {COLOR_RESET}").strip()
|
||||
|
||||
@@ -52,9 +49,6 @@ class WabbajackMenuHandler:
|
||||
self._execute_legacy_configure_new_modlist(cli_instance)
|
||||
elif selection == "3":
|
||||
self._execute_legacy_configure_existing_modlist(cli_instance)
|
||||
# HIDDEN FOR FIRST RELEASE - UNCOMMENT WHEN READY
|
||||
# elif selection == "4":
|
||||
# self._execute_legacy_install_wabbajack(cli_instance)
|
||||
elif selection == "0":
|
||||
break
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user