Compare commits

...

8 Commits

Author SHA1 Message Date
yeongpin
12d46d5f18 Update build.yml to bump version to 1.8.09 and remove changelog extraction step from release process 2025-04-09 16:26:43 +08:00
yeongpin
6cb3ad79af Update CHANGELOG.md for version 1.8.09, adding new entries for bypassing token limits and enhancing multilingual support, along with minor issue fixes. 2025-04-09 16:17:23 +08:00
yeongpin
6470c65f8b Update CHANGELOG.md for version 1.8.09, adding a fix for reset break and enhancing the button replacement logic in reset_machine_manual.py for improved maintainability and clarity. 2025-04-09 16:14:57 +08:00
yeongpin
491b227486 Bump version to 1.8.09 in .env file 2025-04-09 10:30:48 +08:00
Pin Studios
96c0cd5274 Merge pull request #528 from Cantue35/fix/disable-forced-update
Fix forced update config deletion when update check is disabled
2025-04-09 10:29:55 +08:00
yeongpin
60a438e618 Update CHANGELOG.md for version 1.8.09, adding new entries for force update configuration enhancements and multilingual support, along with minor issue fixes. 2025-04-09 10:29:43 +08:00
yeongpin
6a25871366 feat: Enhance force update configuration with new options and multilingual support
- Added 'enabled_force_update' option in the [Utils] section of the configuration.
- Updated the force_update_config() function to utilize the new option for determining update behavior.
- Improved user feedback messages for force update status in English, Simplified Chinese, and Traditional Chinese locale files.
- Ensured consistent messaging for enabling and disabling force updates.
2025-04-09 10:29:28 +08:00
Cantue35
b46a58bd23 Fix forced update config deletion when update check is disabled
- Added a conditional check in force_update_config() to verify that enabled_update_check in the [Utils] section is read as False.
- If disabled, the config file will not be deleted.
- This prevents loss of custom configuration and improves usability.
- Tested on macOS with our modifications.
2025-04-08 20:35:09 +03:00
8 changed files with 94 additions and 59 deletions

4
.env
View File

@@ -1,2 +1,2 @@
version=1.8.08
VERSION=1.8.08
version=1.8.09
VERSION=1.8.09

View File

@@ -6,7 +6,7 @@ on:
version:
description: 'Version number (e.g. 1.0.9)'
required: true
default: '1.8.08'
default: '1.8.09'
permissions:
contents: write
@@ -241,4 +241,4 @@ jobs:
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,5 +1,13 @@
# Change Log
## v1.8.09
1. Add: Bypass Token Limit Check | 繞過 Token 使用限制檢查
2. AddBypass Claude Limit 30000 set to 900000(9e5) | 繞過 Claude 使用限制 30000 設置為 900000(9e5)
3. Add: Force Update Config | 添加強制更新配置
4. Add: Multilanguage support for force update | 添加強制更新功能的多語言支持
5. Fix: Reset break | 修復重置中斷
4. Fix: Some Issues | 修復一些問題
## v1.8.08
1. Add: Force Update Config | 添加強制更新配置
2. Add: Multilanguage support for force update | 添加強制更新功能的多語言支持

View File

