#!/usr/bin/env python3 """ PetBot Prerequisites Installation Script This script installs all required Python packages and dependencies for running PetBot. """ import subprocess import sys import os import importlib.util from pathlib import Path def print_header(): """Print installation header.""" print("=" * 60) print("๐Ÿพ PetBot Prerequisites Installation Script") print("=" * 60) print() def check_python_version(): """Check if Python version is compatible.""" print("๐Ÿ” Checking Python version...") version = sys.version_info required_major = 3 required_minor = 7 if version.major < required_major or (version.major == required_major and version.minor < required_minor): print(f"โŒ Python {required_major}.{required_minor}+ required. Current version: {version.major}.{version.minor}.{version.micro}") print("Please upgrade Python and try again.") return False print(f"โœ… Python {version.major}.{version.minor}.{version.micro} is compatible") return True def check_pip_available(): """Check if pip is available.""" print("\n๐Ÿ” Checking pip availability...") try: import pip print("โœ… pip is available") return True except ImportError: pass # Try alternative ways to check pip try: result = subprocess.run([sys.executable, "-m", "pip", "--version"], capture_output=True, text=True, check=True) print(f"โœ… pip is available: {result.stdout.strip()}") return True except (subprocess.CalledProcessError, FileNotFoundError): print("โŒ pip is not available") print("Please install pip first:") print(" - On Ubuntu/Debian: sudo apt install python3-pip") print(" - On CentOS/RHEL: sudo yum install python3-pip") print(" - On macOS: brew install python3") return False def check_package_installed(package_name): """Check if a package is already installed.""" try: importlib.import_module(package_name) return True except ImportError: return False def install_package(package_spec): """Install a package using pip.""" print(f"๐Ÿ“ฆ Installing {package_spec}...") try: result = subprocess.run([ sys.executable, "-m", "pip", "install", package_spec ], capture_output=True, text=True, check=True) print(f"โœ… Successfully installed {package_spec}") return True except subprocess.CalledProcessError as e: print(f"โŒ Failed to install {package_spec}") print(f"Error output: {e.stderr}") return False def install_requirements(): """Install packages from requirements.txt if it exists.""" print("\n๐Ÿ“‹ Installing packages from requirements.txt...") requirements_file = Path("requirements.txt") if not requirements_file.exists(): print("โŒ requirements.txt not found") return False try: result = subprocess.run([ sys.executable, "-m", "pip", "install", "-r", "requirements.txt" ], capture_output=True, text=True, check=True) print("โœ… Successfully installed packages from requirements.txt") return True except subprocess.CalledProcessError as e: print("โŒ Failed to install from requirements.txt") print(f"Error output: {e.stderr}") return False def install_individual_packages(): """Install individual packages if requirements.txt fails.""" print("\n๐Ÿ“ฆ Installing individual packages...") packages = [ ("irc", "irc>=20.3.0", "IRC client library"), ("aiosqlite", "aiosqlite>=0.19.0", "Async SQLite database interface"), ("dotenv", "python-dotenv>=1.0.0", "Environment variable loading") ] results = [] for import_name, package_spec, description in packages: print(f"\n๐Ÿ” Checking {import_name} ({description})...") if check_package_installed(import_name): print(f"โœ… {import_name} is already installed") results.append(True) else: print(f"โŒ {import_name} is not installed") success = install_package(package_spec) results.append(success) return all(results) def verify_installation(): """Verify that all required packages are installed correctly.""" print("\n๐Ÿ” Verifying installation...") test_imports = [ ("irc", "IRC client library"), ("aiosqlite", "Async SQLite database"), ("dotenv", "Environment variable loading"), ("asyncio", "Async programming (built-in)"), ("sqlite3", "SQLite database (built-in)"), ("json", "JSON handling (built-in)"), ("socket", "Network communication (built-in)"), ("threading", "Threading (built-in)") ] all_good = True for module_name, description in test_imports: try: importlib.import_module(module_name) print(f"โœ… {module_name}: {description}") except ImportError as e: print(f"โŒ {module_name}: {description} - {e}") all_good = False return all_good def check_directory_structure(): """Check if we're in the correct directory and required files exist.""" print("\n๐Ÿ” Checking directory structure...") required_files = [ "requirements.txt", "src/database.py", "src/game_engine.py", "src/bot.py", "webserver.py", "run_bot_debug.py" ] missing_files = [] for file_path in required_files: if not Path(file_path).exists(): missing_files.append(file_path) if missing_files: print("โŒ Missing required files:") for file_path in missing_files: print(f" - {file_path}") print("\nPlease make sure you're running this script from the PetBot project directory.") return False print("โœ… All required files found") return True def create_data_directory(): """Create data directory if it doesn't exist.""" print("\n๐Ÿ” Checking data directory...") data_dir = Path("data") if not data_dir.exists(): try: data_dir.mkdir() print("โœ… Created data directory") except Exception as e: print(f"โŒ Failed to create data directory: {e}") return False else: print("โœ… Data directory already exists") return True def create_backups_directory(): """Create backups directory if it doesn't exist.""" print("\n๐Ÿ” Checking backups directory...") backups_dir = Path("backups") if not backups_dir.exists(): try: backups_dir.mkdir() print("โœ… Created backups directory") except Exception as e: print(f"โŒ Failed to create backups directory: {e}") return False else: print("โœ… Backups directory already exists") return True def test_basic_imports(): """Test basic functionality by importing key modules.""" print("\n๐Ÿงช Testing basic imports...") try: # Test database import sys.path.append(os.path.dirname(os.path.abspath(__file__))) from src.database import Database print("โœ… Database module imports successfully") # Test connection manager import from src.irc_connection_manager import IRCConnectionManager print("โœ… IRC connection manager imports successfully") # Test backup manager import from src.backup_manager import BackupManager print("โœ… Backup manager imports successfully") return True except ImportError as e: print(f"โŒ Import test failed: {e}") return False def show_next_steps(): """Show next steps after successful installation.""" print("\n๐ŸŽ‰ Installation completed successfully!") print("\n๐Ÿ“‹ Next steps:") print("1. Review and update configuration files in the config/ directory") print("2. Test the bot with: python3 run_bot_debug.py") print("3. Or use the new reconnection system: python3 run_bot_with_reconnect.py") print("4. Check the web interface at: http://localhost:8080") print("5. Review CLAUDE.md for development guidelines") print("\n๐Ÿ”ง Available test commands:") print(" python3 test_backup_simple.py - Test backup system") print(" python3 test_reconnection.py - Test IRC reconnection") print("\n๐Ÿ“š Documentation:") print(" README.md - Project overview") print(" CLAUDE.md - Development guide") print(" TODO.md - Current status") print(" issues.txt - Security audit findings") print(" BACKUP_SYSTEM_INTEGRATION.md - Backup system guide") def main(): """Main installation function.""" print_header() # Check prerequisites if not check_python_version(): return False if not check_pip_available(): return False if not check_directory_structure(): return False # Create directories if not create_data_directory(): return False if not create_backups_directory(): return False # Install packages success = install_requirements() if not success: print("\nโš ๏ธ requirements.txt installation failed, trying individual packages...") success = install_individual_packages() if not success: print("\nโŒ Package installation failed") return False # Verify installation if not verify_installation(): print("\nโŒ Installation verification failed") return False # Test imports if not test_basic_imports(): print("\nโŒ Basic import tests failed") return False # Show next steps show_next_steps() return True if __name__ == "__main__": try: success = main() if success: print("\nโœ… PetBot prerequisites installation completed successfully!") sys.exit(0) else: print("\nโŒ Installation failed. Please check the errors above.") sys.exit(1) except KeyboardInterrupt: print("\n๐Ÿ›‘ Installation interrupted by user") sys.exit(1) except Exception as e: print(f"\n๐Ÿ’ฅ Unexpected error: {e}") import traceback traceback.print_exc() sys.exit(1)