Major Features Added: - Complete token bucket rate limiting for IRC commands and web interface - Per-user rate tracking with category-based limits (Basic, Gameplay, Management, Admin, Web) - Admin commands for rate limit management (\!rate_stats, \!rate_user, \!rate_unban, \!rate_reset) - Automatic violation tracking and temporary bans with cleanup - Global item spawn multiplier system with 75% spawn rate reduction - Central admin configuration system (config.py) - One-command bot startup script (start_petbot.sh) Rate Limiting: - Token bucket algorithm with burst capacity and refill rates - Category limits: Basic (20/min), Gameplay (10/min), Management (5/min), Web (60/min) - Graceful violation handling with user-friendly error messages - Admin exemption and override capabilities - Background cleanup of old violations and expired bans Item Spawn System: - Added global_spawn_multiplier to config/items.json for easy adjustment - Reduced all individual spawn rates by 75% (multiplied by 0.25) - Admins can fine-tune both global multiplier and individual item rates - Game engine integration applies multiplier to all spawn calculations Infrastructure: - Single admin user configuration in config.py - Enhanced startup script with dependency management and verification - Updated documentation and help system with rate limiting guide - Comprehensive test suite for rate limiting functionality Security: - Rate limiting protects against command spam and abuse - IP-based tracking for web interface requests - Proper error handling and status codes (429 for rate limits) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
376 lines
No EOL
12 KiB
Python
Executable file
376 lines
No EOL
12 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""
|
|
PetBot Prerequisites Installation Script (Fixed for externally-managed-environment)
|
|
This script handles the externally-managed-environment error by using virtual environments.
|
|
"""
|
|
|
|
import subprocess
|
|
import sys
|
|
import os
|
|
import importlib.util
|
|
import venv
|
|
from pathlib import Path
|
|
|
|
|
|
def print_header():
|
|
"""Print installation header."""
|
|
print("=" * 60)
|
|
print("🐾 PetBot Prerequisites Installation Script (Fixed)")
|
|
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_venv_available():
|
|
"""Check if venv module is available."""
|
|
print("\n🔍 Checking venv availability...")
|
|
|
|
try:
|
|
import venv
|
|
print("✅ venv module is available")
|
|
return True
|
|
except ImportError:
|
|
print("❌ venv module is not available")
|
|
print("Please install python3-venv:")
|
|
print(" Ubuntu/Debian: sudo apt install python3-venv")
|
|
print(" CentOS/RHEL: sudo yum install python3-venv")
|
|
return False
|
|
|
|
|
|
def create_virtual_environment():
|
|
"""Create a virtual environment for the project."""
|
|
print("\n🔧 Creating virtual environment...")
|
|
|
|
venv_path = Path("venv")
|
|
|
|
if venv_path.exists():
|
|
print("✅ Virtual environment already exists")
|
|
return str(venv_path)
|
|
|
|
try:
|
|
venv.create(venv_path, with_pip=True)
|
|
print("✅ Virtual environment created successfully")
|
|
return str(venv_path)
|
|
except Exception as e:
|
|
print(f"❌ Failed to create virtual environment: {e}")
|
|
return None
|
|
|
|
|
|
def get_venv_python_path(venv_path):
|
|
"""Get the Python executable path in the virtual environment."""
|
|
if os.name == 'nt': # Windows
|
|
return os.path.join(venv_path, 'Scripts', 'python.exe')
|
|
else: # Linux/macOS
|
|
return os.path.join(venv_path, 'bin', 'python')
|
|
|
|
|
|
def get_venv_pip_path(venv_path):
|
|
"""Get the pip executable path in the virtual environment."""
|
|
if os.name == 'nt': # Windows
|
|
return os.path.join(venv_path, 'Scripts', 'pip.exe')
|
|
else: # Linux/macOS
|
|
return os.path.join(venv_path, 'bin', 'pip')
|
|
|
|
|
|
def install_packages_in_venv(venv_path):
|
|
"""Install packages in the virtual environment."""
|
|
print("\n📦 Installing packages in virtual environment...")
|
|
|
|
venv_pip = get_venv_pip_path(venv_path)
|
|
|
|
if not os.path.exists(venv_pip):
|
|
print("❌ pip not found in virtual environment")
|
|
return False
|
|
|
|
# Upgrade pip first
|
|
print("🔄 Upgrading pip...")
|
|
try:
|
|
subprocess.run([venv_pip, "install", "--upgrade", "pip"], check=True, capture_output=True)
|
|
print("✅ pip upgraded successfully")
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"⚠️ pip upgrade failed: {e}")
|
|
|
|
# Install from requirements.txt
|
|
requirements_file = Path("requirements.txt")
|
|
if requirements_file.exists():
|
|
print("📋 Installing from requirements.txt...")
|
|
try:
|
|
result = subprocess.run([venv_pip, "install", "-r", "requirements.txt"],
|
|
check=True, capture_output=True, text=True)
|
|
print("✅ Successfully installed packages from requirements.txt")
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"❌ Failed to install from requirements.txt: {e.stderr}")
|
|
|
|
# Install individual packages
|
|
print("📦 Installing individual packages...")
|
|
packages = [
|
|
"irc>=20.3.0",
|
|
"aiosqlite>=0.19.0",
|
|
"python-dotenv>=1.0.0"
|
|
]
|
|
|
|
success = True
|
|
for package in packages:
|
|
print(f"Installing {package}...")
|
|
try:
|
|
subprocess.run([venv_pip, "install", package], check=True, capture_output=True)
|
|
print(f"✅ Successfully installed {package}")
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"❌ Failed to install {package}")
|
|
success = False
|
|
|
|
return success
|
|
|
|
|
|
def verify_installation_in_venv(venv_path):
|
|
"""Verify installation in virtual environment."""
|
|
print("\n🔍 Verifying installation in virtual environment...")
|
|
|
|
venv_python = get_venv_python_path(venv_path)
|
|
|
|
test_modules = [
|
|
"irc",
|
|
"aiosqlite",
|
|
"dotenv",
|
|
"asyncio",
|
|
"sqlite3",
|
|
"json",
|
|
"socket"
|
|
]
|
|
|
|
all_good = True
|
|
|
|
for module in test_modules:
|
|
try:
|
|
result = subprocess.run([venv_python, "-c", f"import {module}"],
|
|
check=True, capture_output=True)
|
|
print(f"✅ {module}: Available")
|
|
except subprocess.CalledProcessError:
|
|
print(f"❌ {module}: Not available")
|
|
all_good = False
|
|
|
|
return all_good
|
|
|
|
|
|
def create_activation_script():
|
|
"""Create a script to activate the virtual environment."""
|
|
print("\n🔧 Creating activation script...")
|
|
|
|
activation_script = """#!/bin/bash
|
|
# PetBot Virtual Environment Activation Script
|
|
|
|
echo "🐾 Activating PetBot virtual environment..."
|
|
|
|
if [ -d "venv" ]; then
|
|
source venv/bin/activate
|
|
echo "✅ Virtual environment activated"
|
|
echo "🚀 You can now run:"
|
|
echo " python run_bot_with_reconnect.py"
|
|
echo " python test_backup_simple.py"
|
|
echo " python test_reconnection.py"
|
|
echo ""
|
|
echo "💡 To deactivate: deactivate"
|
|
else
|
|
echo "❌ Virtual environment not found"
|
|
echo "Run: python3 install_prerequisites_fixed.py"
|
|
fi
|
|
"""
|
|
|
|
try:
|
|
with open("activate_petbot.sh", "w") as f:
|
|
f.write(activation_script)
|
|
os.chmod("activate_petbot.sh", 0o755)
|
|
print("✅ Created activate_petbot.sh")
|
|
return True
|
|
except Exception as e:
|
|
print(f"❌ Failed to create activation script: {e}")
|
|
return False
|
|
|
|
|
|
def create_run_scripts():
|
|
"""Create wrapper scripts that use the virtual environment."""
|
|
print("\n🔧 Creating wrapper scripts...")
|
|
|
|
scripts = {
|
|
"run_petbot.sh": """#!/bin/bash
|
|
# PetBot Runner Script (uses virtual environment)
|
|
|
|
if [ -d "venv" ]; then
|
|
source venv/bin/activate
|
|
echo "🚀 Starting PetBot with auto-reconnect..."
|
|
python run_bot_with_reconnect.py
|
|
else
|
|
echo "❌ Virtual environment not found"
|
|
echo "Run: python3 install_prerequisites_fixed.py"
|
|
fi
|
|
""",
|
|
"run_petbot_debug.sh": """#!/bin/bash
|
|
# PetBot Debug Runner Script (uses virtual environment)
|
|
|
|
if [ -d "venv" ]; then
|
|
source venv/bin/activate
|
|
echo "🚀 Starting PetBot in debug mode..."
|
|
python run_bot_debug.py
|
|
else
|
|
echo "❌ Virtual environment not found"
|
|
echo "Run: python3 install_prerequisites_fixed.py"
|
|
fi
|
|
""",
|
|
"test_petbot.sh": """#!/bin/bash
|
|
# PetBot Test Script (uses virtual environment)
|
|
|
|
if [ -d "venv" ]; then
|
|
source venv/bin/activate
|
|
echo "🧪 Running PetBot tests..."
|
|
echo "1. Testing backup system..."
|
|
python test_backup_simple.py
|
|
echo ""
|
|
echo "2. Testing reconnection system..."
|
|
python test_reconnection.py
|
|
else
|
|
echo "❌ Virtual environment not found"
|
|
echo "Run: python3 install_prerequisites_fixed.py"
|
|
fi
|
|
"""
|
|
}
|
|
|
|
success = True
|
|
for script_name, script_content in scripts.items():
|
|
try:
|
|
with open(script_name, "w") as f:
|
|
f.write(script_content)
|
|
os.chmod(script_name, 0o755)
|
|
print(f"✅ Created {script_name}")
|
|
except Exception as e:
|
|
print(f"❌ Failed to create {script_name}: {e}")
|
|
success = False
|
|
|
|
return success
|
|
|
|
|
|
def create_directories():
|
|
"""Create required directories."""
|
|
print("\n🔧 Creating required directories...")
|
|
|
|
directories = ["data", "backups", "logs"]
|
|
|
|
for directory in directories:
|
|
dir_path = Path(directory)
|
|
if not dir_path.exists():
|
|
try:
|
|
dir_path.mkdir()
|
|
print(f"✅ Created {directory}/ directory")
|
|
except Exception as e:
|
|
print(f"❌ Failed to create {directory}/ directory: {e}")
|
|
return False
|
|
else:
|
|
print(f"✅ {directory}/ directory already exists")
|
|
|
|
return True
|
|
|
|
|
|
def show_usage_instructions():
|
|
"""Show usage instructions after installation."""
|
|
print("\n🎉 Installation completed successfully!")
|
|
print("\n📋 How to use PetBot:")
|
|
print("\n🔧 Method 1: Using activation script (recommended)")
|
|
print(" ./activate_petbot.sh")
|
|
print(" python run_bot_with_reconnect.py")
|
|
print("\n🔧 Method 2: Using wrapper scripts")
|
|
print(" ./run_petbot.sh # Start bot with auto-reconnect")
|
|
print(" ./run_petbot_debug.sh # Start bot in debug mode")
|
|
print(" ./test_petbot.sh # Run tests")
|
|
print("\n🔧 Method 3: Manual activation")
|
|
print(" source venv/bin/activate")
|
|
print(" python run_bot_with_reconnect.py")
|
|
print(" deactivate # when done")
|
|
print("\n📚 Documentation:")
|
|
print(" QUICKSTART.md # Quick start guide")
|
|
print(" INSTALLATION.md # Detailed installation guide")
|
|
print(" CLAUDE.md # Development guidelines")
|
|
print("\n🌐 Web Interface:")
|
|
print(" http://localhost:8080 # Access after starting bot")
|
|
print("\n⚠️ Important Notes:")
|
|
print(" - Always activate the virtual environment before running Python scripts")
|
|
print(" - Use the wrapper scripts for convenience")
|
|
print(" - The virtual environment is in the 'venv' directory")
|
|
|
|
|
|
def main():
|
|
"""Main installation function."""
|
|
print_header()
|
|
|
|
# Check prerequisites
|
|
if not check_python_version():
|
|
return False
|
|
|
|
if not check_venv_available():
|
|
return False
|
|
|
|
# Create virtual environment
|
|
venv_path = create_virtual_environment()
|
|
if not venv_path:
|
|
return False
|
|
|
|
# Install packages in virtual environment
|
|
if not install_packages_in_venv(venv_path):
|
|
print("\n❌ Package installation failed")
|
|
return False
|
|
|
|
# Verify installation
|
|
if not verify_installation_in_venv(venv_path):
|
|
print("\n❌ Installation verification failed")
|
|
return False
|
|
|
|
# Create directories
|
|
if not create_directories():
|
|
return False
|
|
|
|
# Create helper scripts
|
|
if not create_activation_script():
|
|
return False
|
|
|
|
if not create_run_scripts():
|
|
return False
|
|
|
|
# Show usage instructions
|
|
show_usage_instructions()
|
|
|
|
return True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
success = main()
|
|
if success:
|
|
print("\n✅ PetBot virtual environment setup completed successfully!")
|
|
print("🚀 Use './run_petbot.sh' to start the bot")
|
|
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) |