Files
cursor-free-vip-main/bypass_version.py
XnsYT fe445cc298 feat: Add enhanced configuration, error handling and utility systems v1.11.04
## 🚀 Enhanced Features Implementation

This PR introduces significant improvements to the Cursor Free VIP project with enhanced configuration management, error handling, and utility systems.

###  New Features

#### 🔧 Enhanced Configuration Management (`enhanced_config.py`)
- **Multi-format support**: INI, JSON, YAML configuration formats
- **Automatic validation**: Built-in configuration validation with detailed error reporting
- **Backup system**: Automatic configuration backup and restore functionality
- **Platform-specific paths**: Automatic detection and management of paths for Windows, macOS, and Linux
- **Type safety**: Improved type checking and error handling

#### 🛡️ Enhanced Error Handling (`enhanced_error_handler.py`)
- **Automatic categorization**: Intelligent error classification (Network, File System, Process, etc.)
- **Severity-based logging**: Critical, High, Medium, Low severity levels
- **Recovery strategies**: Automatic retry logic with exponential backoff
- **Error history**: Comprehensive error tracking and resolution management
- **Custom callbacks**: Registerable error handlers for specific categories

#### 🛠️ Enhanced Utility System (`enhanced_utils.py`)
- **Advanced path management**: Cross-platform path detection and validation
- **Multi-browser support**: Automatic detection of Chrome, Firefox, Edge, Brave, Opera
- **Process monitoring**: Real-time process tracking and management
- **System information**: Detailed system resource monitoring
- **Network connectivity**: Automated network testing and validation

### 🔧 Technical Improvements

- **Type safety**: Fixed all linter errors and type annotation issues
- **Code robustness**: Improved error handling and exception management
- **Maintainability**: Better code organization and documentation
- **Cross-platform compatibility**: Enhanced support for Windows, macOS, and Linux

### �� Files Changed

- `enhanced_config.py` - New enhanced configuration management system
- `enhanced_utils.py` - New enhanced utility and system management
- `enhanced_error_handler.py` - New enhanced error handling system
- `CHANGELOG.md` - Updated with v1.11.04 release notes

### �� Testing

- All new systems have been tested on Windows, macOS, and Linux
- Type checking passes with no linter errors
- Backward compatibility maintained with existing functionality

### 📝 Documentation

- Comprehensive inline documentation for all new features
- Updated CHANGELOG with detailed feature descriptions
- Follows existing code style and conventions

---

**Note**: These enhancements provide a solid foundation for future development while maintaining full backward compatibility with existing functionality.
2025-07-10 18:46:02 +02:00

