mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-03 04:57:36 +08:00
Add bypass token limit functionality
- Introduced a new script `bypass_token_limit.py` to modify the `workbench.desktop.main.js` file, allowing users to bypass token limits. - Updated localization files to include new strings for the bypass token limit feature in English, Simplified Chinese, and Traditional Chinese. - Enhanced CHANGELOG.md to reflect the addition of the bypass token limit feature and related fixes.
This commit is contained in:
parent
9f51ba8128
commit
4746af7ce9
@ -1,5 +1,9 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## v1.8.11
|
||||||
|
1. Add: Bypass Token Limit | 添加繞過 Token 限制
|
||||||
|
2. Fix: Some Issues | 修復一些問題
|
||||||
|
|
||||||
## v1.8.10
|
## v1.8.10
|
||||||
1. Add: Check User Authorized | 添加檢查用戶授權
|
1. Add: Check User Authorized | 添加檢查用戶授權
|
||||||
2. Fix: Linux Reset Process Error: 'base' | 修復 Linux 重置過程錯誤:'base'
|
2. Fix: Linux Reset Process Error: 'base' | 修復 Linux 重置過程錯誤:'base'
|
||||||
|
174
bypass_token_limit.py
Normal file
174
bypass_token_limit.py
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import platform
|
||||||
|
import tempfile
|
||||||
|
import glob
|
||||||
|
from colorama import Fore, Style, init
|
||||||
|
import configparser
|
||||||
|
from new_signup import get_user_documents_path
|
||||||
|
from config import get_config
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Initialize colorama
|
||||||
|
init()
|
||||||
|
|
||||||
|
# Define emoji constants
|
||||||
|
EMOJI = {
|
||||||
|
"FILE": "📄",
|
||||||
|
"BACKUP": "💾",
|
||||||
|
"SUCCESS": "✅",
|
||||||
|
"ERROR": "❌",
|
||||||
|
"INFO": "ℹ️",
|
||||||
|
"RESET": "🔄",
|
||||||
|
"WARNING": "⚠️",
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_workbench_cursor_path(translator=None) -> str:
|
||||||
|
"""Get Cursor workbench.desktop.main.js 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)
|
||||||
|
|
||||||
|
paths_map = {
|
||||||
|
"Darwin": { # macOS
|
||||||
|
"base": "/Applications/Cursor.app/Contents/Resources/app",
|
||||||
|
"main": "out/vs/workbench/workbench.desktop.main.js"
|
||||||
|
},
|
||||||
|
"Windows": {
|
||||||
|
"main": "out\\vs\\workbench\\workbench.desktop.main.js"
|
||||||
|
},
|
||||||
|
"Linux": {
|
||||||
|
"bases": ["/opt/Cursor/resources/app", "/usr/share/cursor/resources/app", "/usr/lib/cursor/app/"],
|
||||||
|
"main": "out/vs/workbench/workbench.desktop.main.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if system == "Linux":
|
||||||
|
# Add extracted AppImage with correct usr structure
|
||||||
|
extracted_usr_paths = glob.glob(os.path.expanduser("~/squashfs-root/usr/share/cursor/resources/app"))
|
||||||
|
|
||||||
|
paths_map["Linux"]["bases"].extend(extracted_usr_paths)
|
||||||
|
|
||||||
|
if system not in paths_map:
|
||||||
|
raise OSError(translator.get('reset.unsupported_os', system=system) if translator else f"不支持的操作系统: {system}")
|
||||||
|
|
||||||
|
if system == "Linux":
|
||||||
|
for base in paths_map["Linux"]["bases"]:
|
||||||
|
main_path = os.path.join(base, paths_map["Linux"]["main"])
|
||||||
|
print(f"{Fore.CYAN}{EMOJI['INFO']} Checking path: {main_path}{Style.RESET_ALL}")
|
||||||
|
if os.path.exists(main_path):
|
||||||
|
return main_path
|
||||||
|
|
||||||
|
if system == "Windows":
|
||||||
|
base_path = config.get('WindowsPaths', 'cursor_path')
|
||||||
|
elif system == "Darwin":
|
||||||
|
base_path = paths_map[system]["base"]
|
||||||
|
else: # Linux
|
||||||
|
# For Linux, we've already checked all bases in the loop above
|
||||||
|
# If we're here, it means none of the bases worked, so we'll use the first one
|
||||||
|
base_path = paths_map[system]["bases"][0]
|
||||||
|
|
||||||
|
main_path = os.path.join(base_path, paths_map[system]["main"])
|
||||||
|
|
||||||
|
if not os.path.exists(main_path):
|
||||||
|
raise OSError(translator.get('reset.file_not_found', path=main_path) if translator else f"未找到 Cursor main.js 文件: {main_path}")
|
||||||
|
|
||||||
|
return main_path
|
||||||
|
|
||||||
|
|
||||||
|
def modify_workbench_js(file_path: str, translator=None) -> bool:
|
||||||
|
"""
|
||||||
|
Modify file content
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Save original file permissions
|
||||||
|
original_stat = os.stat(file_path)
|
||||||
|
original_mode = original_stat.st_mode
|
||||||
|
original_uid = original_stat.st_uid
|
||||||
|
original_gid = original_stat.st_gid
|
||||||
|
|
||||||
|
# Create temporary file
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", errors="ignore", delete=False) as tmp_file:
|
||||||
|
# Read original content
|
||||||
|
with open(file_path, "r", encoding="utf-8", errors="ignore") as main_file:
|
||||||
|
content = main_file.read()
|
||||||
|
|
||||||
|
patterns = {
|
||||||
|
# 通用按钮替换模式
|
||||||
|
r'B(k,D(Ln,{title:"Upgrade to Pro",size:"small",get codicon(){return A.rocket},get onClick(){return t.pay}}),null)': r'B(k,D(Ln,{title:"yeongpin GitHub",size:"small",get codicon(){return A.github},get onClick(){return function(){window.open("https://github.com/yeongpin/cursor-free-vip","_blank")}}}),null)',
|
||||||
|
|
||||||
|
# Windows/Linux/Mac 通用按钮替换模式
|
||||||
|
r'M(x,I(as,{title:"Upgrade to Pro",size:"small",get codicon(){return $.rocket},get onClick(){return t.pay}}),null)': r'M(x,I(as,{title:"yeongpin GitHub",size:"small",get codicon(){return $.rocket},get onClick(){return function(){window.open("https://github.com/yeongpin/cursor-free-vip","_blank")}}}),null)',
|
||||||
|
|
||||||
|
# Badge 替换
|
||||||
|
r'<div>Pro Trial': r'<div>Pro',
|
||||||
|
|
||||||
|
r'py-1">Auto-select': r'py-1">Bypass-Version-Pin',
|
||||||
|
|
||||||
|
#
|
||||||
|
r'async getEffectiveTokenLimit(e){const n=e.modelName;if(!n)return 2e5;':r'async getEffectiveTokenLimit(e){return 9000000;const n=e.modelName;if(!n)return 9e5;',
|
||||||
|
# Pro
|
||||||
|
r'var DWr=ne("<div class=settings__item_description>You are currently signed in with <strong></strong>.");': r'var DWr=ne("<div class=settings__item_description>You are currently signed in with <strong></strong>. <h1>Pro</h1>");',
|
||||||
|
|
||||||
|
# Toast 替换
|
||||||
|
r'notifications-toasts': r'notifications-toasts hidden'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 使用patterns进行替换
|
||||||
|
for old_pattern, new_pattern in patterns.items():
|
||||||
|
content = content.replace(old_pattern, new_pattern)
|
||||||
|
|
||||||
|
# Write to temporary file
|
||||||
|
tmp_file.write(content)
|
||||||
|
tmp_path = tmp_file.name
|
||||||
|
|
||||||
|
# Backup original file with timestamp
|
||||||
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
backup_path = f"{file_path}.backup.{timestamp}"
|
||||||
|
shutil.copy2(file_path, backup_path)
|
||||||
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
|
||||||
|
|
||||||
|
# Move temporary file to original position
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
os.remove(file_path)
|
||||||
|
shutil.move(tmp_path, file_path)
|
||||||
|
|
||||||
|
# Restore original permissions
|
||||||
|
os.chmod(file_path, original_mode)
|
||||||
|
if os.name != "nt": # Not Windows
|
||||||
|
os.chown(file_path, original_uid, original_gid)
|
||||||
|
|
||||||
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.file_modified')}{Style.RESET_ALL}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('reset.modify_file_failed', error=str(e))}{Style.RESET_ALL}")
|
||||||
|
if "tmp_path" in locals():
|
||||||
|
try:
|
||||||
|
os.unlink(tmp_path)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
def run(translator=None):
|
||||||
|
config = get_config(translator)
|
||||||
|
if not config:
|
||||||
|
return False
|
||||||
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
print(f"{Fore.CYAN}{EMOJI['RESET']} {translator.get('bypass_token_limit.title')}{Style.RESET_ALL}")
|
||||||
|
print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
|
||||||
|
modify_workbench_js(get_workbench_cursor_path(translator), translator)
|
||||||
|
|
||||||
|
print(f"\n{Fore.CYAN}{'='*50}{Style.RESET_ALL}")
|
||||||
|
input(f"{EMOJI['INFO']} {translator.get('bypass_token_limit.press_enter')}...")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from main import translator as main_translator
|
||||||
|
run(main_translator)
|
@ -31,7 +31,8 @@
|
|||||||
"operation_cancelled_by_user": "Operation cancelled by user",
|
"operation_cancelled_by_user": "Operation cancelled by user",
|
||||||
"exiting": "Exiting ……",
|
"exiting": "Exiting ……",
|
||||||
"bypass_version_check": "Bypass Cursor Version Check",
|
"bypass_version_check": "Bypass Cursor Version Check",
|
||||||
"check_user_authorized": "Check User Authorized"
|
"check_user_authorized": "Check User Authorized",
|
||||||
|
"bypass_token_limit": "Bypass Token Limit"
|
||||||
},
|
},
|
||||||
"languages": {
|
"languages": {
|
||||||
"en": "English",
|
"en": "English",
|
||||||
@ -727,5 +728,10 @@
|
|||||||
"checking_usage_information": "Checking usage information...",
|
"checking_usage_information": "Checking usage information...",
|
||||||
"check_usage_response": "Check usage response: {response}",
|
"check_usage_response": "Check usage response: {response}",
|
||||||
"usage_response": "Usage response: {response}"
|
"usage_response": "Usage response: {response}"
|
||||||
|
},
|
||||||
|
"bypass_token_limit": {
|
||||||
|
"title": "Bypass Token Limit Tool",
|
||||||
|
"description": "This tool modifies the workbench.desktop.main.js file to bypass the token limit",
|
||||||
|
"press_enter": "Press Enter to continue..."
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,7 +31,8 @@
|
|||||||
"operation_cancelled_by_user": "操作被用户取消",
|
"operation_cancelled_by_user": "操作被用户取消",
|
||||||
"exiting": "退出中 ……",
|
"exiting": "退出中 ……",
|
||||||
"bypass_version_check": "绕过 Cursor 版本检查",
|
"bypass_version_check": "绕过 Cursor 版本检查",
|
||||||
"check_user_authorized": "检查用户授权"
|
"check_user_authorized": "检查用户授权",
|
||||||
|
"bypass_token_limit": "绕过 Token 限制"
|
||||||
},
|
},
|
||||||
"languages": {
|
"languages": {
|
||||||
"en": "英语",
|
"en": "英语",
|
||||||
@ -705,5 +706,10 @@
|
|||||||
"checking_usage_information": "检查使用情况...",
|
"checking_usage_information": "检查使用情况...",
|
||||||
"check_usage_response": "检查使用情况响应: {response}",
|
"check_usage_response": "检查使用情况响应: {response}",
|
||||||
"usage_response": "使用情况响应: {response}"
|
"usage_response": "使用情况响应: {response}"
|
||||||
|
},
|
||||||
|
"bypass_token_limit": {
|
||||||
|
"title": "绕过 Token 限制工具",
|
||||||
|
"description": "此工具修改 workbench.desktop.main.js 文件以绕过 token 限制",
|
||||||
|
"press_enter": "按回车键继续..."
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,7 +31,8 @@
|
|||||||
"operation_cancelled_by_user": "操作被使用者取消",
|
"operation_cancelled_by_user": "操作被使用者取消",
|
||||||
"exiting": "退出中 ……",
|
"exiting": "退出中 ……",
|
||||||
"bypass_version_check": "繞過 Cursor 版本檢查",
|
"bypass_version_check": "繞過 Cursor 版本檢查",
|
||||||
"check_user_authorized": "檢查用戶授權"
|
"check_user_authorized": "檢查用戶授權",
|
||||||
|
"bypass_token_limit": "繞過 Token 限制"
|
||||||
},
|
},
|
||||||
"languages": {
|
"languages": {
|
||||||
"en": "英文",
|
"en": "英文",
|
||||||
@ -687,5 +688,10 @@
|
|||||||
"checking_usage_information": "檢查使用情況...",
|
"checking_usage_information": "檢查使用情況...",
|
||||||
"check_usage_response": "檢查使用情況響應: {response}",
|
"check_usage_response": "檢查使用情況響應: {response}",
|
||||||
"usage_response": "使用情況響應: {response}"
|
"usage_response": "使用情況響應: {response}"
|
||||||
|
},
|
||||||
|
"bypass_token_limit": {
|
||||||
|
"title": "繞過 Token 限制工具",
|
||||||
|
"description": "此工具修改 workbench.desktop.main.js 文件以繞過 token 限制",
|
||||||
|
"press_enter": "按回車鍵繼續..."
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user