@@ -54,6 +54,7 @@ def setup_config(translator=None):
},
'Utils': {
'enabled_update_check': 'True',
'enabled_force_update': 'True',
'enabled_account_info': 'True'
}
}
@@ -261,7 +262,7 @@ def print_config(config, translator=None):
def force_update_config(translator=None):
"""
Force update configuration file with latest defaults
Force update configuration file with latest defaults if update check is enabled.
Args:
translator: Translator instance
Returns:
@@ -271,26 +272,39 @@ def force_update_config(translator=None):
config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip")
config_file = os.path.join(config_dir, "config.ini")
current_time = datetime.datetime.now()
# If the config file exists, check if forced update is enabled
if os.path.exists(config_file):
try:
# create backup
backup_file = f"{config_file}.bak.{current_time.strftime('%Y%m%d_%H%M%S')}"
shutil.copy2(config_file, backup_file)
# First, read the existing configuration
existing_config = configparser.ConfigParser()
existing_config.read(config_file, encoding='utf-8')
# Check if "enabled_update_check" is True
update_enabled = True # Default to True if not set
if existing_config.has_section('Utils') and existing_config.has_option('Utils', 'enabled_force_update'):
update_enabled = existing_config.get('Utils', 'enabled_force_update').strip().lower() in ('true', 'yes', '1', 'on')
if update_enabled:
try:
# Create a backup
backup_file = f"{config_file}.bak.{current_time.strftime('%Y%m%d_%H%M%S')}"
shutil.copy2(config_file, backup_file)
if translator:
print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('config.backup_created', path=backup_file) if translator else f'Backup created: {backup_file}'}{Style.RESET_ALL}")
print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('config.config_force_update_enabled') if translator else 'Config file force update enabled'}{Style.RESET_ALL}")
# Delete the original config file (forced update)
os.remove(config_file)
if translator:
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('config.config_removed') if translator else 'Config file removed for forced update'}{Style.RESET_ALL}")
except Exception as e:
if translator:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.backup_failed', error=str(e)) if translator else f'Failed to backup config: {str(e)}'}{Style.RESET_ALL}")
else:
if translator:
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('config.backup_created', path=backup_file) if translator else f'Backup created: {backup_file}'}{Style.RESET_ALL}")
# delete original file
os.remove(config_file)
if translator:
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('config.config_removed') if translator else 'Config file removed for forced update'}{Style.RESET_ALL}")
except Exception as e:
if translator:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.backup_failed', error=str(e)) if translator else f'Failed to backup config: {str(e)}'}{Style.RESET_ALL}")
# use existing setup_config function to create new config
print(f"\n{Fore.CYAN}{EMOJI['INFO']} {translator.get('config.config_force_update_disabled', fallback='Config file force update disabled by configuration. Keeping existing config file.') if translator else 'Config file force update disabled by configuration. Keeping existing config file.'}{Style.RESET_ALL}")
# Generate a new (or updated) configuration if needed
return setup_config(translator)
except Exception as e:
if translator:
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.force_update_failed', error=str(e)) if translator else f'Force update config failed: {str(e)}'}{Style.RESET_ALL}")

View File

@@ -560,7 +560,9 @@
"backup_created": "Backup created: {path}",
"config_removed": "Config file removed for forced update",
"backup_failed": "Failed to backup config: {error}",
"force_update_failed": "Force update config failed: {error}"
"force_update_failed": "Force update config failed: {error}",
"config_force_update_disabled": "Config file force update disabled , skipping forced update",
"config_force_update_enabled": "Config file force update enabled , performing forced update"
},
"oauth": {
"authentication_button_not_found": "Authentication button not found",

View File

@@ -538,7 +538,9 @@
"backup_created": "备份创建: {path}",
"config_removed": "配置文件已删除用于强制更新",
"backup_failed": "备份失败: {error}",
"force_update_failed": "强制更新配置失败: {error}"
"force_update_failed": "强制更新配置失败: {error}",
"config_force_update_disabled": "配置文件强制更新已禁用,跳过强制更新",
"config_force_update_enabled": "配置文件强制更新已启用,正在执行强制更新"
},
"oauth": {
"authentication_button_not_found": "未找到认证按钮",

View File

@@ -520,7 +520,9 @@
"backup_created": "備份已創建: {path}",
"config_removed": "配置文件已刪除用於強制更新",
"backup_failed": "備份失敗: {error}",
"force_update_failed": "強制更新配置失敗: {error}"
"force_update_failed": "強制更新配置失敗: {error}",
"config_force_update_disabled": "配置文件強制更新已禁用,跳過強制更新",
"config_force_update_enabled": "配置文件強制更新已啟用,正在執行強制更新"
},
"oauth": {
"authentication_button_not_found": "未找到認證按鈕",

View File

@@ -15,6 +15,7 @@ import configparser
from new_signup import get_user_documents_path
import traceback
from config import get_config
from datetime import datetime
# Initialize colorama
init()
@@ -334,37 +335,40 @@ def modify_workbench_js(file_path: str, translator=None) -> bool:
with open(file_path, "r", encoding="utf-8", errors="ignore") as main_file:
content = main_file.read()
if sys.platform == "win32":
# Define replacement patterns
CButton_old_pattern = r'M(x,I(as,{title:"Upgrade to Pro",size:"small",get codicon(){return $.rocket},get onClick(){return t.pay}}),null)'
CButton_new_pattern = 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)'
elif sys.platform == "linux":
CButton_old_pattern = r'M(x,I(as,{title:"Upgrade to Pro",size:"small",get codicon(){return $.rocket},get onClick(){return t.pay}}),null)'
CButton_new_pattern = 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)'
elif sys.platform == "darwin":
CButton_old_pattern = r'M(x,I(as,{title:"Upgrade to Pro",size:"small",get codicon(){return $.rocket},get onClick(){return t.pay}}),null)'
CButton_new_pattern = 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)'
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',
CBadge_old_pattern = r'<div>Pro Trial'
CBadge_new_pattern = 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'
}
CToast_old_pattern = r'notifications-toasts'
CToast_new_pattern = r'notifications-toasts hidden'
# Replace content
content = content.replace(CButton_old_pattern, CButton_new_pattern)
content = content.replace(CBadge_old_pattern, CBadge_new_pattern)
content = content.replace(CToast_old_pattern, CToast_new_pattern)
# 使用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
backup_path = file_path + ".backup"
if os.path.exists(backup_path):
os.remove(backup_path)
# 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):
@@ -411,7 +415,10 @@ def modify_main_js(main_path: str, translator) -> bool:
tmp_file.write(content)
tmp_path = tmp_file.name
shutil.copy2(main_path, main_path + ".old")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = f"{main_path}.old.{timestamp}"
shutil.copy2(main_path, backup_path)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
shutil.move(tmp_path, main_path)
os.chmod(main_path, original_mode)
@@ -461,7 +468,8 @@ def patch_cursor_get_machine_id(translator) -> bool:
print(f"{Fore.CYAN}{EMOJI['INFO']} {translator.get('reset.version_check_passed')}{Style.RESET_ALL}")
# Backup file
backup_path = main_path + ".bak"
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = f"{main_path}.bak.{timestamp}"
if not os.path.exists(backup_path):
shutil.copy2(main_path, backup_path)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('reset.backup_created', path=backup_path)}{Style.RESET_ALL}")
@@ -638,8 +646,8 @@ class MachineIDResetter:
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
winreg.CloseKey(key)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('reset.windows_machine_guid_updated')}{Style.RESET_ALL}")
except PermissionError:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_denied')}{Style.RESET_ALL}")
except PermissionError as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.permission_denied', error=str(e))}{Style.RESET_ALL}")
raise
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('reset.update_windows_machine_guid_failed', error=str(e))}{Style.RESET_ALL}")
@@ -717,12 +725,10 @@ class MachineIDResetter:
with open(self.db_path, "r", encoding="utf-8") as f:
config = json.load(f)
backup_path = self.db_path + ".bak"
if not os.path.exists(backup_path):
print(f"{Fore.YELLOW}{EMOJI['BACKUP']} {self.translator.get('reset.creating_backup')}: {backup_path}{Style.RESET_ALL}")
shutil.copy2(self.db_path, backup_path)
else:
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('reset.backup_exists')}{Style.RESET_ALL}")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = f"{self.db_path}.bak.{timestamp}"
print(f"{Fore.YELLOW}{EMOJI['BACKUP']} {self.translator.get('reset.creating_backup')}: {backup_path}{Style.RESET_ALL}")
shutil.copy2(self.db_path, backup_path)
print(f"{Fore.CYAN}{EMOJI['RESET']} {self.translator.get('reset.generating')}...{Style.RESET_ALL}")
new_ids = self.generate_new_ids()
@@ -786,7 +792,8 @@ class MachineIDResetter:
# Create backup if file exists
if os.path.exists(machine_id_path):
backup_path = machine_id_path + ".backup"
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = f"{machine_id_path}.backup.{timestamp}"
try:
shutil.copy2(machine_id_path, backup_path)
print(f"{Fore.GREEN}{EMOJI['INFO']} {self.translator.get('reset.backup_created', path=backup_path) if self.translator else f'Backup created at: {backup_path}'}{Style.RESET_ALL}")