diff --git a/.SRCINFO b/.SRCINFO
index d143943..a732162 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,10 +1,11 @@
pkgbase = cursor-free-vip-git
pkgdesc = Reset Cursor AI MachineID & Auto Sign Up / In & Bypass Higher Token Limit
- pkgver = 1.9.03.2.g43a58db
+ pkgver = 1.9.04.10.g5863891
pkgrel = 1
url = https://github.com/yeongpin/cursor-free-vip
arch = x86_64
license = MIT
+ license = Attribution-NonCommercial-NoDerivatives 4.0 International
makedepends = git
makedepends = python
makedepends = pyinstaller
@@ -13,6 +14,8 @@ pkgbase = cursor-free-vip-git
depends = cursor-bin
provides = cursor-free-vip
source = cursor-free-vip::git+https://github.com/yeongpin/cursor-free-vip.git
+ source = https://raw.githubusercontent.com/canmi21/openjlc/refs/heads/main/LICENSE
+ sha256sums = SKIP
sha256sums = SKIP
pkgname = cursor-free-vip-git
diff --git a/.env b/.env
index 05af5ad..8449e55 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
-version=1.9.03
-VERSION=1.9.03
+version=1.9.05
+VERSION=1.9.05
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1daddd0..6395afc 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -153,7 +153,7 @@ jobs:
- name: Build in ARM64 Docker container
run: |
- docker run --rm --platform linux/arm64 -v ${{ github.workspace }}:/app -w /app arm64v8/python:3.9-slim bash -c "
+ docker run --rm --platform linux/arm64 -v ${{ github.workspace }}:/app -w /app arm64v8/python:3.10-slim bash -c "
apt-get update && apt-get install -y build-essential
pip install --upgrade pip
pip install pyinstaller
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2f0f41..6c9effa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,20 @@
# Change Log
-## v1.9.03
+## v1.9.05
+1. Refactor: Using match-case to refactor language mapping and menu selection logic, making the code clearer and more maintainable. | 使用 match-case 重构语言映射和菜单选择逻辑,使代码更清晰、可维护性更高。
+2. Ci: Update the Python version in the ARM64 Docker build container to 3.10, making it more compatible and easier to migrate in the future. | 更新 ARM64 Docker 构建容器中的 Python 版本至 3.10,兼容性更强,方便未来迁移。
+3. Fix: f-string backslash expression errors in multiple files | 修復多個文件中的 f-string 反斜杠表達式錯誤
+4. Fix: Some Issues | 修復一些問題
+
+## v1.9.04
+1. Add: Opera GX Support | 添加 Opera GX 支持
+2. Same as v1.9.03 | 與 v1.9.03 相同
+3. Hotfix: Some Issues | 修復一些問題
+4. Add: Bypass Cursor JWT EXP Problem | 添加繞過 Cursor JWT EXP 問題
+5. Fix: Cursor editor redirects to logout page and logout automatically | 修復 Cursor 編輯器重定向到登出頁面並自動登出
+6. Fix: Some Issues | 修復一些問題
+
+## v1.9.03[Skip & Merge to v1.9.04]
1. Hotfix: Some Issues | 修復一些問題
2. Add: Bypass Cursor JWT EXP Problem | 添加繞過 Cursor JWT EXP 問題
3. Fix: Cursor editor redirects to logout page and logout automatically | 修復 Cursor 編輯器重定向到登出頁面並自動登出
diff --git a/PKGBUILD b/PKGBUILD
index 97c5636..1b81dda 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -2,17 +2,17 @@
# Contributor: Canmi (Canmi21)
pkgname=cursor-free-vip-git
-pkgver=1.9.03.2.g43a58db
+pkgver=1.9.04.10.g5863891
pkgrel=1
pkgdesc="Reset Cursor AI MachineID & Auto Sign Up / In & Bypass Higher Token Limit"
arch=('x86_64')
url="https://github.com/yeongpin/cursor-free-vip"
-license=('MIT')
+license=('MIT' 'Attribution-NonCommercial-NoDerivatives 4.0 International')
depends=('python' 'cursor-bin')
makedepends=('git' 'python' 'pyinstaller' 'uv')
provides=('cursor-free-vip')
-source=("cursor-free-vip::git+https://github.com/yeongpin/cursor-free-vip.git")
-sha256sums=('SKIP')
+source=("cursor-free-vip::git+https://github.com/yeongpin/cursor-free-vip.git" "https://raw.githubusercontent.com/canmi21/openjlc/refs/heads/main/LICENSE")
+sha256sums=('SKIP' 'SKIP')
pkgver() {
cd "$srcdir/cursor-free-vip"
@@ -28,5 +28,7 @@ build() {
}
package() {
+ install -Dm644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/mit_license"
+ install -Dm644 "$srcdir/cursor-free-vip/LICENSE.md" "$pkgdir/usr/share/licenses/$pkgname/attribution_non_commercial_no_derivatives_license"
install -Dm755 "$srcdir/cursor-free-vip/dist/cursor-free-vip" "$pkgdir/usr/bin/cursor-free-vip"
}
\ No newline at end of file
diff --git a/README.md b/README.md
index 2991a4e..29c1a5c 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,10 @@
-[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
+[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
[](https://creativecommons.org/licenses/by-nc-nd/4.0/)
-[](https://github.com/yeongpin/cursor-free-vip/stargazers)
-[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
+[](https://github.com/yeongpin/cursor-free-vip/stargazers)
+[](https://github.com/yeongpin/cursor-free-vip/releases/latest)
diff --git a/config.py b/config.py
index 400353d..38cc332 100644
--- a/config.py
+++ b/config.py
@@ -60,18 +60,17 @@ def setup_config(translator=None):
'Browser': {
'default_browser': 'chrome',
'chrome_path': get_default_browser_path('chrome'),
- 'edge_path': get_default_browser_path('edge'),
- 'firefox_path': get_default_browser_path('firefox'),
- 'brave_path': get_default_browser_path('brave'),
'chrome_driver_path': get_default_driver_path('chrome'),
+ 'edge_path': get_default_browser_path('edge'),
'edge_driver_path': get_default_driver_path('edge'),
+ 'firefox_path': get_default_browser_path('firefox'),
'firefox_driver_path': get_default_driver_path('firefox'),
+ 'brave_path': get_default_browser_path('brave'),
'brave_driver_path': get_default_driver_path('brave'),
'opera_path': get_default_browser_path('opera'),
- 'opera_driver_path': get_default_driver_path('opera')
- },
- 'Chrome': {
- 'chromepath': get_default_browser_path('chrome')
+ 'opera_driver_path': get_default_driver_path('opera'),
+ 'operagx_path': get_default_browser_path('operagx'),
+ 'operagx_driver_path': get_default_driver_path('chrome') # Opera GX 使用 Chrome 驱动
},
'Turnstile': {
'handle_turnstile_time': '2',
diff --git a/cursor_register_manual.py b/cursor_register_manual.py
index d33df91..e0f8b3e 100644
--- a/cursor_register_manual.py
+++ b/cursor_register_manual.py
@@ -79,7 +79,7 @@ class CursorRegistration:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.invalid_email') if self.translator else '无效的邮箱地址'}{Style.RESET_ALL}")
return False
- print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.email_address')}: {self.email_address}\n{Style.RESET_ALL}")
+ print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.email_address')}: {self.email_address}" + "\n" + f"{Style.RESET_ALL}")
return True
except Exception as e:
diff --git a/delete_cursor_google.py b/delete_cursor_google.py
index baa233f..3bffac9 100644
--- a/delete_cursor_google.py
+++ b/delete_cursor_google.py
@@ -247,11 +247,11 @@ class CursorGoogleAccountDeleter(OAuthHandler):
except:
# Try direct JavaScript input as fallback
try:
- self.browser.run_js(f"""
+ self.browser.run_js(r"""
arguments[0].value = "Delete";
- const event = new Event('input', {{ bubbles: true }});
+ const event = new Event('input', { bubbles: true });
arguments[0].dispatchEvent(event);
- const changeEvent = new Event('change', {{ bubbles: true }});
+ const changeEvent = new Event('change', { bubbles: true });
arguments[0].dispatchEvent(changeEvent);
""", delete_input)
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('account_delete.typed_delete_js', fallback='Typed \"Delete\" using JavaScript')}{Style.RESET_ALL}")
diff --git a/main.py b/main.py
index e3555a9..c3759db 100644
--- a/main.py
+++ b/main.py
@@ -110,18 +110,24 @@ class Translator:
threadid = user32.GetWindowThreadProcessId(hwnd, 0)
layout_id = user32.GetKeyboardLayout(threadid) & 0xFFFF
- # Map language ID to our language codes
- language_map = {
- 0x0409: 'en', # English
- 0x0404: 'zh_tw', # Traditional Chinese
- 0x0804: 'zh_cn', # Simplified Chinese
- 0x0422: 'vi', # Vietnamese
- 0x0419: 'ru', # Russian
- 0x0415: 'tr', # Turkish
- 0x0402: 'bg', # Bulgarian
- }
-
- return language_map.get(layout_id, 'en')
+ # Map language ID to our language codes using match-case
+ match layout_id:
+ case 0x0409:
+ return 'en' # English
+ case 0x0404:
+ return 'zh_tw' # Traditional Chinese
+ case 0x0804:
+ return 'zh_cn' # Simplified Chinese
+ case 0x0422:
+ return 'vi' # Vietnamese
+ case 0x0419:
+ return 'ru' # Russian
+ case 0x0415:
+ return 'tr' # Turkish
+ case 0x0402:
+ return 'bg' # Bulgarian
+ case _:
+ return 'en' # Default to English
except:
return self._detect_unix_language()
@@ -136,53 +142,56 @@ class Translator:
system_locale = system_locale.lower()
- # Map locale to our language codes
- if system_locale.startswith('zh_tw') or system_locale.startswith('zh_hk'):
- return 'zh_tw'
- elif system_locale.startswith('zh_cn'):
- return 'zh_cn'
- elif system_locale.startswith('en'):
- return 'en'
- elif system_locale.startswith('vi'):
- return 'vi'
- elif system_locale.startswith('nl'):
- return 'nl'
- elif system_locale.startswith('de'):
- return 'de'
- elif system_locale.startswith('fr'):
- return 'fr'
- elif system_locale.startswith('pt'):
- return 'pt'
- elif system_locale.startswith('ru'):
- return 'ru'
- elif system_locale.startswith('tr'):
- return 'tr'
- elif system_locale.startswith('bg'):
- return 'bg'
- # Try to get language from LANG environment variable as fallback
- env_lang = os.getenv('LANG', '').lower()
- if 'tw' in env_lang or 'hk' in env_lang:
- return 'zh_tw'
- elif 'cn' in env_lang:
- return 'zh_cn'
- elif 'vi' in env_lang:
- return 'vi'
- elif 'nl' in env_lang:
- return 'nl'
- elif 'de' in env_lang:
- return 'de'
- elif 'fr' in env_lang:
- return 'fr'
- elif 'pt' in env_lang:
- return 'pt'
- elif 'ru' in env_lang:
- return 'ru'
- elif 'tr' in env_lang:
- return 'tr'
- elif 'bg' in env_lang:
- return 'bg'
-
- return 'en'
+ # Map locale to our language codes using match-case
+ match system_locale:
+ case s if s.startswith('zh_tw') or s.startswith('zh_hk'):
+ return 'zh_tw'
+ case s if s.startswith('zh_cn'):
+ return 'zh_cn'
+ case s if s.startswith('en'):
+ return 'en'
+ case s if s.startswith('vi'):
+ return 'vi'
+ case s if s.startswith('nl'):
+ return 'nl'
+ case s if s.startswith('de'):
+ return 'de'
+ case s if s.startswith('fr'):
+ return 'fr'
+ case s if s.startswith('pt'):
+ return 'pt'
+ case s if s.startswith('ru'):
+ return 'ru'
+ case s if s.startswith('tr'):
+ return 'tr'
+ case s if s.startswith('bg'):
+ return 'bg'
+ case _:
+ # Try to get language from LANG environment variable as fallback
+ env_lang = os.getenv('LANG', '').lower()
+ match env_lang:
+ case s if 'tw' in s or 'hk' in s:
+ return 'zh_tw'
+ case s if 'cn' in s:
+ return 'zh_cn'
+ case s if 'vi' in s:
+ return 'vi'
+ case s if 'nl' in s:
+ return 'nl'
+ case s if 'de' in s:
+ return 'de'
+ case s if 'fr' in s:
+ return 'fr'
+ case s if 'pt' in s:
+ return 'pt'
+ case s if 'ru' in s:
+ return 'ru'
+ case s if 'tr' in s:
+ return 'tr'
+ case s if 'bg' in s:
+ return 'bg'
+ case _:
+ return 'en'
except:
return 'en'
@@ -566,87 +575,88 @@ def main():
choice_num = 17
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{choice_num}')}: {Style.RESET_ALL}")
- if choice == "0":
- print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}")
- print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}")
- return
- elif choice == "1":
- import reset_machine_manual
- reset_machine_manual.run(translator)
- print_menu()
- elif choice == "2":
- import cursor_register
- cursor_register.main(translator)
- print_menu()
- elif choice == "3":
- import cursor_register_google
- cursor_register_google.main(translator)
- print_menu()
- elif choice == "4":
- import cursor_register_github
- cursor_register_github.main(translator)
- print_menu()
- elif choice == "5":
- import cursor_register_manual
- cursor_register_manual.main(translator)
- print_menu()
- elif choice == "6":
- import github_cursor_register
- print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.coming_soon')}{Style.RESET_ALL}")
- # github_cursor_register.main(translator)
- print_menu()
- elif choice == "7":
- import quit_cursor
- quit_cursor.quit_cursor(translator)
- print_menu()
- elif choice == "8":
- if select_language():
+ match choice:
+ case "0":
+ print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}")
+ print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}")
+ return
+ case "1":
+ import reset_machine_manual
+ reset_machine_manual.run(translator)
+ print_menu()
+ case "2":
+ import cursor_register
+ cursor_register.main(translator)
+ print_menu()
+ case "3":
+ import cursor_register_google
+ cursor_register_google.main(translator)
+ print_menu()
+ case "4":
+ import cursor_register_github
+ cursor_register_github.main(translator)
+ print_menu()
+ case "5":
+ import cursor_register_manual
+ cursor_register_manual.main(translator)
+ print_menu()
+ case "6":
+ import github_cursor_register
+ print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.coming_soon')}{Style.RESET_ALL}")
+ # github_cursor_register.main(translator)
+ print_menu()
+ case "7":
+ import quit_cursor
+ quit_cursor.quit_cursor(translator)
+ print_menu()
+ case "8":
+ if select_language():
+ print_menu()
+ continue
+ case "9":
+ import disable_auto_update
+ disable_auto_update.run(translator)
+ print_menu()
+ case "10":
+ import totally_reset_cursor
+ totally_reset_cursor.run(translator)
+ # print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.fixed_soon')}{Style.RESET_ALL}")
+ print_menu()
+ case "11":
+ import logo
+ print(logo.CURSOR_CONTRIBUTORS)
+ print_menu()
+ case "12":
+ from config import print_config
+ print_config(get_config(), translator)
+ print_menu()
+ case "13":
+ from oauth_auth import OAuthHandler
+ oauth = OAuthHandler(translator)
+ oauth._select_profile()
+ print_menu()
+ case "14":
+ import delete_cursor_google
+ delete_cursor_google.main(translator)
+ print_menu()
+ case "15":
+ import bypass_version
+ bypass_version.main(translator)
+ print_menu()
+ case "16":
+ import check_user_authorized
+ check_user_authorized.main(translator)
+ print_menu()
+ case "17":
+ import bypass_token_limit
+ bypass_token_limit.run(translator)
+ print_menu()
+ case _:
+ print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
print_menu()
- continue
- elif choice == "9":
- import disable_auto_update
- disable_auto_update.run(translator)
- print_menu()
- elif choice == "10":
- import totally_reset_cursor
- totally_reset_cursor.run(translator)
- # print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.fixed_soon')}{Style.RESET_ALL}")
- print_menu()
- elif choice == "11":
- import logo
- print(logo.CURSOR_CONTRIBUTORS)
- print_menu()
- elif choice == "12":
- from config import print_config
- print_config(get_config(), translator)
- print_menu()
- elif choice == "13":
- from oauth_auth import OAuthHandler
- oauth = OAuthHandler(translator)
- oauth._select_profile()
- print_menu()
- elif choice == "14":
- import delete_cursor_google
- delete_cursor_google.main(translator)
- print_menu()
- elif choice == "15":
- import bypass_version
- bypass_version.main(translator)
- print_menu()
- elif choice == "16":
- import check_user_authorized
- check_user_authorized.main(translator)
- print_menu()
- elif choice == "17":
- import bypass_token_limit
- bypass_token_limit.run(translator)
- print_menu()
- else:
- print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
- print_menu()
except KeyboardInterrupt:
- print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.program_terminated')}{Style.RESET_ALL}")
+ print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.program_terminated')}{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}")
return
except Exception as e:
diff --git a/oauth_auth.py b/oauth_auth.py
index f70e243..4313041 100644
--- a/oauth_auth.py
+++ b/oauth_auth.py
@@ -1,3 +1,4 @@
+# oauth_auth.py
import os
from colorama import Fore, Style, init
import time
@@ -30,7 +31,7 @@ class OAuthHandler:
def __init__(self, translator=None, auth_type=None):
self.translator = translator
self.config = get_config(translator)
- self.auth_type = auth_type # make sure the auth_type is not None
+ self.auth_type = auth_type
os.environ['BROWSER_HEADLESS'] = 'False'
self.browser = None
self.selected_profile = None
@@ -176,10 +177,15 @@ class OAuthHandler:
browser_path = self._get_browser_path()
if not browser_path:
- raise Exception(f"{self.translator.get('oauth.no_compatible_browser_found') if self.translator else 'No compatible browser found. Please install Google Chrome or Chromium.'}\n{self.translator.get('oauth.supported_browsers', platform=platform_name)}\n" +
- "- Windows: Google Chrome, Chromium\n" +
- "- macOS: Google Chrome, Chromium\n" +
- "- Linux: Google Chrome, Chromium, chromium-browser")
+ error_msg = (
+ f"{self.translator.get('oauth.no_compatible_browser_found') if self.translator else 'No compatible browser found. Please install Google Chrome or Chromium.'}" +
+ "\n" +
+ f"{self.translator.get('oauth.supported_browsers', platform=platform_name)}\n" +
+ "- Windows: Google Chrome, Chromium\n" +
+ "- macOS: Google Chrome, Chromium\n" +
+ "- Linux: Google Chrome, Chromium, google-chrome-stable"
+ )
+ raise Exception(error_msg)
print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.found_browser_data_directory', path=user_data_dir) if self.translator else f'Found browser data directory: {user_data_dir}'}{Style.RESET_ALL}")
@@ -239,7 +245,7 @@ class OAuthHandler:
browser_processes = {
'chrome': {
'win': ['chrome.exe', 'chromium.exe'],
- 'linux': ['chrome', 'chromium', 'chromium-browser'],
+ 'linux': ['chrome', 'chromium', 'chromium-browser', 'google-chrome-stable'],
'mac': ['Chrome', 'Chromium']
},
'brave': {
@@ -305,7 +311,8 @@ class OAuthHandler:
'brave': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'BraveSoftware', 'Brave-Browser', 'User Data'),
'edge': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Microsoft', 'Edge', 'User Data'),
'firefox': os.path.join(os.environ.get('APPDATA', ''), 'Mozilla', 'Firefox', 'Profiles'),
- 'opera': os.path.join(os.environ.get('APPDATA', ''), 'Opera Software', 'Opera Stable')
+ 'opera': os.path.join(os.environ.get('APPDATA', ''), 'Opera Software', 'Opera Stable'),
+ 'operagx': os.path.join(os.environ.get('APPDATA', ''), 'Opera Software', 'Opera GX Stable')
}
elif sys.platform == 'darwin': # macOS
user_data_dirs = {
@@ -313,7 +320,8 @@ class OAuthHandler:
'brave': os.path.expanduser('~/Library/Application Support/BraveSoftware/Brave-Browser'),
'edge': os.path.expanduser('~/Library/Application Support/Microsoft Edge'),
'firefox': os.path.expanduser('~/Library/Application Support/Firefox/Profiles'),
- 'opera': os.path.expanduser('~/Library/Application Support/com.operasoftware.Opera')
+ 'opera': os.path.expanduser('~/Library/Application Support/com.operasoftware.Opera'),
+ 'operagx': os.path.expanduser('~/Library/Application Support/com.operasoftware.OperaGX')
}
else: # Linux
user_data_dirs = {
@@ -321,7 +329,8 @@ class OAuthHandler:
'brave': os.path.expanduser('~/.config/BraveSoftware/Brave-Browser'),
'edge': os.path.expanduser('~/.config/microsoft-edge'),
'firefox': os.path.expanduser('~/.mozilla/firefox'),
- 'opera': os.path.expanduser('~/.config/opera')
+ 'opera': os.path.expanduser('~/.config/opera'),
+ 'operagx': os.path.expanduser('~/.config/opera-gx')
}
# 获取选定浏览器的用户数据目录,如果找不到则使用 Chrome 的
@@ -420,7 +429,12 @@ class OAuthHandler:
elif browser_type == 'firefox':
possible_paths = ['/usr/bin/firefox']
else: # 默认为 Chrome
- possible_paths = ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser']
+ possible_paths = [
+ '/usr/bin/google-chrome-stable', # 优先检查 google-chrome-stable
+ '/usr/bin/google-chrome',
+ '/usr/bin/chromium',
+ '/usr/bin/chromium-browser'
+ ]
# 检查每个可能的路径
for path in possible_paths:
@@ -428,7 +442,7 @@ class OAuthHandler:
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.found_browser_at', path=path) if self.translator else f'Found browser at: {path}'}{Style.RESET_ALL}")
return path
- # 如果找不到指定浏览器,则尝试使用Chrome
+ # 如果找不到指定浏览器,则尝试使用 Chrome
if browser_type != 'chrome':
print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('oauth.browser_not_found_trying_chrome', browser=browser_type) if self.translator else f'Could not find {browser_type}, trying Chrome instead'}{Style.RESET_ALL}")
return self._get_chrome_path()
@@ -438,29 +452,6 @@ class OAuthHandler:
except Exception as e:
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_finding_browser_path', error=str(e)) if self.translator else f'Error finding browser path: {e}'}{Style.RESET_ALL}")
return None
-
- def _get_chrome_path(self):
- """Fallback method to get Chrome path"""
- try:
- if os.name == 'nt': # Windows
- possible_paths = [
- os.path.join(os.environ.get('PROGRAMFILES', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'),
- os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'),
- os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google', 'Chrome', 'Application', 'chrome.exe')
- ]
- elif sys.platform == 'darwin': # macOS
- possible_paths = ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome']
- else: # Linux
- possible_paths = ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser']
-
- for path in possible_paths:
- if os.path.exists(path):
- print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.found_chrome_at', path=path) if self.translator else f'Found Chrome at: {path}'}{Style.RESET_ALL}")
- return path
- return None
- except Exception as e:
- print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_finding_chrome_path', error=str(e)) if self.translator else f'Error finding Chrome path: {e}'}{Style.RESET_ALL}")
- return None
def _configure_browser_options(self, browser_path, user_data_dir, active_profile):
"""Configure browser options based on platform"""
@@ -473,6 +464,7 @@ class OAuthHandler:
co.set_argument('--no-first-run')
co.set_argument('--no-default-browser-check')
co.set_argument('--disable-gpu')
+ co.set_argument('--remote-debugging-port=9222') # 明确指定调试端口
# Platform-specific options
if sys.platform.startswith('linux'):
@@ -955,7 +947,8 @@ class OAuthHandler:
value = cookie.get("value", "")
token = get_token_from_cookie(value, self.translator)
except Exception as e:
- print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.token_extraction_error', error=str(e)) if self.translator else f'Token extraction error: {str(e)}'}{Style.RESET_ALL}")
+ error_message = f'Failed to extract auth info: {str(e)}' if not self.translator else self.translator.get('oauth.failed_to_extract_auth_info', error=str(e))
+ print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}")
elif name == "cursor_email":
email = cookie.get("value")
@@ -968,11 +961,13 @@ class OAuthHandler:
missing.append("email")
if not token:
missing.append("token")
- print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.missing_authentication_data', data=', '.join(missing)) if self.translator else f'Missing authentication data: {", ".join(missing)}'}{Style.RESET_ALL}")
+ error_message = f"Missing authentication data: {', '.join(missing)}" if not self.translator else self.translator.get('oauth.missing_authentication_data', data=', '.join(missing))
+ print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}")
return False, None
except Exception as e:
- print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed_to_extract_auth_info', error=str(e)) if self.translator else f'Failed to extract auth info: {str(e)}'}{Style.RESET_ALL}")
+ error_message = f'Failed to extract auth info: {str(e)}' if not self.translator else self.translator.get('oauth.failed_to_extract_auth_info', error=str(e))
+ print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}")
return False, None
def _delete_current_account(self):
@@ -1014,7 +1009,8 @@ class OAuthHandler:
return True
except Exception as e:
- print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed_to_delete_account', error=str(e)) if self.translator else f'Failed to delete account: {str(e)}'}{Style.RESET_ALL}")
+ error_message = f'Failed to delete account: {str(e)}' if not self.translator else self.translator.get('oauth.failed_to_delete_account', error=str(e))
+ print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}")
return False
def main(auth_type, translator=None):
diff --git a/utils.py b/utils.py
index 8a66dbd..8922f86 100644
--- a/utils.py
+++ b/utils.py
@@ -84,14 +84,24 @@ def get_default_browser_path(browser_type='chrome'):
r"C:\Program Files\Opera\opera.exe",
r"C:\Program Files (x86)\Opera\opera.exe",
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera', 'launcher.exe'),
- os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera', 'opera.exe'),
- os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'launcher.exe'),
- os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'opera.exe')
+ os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera', 'opera.exe')
]
for path in opera_paths:
if os.path.exists(path):
return path
return opera_paths[0] # 返回第一个路径,即使它不存在
+ elif browser_type == 'operagx':
+ # 尝试多个可能的 Opera GX 路径
+ operagx_paths = [
+ os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'launcher.exe'),
+ os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'opera.exe'),
+ r"C:\Program Files\Opera GX\opera.exe",
+ r"C:\Program Files (x86)\Opera GX\opera.exe"
+ ]
+ for path in operagx_paths:
+ if os.path.exists(path):
+ return path
+ return operagx_paths[0] # 返回第一个路径,即使它不存在
elif browser_type == 'brave':
# Brave 浏览器的默认安装路径
paths = [
@@ -115,6 +125,8 @@ def get_default_browser_path(browser_type='chrome'):
return "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
elif browser_type == 'opera':
return "/Applications/Opera.app/Contents/MacOS/Opera"
+ elif browser_type == 'operagx':
+ return "/Applications/Opera GX.app/Contents/MacOS/Opera"
else: # Linux
if browser_type == 'chrome':
@@ -135,6 +147,18 @@ def get_default_browser_path(browser_type='chrome'):
return "/usr/bin/firefox"
elif browser_type == 'opera':
return "/usr/bin/opera"
+ elif browser_type == 'operagx':
+ # 尝试常见的 Opera GX 路径
+ operagx_names = ["opera-gx"]
+ for name in operagx_names:
+ try:
+ import shutil
+ path = shutil.which(name)
+ if path:
+ return path
+ except:
+ pass
+ return "/usr/bin/opera-gx"
elif browser_type == 'brave':
# 尝试常见的 Brave 路径
brave_names = ["brave", "brave-browser"]