mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-03 13:07:35 +08:00
feat: Implement Cursor version bypass tool with multilingual support
- Updated version to 1.8.07 in .env file. - Added bypass_version.py to modify product.json for bypassing version checks. - Enhanced user experience with multilingual support for bypass messages in English, Chinese (Simplified and Traditional). - Updated CHANGELOG.md to reflect new features and fixes.
This commit is contained in:
parent
c48c35fd09
commit
849ec5ea8d
@ -1,5 +1,10 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## v1.8.07
|
||||||
|
1. Add: Bypass Cursor Version Check | 添加繞過 Cursor 版本檢查
|
||||||
|
2. Add: Multilanguage support for bypass | 添加繞過的多語言支持
|
||||||
|
3. Fix: Some Issues | 修復一些問題
|
||||||
|
|
||||||
## v1.8.06
|
## v1.8.06
|
||||||
1. Add: Google Account Deletion Feature | 添加 Google 账号删除功能
|
1. Add: Google Account Deletion Feature | 添加 Google 账号删除功能
|
||||||
2. Update: Menu with new account deletion option | 更新菜单添加账号删除选项
|
2. Update: Menu with new account deletion option | 更新菜单添加账号删除选项
|
||||||
|
158
bypass_version.py
Normal file
158
bypass_version.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
import platform
|
||||||
|
import configparser
|
||||||
|
import time
|
||||||
|
from colorama import Fore, Style, init
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
from utils import get_user_documents_path
|
||||||
|
|
||||||
|
# Initialize colorama
|
||||||
|
init()
|
||||||
|
|
||||||
|
# Define emoji constants
|
||||||
|
EMOJI = {
|
||||||
|
'INFO': 'ℹ️',
|
||||||
|
'SUCCESS': '✅',
|
||||||
|
'ERROR': '❌',
|
||||||
|
'WARNING': '⚠️',
|
||||||
|
'FILE': '📄',
|
||||||
|
'BACKUP': '💾',
|
||||||
|
'RESET': '🔄',
|
||||||
|
'VERSION': '🏷️'
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_product_json_path(translator=None):
|
||||||
|
"""Get Cursor product.json path"""
|
||||||
|
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)
|
||||||
|
|
||||||
|
if system == "Windows":
|
||||||
|
localappdata = os.environ.get("LOCALAPPDATA")
|
||||||
|
if not localappdata:
|
||||||
|
raise OSError(translator.get('bypass.localappdata_not_found') if translator else "LOCALAPPDATA environment variable not found")
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
for path in possible_paths:
|
||||||
|
if os.path.exists(path):
|
||||||
|
product_json_path = path
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise OSError(translator.get('bypass.product_json_not_found') if translator else "product.json not found in common Linux paths")
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise OSError(translator.get('bypass.unsupported_os', system=system) if translator else f"Unsupported operating system: {system}")
|
||||||
|
|
||||||
|
if not os.path.exists(product_json_path):
|
||||||
|
raise OSError(translator.get('bypass.file_not_found', path=product_json_path) if translator else f"File not found: {product_json_path}")
|
||||||
|
|
||||||
|
return product_json_path
|
||||||
|
|
||||||
|
def compare_versions(version1, version2):
|
||||||
|
"""Compare two version strings"""
|
||||||
|
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
|
||||||
|
|
||||||
|
def bypass_version(translator=None):
|
||||||
|
"""Bypass Cursor version check by modifying product.json"""
|
||||||
|
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 Exception as 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}")
|
||||||
|
|
||||||
|
# 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}"
|
||||||
|
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}")
|
||||||
|
|
||||||
|
# Modify version
|
||||||
|
new_version = "0.48.7"
|
||||||
|
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)
|
||||||
|
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:
|
||||||
|
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}")
|
||||||
|
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:
|
||||||
|
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 main(translator=None):
|
||||||
|
"""Main function"""
|
||||||
|
return bypass_version(translator)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -669,5 +669,25 @@
|
|||||||
"found_email": "Found email: {email}",
|
"found_email": "Found email: {email}",
|
||||||
"email_not_found": "Email not found: {error}",
|
"email_not_found": "Email not found: {error}",
|
||||||
"confirm_prompt": "Are you sure you want to proceed? (y/N): "
|
"confirm_prompt": "Are you sure you want to proceed? (y/N): "
|
||||||
|
},
|
||||||
|
"bypass": {
|
||||||
|
"starting": "Starting Cursor version bypass...",
|
||||||
|
"found_product_json": "Found product.json: {path}",
|
||||||
|
"no_write_permission": "No write permission for file: {path}",
|
||||||
|
"read_failed": "Failed to read product.json: {error}",
|
||||||
|
"current_version": "Current version: {version}",
|
||||||
|
"backup_created": "Backup created: {path}",
|
||||||
|
"version_updated": "Version updated from {old} to {new}",
|
||||||
|
"write_failed": "Failed to write product.json: {error}",
|
||||||
|
"no_update_needed": "No update needed. Current version {version} is already >= 0.46.0",
|
||||||
|
"bypass_failed": "Version bypass failed: {error}",
|
||||||
|
"stack_trace": "Stack trace",
|
||||||
|
"localappdata_not_found": "LOCALAPPDATA environment variable not found",
|
||||||
|
"product_json_not_found": "product.json not found in common Linux paths",
|
||||||
|
"unsupported_os": "Unsupported operating system: {system}",
|
||||||
|
"file_not_found": "File not found: {path}",
|
||||||
|
"title": "Cursor Version Bypass Tool",
|
||||||
|
"description": "This tool modifies Cursor's product.json to bypass version restrictions",
|
||||||
|
"menu_option": "Bypass Cursor Version Check"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -647,5 +647,25 @@
|
|||||||
"email_not_found": "未找到邮箱: {error}",
|
"email_not_found": "未找到邮箱: {error}",
|
||||||
"found_danger_zone": "已找到危险区域部分",
|
"found_danger_zone": "已找到危险区域部分",
|
||||||
"confirm_prompt": "您确定要继续吗?(y/N): "
|
"confirm_prompt": "您确定要继续吗?(y/N): "
|
||||||
|
},
|
||||||
|
"bypass": {
|
||||||
|
"starting": "开始绕过 Cursor 版本限制...",
|
||||||
|
"found_product_json": "找到 product.json: {path}",
|
||||||
|
"no_write_permission": "没有写入权限: {path}",
|
||||||
|
"read_failed": "读取 product.json 失败: {error}",
|
||||||
|
"current_version": "当前版本: {version}",
|
||||||
|
"backup_created": "备份创建: {path}",
|
||||||
|
"version_updated": "版本从 {old} 更新到 {new}",
|
||||||
|
"write_failed": "写入 product.json 失败: {error}",
|
||||||
|
"no_update_needed": "不需要更新。当前版本 {version} 已 >= 0.46.0",
|
||||||
|
"bypass_failed": "绕过版本限制失败: {error}",
|
||||||
|
"stack_trace": "堆栈跟踪",
|
||||||
|
"localappdata_not_found": "LOCALAPPDATA 环境变量未找到",
|
||||||
|
"product_json_not_found": "product.json 未在常见 Linux 路径中找到",
|
||||||
|
"unsupported_os": "不支持的操作系统: {system}",
|
||||||
|
"file_not_found": "文件未找到: {path}",
|
||||||
|
"title": "Cursor 版本绕过工具",
|
||||||
|
"description": "此工具修改 Cursor 的 product.json 以绕过版本限制",
|
||||||
|
"menu_option": "绕过 Cursor 版本检查"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -629,5 +629,25 @@
|
|||||||
"found_danger_zone": "已找到危險區域部分",
|
"found_danger_zone": "已找到危險區域部分",
|
||||||
"confirm_prompt": "您確定要繼續嗎?(y/N): ",
|
"confirm_prompt": "您確定要繼續嗎?(y/N): ",
|
||||||
"typed_delete_js": "已使用 JavaScript 輸入\"Delete\""
|
"typed_delete_js": "已使用 JavaScript 輸入\"Delete\""
|
||||||
|
},
|
||||||
|
"bypass": {
|
||||||
|
"starting": "開始繞過 Cursor 版本限制...",
|
||||||
|
"found_product_json": "找到 product.json: {path}",
|
||||||
|
"no_write_permission": "沒有寫入權限: {path}",
|
||||||
|
"read_failed": "讀取 product.json 失敗: {error}",
|
||||||
|
"current_version": "當前版本: {version}",
|
||||||
|
"backup_created": "備份已創建: {path}",
|
||||||
|
"version_updated": "版本從 {old} 更新到 {new}",
|
||||||
|
"write_failed": "寫入 product.json 失敗: {error}",
|
||||||
|
"no_update_needed": "不需要更新。當前版本 {version} 已 >= 0.46.0",
|
||||||
|
"bypass_failed": "繞過版本限制失敗: {error}",
|
||||||
|
"stack_trace": "堆疊跟踪",
|
||||||
|
"localappdata_not_found": "LOCALAPPDATA 環境變量未找到",
|
||||||
|
"product_json_not_found": "product.json 未在常見 Linux 路徑中找到",
|
||||||
|
"unsupported_os": "不支持的操作系統: {system}",
|
||||||
|
"file_not_found": "文件未找到: {path}",
|
||||||
|
"title": "Cursor 版本繞過工具",
|
||||||
|
"description": "此工具修改 Cursor 的 product.json 以繞過版本限制",
|
||||||
|
"menu_option": "繞過 Cursor 版本檢查"
|
||||||
}
|
}
|
||||||
}
|
}
|
4
main.py
4
main.py
@ -275,8 +275,8 @@ def print_menu():
|
|||||||
0: f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}",
|
0: f"{Fore.GREEN}0{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.exit')}",
|
||||||
1: f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}",
|
1: f"{Fore.GREEN}1{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.reset')}",
|
||||||
2: f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL})",
|
2: f"{Fore.GREEN}2{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL})",
|
||||||
3: f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['SUN']} {translator.get('menu.register_google')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')}{Style.RESET_ALL})",
|
3: f"{Fore.GREEN}3{Style.RESET_ALL}. {EMOJI['SUN']} {translator.get('menu.register_google')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL}))",
|
||||||
4: f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['STAR']} {translator.get('menu.register_github')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')}{Style.RESET_ALL})",
|
4: f"{Fore.GREEN}4{Style.RESET_ALL}. {EMOJI['STAR']} {translator.get('menu.register_github')} {EMOJI['ROCKET']} ({Fore.YELLOW}{translator.get('menu.lifetime_access_enabled')} ({Fore.RED}{translator.get('menu.outdate')}{Style.RESET_ALL}))",
|
||||||
5: f"{Fore.GREEN}5{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register_manual')}",
|
5: f"{Fore.GREEN}5{Style.RESET_ALL}. {EMOJI['SUCCESS']} {translator.get('menu.register_manual')}",
|
||||||
6: f"{Fore.GREEN}6{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.temp_github_register')}",
|
6: f"{Fore.GREEN}6{Style.RESET_ALL}. {EMOJI['RESET']} {translator.get('menu.temp_github_register')}",
|
||||||
7: f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}",
|
7: f"{Fore.GREEN}7{Style.RESET_ALL}. {EMOJI['ERROR']} {translator.get('menu.quit')}",
|
||||||
|
@ -111,7 +111,7 @@ def get_cursor_paths(translator=None) -> Tuple[str, str]:
|
|||||||
# For Linux, try to find the first existing path if the configured one doesn't exist
|
# For Linux, try to find the first existing path if the configured one doesn't exist
|
||||||
if system == "Linux" and not os.path.exists(base_path):
|
if system == "Linux" and not os.path.exists(base_path):
|
||||||
for path in default_paths["Linux"]:
|
for path in default_paths["Linux"]:
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
base_path = path
|
base_path = path
|
||||||
# Update config with the found path
|
# Update config with the found path
|
||||||
config.set(section, 'cursor_path', path)
|
config.set(section, 'cursor_path', path)
|
||||||
@ -529,7 +529,7 @@ class MachineIDResetter:
|
|||||||
self.db_path = config.get('LinuxPaths', 'storage_path')
|
self.db_path = config.get('LinuxPaths', 'storage_path')
|
||||||
self.sqlite_path = config.get('LinuxPaths', 'sqlite_path')
|
self.sqlite_path = config.get('LinuxPaths', 'sqlite_path')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
|
raise NotImplementedError(f"Not Supported OS: {sys.platform}")
|
||||||
|
|
||||||
# Save any changes to config file
|
# Save any changes to config file
|
||||||
|
Loading…
x
Reference in New Issue
Block a user