mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 19:47:00 +01:00
Sync from development - prepare for v0.2.0
This commit is contained in:
@@ -25,7 +25,6 @@ from .commands.install_modlist import InstallModlistCommand
|
||||
# Import our menu handlers
|
||||
from .menus.main_menu import MainMenuHandler
|
||||
from .menus.wabbajack_menu import WabbajackMenuHandler
|
||||
from .menus.hoolamike_menu import HoolamikeMenuHandler
|
||||
from .menus.additional_menu import AdditionalMenuHandler
|
||||
|
||||
# Import backend handlers for legacy compatibility
|
||||
@@ -59,10 +58,18 @@ class JackifyCLI:
|
||||
|
||||
# Configure logging to be quiet by default - will be adjusted after arg parsing
|
||||
self._configure_logging_early()
|
||||
|
||||
# Determine system info
|
||||
self.system_info = SystemInfo(is_steamdeck=self._is_steamdeck())
|
||||
|
||||
|
||||
# Detect Steam installation types once at startup
|
||||
from ...shared.steam_utils import detect_steam_installation_types
|
||||
is_flatpak, is_native = detect_steam_installation_types()
|
||||
|
||||
# Determine system info with Steam detection
|
||||
self.system_info = SystemInfo(
|
||||
is_steamdeck=self._is_steamdeck(),
|
||||
is_flatpak_steam=is_flatpak,
|
||||
is_native_steam=is_native
|
||||
)
|
||||
|
||||
# Apply resource limits for optimal operation
|
||||
self._apply_resource_limits()
|
||||
|
||||
@@ -290,7 +297,6 @@ class JackifyCLI:
|
||||
menus = {
|
||||
'main': MainMenuHandler(dev_mode=getattr(self, 'dev_mode', False)),
|
||||
'wabbajack': WabbajackMenuHandler(),
|
||||
'hoolamike': HoolamikeMenuHandler(),
|
||||
'additional': AdditionalMenuHandler()
|
||||
}
|
||||
|
||||
@@ -419,9 +425,6 @@ class JackifyCLI:
|
||||
elif command == "install-wabbajack":
|
||||
# Legacy functionality - TODO: extract to command handler
|
||||
return self._handle_legacy_install_wabbajack()
|
||||
elif command == "hoolamike":
|
||||
# Legacy functionality - TODO: extract to command handler
|
||||
return self._handle_legacy_hoolamike()
|
||||
elif command == "install-mo2":
|
||||
print("MO2 installation not yet implemented")
|
||||
print("This functionality is coming soon!")
|
||||
@@ -495,9 +498,6 @@ class JackifyCLI:
|
||||
print("Install Wabbajack functionality not yet migrated to new structure")
|
||||
return 1
|
||||
|
||||
def _handle_legacy_hoolamike(self):
|
||||
"""Handle hoolamike command (legacy functionality)"""
|
||||
print("Hoolamike functionality not yet migrated to new structure")
|
||||
return 1
|
||||
|
||||
def _handle_legacy_recovery(self, args):
|
||||
|
||||
@@ -5,14 +5,12 @@ Extracted from the legacy monolithic CLI system
|
||||
|
||||
from .main_menu import MainMenuHandler
|
||||
from .wabbajack_menu import WabbajackMenuHandler
|
||||
from .hoolamike_menu import HoolamikeMenuHandler
|
||||
from .additional_menu import AdditionalMenuHandler
|
||||
from .recovery_menu import RecoveryMenuHandler
|
||||
|
||||
__all__ = [
|
||||
'MainMenuHandler',
|
||||
'WabbajackMenuHandler',
|
||||
'HoolamikeMenuHandler',
|
||||
'AdditionalMenuHandler',
|
||||
'RecoveryMenuHandler'
|
||||
]
|
||||
@@ -29,19 +29,23 @@ class AdditionalMenuHandler:
|
||||
self._clear_screen()
|
||||
print_jackify_banner()
|
||||
print_section_header("Additional Tasks & Tools")
|
||||
print(f"{COLOR_INFO}Additional Tasks & Tools, such as TTW Installation{COLOR_RESET}\n")
|
||||
print(f"{COLOR_INFO}Nexus Authentication, TTW Install & more{COLOR_RESET}\n")
|
||||
|
||||
print(f"{COLOR_SELECTION}1.{COLOR_RESET} Tale of Two Wastelands (TTW) Installation")
|
||||
print(f" {COLOR_ACTION}→ Install TTW using Hoolamike native automation{COLOR_RESET}")
|
||||
print(f"{COLOR_SELECTION}2.{COLOR_RESET} Coming Soon...")
|
||||
print(f"{COLOR_SELECTION}1.{COLOR_RESET} Nexus Mods Authorization")
|
||||
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}0.{COLOR_RESET} Return to Main Menu")
|
||||
selection = input(f"\n{COLOR_PROMPT}Enter your selection (0-2): {COLOR_RESET}").strip()
|
||||
|
||||
selection = input(f"\n{COLOR_PROMPT}Enter your selection (0-3): {COLOR_RESET}").strip()
|
||||
|
||||
if selection.lower() == 'q': # Allow 'q' to re-display menu
|
||||
continue
|
||||
if selection == "1":
|
||||
self._execute_hoolamike_ttw_install(cli_instance)
|
||||
self._execute_nexus_authorization(cli_instance)
|
||||
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...")
|
||||
elif selection == "0":
|
||||
@@ -68,57 +72,211 @@ class AdditionalMenuHandler:
|
||||
recovery_handler.logger = self.logger
|
||||
recovery_handler.show_recovery_menu(cli_instance)
|
||||
|
||||
def _execute_hoolamike_ttw_install(self, cli_instance):
|
||||
"""Execute TTW installation using Hoolamike handler"""
|
||||
from ....backend.handlers.hoolamike_handler import HoolamikeHandler
|
||||
def _execute_ttw_install(self, cli_instance):
|
||||
"""Execute TTW installation using TTW_Linux_Installer handler"""
|
||||
from ....backend.handlers.ttw_installer_handler import TTWInstallerHandler
|
||||
from ....backend.models.configuration import SystemInfo
|
||||
from ....shared.colors import COLOR_ERROR
|
||||
from ....shared.colors import COLOR_ERROR, COLOR_WARNING, COLOR_SUCCESS, COLOR_INFO, COLOR_PROMPT
|
||||
from pathlib import Path
|
||||
|
||||
system_info = SystemInfo(is_steamdeck=cli_instance.system_info.is_steamdeck)
|
||||
hoolamike_handler = HoolamikeHandler(
|
||||
ttw_installer_handler = TTWInstallerHandler(
|
||||
steamdeck=system_info.is_steamdeck,
|
||||
verbose=cli_instance.verbose,
|
||||
filesystem_handler=cli_instance.filesystem_handler,
|
||||
config_handler=cli_instance.config_handler,
|
||||
menu_handler=cli_instance.menu_handler
|
||||
config_handler=cli_instance.config_handler
|
||||
)
|
||||
|
||||
# First check if Hoolamike is installed
|
||||
if not hoolamike_handler.hoolamike_installed:
|
||||
print(f"\n{COLOR_WARNING}Hoolamike is not installed. Installing Hoolamike first...{COLOR_RESET}")
|
||||
if not hoolamike_handler.install_update_hoolamike():
|
||||
print(f"{COLOR_ERROR}Failed to install Hoolamike. Cannot proceed with TTW installation.{COLOR_RESET}")
|
||||
# First check if TTW_Linux_Installer is installed
|
||||
if not ttw_installer_handler.ttw_installer_installed:
|
||||
print(f"\n{COLOR_WARNING}TTW_Linux_Installer is not installed. Installing TTW_Linux_Installer first...{COLOR_RESET}")
|
||||
success, message = ttw_installer_handler.install_ttw_installer()
|
||||
if not success:
|
||||
print(f"{COLOR_ERROR}Failed to install TTW_Linux_Installer. Cannot proceed with TTW installation.{COLOR_RESET}")
|
||||
print(f"{COLOR_ERROR}Error: {message}{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
|
||||
# Run TTW installation workflow
|
||||
# Check for required games
|
||||
detected_games = ttw_installer_handler.path_handler.find_vanilla_game_paths()
|
||||
required_games = ['Fallout 3', 'Fallout New Vegas']
|
||||
missing_games = [game for game in required_games if game not in detected_games]
|
||||
if missing_games:
|
||||
print(f"\n{COLOR_ERROR}Missing required games: {', '.join(missing_games)}")
|
||||
print(f"TTW requires both Fallout 3 and Fallout New Vegas to be installed.{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
|
||||
# Prompt for TTW .mpi file
|
||||
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 not mpi_path:
|
||||
print(f"{COLOR_WARNING}No .mpi file specified. Cancelling.{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
|
||||
mpi_path = Path(mpi_path).expanduser()
|
||||
if not mpi_path.exists() or not mpi_path.is_file():
|
||||
print(f"{COLOR_ERROR}TTW .mpi file not found: {mpi_path}{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
|
||||
# Prompt for output directory
|
||||
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 not output_path:
|
||||
output_path = default_output
|
||||
else:
|
||||
output_path = Path(output_path).expanduser()
|
||||
|
||||
# Run TTW installation
|
||||
print(f"\n{COLOR_INFO}Starting TTW installation workflow...{COLOR_RESET}")
|
||||
result = hoolamike_handler.install_ttw()
|
||||
if result is None:
|
||||
print(f"\n{COLOR_WARNING}TTW installation returned without result.{COLOR_RESET}")
|
||||
success, message = ttw_installer_handler.install_ttw_backend(mpi_path, output_path)
|
||||
|
||||
if success:
|
||||
print(f"\n{COLOR_SUCCESS}TTW installation completed successfully!{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}TTW installed to: {output_path}{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}TTW installation failed.{COLOR_RESET}")
|
||||
print(f"{COLOR_ERROR}Error: {message}{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
|
||||
def _execute_hoolamike_modlist_install(self, cli_instance):
|
||||
"""Execute modlist installation using Hoolamike handler"""
|
||||
from ....backend.handlers.hoolamike_handler import HoolamikeHandler
|
||||
from ....backend.models.configuration import SystemInfo
|
||||
def _execute_nexus_authorization(self, cli_instance):
|
||||
"""Execute Nexus authorization menu (OAuth or API key)"""
|
||||
from ....backend.services.nexus_auth_service import NexusAuthService
|
||||
from ....backend.services.api_key_service import APIKeyService
|
||||
from ....shared.colors import COLOR_ERROR, COLOR_SUCCESS
|
||||
|
||||
system_info = SystemInfo(is_steamdeck=cli_instance.system_info.is_steamdeck)
|
||||
hoolamike_handler = HoolamikeHandler(
|
||||
steamdeck=system_info.is_steamdeck,
|
||||
verbose=cli_instance.verbose,
|
||||
filesystem_handler=cli_instance.filesystem_handler,
|
||||
config_handler=cli_instance.config_handler,
|
||||
menu_handler=cli_instance.menu_handler
|
||||
)
|
||||
auth_service = NexusAuthService()
|
||||
|
||||
# First check if Hoolamike is installed
|
||||
if not hoolamike_handler.hoolamike_installed:
|
||||
print(f"\n{COLOR_WARNING}Hoolamike is not installed. Installing Hoolamike first...{COLOR_RESET}")
|
||||
if not hoolamike_handler.install_update_hoolamike():
|
||||
print(f"{COLOR_ERROR}Failed to install Hoolamike. Cannot proceed with modlist installation.{COLOR_RESET}")
|
||||
input("Press Enter to return to menu...")
|
||||
return
|
||||
while True:
|
||||
self._clear_screen()
|
||||
print_jackify_banner()
|
||||
print_section_header("Nexus Mods Authorization")
|
||||
|
||||
# Run modlist installation
|
||||
hoolamike_handler.install_modlist()
|
||||
# Get current auth status
|
||||
authenticated, method, username = auth_service.get_auth_status()
|
||||
|
||||
if authenticated:
|
||||
if method == 'oauth':
|
||||
print(f"\n{COLOR_SUCCESS}Status: Authorized via OAuth{COLOR_RESET}")
|
||||
if username:
|
||||
print(f"{COLOR_INFO}Logged in as: {username}{COLOR_RESET}")
|
||||
elif method == 'api_key':
|
||||
print(f"\n{COLOR_WARNING}Status: Using API Key (Legacy){COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Consider switching to OAuth for better security{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_WARNING}Status: Not Authorized{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}You need to authorize to download mods from Nexus{COLOR_RESET}")
|
||||
|
||||
print(f"\n{COLOR_SELECTION}1.{COLOR_RESET} Authorize with Nexus (OAuth)")
|
||||
print(f" {COLOR_ACTION}→ Opens browser for secure authorization{COLOR_RESET}")
|
||||
|
||||
if method == 'oauth':
|
||||
print(f"{COLOR_SELECTION}2.{COLOR_RESET} Revoke OAuth Authorization")
|
||||
print(f" {COLOR_ACTION}→ Remove OAuth token{COLOR_RESET}")
|
||||
|
||||
print(f"{COLOR_SELECTION}3.{COLOR_RESET} Set API Key (Legacy Fallback)")
|
||||
print(f" {COLOR_ACTION}→ Manually enter Nexus API key{COLOR_RESET}")
|
||||
|
||||
if authenticated:
|
||||
print(f"{COLOR_SELECTION}4.{COLOR_RESET} Clear All Authentication")
|
||||
print(f" {COLOR_ACTION}→ Remove both OAuth and API key{COLOR_RESET}")
|
||||
|
||||
print(f"{COLOR_SELECTION}0.{COLOR_RESET} Return to Additional Tasks Menu")
|
||||
|
||||
selection = input(f"\n{COLOR_PROMPT}Enter your selection: {COLOR_RESET}").strip()
|
||||
|
||||
if selection == "1":
|
||||
# OAuth authorization
|
||||
print(f"\n{COLOR_INFO}Starting OAuth authorization...{COLOR_RESET}")
|
||||
print(f"{COLOR_WARNING}Your browser will open shortly.{COLOR_RESET}")
|
||||
print(f"{COLOR_WARNING}Please check your browser and authorize Jackify.{COLOR_RESET}")
|
||||
print(f"\n{COLOR_INFO}Note: Your browser may ask permission to open 'xdg-open' or{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Jackify's protocol handler - please click 'Open' or 'Allow'.{COLOR_RESET}")
|
||||
|
||||
input(f"\n{COLOR_PROMPT}Press Enter to open browser...{COLOR_RESET}")
|
||||
|
||||
# Perform OAuth authorization
|
||||
def show_message(msg):
|
||||
print(f"\n{COLOR_INFO}{msg}{COLOR_RESET}")
|
||||
|
||||
success = auth_service.authorize_oauth(show_browser_message_callback=show_message)
|
||||
|
||||
if success:
|
||||
print(f"\n{COLOR_SUCCESS}OAuth authorization successful!{COLOR_RESET}")
|
||||
# Get username
|
||||
_, _, username = auth_service.get_auth_status()
|
||||
if username:
|
||||
print(f"{COLOR_INFO}Authorized as: {username}{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}OAuth authorization failed.{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}You can try again or use API key as fallback.{COLOR_RESET}")
|
||||
|
||||
input(f"\n{COLOR_PROMPT}Press Enter to continue...{COLOR_RESET}")
|
||||
|
||||
elif selection == "2" and method == 'oauth':
|
||||
# Revoke OAuth
|
||||
print(f"\n{COLOR_WARNING}Are you sure you want to revoke OAuth authorization?{COLOR_RESET}")
|
||||
confirm = input(f"{COLOR_PROMPT}Type 'yes' to confirm: {COLOR_RESET}").strip().lower()
|
||||
|
||||
if confirm == 'yes':
|
||||
if auth_service.revoke_oauth():
|
||||
print(f"\n{COLOR_SUCCESS}OAuth authorization revoked.{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}Failed to revoke OAuth authorization.{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_INFO}Cancelled.{COLOR_RESET}")
|
||||
|
||||
input(f"\n{COLOR_PROMPT}Press Enter to continue...{COLOR_RESET}")
|
||||
|
||||
elif selection == "3":
|
||||
# Set API key
|
||||
print(f"\n{COLOR_INFO}Enter your Nexus API Key{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}(Get it from: https://www.nexusmods.com/users/myaccount?tab=api){COLOR_RESET}")
|
||||
|
||||
api_key = input(f"\n{COLOR_PROMPT}API Key: {COLOR_RESET}").strip()
|
||||
|
||||
if api_key:
|
||||
if auth_service.save_api_key(api_key):
|
||||
print(f"\n{COLOR_SUCCESS}API key saved successfully.{COLOR_RESET}")
|
||||
|
||||
# Optionally validate
|
||||
print(f"\n{COLOR_INFO}Validating API key...{COLOR_RESET}")
|
||||
valid, result = auth_service.validate_api_key(api_key)
|
||||
|
||||
if valid:
|
||||
print(f"{COLOR_SUCCESS}API key validated successfully!{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Username: {result}{COLOR_RESET}")
|
||||
else:
|
||||
print(f"{COLOR_WARNING}Warning: API key validation failed: {result}{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}Key saved, but may not work correctly.{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}Failed to save API key.{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_INFO}Cancelled.{COLOR_RESET}")
|
||||
|
||||
input(f"\n{COLOR_PROMPT}Press Enter to continue...{COLOR_RESET}")
|
||||
|
||||
elif selection == "4" and authenticated:
|
||||
# Clear all authentication
|
||||
print(f"\n{COLOR_WARNING}Are you sure you want to clear ALL authentication?{COLOR_RESET}")
|
||||
print(f"{COLOR_WARNING}This will remove both OAuth token and API key.{COLOR_RESET}")
|
||||
confirm = input(f"{COLOR_PROMPT}Type 'yes' to confirm: {COLOR_RESET}").strip().lower()
|
||||
|
||||
if confirm == 'yes':
|
||||
if auth_service.clear_all_auth():
|
||||
print(f"\n{COLOR_SUCCESS}All authentication cleared.{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_INFO}No authentication to clear.{COLOR_RESET}")
|
||||
else:
|
||||
print(f"\n{COLOR_INFO}Cancelled.{COLOR_RESET}")
|
||||
|
||||
input(f"\n{COLOR_PROMPT}Press Enter to continue...{COLOR_RESET}")
|
||||
|
||||
elif selection == "0":
|
||||
break
|
||||
else:
|
||||
print(f"\n{COLOR_ERROR}Invalid selection.{COLOR_RESET}")
|
||||
time.sleep(1)
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
"""
|
||||
Hoolamike Menu Handler for Jackify CLI Frontend
|
||||
Extracted from src.modules.menu_handler.MenuHandler.show_hoolamike_menu()
|
||||
"""
|
||||
|
||||
from jackify.shared.colors import COLOR_INFO, COLOR_PROMPT, COLOR_RESET
|
||||
|
||||
class HoolamikeMenuHandler:
|
||||
"""
|
||||
Handles the Hoolamike Tasks menu
|
||||
Extracted from legacy MenuHandler class
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.logger = None # Will be set by CLI when needed
|
||||
|
||||
def show_hoolamike_menu(self, cli_instance):
|
||||
"""
|
||||
LEGACY BRIDGE: Delegate to legacy menu handler until full backend migration
|
||||
|
||||
Args:
|
||||
cli_instance: Reference to main CLI instance for access to handlers
|
||||
"""
|
||||
print(f"{COLOR_INFO}Hoolamike menu functionality has been extracted but needs migration to backend services.{COLOR_RESET}")
|
||||
print(f"{COLOR_INFO}This will be implemented in Phase 2.3 (Menu Backend Integration).{COLOR_RESET}")
|
||||
|
||||
# LEGACY BRIDGE: Use the original menu handler's method
|
||||
if hasattr(cli_instance, 'menu') and hasattr(cli_instance.menu, 'show_hoolamike_menu'):
|
||||
cli_instance.menu.show_hoolamike_menu(cli_instance)
|
||||
else:
|
||||
print(f"{COLOR_INFO}Legacy menu handler not available - returning to main menu.{COLOR_RESET}")
|
||||
input(f"{COLOR_PROMPT}Press Enter to continue...{COLOR_RESET}")
|
||||
Reference in New Issue
Block a user