282 lines
12 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import json
import shutil
import platform
import configparser
import time
import logging
from colorama import Fore, Style, init
import sys
import traceback
from pathlib import Path
from typing import Optional, Dict, List, Union, Tuple, Any
from utils import get_user_documents_path
# Initialize colorama
init(autoreset=True)
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
logger = logging.getLogger(__name__)
# Define emoji constants
EMOJI = {
'INFO': '',
'SUCCESS': '',
'ERROR': '',
'WARNING': '⚠️',
'FILE': '📄',
'BACKUP': '💾',
'RESET': '🔄',
'VERSION': '🏷️'
}
def get_product_json_path(translator: Any = None) -> str:
"""Get Cursor product.json path based on the operating system.
Args:
translator: Optional translator for internationalization
Returns:
str: Path to the product.json file
Raises:
OSError: If the file is not found or the OS is not supported
"""
system = platform.system()
# Read configuration
config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip")
config_file = os.path.join(config_dir, "config.ini")
config = configparser.ConfigParser()
if os.path.exists(config_file):
config.read(config_file)
# Define paths for different operating systems
if system == "Windows":
localappdata = os.environ.get("LOCALAPPDATA")
if not localappdata:
error_msg = "LOCALAPPDATA environment variable not found"
logger.error(error_msg)
raise OSError(translator.get('bypass.localappdata_not_found') if translator else error_msg)
product_json_path = os.path.join(localappdata, "Programs", "Cursor", "resources", "app", "product.json")
# Check if path exists in config
if 'WindowsPaths' in config and 'cursor_path' in config['WindowsPaths']:
cursor_path = config.get('WindowsPaths', 'cursor_path')
product_json_path = os.path.join(cursor_path, "product.json")
elif system == "Darwin": # macOS
product_json_path = "/Applications/Cursor.app/Contents/Resources/app/product.json"
if config.has_section('MacPaths') and config.has_option('MacPaths', 'product_json_path'):
product_json_path = config.get('MacPaths', 'product_json_path')
elif system == "Linux":
# Try multiple common paths
possible_paths = [
"/opt/Cursor/resources/app/product.json",
"/usr/share/cursor/resources/app/product.json",
"/usr/lib/cursor/app/product.json"
]
# Add extracted AppImage paths
extracted_usr_paths = os.path.expanduser("~/squashfs-root/usr/share/cursor/resources/app/product.json")
if os.path.exists(extracted_usr_paths):
possible_paths.append(extracted_usr_paths)
# Find first existing path
for path in possible_paths:
if os.path.exists(path):
product_json_path = path
break
else:
error_msg = "product.json not found in common Linux paths"
logger.error(error_msg)
raise OSError(translator.get('bypass.product_json_not_found') if translator else error_msg)
else:
error_msg = f"Unsupported operating system: {system}"
logger.error(error_msg)
raise OSError(translator.get('bypass.unsupported_os', system=system) if translator else error_msg)
# Verify that the file exists
if not os.path.exists(product_json_path):
error_msg = f"File not found: {product_json_path}"
logger.error(error_msg)
raise OSError(translator.get('bypass.file_not_found', path=product_json_path) if translator else error_msg)
logger.info(f"Found product.json at: {product_json_path}")
return product_json_path
def compare_versions(version1: str, version2: str) -> int:
"""Compare two version strings.
Args:
version1: First version string (e.g., "0.48.7")
version2: Second version string (e.g., "0.46.0")
Returns:
int: -1 if version1 < version2, 0 if version1 == version2, 1 if version1 > version2
"""
try:
v1_parts = [int(x) for x in version1.split('.')]
v2_parts = [int(x) for x in version2.split('.')]
for i in range(max(len(v1_parts), len(v2_parts))):
v1 = v1_parts[i] if i < len(v1_parts) else 0
v2 = v2_parts[i] if i < len(v2_parts) else 0
if v1 < v2:
return -1
elif v1 > v2:
return 1
return 0
except (ValueError, TypeError) as e:
logger.warning(f"Error comparing versions {version1} and {version2}: {e}")
# Fall back to string comparison if numeric comparison fails
if version1 < version2:
return -1
elif version1 > version2:
return 1
else:
return 0
def bypass_version(translator: Any = None) -> bool:
"""Bypass Cursor version check by modifying product.json.
Args:
translator: Optional translator for internationalization
Returns:
bool: True if the version was successfully bypassed, False otherwise
"""
try:
print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('bypass.starting') if translator else 'Starting Cursor version bypass...'}{Style.RESET_ALL}")
# Get product.json path
product_json_path = get_product_json_path(translator)
print(f"{Fore.CYAN}{EMOJI['FILE']} {translator.get('bypass.found_product_json', path=product_json_path) if translator else f'Found product.json: {product_json_path}'}{Style.RESET_ALL}")
# Check file permissions
if not os.access(product_json_path, os.W_OK):
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.no_write_permission', path=product_json_path) if translator else f'No write permission for file: {product_json_path}'}{Style.RESET_ALL}")
return False
# Read product.json
try:
with open(product_json_path, "r", encoding="utf-8") as f:
product_data = json.load(f)
except json.JSONDecodeError as e:
logger.error(f"Invalid JSON in product.json: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.invalid_json', error=str(e)) if translator else f'Invalid JSON in product.json: {str(e)}'}{Style.RESET_ALL}")
return False
except Exception as e:
logger.error(f"Failed to read product.json: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.read_failed', error=str(e)) if translator else f'Failed to read product.json: {str(e)}'}{Style.RESET_ALL}")
return False
# Get current version
current_version = product_data.get("version", "0.0.0")
print(f"{Fore.CYAN}{EMOJI['VERSION']} {translator.get('bypass.current_version', version=current_version) if translator else f'Current version: {current_version}'}{Style.RESET_ALL}")
# Target version to set
new_version = "0.48.7"
# Check if version needs to be modified
if compare_versions(current_version, "0.46.0") < 0:
# Create backup
timestamp = time.strftime("%Y%m%d%H%M%S")
backup_path = f"{product_json_path}.{timestamp}"
try:
shutil.copy2(product_json_path, backup_path)
print(f"{Fore.GREEN}{EMOJI['BACKUP']} {translator.get('bypass.backup_created', path=backup_path) if translator else f'Backup created: {backup_path}'}{Style.RESET_ALL}")
except Exception as e:
logger.error(f"Failed to create backup: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.backup_failed', error=str(e)) if translator else f'Failed to create backup: {str(e)}'}{Style.RESET_ALL}")
return False
# Modify version
product_data["version"] = new_version
# Save modified product.json
try:
with open(product_json_path, "w", encoding="utf-8") as f:
json.dump(product_data, f, indent=2)
logger.info(f"Version updated from {current_version} to {new_version}")
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('bypass.version_updated', old=current_version, new=new_version) if translator else f'Version updated from {current_version} to {new_version}'}{Style.RESET_ALL}")
return True
except Exception as e:
logger.error(f"Failed to write product.json: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.write_failed', error=str(e)) if translator else f'Failed to write product.json: {str(e)}'}{Style.RESET_ALL}")
# Try to restore from backup if write fails
try:
if os.path.exists(backup_path):
shutil.copy2(backup_path, product_json_path)
print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('bypass.restored_from_backup') if translator else 'Restored from backup'}{Style.RESET_ALL}")
except Exception as restore_error:
logger.error(f"Failed to restore from backup: {restore_error}")
return False
else:
print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('bypass.no_update_needed', version=current_version) if translator else f'No update needed. Current version {current_version} is already >= 0.46.0'}{Style.RESET_ALL}")
return True
except Exception as e:
logger.error(f"Version bypass failed: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('bypass.bypass_failed', error=str(e)) if translator else f'Version bypass failed: {str(e)}'}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('bypass.stack_trace') if translator else 'Stack trace'}: {traceback.format_exc()}{Style.RESET_ALL}")
return False
def run(translator: Any = None) -> bool:
"""Main function to run the version bypass.
Args:
translator: Optional translator for internationalization
Returns:
bool: True if successful, False otherwise
"""
try:
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('bypass_version.title') if translator else 'Bypass Version Check'}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
success = bypass_version(translator)
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
input(f"{EMOJI['INFO']} {translator.get('bypass_version.press_enter') if translator else 'Press Enter to continue...'}")
return success
except Exception as e:
logger.error(f"Error in run function: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} An unexpected error occurred: {str(e)}{Style.RESET_ALL}")
return False
def main(translator: Any = None) -> bool:
"""Entry point when called directly.
Args:
translator: Optional translator for internationalization
Returns:
bool: True if successful, False otherwise
"""
return run(translator)
if __name__ == "__main__":
try:
from main import translator as main_translator
main(main_translator)
except ImportError:
logger.warning("Failed to import translator from main.py, running without translation")
main(None)
except Exception as e:
logger.error(f"Error running bypass_version.py: {e}")
print(f"{Fore.RED}{EMOJI['ERROR']} An unexpected error occurred: {str(e)}{Style.RESET_ALL}")